Merge "ARM: qcom: disable power collapse when camera is working"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index 5e964bb..a0d1041 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -59,6 +59,9 @@
 - QCS403
   compatible = "qcom,qcs403"
 
+- QCS401
+  compatible = "qcom,qcs401"
+
 - SDXPRAIRIE
   compatible = "qcom,sdxprairie"
 
@@ -68,6 +71,15 @@
 - TRINKET
   compatible = "qcom,trinket"
 
+- ATOLL
+  compatible = "qcom,atoll"
+
+- QCS610
+  compatible = "qcom,qcs610"
+
+- QCS410
+  compatible = "qcom,qcs410"
+
 Generic board variants:
 
 - CDP device:
@@ -182,6 +194,7 @@
 compatible = "qcom,qcs405-rumi"
 compatible = "qcom,qcs405-iot"
 compatible = "qcom,qcs403-iot"
+compatible = "qcom,qcs401-iot"
 compatible = "qcom,sa8155-adp-star"
 compatible = "qcom,sa8155p-adp-star"
 compatible = "qcom,adp-star"
@@ -199,8 +212,12 @@
 compatible = "qcom,sdmmagpie-atp"
 compatible = "qcom,sdmmagpie-qrd"
 compatible = "qcom,sdmmagpiep-idp"
+compatible = "qcom,sdmmagpiep-atp"
 compatible = "qcom,sdmmagpiep"
 compatible = "qcom,sdmmagpiep-qrd"
 compatible = "qcom,trinket-rumi"
 compatible = "qcom,trinket-idp"
 compatible = "qcom,trinket-qrd"
+compatible = "qcom,atoll-rumi"
+compatible = "qcom,qcs610-iot"
+compatible = "qcom,qcs410-iot"
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
index f6a1dee..5d0cc60 100644
--- a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -99,7 +99,8 @@
 		qcom,sdmshrike-llcc,
 		qcom,sm6150-llcc,
 		qcom,sdmmagpie-llcc,
-		qcom,sdxprairie-llcc
+		qcom,sdxprairie-llcc,
+		qcom,atoll-llcc
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
index f99295e..4b68813 100644
--- a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
@@ -11,7 +11,8 @@
 	Value type: <string>
 	Definition: must be "qcom,clk-cpu-osm" or "qcom,clk-cpu-osm-sdmshrike"
 			or "qcom,clk-cpu-osm-sm6150" or
-			"qcom,clk-cpu-osm-sdmmagpie".
+			"qcom,clk-cpu-osm-sdmmagpie" or
+			"qcom,clk-cpu-osm-trinket".
 
 - reg
 	Usage:      required
diff --git a/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt b/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt
index 8b4804d..c1e6e1f 100644
--- a/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt
+++ b/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt
@@ -7,6 +7,7 @@
 	- compatible: Should be set to one of the following:
 		qca,ar3002
 		qca,qca6174
+		qca,qca6390
 		qca,wcn3990
 	- qca,bt-reset-gpio: GPIO pin to bring BT Controller out of reset
 
diff --git a/Documentation/devicetree/bindings/clock/qcom,virt.txt b/Documentation/devicetree/bindings/clock/qcom,virt.txt
new file mode 100644
index 0000000..028658e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,virt.txt
@@ -0,0 +1,18 @@
+Qualcomm Technologies, Inc. Virtual Clocks
+
+Required properties:
+- compatible:	Shall contain one of the following:
+		"qcom,virt-clk-sm8150-gcc",
+		"qcom,virt-clk-sm8150-scc",
+		"qcom,virt-clk-sm6150-gcc",
+		"qcom,virt-clk-sm6150-scc".
+
+- #clock-cells:	Shall contain 1.
+- #reset-cells:	Shall contain 1.
+
+Example:
+	qcom,virtclk {
+		compatible = "qcom,virt-clk-sm8150-gcc";
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
diff --git a/Documentation/devicetree/bindings/cnss/cnss-wlan.txt b/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
index 5b1e25f..714919f 100644
--- a/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
+++ b/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
@@ -74,6 +74,8 @@
                           optional "supply-name" is "vdd-wlan-rfa".
   - qcom,<supply-name>-info: Specifies configuration for supply. Should be
                              specified in <min_uV max_uV load_uA delay_us>.
+  - pcie-disable-l1: Boolean property to decide whether to disable PCIe L1 PM.
+  - pcie-disable-l1ss: Boolean property to decide whether to disable PCIe L1ss.
 
 List of chip specific sub nodes:
   - chip_cfg@X: represent chip specific configurations
diff --git a/Documentation/devicetree/bindings/cnss/icnss.txt b/Documentation/devicetree/bindings/cnss/icnss.txt
index e9d41eb..127e817 100644
--- a/Documentation/devicetree/bindings/cnss/icnss.txt
+++ b/Documentation/devicetree/bindings/cnss/icnss.txt
@@ -27,6 +27,8 @@
 			   uS.
   - qcom,icnss-vadc: VADC handle for vph_pwr read APIs.
   - qcom,icnss-adc_tm: VADC handle for vph_pwr notification APIs.
+  - io-channels: IIO channel to monitor for vph_pwr power.
+  - io-channel-names: IIO channel name as per the client name.
   - qcom,smmu-s1-bypass: Boolean context flag to set SMMU to S1 bypass
   - qcom,wlan-msa-fixed-region: phandle, specifier pairs to children of /reserved-memory
   - qcom,hyp_disabled: Boolean context flag to disable hyperviser
diff --git a/Documentation/devicetree/bindings/display/msm/sde.txt b/Documentation/devicetree/bindings/display/msm/sde.txt
index 85dea59..65c49d6 100644
--- a/Documentation/devicetree/bindings/display/msm/sde.txt
+++ b/Documentation/devicetree/bindings/display/msm/sde.txt
@@ -443,6 +443,8 @@
 				ordering block
 				0: lower priority pipe has to be on the left for a given pair of pipes.
 				1: priority have to be explicitly configured for a given pair of pipes.
+- qcom,sde-num-mnoc-ports:	A u32 property to indicate the number of mnoc ports
+- qcom,sde-axi-bus-width:	A u32 property to indicate the axi bus width value in bytes
 
 Bus Scaling Subnodes:
 - qcom,sde-reg-bus:		Property to provide Bus scaling for register access for
diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dp.txt b/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
index c3bfd3d..9d9c619 100644
--- a/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
+++ b/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
@@ -107,6 +107,7 @@
 				controller. These pin configurations are installed in the pinctrl
 				device node. Refer to pinctrl-bindings.txt
 - qcom,max-lclk-frequency-khz:	An integer specifying the max. link clock in KHz supported by Display Port.
+- qcom,mst-fixed-topology-ports: u32 values of which MST output port to reserve, start from one
 
 [Optional child nodes]: These nodes are for devices which are
 dependent on msm_ext_disp. If msm_ext_disp is disabled then
diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
index dbb52c4..74d9584 100644
--- a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
@@ -83,6 +83,7 @@
 					-- qcom,supply-max-voltage: maximum voltage level (uV)
 					-- qcom,supply-enable-load: load drawn (uA) from enabled supply
 					-- qcom,supply-disable-load: load drawn (uA) from disabled supply
+					-- qcom,supply-off-min-voltage: minimum voltage level (uV) when turned off
 					-- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on
 					-- qcom,supply-post-on-sleep: time to sleep (ms) after turning on
 					-- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off
diff --git a/Documentation/devicetree/bindings/drm/msm/sde-shd.txt b/Documentation/devicetree/bindings/drm/msm/sde-shd.txt
new file mode 100644
index 0000000..c720e3b
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/msm/sde-shd.txt
@@ -0,0 +1,101 @@
+QTI Snapdragon Display Engine (SDE) shared display
+
+Required properties:
+- compatible:		"qcom,shared-display"
+- qcom,shared-display-base: node handle of qcom,shared-display-base, see below.
+- qcom,blend-stage-range: A pair of u32 property <start size> defines the blend
+			stage start and size for the shared display. For example
+			<4 5> indicates this shared display's blending stage starts
+			from 4 and there are 5 stages in total. Different shared
+			display located on the same base display should not overlap
+			with their blend stages. The maximum stages should be within
+			the range of layer mixer hardware capability.
+- qcom,shared-display-src-mode: source resolution of the shared display, which is also
+			the framebuffer size. It contains two properties:
+			qcom,mode-h-active: A u32 property defines horizontal resolution.
+			qcom,mode-v-active: A u32 property defines vertical resolution.
+- qcom,shared-display-dst-mode: destination rectangle in the shared display, which also
+			includes the padding lines if line padding feature is enabled.
+			It contains 4 properties:
+			qcom,mode-x-offset: A u32 property of x offset.
+			qcom,mode-y-offset: A u32 property of y offset.
+			qcom,mode-width: A u32 property of width.
+			qcom,mode-height: A u32 property of height, including line padding.
+
+
+qcom,shared-display-base properties:
+- qcom,shared-display-base-intf: A u32 property defines intf index of the base display.
+- qcom,shared-display-base-mst: A u32 property defines the DP MST branch port, needed if
+			the base display sits on DP MST display.
+- qcom,shared-display-base-mode: timing of the physical base display, contains the
+			following properties:
+			qcom,mode-h-active: A u32 property defines the horizontal active size.
+			qcom,mode-h-front-porch: A u32 property defines the horizontal front porch.
+			qcom,mode-h-pulse-width: A u32 property defines the horizontal pulse.
+			qcom,mode-h-back-porch: A u32 property defines the horizontal back porch.
+			qcom,mode-h-active-high: A boolean property defines if horizontal polarity
+						is high.
+			qcom,mode-v-active: A u32 property defines the vertical active size.
+			qcom,mode-v-front-porch: A u32 property defines the vertical front portch.
+			qcom,mode-v-pulse-width: A u32 property defines the vertical pulse width.
+			qcom,mode-v-back-porch: A u32 property defines the vertical back porch.
+			qcom,mode-v-active-high: A boolean property defines if vertical polarity
+						is high.
+			qcom,mode-refresh-rate: A u32 property defines vertial refresh rate.
+			qcom,mode-clock-in-khz: A u32 property defines clock in kHz.
+
+Example:
+
+/ {
+	...
+
+	sde_sh_base0: qcom,shared-display-base@0 {
+		qcom,shared-display-base-intf = <0>;
+		qcom,shared-display-base-mode {
+			qcom,mode-h-active = <3840>;
+			qcom,mode-h-front-porch = <176>;
+			qcom,mode-h-pulse-width = <88>;
+			qcom,mode-h-back-porch = <296>;
+			qcom,mode-h-active-high;
+			qcom,mode-v-active = <2160>;
+			qcom,mode-v-front-porch = <8>;
+			qcom,mode-v-pulse-width = <10>;
+			qcom,mode-v-back-porch = <72>;
+			qcom,mode-v-active-high;
+			qcom,mode-refresh-rate = <30>;
+			qcom,mode-clock-in-khz = <297000>;
+		};
+	};
+
+	sde_sh0: qcom,shared-display@0 {
+		compatible = "qcom,shared-display";
+		qcom,shared-display-base = <&sde_sh_base0>;
+		qcom,blend-stage-range = <0 5>;
+		qcom,shared-display-src-mode {
+			qcom,mode-h-active = <1920>;
+			qcom,mode-v-active = <2160>;
+		};
+		qcom,shared-display-dst-mode {
+			qcom,mode-x-offset = <0>;
+			qcom,mode-y-offset = <0>;
+			qcom,mode-width = <1920>;
+			qcom,mode-height = <2160>;
+		};
+	};
+
+	sde_sh1: qcom,shared-display@1 {
+		compatible = "qcom,shared-display";
+		qcom,shared-display-base = <&sde_sh_base0>;
+		qcom,blend-stage-range = <5 5>;
+		qcom,shared-display-src-mode {
+			qcom,mode-h-active = <1920>;
+			qcom,mode-v-active = <2160>;
+		};
+		qcom,shared-display-dst-mode {
+			qcom,mode-x-offset = <1920>;
+			qcom,mode-y-offset = <0>;
+			qcom,mode-width = <1920>;
+			qcom,mode-height = <2160>;
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/eeprom/eeprom.txt b/Documentation/devicetree/bindings/eeprom/eeprom.txt
index afc0458..3c9a822 100644
--- a/Documentation/devicetree/bindings/eeprom/eeprom.txt
+++ b/Documentation/devicetree/bindings/eeprom/eeprom.txt
@@ -6,7 +6,8 @@
 
 	"atmel,24c00", "atmel,24c01", "atmel,24c02", "atmel,24c04",
 	"atmel,24c08", "atmel,24c16", "atmel,24c32", "atmel,24c64",
-	"atmel,24c128", "atmel,24c256", "atmel,24c512", "atmel,24c1024"
+	"atmel,24c128", "atmel,24c256", "atmel,24c512", "atmel,24c1024",
+	"atmel,24c2048"
 
 	"catalyst,24c32"
 
@@ -23,7 +24,7 @@
 	 device with <type> and manufacturer "atmel" should be used.
 	 Possible types are:
 	 "24c00", "24c01", "24c02", "24c04", "24c08", "24c16", "24c32", "24c64",
-	 "24c128", "24c256", "24c512", "24c1024", "spd"
+	 "24c128", "24c256", "24c512", "24c1024", "24c2048", "spd"
 
   - reg : the I2C address of the EEPROM
 
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index e01dacc..26b523b 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -144,6 +144,14 @@
 				mask   - mask for the relevant bits in the efuse register.
 				shift  - number of bits to right shift to get the speed bin
 				value.
+
+- qcom,gpu-gaming-bin:  	GPU gaming bin information in the format
+				<offset mask shift>
+				offset - offset of the efuse register from the base.
+				mask   - mask for the relevant bits in the efuse register.
+				shift  - number of bits to right shift to get the value of
+				relevant bits.
+
 - qcom,gpu-disable-fuse:	GPU disable fuse
 				<offset mask shift>
 				offset - offset of the efuse register from the base.
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..a8d1554
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/st-asm330.txt
@@ -0,0 +1,46 @@
+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
+- vio-supply: 1.8V regulator supply
+- vdd-supply: 3V regulator supply
+- 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/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index c8ad1b3..48eef24 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -137,6 +137,15 @@
 		  and end of all mapped buffers to prefetch size boundary, which
 		  is defined by ARM_SMMU_MIN_IOVA_ALIGN.
 
+- qcom,no-dynamic-asid:
+		  Clients that uses the dynamic domains will have an unique asid
+		  per each domain and all domains can share the same context bank.
+		  When ASID based invalidation is used, on some hardware revisions,
+		  as a result of multiple ASID's associated with the same context
+		  bank, TLB entries are not invalidated properly. On such systems,
+		  we can choose to have a single ASID associated with all domains
+		  for a context bank.
+
 - clocks        : List of clocks to be used during SMMU register access. See
                   Documentation/devicetree/bindings/clock/clock-bindings.txt
                   for information about the format. For each clock specified
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-smmu.txt b/Documentation/devicetree/bindings/media/video/msm-cam-smmu.txt
index eca2bd8..4b1f086 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-smmu.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-smmu.txt
@@ -32,6 +32,11 @@
   Value type: <string>
   Definition: Should be "qcom,msm-cam-smmu".
 
+- qcom,camera-secure-sid
+  Usage: optional
+  Value type: boolean
+  Definition: Specifies if the sensor stream is a secure stream.
+
 ===================================================================
 Second Level Node - CAM SMMU context bank device or firmware device
 ===================================================================
@@ -98,6 +103,7 @@
 Example:
 	qcom,cam_smmu@0 {
 		compatible = "qcom,msm-cam-smmu";
+		qcom,camera-secure-sid;
 
 		msm_cam_smmu_icp {
 			compatible = "qcom,msm-cam-smmu-cb";
diff --git a/Documentation/devicetree/bindings/net/qcom-ssdk.txt b/Documentation/devicetree/bindings/net/qcom-ssdk.txt
new file mode 100644
index 0000000..96edb629
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/qcom-ssdk.txt
@@ -0,0 +1,35 @@
+
+* Qualcomm Technologies Inc. SSDK Driver.
+
+Add missing DT bindings documentation for 8337 ethernet switch.
+
+Required properties:
+- compatible: Should be "qcom,ess-switch-qca83xx"
+- qcom,switch-access-mode: Should be "mdio" or "local bus"
+- qcom,link-intr-gpio: Link interrupt number used by switch
+- qcom,switch-cpu-bmp: Switch cpu port bitmap
+- qcom,switch-lan-bmp: Switch lan port bitmap
+- qcom,switch-wan-bmp: Switch wan port bitmap
+- qcom,ar8327-initvals: Initial qca83xx configuration
+
+Optional:
+- qcom,link-polling-required: Boolean- Present if using polling for link check
+
+Example:
+
+ess-switch@0 {
+	compatible = "qcom,ess-switch-qca83xx";
+	qcom,switch-access-mode = "mdio";
+	qcom,ar8327-initvals = <
+		0x00004 0x4200000   /* PAD0_MODE */
+		0x00008 0x0         /* PAD5_MODE */
+		0x000e4 0xaa545     /* MAC_POWER_SEL */
+		0x000e0 0xc74164de  /* SGMII_CTRL */
+		0x0007c 0x4e        /* PORT0_STATUS */
+		0x00094 0x4e        /* PORT6_STATUS */
+	>;
+	qcom,link-intr-gpio = <84>;
+	qcom,switch-cpu-bmp = <0x01>;    /* cpu port bitmap */
+	qcom,switch-lan-bmp = <0x3e>;    /* lan port bitmap */
+	qcom,switch-wan-bmp = <0x0>;     /* wan port bitmap */
+};
diff --git a/Documentation/devicetree/bindings/pci/msm_ep_pcie.txt b/Documentation/devicetree/bindings/pci/msm_ep_pcie.txt
index be84da0..e78b164 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.
@@ -49,6 +50,8 @@
   - qcom,phy-status-reg: Register offset for PHY status.
   - qcom,dbi-base-reg: Register offset for DBI base address.
   - qcom,slv-space-reg: Register offset for slave address space size.
+  - qcom,pcie-vendor-id: Vendor id to be written to the Vendor ID register.
+  - qcom,pcie-device-id: Device id to be written to the Device ID register.
   - qcom,pcie-link-speed: generation of PCIe link speed. The value could be
     1, 2 or 3.
   - qcom,pcie-active-config: boolean type; active configuration of PCIe
@@ -76,8 +79,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/pinctrl/qcom,atoll-pinctrl b/Documentation/devicetree/bindings/pinctrl/qcom,atoll-pinctrl
new file mode 100644
index 0000000..2510cc8
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,atoll-pinctrl
@@ -0,0 +1,192 @@
+Qualcomm Technologies, Inc. ATOLL TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+ATOLL platform.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be "qcom,atoll-pinctrl"
+
+- reg:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: the base address and size of the TLMM register space
+		    provided as "pinctrl" and optional base address
+		    of shared SPI config registers provided as "spi_cfg".
+
+- reg-names:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: Provides labels for the reg property.
+
+- interrupts:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/gpio/gpio.h>
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+	Usage: required
+	Value type: <string-array>
+	Definition: List of gpio pins affected by the properties specified in
+		    this subnode.
+
+		    Valid pins are:
+		      gpio0-gpio149
+		        Supports mux, bias and drive-strength
+
+		      sdc1_clk, sdc1_cmd, sdc1_data sdc2_clk, sdc2_cmd,
+		      sdc2_data sdc1_rclk
+		        Supports bias and drive-strength
+
+- function:
+	Usage: required
+	Value type: <string>
+	Definition: Specify the alternative function to be configured for the
+		    specified pins. Functions are only valid for gpio pins.
+		    Valid values are:
+
+		    blsp_uart1, blsp_spi1, blsp_i2c1, blsp_uim1, atest_tsens,
+		    bimc_dte1, dac_calib0, blsp_spi8, blsp_uart8, blsp_uim8,
+		    qdss_cti_trig_out_b, bimc_dte0, dac_calib1, qdss_cti_trig_in_b,
+		    dac_calib2, atest_tsens2, atest_usb1, blsp_spi10, blsp_uart10,
+		    blsp_uim10, atest_bbrx1, atest_usb13, atest_bbrx0, atest_usb12,
+		    mdp_vsync, edp_lcd, blsp_i2c10, atest_gpsadc1, atest_usb11,
+		    atest_gpsadc0, edp_hot, atest_usb10, m_voc, dac_gpio, atest_char,
+		    cam_mclk, pll_bypassnl, qdss_stm7, blsp_i2c8, qdss_tracedata_b,
+		    pll_reset, qdss_stm6, qdss_stm5, qdss_stm4, atest_usb2, cci_i2c,
+		    qdss_stm3, dac_calib3, atest_usb23, atest_char3, dac_calib4,
+		    qdss_stm2, atest_usb22, atest_char2, qdss_stm1, dac_calib5,
+		    atest_usb21, atest_char1, dbg_out, qdss_stm0, dac_calib6,
+		    atest_usb20, atest_char0, dac_calib10, qdss_stm10,
+		    qdss_cti_trig_in_a, cci_timer4, blsp_spi6, blsp_uart6, blsp_uim6,
+		    blsp2_spi, qdss_stm9, qdss_cti_trig_out_a, dac_calib11,
+		    qdss_stm8, cci_timer0, qdss_stm13, dac_calib7, cci_timer1,
+		    qdss_stm12, dac_calib8, cci_timer2, blsp1_spi, qdss_stm11,
+		    dac_calib9, cci_timer3, cci_async, dac_calib12, blsp_i2c6,
+		    qdss_tracectl_a, dac_calib13, qdss_traceclk_a, dac_calib14,
+		    dac_calib15, hdmi_rcv, dac_calib16, hdmi_cec, pwr_modem,
+		    dac_calib17, hdmi_ddc, pwr_nav, dac_calib18, pwr_crypto,
+		    dac_calib19, hdmi_hot, dac_calib20, dac_calib21, pcie_ep,
+		    dac_calib22, dac_calib23, dac_calib24, tsif1_sync, dac_calib25,
+		    sd_write, tsif1_error, blsp_spi2, blsp_uart2, blsp_uim2,
+		    qdss_cti, blsp_i2c2, blsp_spi3, blsp_uart3, blsp_uim3, blsp_i2c3,
+		    uim3, blsp_spi9, blsp_uart9, blsp_uim9, blsp10_spi, blsp_i2c9,
+		    blsp_spi7, blsp_uart7, blsp_uim7, qdss_tracedata_a, blsp_i2c7,
+		    qua_mi2s, gcc_gp1_clk_a, ssc_irq, uim4, blsp_spi11, blsp_uart11,
+		    blsp_uim11, gcc_gp2_clk_a, gcc_gp3_clk_a, blsp_i2c11, cri_trng0,
+		    cri_trng1, cri_trng, qdss_stm18, pri_mi2s, qdss_stm17, blsp_spi4,
+		    blsp_uart4, blsp_uim4, qdss_stm16, qdss_stm15, blsp_i2c4,
+		    qdss_stm14, dac_calib26, spkr_i2s, audio_ref, lpass_slimbus,
+		    isense_dbg, tsense_pwm1, tsense_pwm2, btfm_slimbus, ter_mi2s,
+		    qdss_stm22, qdss_stm21, qdss_stm20, qdss_stm19, gcc_gp1_clk_b,
+		    sec_mi2s, blsp_spi5, blsp_uart5, blsp_uim5, gcc_gp2_clk_b,
+		    gcc_gp3_clk_b, blsp_i2c5, blsp_spi12, blsp_uart12, blsp_uim12,
+		    qdss_stm25, qdss_stm31, blsp_i2c12, qdss_stm30, qdss_stm29,
+		    tsif1_clk, qdss_stm28, tsif1_en, tsif1_data, sdc4_cmd, qdss_stm27,
+		    qdss_traceclk_b, tsif2_error, sdc43, vfr_1, qdss_stm26, tsif2_clk,
+		    sdc4_clk, qdss_stm24, tsif2_en, sdc42, qdss_stm23, qdss_tracectl_b,
+		    sd_card, tsif2_data, sdc41, tsif2_sync, sdc40, mdp_vsync_p_b,
+		    ldo_en, mdp_vsync_s_b, ldo_update, blsp11_uart_tx_b, blsp11_uart_rx_b,
+		    blsp11_i2c_sda_b, prng_rosc, blsp11_i2c_scl_b, uim2, uim1, uim_batt,
+		    pcie_clk, pa_indicator, adsp_ext, ddr_bist, qdss_tracedata_11,
+		    qdss_tracedata_12, modem_tsync, nav_dr, nav_pps, gsm_tx, qspi_cs,
+		    ssbi2, ssbi1, mss_lte, qspi_clk, qspi0, qspi1, qspi2, qspi3, gpio
+
+- bias-disable:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull up.
+
+- output-high:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    high.
+		    Not valid for sdc pins.
+
+- output-low:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    low.
+		    Not valid for sdc pins.
+
+- drive-strength:
+	Usage: optional
+	Value type: <u32>
+	Definition: Selects the drive strength for the specified pins, in mA.
+		    Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+	tlmm: pinctrl@03000000 {
+		compatible = "qcom,atoll-pinctrl";
+		reg = <0x03000000 0xdc2000>;
+		interrupts = <0 208 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt
index e52a65d..17da5e3 100644
--- a/Documentation/devicetree/bindings/platform/msm/ipa.txt
+++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt
@@ -61,6 +61,8 @@
                                 a pipe reset via the IPA uC is required
 - qcom,ipa-wdi2:		Boolean context flag to indicate whether
 				using wdi-2.0 or not
+- qcom,ipa-wdi3-over-gsi:       Boolean context flag to indicate whether
+                                using wdi-3.0 or not
 - qcom,bandwidth-vote-for-ipa:	Boolean context flag to indicate whether
 				ipa clock voting is done by bandwidth
 				voting via msm-bus-scale driver or not
@@ -104,6 +106,12 @@
 				control.
 - qcom,entire-ipa-block-size: Complete size of the ipa block in which all
 				registers, collected upon crash, reside.
+- qcom,ipa-endp-delay-wa: Boolean context flag to indicate end point delay work around
+				supported or not.
+- qcom,secure-debug-check-action: Drives secure memory debug check. Three values allowed:
+				0 (use scm call),
+				1 (override scm call as though it returned true), and
+				2 (override scm call as though it returned false)
 
 IPA pipe sub nodes (A2 static pipes configurations):
 
diff --git a/Documentation/devicetree/bindings/platform/msm/ipa_mpm.txt b/Documentation/devicetree/bindings/platform/msm/ipa_mpm.txt
new file mode 100644
index 0000000..1198d53
--- /dev/null
+++ b/Documentation/devicetree/bindings/platform/msm/ipa_mpm.txt
@@ -0,0 +1,23 @@
+* Qualcomm Technologies, Inc. IPA MHI Prime Manager driver module
+
+This module enables IPA Modem to IPA  APQ communication using
+MHI Prime.
+
+Required properties:
+- compatible:		Must be "qcom,ipa-mpm"
+- qcom,mhi-chdb-base:	MHI channel doorbell base address in MMIO space.
+- qcom,mhi-erdb-base:	MHI event doorbell base address in MMIO space.
+
+Optional:
+- qcom,iova-mapping:	Start address and size of the carved IOVA space
+				dedicated for MHI control structures
+				(such as transfer rings, event rings, doorbells).
+				If not present, SMMU S1 is considered to be in bypass mode.
+
+Example:
+	ipa_mpm: qcom,ipa-mpm {
+		compatible = "qcom,ipa-mpm";
+		qcom,mhi-chdb-base = <0x40300300>;
+		qcom,mhi-erdb-base = <0x40300700>;
+		qcom,iova-mapping = <0x10000000 0x1FFFFFFF>;
+	}
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt
index 9bc43dc..5640020 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt
@@ -31,6 +31,19 @@
 
 - #thermal-sensor-cells: Should be 0. See thermal.txt for the description.
 
+- nvmem-names:
+	Usage: optional
+	Value type: <string>
+	Definition: Nvmem device name for SDAM to store parameters like cycle
+		    counters and learned capacity. It must be defined as
+		    "fg_sdam".
+
+- nvmem:
+	Usage: optional
+	Value type: <phandle>
+	Definition: Phandle of the nvmem device name to access SDAM to store
+		    parameters.
+
 - qcom,fg-cutoff-voltage
 	Usage:      optional
 	Value type: <u32>
@@ -52,6 +65,15 @@
 		    is not specified, then the default value used will be
 		    2812 mV.
 
+- qcom,fg-sys-min-voltage
+	Usage:      optional
+	Value type: <u32>
+	Definition: The voltage threshold (in mV) which describes the system
+		    minimum voltage as per the hardware recommendation. This
+		    is not used for any configuration but only for calculating
+		    the available power. If this property is not specified,
+		    then the default value used is 2800 mV.
+
 - qcom,fg-sys-term-current
 	Usage:      optional
 	Value type: <u32>
@@ -426,6 +448,30 @@
 		    resolution of monotonic SOC under CAPACITY_RAW property
 		    during charging in the scale of 0-10000.
 
+- qcom,soc-scale-mode-en
+	Usage:      optional
+	Value type: <boolean>
+	Definition: A boolean property that when specified will enable scaling
+		    of the SOC linearly, based on the filtered battery voltage
+		    after crossing below a Vbatt threshold.
+
+- qcom,soc-scale-vbatt-mv
+	Usage:      optional
+	Value type: <u32>
+	Definition: Threshold voltage to decide when SOC should
+		    be scaled based on filtered voltage when
+		    qcom,soc-scale-mode-en is specified. If this
+		    is not specified, then the default value is 3400.
+		    Unit is in mV.
+
+- qcom,soc-scale-time-ms
+	Usage:      optional
+	Value type: <u32>
+	Definition: Timer value for doing SOC calculation based on
+		    filtered voltage when qcom,soc-scale-mode-en is
+		    specified. If this is not specified, then the
+		    default value is 10000. Unit is in ms.
+
 ==========================================================
 Second Level Nodes - Peripherals managed by FG Gen4 driver
 ==========================================================
@@ -454,6 +500,8 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 	qcom,pmic-revid = <&pm8150b_revid>;
+	nvmem-names = "fg_sdam";
+	nvmem = <&pm8150_sdam_2>;
 	#thermal-cells = <0>;
 	status = "okay";
 
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
index 9eb7ed76..e81bdbd 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
@@ -337,6 +337,11 @@
 		    for the shutdown SOC to be used. If the difference is
 		    beyond this value the PON SOC is used.
 
+- qcom,qg-use-s7-ocv
+	Usage:      optional
+	Value type: <bool>
+	Definition: Boolean property to use S7 for PON OCV.
+
 ==========================================================
 Second Level Nodes - Peripherals managed by QGAUGE driver
 ==========================================================
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-amoled-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-amoled-regulator.txt
index dca7de3..eaf2ded 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-amoled-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-amoled-regulator.txt
@@ -61,6 +61,12 @@
 		    controlled by SWIRE signal. When this is specified, output
 		    voltage of the regulator is not controlled by SW.
 
+- qcom,aod-pd-control:
+	Usage:      optional
+	Value type: <empty>
+	Definition: A boolean property to specify that the pull down control
+		    for AB/IBB needs to be configured during AOD mode.
+
 Example:
 
 pm8150a_amoled: oledb@e000 {
@@ -82,6 +88,7 @@
 		regulator-min-microvolt = <4600000>;
 		regulator-max-microvolt = <6100000>;
 		qcom,swire-control;
+		qcom,aod-pd-control;
 	};
 
 	ibb_vreg: ibb@dc00 {
@@ -91,5 +98,6 @@
 		regulator-min-microvolt = <800000>;
 		regulator-max-microvolt = <5400000>;
 		qcom,swire-control;
+		qcom,aod-pd-control;
 	};
 };
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt
index 6fae418..601a8e7 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/regulator/rpm-smd-regulator.txt b/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt
index ccefc98..0503db0 100644
--- a/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/rpm-smd-regulator.txt
@@ -42,6 +42,14 @@
 			for every request sent for this regulator including
 			those which are for a strictly lower power state.
 
+- qcom,regulator-hw-type: Specifies the regulator LDO hardware type. This
+			  property must be specified if "qcom,regulator-type"
+			  has been specified with a value of 0 (LDO).
+
+			  Must be one of the below:
+			  "pmic4-ldo" for PMIC4.
+			  "pmic5-ldo" for PMIC5.
+
 [Second Level Nodes]
 
 Required properties:
diff --git a/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt b/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
index b616bf3..0fbbda7e9 100644
--- a/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
+++ b/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
@@ -12,9 +12,10 @@
 - reg: Should contain UART register location and length.
 - interrupts: Should contain UART core interrupts.
 - clocks: clocks needed for UART, includes the core and AHB clock.
-- pinctrl-names/pinctrl-0/1: The GPIOs assigned to this core. The names
-  Should be "active" and "sleep" for the pin confuguration when core is active
-  or when entering sleep state.
+- pinctrl-names/pinctrl-0/1/2: The GPIOs assigned to this core. The names
+  should be "default", "active" and "sleep" for the pin confuguration.
+  It should be in "default" for the default pin configuration during probe,
+  in "active" when core is active or in "sleep" when entering in sleep state.
 - qcom,wrapper-core: Wrapper QUPv3 core containing this UART controller.
 
 Optional properties:
@@ -29,9 +30,10 @@
 	clocks = <&clock_gcc GCC_QUPV3_WRAP0_S0_CLK>,
 		<&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>,
 		<&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>;
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&qup_1_uart_3_active>;
-	pinctrl-1 = <&qup_1_uart_3_sleep>;
+	pinctrl-names = "default", "active", "sleep";
+	pinctrl-0 = <&qup_1_uart_3_default>;
+	pinctrl-1 = <&qup_1_uart_3_active>;
+	pinctrl-2 = <&qup_1_uart_3_sleep>;
 	interrupts = <0 355 0>;
 	qcom,wrapper-core = <&qupv3_0>;
 	qcom,wakeup-byte = <0xFF>;
diff --git a/Documentation/devicetree/bindings/soc/qcom/dcc.txt b/Documentation/devicetree/bindings/soc/qcom/dcc.txt
index c9bf3f5..29cda2d 100644
--- a/Documentation/devicetree/bindings/soc/qcom/dcc.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/dcc.txt
@@ -30,6 +30,11 @@
 - qcom,save-reg: boolean, To save dcc registers state in memory after dcc
 		 enable and disable
 
+- link-list subnode: Each link-list subnode represents a link-list configured by default.
+		     It supports configure multiple link-list nodes.
+
+link-list subnode properties:
+
 - qcom,data-sink: string, To specify default data sink for dcc, should be one
 		  of the following:
 		  "atb"	  : To send captured data over ATB to a trace sink
@@ -54,14 +59,28 @@
 
 		clocks = <&clock_gcc clk_gcc_dcc_ahb_clk>;
 		clock-names = "dcc_clk";
-
-		qcom,curr-link-list = <2>;
-		qcom,link-list = <DCC_READ 0x1740300 6 0>,
-				 <DCC_READ 0x1620500 4 0>,
-				 <DCC_READ 0x7840000 1 0>,
-				 <DCC_READ 0x7841010 12 0>,
-				 <DCC_READ 0x7842000 16 0>,
-				 <DCC_READ 0x7842500 2 0>;
 		qcom,save-reg;
+
+		link_list_0 {
+			qcom,curr-link-list = <2>;
+			qcom,data-sink = "sram";
+			qcom,link-list = <DCC_READ 0x1740300 6 0>,
+					 <DCC_READ 0x1620500 4 0>,
+					 <DCC_READ 0x7840000 1 0>,
+					 <DCC_READ 0x7841010 12 0>,
+					 <DCC_READ 0x7842000 16 0>,
+					 <DCC_READ 0x7842500 2 0>;
+		};
+
+		link_list_2 {
+			qcom,curr-link-list = <3>;
+			qcom,data-sink = "atb";
+			qcom,link-list = <DCC_READ 0x18220d14 3 0>,
+					 <DCC_READ 0x18220d30 4 0>,
+					 <DCC_READ 0x18220d44 4 0>,
+					 <DCC_READ 0x18220d58 4 0>,
+					 <DCC_READ 0x18220fb4 3 0>,
+					 <DCC_READ 0x18220fd0 4 0>;
+		};
 	};
 
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index fa3a6bf..e5f44ae 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -1032,6 +1032,13 @@
                                           0 - Unsupported
                                           1 - Supported
 
+ - qcom,msm-cpudai-tdm-lane-mask: tdm lane mask for multi lane configuration.
+				Lane bit mask value:
+				MSM_TDM_LANE0 (1 << 0)
+				MSM_TDM_LANE1 (1 << 1)
+				MSM_TDM_LANE2 (1 << 2)
+				MSM_TDM_LANE3 (1 << 3)
+
 Example:
 
 	qcom,msm-dai-tdm-quat-rx {
@@ -1700,6 +1707,7 @@
 - qcom,mi2s-audio-intf : Property to specify if MI2S interface is used for the target
 - qcom,auxpcm-audio-intf : Property to specify if AUX PCM interface is used for the target
 - qcom,msm-mi2s-master : List of master/slave configuration for MI2S interfaces
+- qcom,msm_audio_ssr_devs: List the snd event framework clients
 
 Example:
 
@@ -1788,6 +1796,7 @@
 				"msm-dai-q6-tdm.36935";
 		asoc-codec = <&stub_codec>;
 		asoc-codec-names = "msm-stub-codec.1";
+		qcom,msm_audio_ssr_devs = <&audio_apr>, <&q6core>;
 	};
 
 * SDX ASoC Machine driver
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt b/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
index 1e65768..e3eea23 100644
--- a/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
@@ -47,6 +47,10 @@
 
 - qcom,slv-ctrl : Set this flag to configure QUPV3 as SPI slave controller.
 
+- qcom,disable-dma : Set this flag to ensure only fifo mode is used for
+			transfers. FIFO mode does not work when FW of SE
+			is configured in GSI mode.
+
 Other optional properties described in
 Documentation/devicetree/bindings/spi/spi-bus.txt
 
diff --git a/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt b/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
index 846eb88..3288a79 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
+++ b/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
@@ -57,6 +57,12 @@
 			register space in index 0 should be LLM and index 1
 			should be OSM.
 
+- qcom,plat-mitigation-disable:
+	Usage: optional
+	Value type: <none>
+	Definition: Should define this property if platform based cpu cooling
+			device is not required.
+
 Example:
 
 	lmh_dcvs0: qcom,limits-dcvs@18350800 {
@@ -69,6 +75,7 @@
 		isens-vref-0p8-settings = <880000 880000 36000>;
 		reg =  <0x18350800 0x1000>, //LLM
 			<0x18323000 0x1000>; //OSM
+		qcom,plat-mitigation-disable;
 	};
 
 	CPU0: cpu@0 {
diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
index 88b6ea1..528ec14 100644
--- a/Documentation/devicetree/bindings/thermal/thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/thermal.txt
@@ -175,6 +175,10 @@
 			2000mW, while on a 10'' tablet is around
 			4500mW.
 
+- wake-capable-sensor:	Set to true if thermal zone sensor is wake up capable
+  Type: bool		and cooling devices binded to this thermal zone are not
+  Size: none		affected during suspend.
+
 Note: The delay properties are bound to the maximum dT/dt (temperature
 derivative over time) in two situations for a thermal zone:
 (i)  - when passive cooling is activated (polling-delay-passive); and
diff --git a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
index 492ff00..c94f8a8 100644
--- a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
+++ b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
@@ -30,9 +30,9 @@
 - vdda-pll-supply   : phandle to PHY PLL and Power-Gen block power supply
 - clocks	    : List of phandle and clock specifier pairs
 - clock-names       : List of clock input name strings sorted in the same
-		      order as the clocks property. "ref_clk_src", "ref_clk",
+		      order as the clocks property. "ref_clk_src",
 		      "tx_iface_clk" & "rx_iface_clk" are mandatory but
-		      "ref_clk_parent" is optional
+		      "ref_clk_parent" and "ref_clk" are optional
 
 Optional properties:
 - vdda-phy-max-microamp : specifies max. load that can be drawn from phy supply
diff --git a/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt b/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt
index 0ee01dd..d62ccc0 100644
--- a/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/qcom,msm-phy.txt
@@ -189,6 +189,9 @@
    de-asserted, it will prevent random leakage from qusb2 phy resulting from
    out of sequence turn on/off of 1p8, 3p3 and DVDD regulators.
    "refgen_north_bg_reg" : address used to read REFGEN status for overriding QUSB PHY register.
+   "tcsr_conn_box_spare" : To enable/disable USB HS AC/DC coupling feature. When
+   enabled, DP/DM signals will take path through capacitor when USB HS device is
+   connected. This is a required property if 'qcom,usb-hs-ac-bitmask' property is present.
  - clocks: a list of phandles to the PHY clocks. Use as per
    Documentation/devicetree/bindings/clock/clock-bindings.txt
  - clock-names: Names of the clocks in 1-1 correspondence with the "clocks"
@@ -205,8 +208,8 @@
  - qcom,hold-reset: Indicates that hold QUSB PHY into reset state.
  - qcom,phy-clk-scheme: Should be one of "cml" or "cmos" if ref_clk_addr is provided.
  - qcom,major-rev: provide major revision number to differentiate power up sequence. default is 2.0
- - pinctrl-names/pinctrl-0/1: The GPIOs configured as output function. Names represents "active"
-   state when attached in host mode and "suspend" state when detached.
+ - pinctrl-names/pinctrl-0/1: The GPIOs configured as output function. Allowed names are
+   "default" and "sleep".
  - qcom,tune2-efuse-correction: The value to be adjusted from fused value for
    improved rise/fall times.
  - qcom,host-chirp-erratum: Indicates host chirp fix is required.
@@ -216,6 +219,11 @@
    usually it is defined by qfprom device node.
  - nvmem-cell-names: specifies the given nvmem cell name as defined in
    qfprom node.
+ - qcom,usb-hs-ac-bitmask: Specifies the polarity and enable bitfields in
+   tcsr_conn_box_spare register so as to enable USB HS AC/DC coupling feature.
+ - qcom,usb-hs-ac-value: Specifies the value to be written to polarity and
+   enable bitfields so as to enable USB HS AC/DC coupling feature. This is a
+   required property if 'qcom,usb-hs-ac-bitmask' property is present.
 
 Example:
 	qusb_phy: qusb@f9b39000 {
diff --git a/Documentation/devicetree/bindings/usb/qcom,usb-ssphy.txt b/Documentation/devicetree/bindings/usb/qcom,usb-ssphy.txt
index db6d49d..f54a115 100644
--- a/Documentation/devicetree/bindings/usb/qcom,usb-ssphy.txt
+++ b/Documentation/devicetree/bindings/usb/qcom,usb-ssphy.txt
@@ -19,6 +19,7 @@
 - qcom,vbus-valid-override: If present, indicates VBUS pin is not connected to
 the USB PHY and the controller must rely on external VBUS notification in
 order to manually relay the notification to the SSPHY.
+-qcom,keep-powerdown: If present, power down the SSPHY to avoid leakage current.
 
 Example:
 ssphy@f9200000 {
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 112e96e..3614416 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -498,7 +498,9 @@
 
 Note that there is no guarantee that every flag and associated mnemonic will
 be present in all further kernel releases. Things get changed, the flags may
-be vanished or the reverse -- new added.
+be vanished or the reverse -- new added. Interpretation of their meaning
+might change in future as well. So each consumer of these flags has to
+follow each specific kernel version for the exact semantic.
 
 The "Name" field will only be present on a mapping that has been named by
 userspace, and will show the name passed in by userspace.
diff --git a/Makefile b/Makefile
index bd2498c..294e89e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 VERSION = 4
 PATCHLEVEL = 14
-SUBLEVEL = 92
+SUBLEVEL = 105
 EXTRAVERSION =
 NAME = Petit Gorille
 
@@ -490,16 +490,18 @@
 ifeq ($(cc-name),clang)
 ifneq ($(CROSS_COMPILE),)
 CLANG_TRIPLE	?= $(CROSS_COMPILE)
-CLANG_TARGET	:= --target=$(notdir $(CLANG_TRIPLE:%-=%))
-GCC_TOOLCHAIN	:= $(realpath $(dir $(shell which $(LD)))/..)
+CLANG_FLAGS	:= --target=$(notdir $(CLANG_TRIPLE:%-=%))
+GCC_TOOLCHAIN_DIR := $(dir $(shell which $(LD)))
+CLANG_FLAGS	+= --prefix=$(GCC_TOOLCHAIN_DIR)
+GCC_TOOLCHAIN	:= $(realpath $(GCC_TOOLCHAIN_DIR)/..)
 endif
 ifneq ($(GCC_TOOLCHAIN),)
-CLANG_GCC_TC	:= --gcc-toolchain=$(GCC_TOOLCHAIN)
+CLANG_FLAGS	+= --gcc-toolchain=$(GCC_TOOLCHAIN)
 endif
-KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) $(CLANG_PREFIX)
-KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) $(CLANG_PREFIX)
-KBUILD_CFLAGS += $(call cc-option, -no-integrated-as)
-KBUILD_AFLAGS += $(call cc-option, -no-integrated-as)
+CLANG_FLAGS	+= -no-integrated-as
+KBUILD_CFLAGS	+= $(CLANG_FLAGS)
+KBUILD_AFLAGS	+= $(CLANG_FLAGS)
+export CLANG_FLAGS
 endif
 
 RETPOLINE_CFLAGS_GCC := -mindirect-branch=thunk-extern -mindirect-branch-register
@@ -739,24 +741,11 @@
 KBUILD_CFLAGS += $(stackp-flag)
 
 ifeq ($(cc-name),clang)
-ifneq ($(CROSS_COMPILE),)
-CLANG_TRIPLE	?= $(CROSS_COMPILE)
-CLANG_TARGET	:= --target=$(notdir $(CLANG_TRIPLE:%-=%))
-GCC_TOOLCHAIN	:= $(realpath $(dir $(shell which $(LD)))/..)
-endif
-ifneq ($(GCC_TOOLCHAIN),)
-CLANG_GCC_TC	:= --gcc-toolchain=$(GCC_TOOLCHAIN)
-endif
-KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) -meabi gnu
-KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
 KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,)
 KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier)
 KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
 KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
 KBUILD_CFLAGS += $(call cc-disable-warning, duplicate-decl-specifier)
-
-KBUILD_CFLAGS += -Wno-asm-operand-widths
-KBUILD_CFLAGS += -Wno-initializer-overrides
 KBUILD_CFLAGS += -fno-builtin
 KBUILD_CFLAGS += $(call cc-option, -Wno-undefined-optimized)
 KBUILD_CFLAGS += $(call cc-option, -Wno-tautological-constant-out-of-range-compare)
@@ -1048,11 +1037,6 @@
   ifeq ($(has_libelf),1)
     objtool_target := tools/objtool FORCE
   else
-    ifdef CONFIG_UNWINDER_ORC
-      $(error "Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel")
-    else
-      $(warning "Cannot use CONFIG_STACK_VALIDATION=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel")
-    endif
     SKIP_STACK_VALIDATION := 1
     export SKIP_STACK_VALIDATION
   endif
@@ -1196,6 +1180,14 @@
 
 PHONY += prepare-objtool
 prepare-objtool: $(objtool_target)
+ifeq ($(SKIP_STACK_VALIDATION),1)
+ifdef CONFIG_UNWINDER_ORC
+	@echo "error: Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel" >&2
+	@false
+else
+	@echo "warning: Cannot use CONFIG_STACK_VALIDATION=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel" >&2
+endif
+endif
 
 # Check for CONFIG flags that require compiler support. Abort the build
 # after .config has been processed, but before the kernel build starts.
diff --git a/arch/alpha/include/asm/irq.h b/arch/alpha/include/asm/irq.h
index 4d17cac..432402c 100644
--- a/arch/alpha/include/asm/irq.h
+++ b/arch/alpha/include/asm/irq.h
@@ -56,15 +56,15 @@
 
 #elif defined(CONFIG_ALPHA_DP264) || \
       defined(CONFIG_ALPHA_LYNX)  || \
-      defined(CONFIG_ALPHA_SHARK) || \
-      defined(CONFIG_ALPHA_EIGER)
+      defined(CONFIG_ALPHA_SHARK)
 # define NR_IRQS	64
 
 #elif defined(CONFIG_ALPHA_TITAN)
 #define NR_IRQS		80
 
 #elif defined(CONFIG_ALPHA_RAWHIDE) || \
-	defined(CONFIG_ALPHA_TAKARA)
+      defined(CONFIG_ALPHA_TAKARA) || \
+      defined(CONFIG_ALPHA_EIGER)
 # define NR_IRQS	128
 
 #elif defined(CONFIG_ALPHA_WILDFIRE)
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index cd3c572..e939230 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -78,7 +78,7 @@ __load_new_mm_context(struct mm_struct *next_mm)
 /* Macro for exception fixup code to access integer registers.  */
 #define dpf_reg(r)							\
 	(((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 :	\
-				 (r) <= 18 ? (r)+8 : (r)-10])
+				 (r) <= 18 ? (r)+10 : (r)-10])
 
 asmlinkage void
 do_page_fault(unsigned long address, unsigned long mmcsr,
diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index 8da87fe..99e6d89 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -340,7 +340,7 @@ static inline __attribute__ ((const)) int __fls(unsigned long x)
 /*
  * __ffs: Similar to ffs, but zero based (0-31)
  */
-static inline __attribute__ ((const)) int __ffs(unsigned long word)
+static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
 {
 	if (!word)
 		return word;
@@ -400,9 +400,9 @@ static inline __attribute__ ((const)) int ffs(unsigned long x)
 /*
  * __ffs: Similar to ffs, but zero based (0-31)
  */
-static inline __attribute__ ((const)) int __ffs(unsigned long x)
+static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
 {
-	int n;
+	unsigned long n;
 
 	asm volatile(
 	"	ffs.f	%0, %1		\n"  /* 0:31; 31(Z) if src 0 */
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
index ff7d323..db681cf 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -52,6 +52,17 @@
 #define cache_line_size()	SMP_CACHE_BYTES
 #define ARCH_DMA_MINALIGN	SMP_CACHE_BYTES
 
+/*
+ * Make sure slab-allocated buffers are 64-bit aligned when atomic64_t uses
+ * ARCv2 64-bit atomics (LLOCKD/SCONDD). This guarantess runtime 64-bit
+ * alignment for any atomic64_t embedded in buffer.
+ * Default ARCH_SLAB_MINALIGN is __alignof__(long long) which has a relaxed
+ * value of 4 (and not 8) in ARC ABI.
+ */
+#if defined(CONFIG_ARC_HAS_LL64) && defined(CONFIG_ARC_HAS_LLSC)
+#define ARCH_SLAB_MINALIGN	8
+#endif
+
 extern void arc_cache_init(void);
 extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len);
 extern void read_decode_cache_bcr(void);
diff --git a/arch/arc/include/asm/perf_event.h b/arch/arc/include/asm/perf_event.h
index 9185541..6958545 100644
--- a/arch/arc/include/asm/perf_event.h
+++ b/arch/arc/include/asm/perf_event.h
@@ -103,7 +103,8 @@ static const char * const arc_pmu_ev_hw_map[] = {
 
 	/* counts condition */
 	[PERF_COUNT_HW_INSTRUCTIONS] = "iall",
-	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp", /* Excludes ZOL jumps */
+	/* All jump instructions that are taken */
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmptak",
 	[PERF_COUNT_ARC_BPOK]         = "bpok",	  /* NP-NT, PT-T, PNT-NT */
 #ifdef CONFIG_ISA_ARCV2
 	[PERF_COUNT_HW_BRANCH_MISSES] = "bpmp",
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S
index 8b90d25..1f945d0 100644
--- a/arch/arc/kernel/head.S
+++ b/arch/arc/kernel/head.S
@@ -17,6 +17,7 @@
 #include <asm/entry.h>
 #include <asm/arcregs.h>
 #include <asm/cache.h>
+#include <asm/irqflags.h>
 
 .macro CPU_EARLY_SETUP
 
@@ -47,6 +48,15 @@
 	sr	r5, [ARC_REG_DC_CTRL]
 
 1:
+
+#ifdef CONFIG_ISA_ARCV2
+	; Unaligned access is disabled at reset, so re-enable early as
+	; gcc 7.3.1 (ARC GNU 2018.03) onwards generates unaligned access
+	; by default
+	lr	r5, [status32]
+	bset	r5, r5, STATUS_AD_BIT
+	kflag	r5
+#endif
 .endm
 
 	.section .init.text, "ax",@progbits
@@ -93,9 +103,9 @@
 #ifdef CONFIG_ARC_UBOOT_SUPPORT
 	; Uboot - kernel ABI
 	;    r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2
-	;    r1 = magic number (board identity, unused as of now
+	;    r1 = magic number (always zero as of now)
 	;    r2 = pointer to uboot provided cmdline or external DTB in mem
-	; These are handled later in setup_arch()
+	; These are handled later in handle_uboot_args()
 	st	r0, [@uboot_tag]
 	st	r2, [@uboot_arg]
 #endif
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index fb83844..709649e 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -414,43 +414,80 @@ void setup_processor(void)
 	arc_chk_core_config();
 }
 
-static inline int is_kernel(unsigned long addr)
+static inline bool uboot_arg_invalid(unsigned long addr)
 {
-	if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
-		return 1;
-	return 0;
+	/*
+	 * Check that it is a untranslated address (although MMU is not enabled
+	 * yet, it being a high address ensures this is not by fluke)
+	 */
+	if (addr < PAGE_OFFSET)
+		return true;
+
+	/* Check that address doesn't clobber resident kernel image */
+	return addr >= (unsigned long)_stext && addr <= (unsigned long)_end;
+}
+
+#define IGNORE_ARGS		"Ignore U-boot args: "
+
+/* uboot_tag values for U-boot - kernel ABI revision 0; see head.S */
+#define UBOOT_TAG_NONE		0
+#define UBOOT_TAG_CMDLINE	1
+#define UBOOT_TAG_DTB		2
+
+void __init handle_uboot_args(void)
+{
+	bool use_embedded_dtb = true;
+	bool append_cmdline = false;
+
+#ifdef CONFIG_ARC_UBOOT_SUPPORT
+	/* check that we know this tag */
+	if (uboot_tag != UBOOT_TAG_NONE &&
+	    uboot_tag != UBOOT_TAG_CMDLINE &&
+	    uboot_tag != UBOOT_TAG_DTB) {
+		pr_warn(IGNORE_ARGS "invalid uboot tag: '%08x'\n", uboot_tag);
+		goto ignore_uboot_args;
+	}
+
+	if (uboot_tag != UBOOT_TAG_NONE &&
+            uboot_arg_invalid((unsigned long)uboot_arg)) {
+		pr_warn(IGNORE_ARGS "invalid uboot arg: '%px'\n", uboot_arg);
+		goto ignore_uboot_args;
+	}
+
+	/* see if U-boot passed an external Device Tree blob */
+	if (uboot_tag == UBOOT_TAG_DTB) {
+		machine_desc = setup_machine_fdt((void *)uboot_arg);
+
+		/* external Device Tree blob is invalid - use embedded one */
+		use_embedded_dtb = !machine_desc;
+	}
+
+	if (uboot_tag == UBOOT_TAG_CMDLINE)
+		append_cmdline = true;
+
+ignore_uboot_args:
+#endif
+
+	if (use_embedded_dtb) {
+		machine_desc = setup_machine_fdt(__dtb_start);
+		if (!machine_desc)
+			panic("Embedded DT invalid\n");
+	}
+
+	/*
+	 * NOTE: @boot_command_line is populated by setup_machine_fdt() so this
+	 * append processing can only happen after.
+	 */
+	if (append_cmdline) {
+		/* Ensure a whitespace between the 2 cmdlines */
+		strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+		strlcat(boot_command_line, uboot_arg, COMMAND_LINE_SIZE);
+	}
 }
 
 void __init setup_arch(char **cmdline_p)
 {
-#ifdef CONFIG_ARC_UBOOT_SUPPORT
-	/* make sure that uboot passed pointer to cmdline/dtb is valid */
-	if (uboot_tag && is_kernel((unsigned long)uboot_arg))
-		panic("Invalid uboot arg\n");
-
-	/* See if u-boot passed an external Device Tree blob */
-	machine_desc = setup_machine_fdt(uboot_arg);	/* uboot_tag == 2 */
-	if (!machine_desc)
-#endif
-	{
-		/* No, so try the embedded one */
-		machine_desc = setup_machine_fdt(__dtb_start);
-		if (!machine_desc)
-			panic("Embedded DT invalid\n");
-
-		/*
-		 * If we are here, it is established that @uboot_arg didn't
-		 * point to DT blob. Instead if u-boot says it is cmdline,
-		 * append to embedded DT cmdline.
-		 * setup_machine_fdt() would have populated @boot_command_line
-		 */
-		if (uboot_tag == 1) {
-			/* Ensure a whitespace between the 2 cmdlines */
-			strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
-			strlcat(boot_command_line, uboot_arg,
-				COMMAND_LINE_SIZE);
-		}
-	}
+	handle_uboot_args();
 
 	/* Save unparsed command line copy for /proc/cmdline */
 	*cmdline_p = boot_command_line;
diff --git a/arch/arc/lib/memset-archs.S b/arch/arc/lib/memset-archs.S
index 62ad4bc..f230bb7 100644
--- a/arch/arc/lib/memset-archs.S
+++ b/arch/arc/lib/memset-archs.S
@@ -7,11 +7,39 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/cache.h>
 
-#undef PREALLOC_NOT_AVAIL
+/*
+ * The memset implementation below is optimized to use prefetchw and prealloc
+ * instruction in case of CPU with 64B L1 data cache line (L1_CACHE_SHIFT == 6)
+ * If you want to implement optimized memset for other possible L1 data cache
+ * line lengths (32B and 128B) you should rewrite code carefully checking
+ * we don't call any prefetchw/prealloc instruction for L1 cache lines which
+ * don't belongs to memset area.
+ */
+
+#if L1_CACHE_SHIFT == 6
+
+.macro PREALLOC_INSTR	reg, off
+	prealloc	[\reg, \off]
+.endm
+
+.macro PREFETCHW_INSTR	reg, off
+	prefetchw	[\reg, \off]
+.endm
+
+#else
+
+.macro PREALLOC_INSTR
+.endm
+
+.macro PREFETCHW_INSTR
+.endm
+
+#endif
 
 ENTRY_CFI(memset)
-	prefetchw [r0]		; Prefetch the write location
+	PREFETCHW_INSTR	r0, 0	; Prefetch the first write location
 	mov.f	0, r2
 ;;; if size is zero
 	jz.d	[blink]
@@ -48,11 +76,8 @@
 
 	lpnz	@.Lset64bytes
 	;; LOOP START
-#ifdef PREALLOC_NOT_AVAIL
-	prefetchw [r3, 64]	;Prefetch the next write location
-#else
-	prealloc  [r3, 64]
-#endif
+	PREALLOC_INSTR	r3, 64	; alloc next line w/o fetching
+
 #ifdef CONFIG_ARC_HAS_LL64
 	std.ab	r4, [r3, 8]
 	std.ab	r4, [r3, 8]
@@ -85,7 +110,6 @@
 	lsr.f	lp_count, r2, 5 ;Last remaining  max 124 bytes
 	lpnz	.Lset32bytes
 	;; LOOP START
-	prefetchw   [r3, 32]	;Prefetch the next write location
 #ifdef CONFIG_ARC_HAS_LL64
 	std.ab	r4, [r3, 8]
 	std.ab	r4, [r3, 8]
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index ba14506..f890b2f 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -138,7 +138,8 @@ void __init setup_arch_memory(void)
 	 */
 
 	memblock_add_node(low_mem_start, low_mem_sz, 0);
-	memblock_reserve(low_mem_start, __pa(_end) - low_mem_start);
+	memblock_reserve(CONFIG_LINUX_LINK_BASE,
+			 __pa(_end) - CONFIG_LINUX_LINK_BASE);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
index c755079..f5902bd 100644
--- a/arch/arm/boot/dts/da850-evm.dts
+++ b/arch/arm/boot/dts/da850-evm.dts
@@ -169,7 +169,7 @@
 
 	sound {
 		compatible = "simple-audio-card";
-		simple-audio-card,name = "DA850/OMAP-L138 EVM";
+		simple-audio-card,name = "DA850-OMAPL138 EVM";
 		simple-audio-card,widgets =
 			"Line", "Line In",
 			"Line", "Line Out";
diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/da850-lcdk.dts
index a0f0916..c9d4cb2 100644
--- a/arch/arm/boot/dts/da850-lcdk.dts
+++ b/arch/arm/boot/dts/da850-lcdk.dts
@@ -28,7 +28,7 @@
 
 	sound {
 		compatible = "simple-audio-card";
-		simple-audio-card,name = "DA850/OMAP-L138 LCDK";
+		simple-audio-card,name = "DA850-OMAPL138 LCDK";
 		simple-audio-card,widgets =
 			"Line", "Line In",
 			"Line", "Line Out";
diff --git a/arch/arm/boot/dts/gemini-dlink-dir-685.dts b/arch/arm/boot/dts/gemini-dlink-dir-685.dts
index e75e2d4..d6f752a 100644
--- a/arch/arm/boot/dts/gemini-dlink-dir-685.dts
+++ b/arch/arm/boot/dts/gemini-dlink-dir-685.dts
@@ -128,20 +128,16 @@
 				read-only;
 			};
 			/*
-			 * Between the boot loader and the rootfs is the kernel
-			 * in a custom Storlink format flashed from the boot
-			 * menu. The rootfs is in squashfs format.
+			 * This firmware image contains the kernel catenated
+			 * with the squashfs root filesystem. For some reason
+			 * this is called "upgrade" on the vendor system.
 			 */
-			partition@1800c0 {
-				label = "rootfs";
-				reg = <0x001800c0 0x01dbff40>;
-				read-only;
-			};
-			partition@1f40000 {
+			partition@40000 {
 				label = "upgrade";
-				reg = <0x01f40000 0x00040000>;
+				reg = <0x00040000 0x01f40000>;
 				read-only;
 			};
+			/* RGDB, Residental Gateway Database? */
 			partition@1f80000 {
 				label = "rgdb";
 				reg = <0x01f80000 0x00040000>;
diff --git a/arch/arm/boot/dts/imx7d-nitrogen7.dts b/arch/arm/boot/dts/imx7d-nitrogen7.dts
index e799830..f8caea1 100644
--- a/arch/arm/boot/dts/imx7d-nitrogen7.dts
+++ b/arch/arm/boot/dts/imx7d-nitrogen7.dts
@@ -117,13 +117,17 @@
 		compatible = "regulator-fixed";
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
-		clocks = <&clks IMX7D_CLKO2_ROOT_DIV>;
-		clock-names = "slow";
 		regulator-name = "reg_wlan";
 		startup-delay-us = <70000>;
 		gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	usdhc2_pwrseq: usdhc2_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&clks IMX7D_CLKO2_ROOT_DIV>;
+		clock-names = "ext_clock";
+	};
 };
 
 &adc1 {
@@ -430,6 +434,7 @@
 	bus-width = <4>;
 	non-removable;
 	vmmc-supply = <&reg_wlan>;
+	mmc-pwrseq = <&usdhc2_pwrseq>;
 	cap-power-off-card;
 	keep-power-in-suspend;
 	status = "okay";
diff --git a/arch/arm/boot/dts/kirkwood-dnskw.dtsi b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
index cbaf06f..eb91746 100644
--- a/arch/arm/boot/dts/kirkwood-dnskw.dtsi
+++ b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
@@ -36,8 +36,8 @@
 		compatible = "gpio-fan";
 		pinctrl-0 = <&pmx_fan_high_speed &pmx_fan_low_speed>;
 		pinctrl-names = "default";
-		gpios = <&gpio1 14 GPIO_ACTIVE_LOW
-			 &gpio1 13 GPIO_ACTIVE_LOW>;
+		gpios = <&gpio1 14 GPIO_ACTIVE_HIGH
+			 &gpio1 13 GPIO_ACTIVE_HIGH>;
 		gpio-fan,speed-map = <0    0
 				      3000 1
 				      6000 2>;
diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
index 766bbb8..47e5b63 100644
--- a/arch/arm/boot/dts/mmp2.dtsi
+++ b/arch/arm/boot/dts/mmp2.dtsi
@@ -220,12 +220,15 @@
 				status = "disabled";
 			};
 
-			twsi2: i2c@d4025000 {
+			twsi2: i2c@d4031000 {
 				compatible = "mrvl,mmp-twsi";
-				reg = <0xd4025000 0x1000>;
-				interrupts = <58>;
+				reg = <0xd4031000 0x1000>;
+				interrupt-parent = <&intcmux17>;
+				interrupts = <0>;
 				clocks = <&soc_clocks MMP2_CLK_TWSI1>;
 				resets = <&soc_clocks MMP2_CLK_TWSI1>;
+				#address-cells = <1>;
+				#size-cells = <0>;
 				status = "disabled";
 			};
 
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index 280d92d..bfad6aa 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -33,6 +33,7 @@
 		gpio = <&gpio2 16 GPIO_ACTIVE_HIGH>;  /* gpio line 48 */
 		enable-active-high;
 		regulator-boot-on;
+		startup-delay-us = <25000>;
 	};
 
 	vbat: fixedregulator-vbat {
diff --git a/arch/arm/configs/vendor/qcs405-perf_defconfig b/arch/arm/configs/vendor/qcs405-perf_defconfig
index 76ec4f0..3e92872 100644
--- a/arch/arm/configs/vendor/qcs405-perf_defconfig
+++ b/arch/arm/configs/vendor/qcs405-perf_defconfig
@@ -155,18 +155,18 @@
 CONFIG_CLD_LL_CORE=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_KEYRESET=y
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_QPNP_POWER_ON=y
 CONFIG_INPUT_KEYCHORD=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=y
-CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVMEM is not set
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
 CONFIG_DIAG_CHAR=y
 CONFIG_MSM_ADSPRPC=y
 CONFIG_I2C=y
@@ -198,6 +198,7 @@
 CONFIG_QTI_VIRTUAL_SENSOR=y
 CONFIG_QTI_QMI_COOLING_DEVICE=y
 CONFIG_REGULATOR_COOLING_DEVICE=y
+CONFIG_QTI_ADC_TM=y
 CONFIG_QTI_RPM_SMD_COOLING_DEVICE=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_REGULATOR=y
@@ -297,6 +298,7 @@
 CONFIG_ICNSS=y
 CONFIG_ICNSS_QMI=y
 CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_EARLY_RANDOM=y
 CONFIG_MSM_TZ_SMMU=y
 CONFIG_QCOM_GLINK=y
 CONFIG_QCOM_GLINK_PKT=y
@@ -312,6 +314,7 @@
 CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_EXTCON_USB_GPIO=y
 CONFIG_IIO=y
+CONFIG_QCOM_SPMI_ADC5=y
 CONFIG_PWM=y
 CONFIG_PWM_QTI_LPG=y
 CONFIG_QTI_MPM=y
@@ -330,6 +333,12 @@
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_UBIFS_FS=y
 CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+# CONFIG_SQUASHFS_ZLIB is not set
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
@@ -360,4 +369,3 @@
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_LIBCRC32C=y
-CONFIG_XZ_DEC=y
diff --git a/arch/arm/configs/vendor/qcs405_defconfig b/arch/arm/configs/vendor/qcs405_defconfig
index d947130..73ffd70 100644
--- a/arch/arm/configs/vendor/qcs405_defconfig
+++ b/arch/arm/configs/vendor/qcs405_defconfig
@@ -281,6 +281,7 @@
 CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
 CONFIG_DIAG_CHAR=y
 CONFIG_MSM_ADSPRPC=y
 CONFIG_I2C_CHARDEV=y
@@ -459,6 +460,7 @@
 CONFIG_ICNSS_DEBUG=y
 CONFIG_ICNSS_QMI=y
 CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_EARLY_RANDOM=y
 CONFIG_MSM_TZ_SMMU=y
 CONFIG_QCOM_GLINK=y
 CONFIG_QCOM_GLINK_PKT=y
@@ -496,6 +498,12 @@
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_UBIFS_FS=y
 CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+# CONFIG_SQUASHFS_ZLIB is not set
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
diff --git a/arch/arm/configs/vendor/sdxprairie-perf_defconfig b/arch/arm/configs/vendor/sdxprairie-perf_defconfig
index 9886168..4e917f6 100644
--- a/arch/arm/configs/vendor/sdxprairie-perf_defconfig
+++ b/arch/arm/configs/vendor/sdxprairie-perf_defconfig
@@ -22,6 +22,7 @@
 CONFIG_EMBEDDED=y
 # CONFIG_SLUB_DEBUG is not set
 CONFIG_SLAB_FREELIST_RANDOM=y
+CONFIG_SLAB_FREELIST_HARDENED=y
 CONFIG_PROFILING=y
 CONFIG_CC_STACKPROTECTOR_STRONG=y
 CONFIG_MODULES=y
@@ -38,6 +39,9 @@
 CONFIG_SECCOMP=y
 CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
 CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_MSM=y
 CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
@@ -154,21 +158,18 @@
 CONFIG_QRTR_SMD=y
 CONFIG_QRTR_MHI=y
 CONFIG_BT=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_HCIUART=y
-CONFIG_BT_HCIUART_H4=y
+# CONFIG_BT_BREDR is not set
+# CONFIG_BT_LE is not set
+# CONFIG_BT_DEBUGFS is not set
 CONFIG_MSM_BT_POWER=y
+# CONFIG_BTFM_SLIM is not set
 CONFIG_CFG80211=y
 CONFIG_CFG80211_DEBUGFS=y
 CONFIG_CFG80211_INTERNAL_REGDB=y
 CONFIG_CFG80211_WEXT=y
 CONFIG_RFKILL=y
 CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=12
@@ -194,7 +195,7 @@
 CONFIG_NETDEVICES=y
 CONFIG_TUN=y
 CONFIG_AQFWD=y
-CONFIG_AQFWD_QCOM=y
+CONFIG_AQFWD_QCOM_IPA=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
 # CONFIG_NET_VENDOR_FARADAY is not set
@@ -217,6 +218,7 @@
 CONFIG_CNSS2=y
 CONFIG_CNSS2_QMI=y
 CONFIG_CNSS_QCA6390=y
+CONFIG_CNSS_UTILS=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
@@ -238,7 +240,7 @@
 CONFIG_SPI_QUP=y
 CONFIG_SPI_SPIDEV=m
 CONFIG_SPMI=y
-CONFIG_PTP_1588_CLOCK=y
+CONFIG_SLIMBUS=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
 CONFIG_PINCTRL_SDXPRAIRIE=y
 CONFIG_GPIOLIB=y
@@ -250,8 +252,17 @@
 CONFIG_QPNP_FG_GEN4=y
 CONFIG_QPNP_SMB5=y
 CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
 CONFIG_QCOM_SPMI_TEMP_ALARM=y
 CONFIG_THERMAL_TSENS=y
+CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_QTI_QMI_SENSOR=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
+CONFIG_QTI_BCL_PMIC5=y
 CONFIG_QTI_ADC_TM=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_REGULATOR=y
@@ -298,6 +309,7 @@
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_VBUS_DRAW=900
 CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
 CONFIG_USB_CONFIGFS_UEVENT=y
@@ -321,16 +333,22 @@
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_QPNP=y
 CONFIG_DMADEVICES=y
+CONFIG_QCOM_SPS_DMA=y
 CONFIG_UIO=y
 CONFIG_STAGING=y
 CONFIG_ION=y
 CONFIG_QPNP_REVID=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_EP_PCIE=y
+CONFIG_EP_PCIE_HW=y
 CONFIG_USB_BAM=y
 CONFIG_GSI_REGISTER_VERSION_2=y
+CONFIG_MSM_MHI_DEV=y
 CONFIG_IPA3=y
 CONFIG_IPA_WDI_UNIFIED_API=y
+CONFIG_IPA_ETH=y
+CONFIG_AQC_IPA=y
 CONFIG_RMNET_IPA3=y
 CONFIG_ECM_IPA=y
 CONFIG_RNDIS_IPA=y
@@ -372,6 +390,8 @@
 CONFIG_SSR_SYSMON_NOTIF_TIMEOUT=20000
 CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000
 CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_QCOM_DCC_V2=y
 CONFIG_QCOM_SECURE_BUFFER=y
 CONFIG_QCOM_EUD=y
 CONFIG_QCOM_BUS_SCALING=y
@@ -391,6 +411,7 @@
 CONFIG_IIO=y
 CONFIG_QCOM_SPMI_ADC5=y
 CONFIG_PWM=y
+CONFIG_QCOM_SHOW_RESUME_IRQ=y
 CONFIG_ANDROID=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT3_FS=y
@@ -424,6 +445,7 @@
 CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
 CONFIG_CORESIGHT_TGU=y
 CONFIG_CORESIGHT_EVENT=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_SECURITY_NETWORK_XFRM=y
diff --git a/arch/arm/configs/vendor/sdxprairie_defconfig b/arch/arm/configs/vendor/sdxprairie_defconfig
index 9d22ac1..8aa9d1d 100644
--- a/arch/arm/configs/vendor/sdxprairie_defconfig
+++ b/arch/arm/configs/vendor/sdxprairie_defconfig
@@ -22,6 +22,7 @@
 CONFIG_KALLSYMS_ALL=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB_FREELIST_RANDOM=y
+CONFIG_SLAB_FREELIST_HARDENED=y
 CONFIG_PROFILING=y
 CONFIG_CC_STACKPROTECTOR_STRONG=y
 CONFIG_MODULES=y
@@ -38,6 +39,9 @@
 CONFIG_SECCOMP=y
 CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
 CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_MSM=y
 CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
@@ -153,9 +157,16 @@
 CONFIG_QRTR=y
 CONFIG_QRTR_SMD=y
 CONFIG_QRTR_MHI=y
+CONFIG_BT=y
+# CONFIG_BT_BREDR is not set
+# CONFIG_BT_LE is not set
+# CONFIG_BT_DEBUGFS is not set
+CONFIG_MSM_BT_POWER=y
+# CONFIG_BTFM_SLIM is not set
 CONFIG_CFG80211=y
 CONFIG_RFKILL=y
 CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=12
@@ -182,7 +193,7 @@
 CONFIG_NETDEVICES=y
 CONFIG_TUN=y
 CONFIG_AQFWD=y
-CONFIG_AQFWD_QCOM=y
+CONFIG_AQFWD_QCOM_IPA=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
 # CONFIG_NET_VENDOR_FARADAY is not set
@@ -206,6 +217,7 @@
 CONFIG_CNSS2_DEBUG=y
 CONFIG_CNSS2_QMI=y
 CONFIG_CNSS_QCA6390=y
+CONFIG_CNSS_UTILS=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
@@ -229,7 +241,6 @@
 CONFIG_SPI_SPIDEV=m
 CONFIG_SPMI=y
 CONFIG_SLIMBUS=y
-CONFIG_PTP_1588_CLOCK=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
 CONFIG_PINCTRL_SDXPRAIRIE=y
 CONFIG_GPIOLIB=y
@@ -241,8 +252,17 @@
 CONFIG_QPNP_FG_GEN4=y
 CONFIG_QPNP_SMB5=y
 CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
 CONFIG_QCOM_SPMI_TEMP_ALARM=y
 CONFIG_THERMAL_TSENS=y
+CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_QTI_QMI_SENSOR=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
+CONFIG_QTI_BCL_PMIC5=y
 CONFIG_QTI_ADC_TM=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_REGULATOR=y
@@ -291,6 +311,7 @@
 CONFIG_USB_GADGET_DEBUG_FS=y
 CONFIG_USB_GADGET_VBUS_DRAW=900
 CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
 CONFIG_USB_CONFIGFS_UEVENT=y
@@ -315,15 +336,24 @@
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_QPNP=y
 CONFIG_DMADEVICES=y
+CONFIG_QCOM_SPS_DMA=y
 CONFIG_UIO=y
 CONFIG_STAGING=y
 CONFIG_ION=y
 CONFIG_QPNP_REVID=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_EP_PCIE=y
+CONFIG_EP_PCIE_HW=y
+CONFIG_USB_BAM=y
 CONFIG_GSI_REGISTER_VERSION_2=y
+CONFIG_MSM_MHI_DEV=y
 CONFIG_IPA3=y
+CONFIG_IPA_DEBUG=y
 CONFIG_IPA_WDI_UNIFIED_API=y
+CONFIG_IPA_ETH=y
+CONFIG_AQC_IPA=y
+CONFIG_AQC_IPA_DEBUG=y
 CONFIG_RMNET_IPA3=y
 CONFIG_ECM_IPA=y
 CONFIG_RNDIS_IPA=y
@@ -366,6 +396,7 @@
 CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000
 CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y
 CONFIG_MSM_BOOT_STATS=y
+CONFIG_QCOM_DCC_V2=y
 CONFIG_QCOM_SECURE_BUFFER=y
 CONFIG_QCOM_EUD=y
 CONFIG_QCOM_BUS_SCALING=y
@@ -385,6 +416,7 @@
 CONFIG_IIO=y
 CONFIG_QCOM_SPMI_ADC5=y
 CONFIG_PWM=y
+CONFIG_QCOM_SHOW_RESUME_IRQ=y
 CONFIG_ANDROID=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT3_FS=y
@@ -421,6 +453,7 @@
 CONFIG_IPC_LOGGING=y
 CONFIG_QCOM_RTB=y
 # CONFIG_FTRACE is not set
+CONFIG_LKDTM=m
 CONFIG_PANIC_ON_DATA_CORRUPTION=y
 CONFIG_DEBUG_USER=y
 CONFIG_CORESIGHT=y
@@ -437,6 +470,7 @@
 CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
 CONFIG_CORESIGHT_TGU=y
 CONFIG_CORESIGHT_EVENT=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_SECURITY_NETWORK_XFRM=y
@@ -444,8 +478,6 @@
 CONFIG_HARDENED_USERCOPY_PAGESPAN=y
 CONFIG_SECURITY_SELINUX=y
 # CONFIG_SECURITY_SELINUX_AVC_STATS is not set
-CONFIG_CRYPTO_CMAC=y
-CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
 CONFIG_CRYPTO_DEV_QCRYPTO=y
 CONFIG_CRYPTO_DEV_QCEDEV=y
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index b17ee03..88286dd 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -467,6 +467,17 @@ THUMB(	orr	\reg , \reg , #PSR_T_BIT	)
 #endif
 	.endm
 
+	.macro uaccess_mask_range_ptr, addr:req, size:req, limit:req, tmp:req
+#ifdef CONFIG_CPU_SPECTRE
+	sub	\tmp, \limit, #1
+	subs	\tmp, \tmp, \addr	@ tmp = limit - 1 - addr
+	addhs	\tmp, \tmp, #1		@ if (tmp >= 0) {
+	subhss	\tmp, \tmp, \size	@ tmp = limit - (addr + size) }
+	movlo	\addr, #0		@ if (tmp < 0) addr = NULL
+	csdb
+#endif
+	.endm
+
 	.macro	uaccess_disable, tmp, isb=1
 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
 	/*
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 3379c2c..25d5231 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -107,6 +107,7 @@
 #define ARM_CPU_PART_SCORPION		0x510002d0
 
 extern unsigned int processor_id;
+struct proc_info_list *lookup_processor(u32 midr);
 
 #ifdef CONFIG_CPU_CP15
 #define read_cpuid(reg)							\
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index e25f439..e1b6f28 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -23,7 +23,7 @@ struct mm_struct;
 /*
  * Don't change this structure - ASM code relies on it.
  */
-extern struct processor {
+struct processor {
 	/* MISC
 	 * get data abort address/flags
 	 */
@@ -79,9 +79,13 @@ extern struct processor {
 	unsigned int suspend_size;
 	void (*do_suspend)(void *);
 	void (*do_resume)(void *);
-} processor;
+};
 
 #ifndef MULTI_CPU
+static inline void init_proc_vtable(const struct processor *p)
+{
+}
+
 extern void cpu_proc_init(void);
 extern void cpu_proc_fin(void);
 extern int cpu_do_idle(void);
@@ -98,17 +102,50 @@ extern void cpu_reset(unsigned long addr, bool hvc) __attribute__((noreturn));
 extern void cpu_do_suspend(void *);
 extern void cpu_do_resume(void *);
 #else
-#define cpu_proc_init			processor._proc_init
-#define cpu_proc_fin			processor._proc_fin
-#define cpu_reset			processor.reset
-#define cpu_do_idle			processor._do_idle
-#define cpu_dcache_clean_area		processor.dcache_clean_area
-#define cpu_set_pte_ext			processor.set_pte_ext
-#define cpu_do_switch_mm		processor.switch_mm
 
-/* These three are private to arch/arm/kernel/suspend.c */
-#define cpu_do_suspend			processor.do_suspend
-#define cpu_do_resume			processor.do_resume
+extern struct processor processor;
+#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+#include <linux/smp.h>
+/*
+ * This can't be a per-cpu variable because we need to access it before
+ * per-cpu has been initialised.  We have a couple of functions that are
+ * called in a pre-emptible context, and so can't use smp_processor_id()
+ * there, hence PROC_TABLE().  We insist in init_proc_vtable() that the
+ * function pointers for these are identical across all CPUs.
+ */
+extern struct processor *cpu_vtable[];
+#define PROC_VTABLE(f)			cpu_vtable[smp_processor_id()]->f
+#define PROC_TABLE(f)			cpu_vtable[0]->f
+static inline void init_proc_vtable(const struct processor *p)
+{
+	unsigned int cpu = smp_processor_id();
+	*cpu_vtable[cpu] = *p;
+	WARN_ON_ONCE(cpu_vtable[cpu]->dcache_clean_area !=
+		     cpu_vtable[0]->dcache_clean_area);
+	WARN_ON_ONCE(cpu_vtable[cpu]->set_pte_ext !=
+		     cpu_vtable[0]->set_pte_ext);
+}
+#else
+#define PROC_VTABLE(f)			processor.f
+#define PROC_TABLE(f)			processor.f
+static inline void init_proc_vtable(const struct processor *p)
+{
+	processor = *p;
+}
+#endif
+
+#define cpu_proc_init			PROC_VTABLE(_proc_init)
+#define cpu_check_bugs			PROC_VTABLE(check_bugs)
+#define cpu_proc_fin			PROC_VTABLE(_proc_fin)
+#define cpu_reset			PROC_VTABLE(reset)
+#define cpu_do_idle			PROC_VTABLE(_do_idle)
+#define cpu_dcache_clean_area		PROC_TABLE(dcache_clean_area)
+#define cpu_set_pte_ext			PROC_TABLE(set_pte_ext)
+#define cpu_do_switch_mm		PROC_VTABLE(switch_mm)
+
+/* These two are private to arch/arm/kernel/suspend.c */
+#define cpu_do_suspend			PROC_VTABLE(do_suspend)
+#define cpu_do_resume			PROC_VTABLE(do_resume)
 #endif
 
 extern void cpu_resume(void);
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index a0e42ca..cfbf32b 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -124,8 +124,8 @@ extern void vfp_flush_hwstate(struct thread_info *);
 struct user_vfp;
 struct user_vfp_exc;
 
-extern int vfp_preserve_user_clear_hwstate(struct user_vfp __user *,
-					   struct user_vfp_exc __user *);
+extern int vfp_preserve_user_clear_hwstate(struct user_vfp *,
+					   struct user_vfp_exc *);
 extern int vfp_restore_user_hwstate(struct user_vfp *,
 				    struct user_vfp_exc *);
 #endif
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 4140be4..a5807b6 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -69,6 +69,14 @@ extern int __put_user_bad(void);
 static inline void set_fs(mm_segment_t fs)
 {
 	current_thread_info()->addr_limit = fs;
+
+	/*
+	 * Prevent a mispredicted conditional call to set_fs from forwarding
+	 * the wrong address limit to access_ok under speculation.
+	 */
+	dsb(nsh);
+	isb();
+
 	modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
 }
 
@@ -92,6 +100,32 @@ static inline void set_fs(mm_segment_t fs)
 	__typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
 
 /*
+ * Sanitise a uaccess pointer such that it becomes NULL if addr+size
+ * is above the current addr_limit.
+ */
+#define uaccess_mask_range_ptr(ptr, size)			\
+	((__typeof__(ptr))__uaccess_mask_range_ptr(ptr, size))
+static inline void __user *__uaccess_mask_range_ptr(const void __user *ptr,
+						    size_t size)
+{
+	void __user *safe_ptr = (void __user *)ptr;
+	unsigned long tmp;
+
+	asm volatile(
+	"	sub	%1, %3, #1\n"
+	"	subs	%1, %1, %0\n"
+	"	addhs	%1, %1, #1\n"
+	"	subhss	%1, %1, %2\n"
+	"	movlo	%0, #0\n"
+	: "+r" (safe_ptr), "=&r" (tmp)
+	: "r" (size), "r" (current_thread_info()->addr_limit)
+	: "cc");
+
+	csdb();
+	return safe_ptr;
+}
+
+/*
  * Single-value transfer routines.  They automatically use the right
  * size if we just have the right pointer type.  Note that the functions
  * which read from user space (*get_*) need to take care not to leak
@@ -362,6 +396,14 @@ do {									\
 	__pu_err;							\
 })
 
+#ifdef CONFIG_CPU_SPECTRE
+/*
+ * When mitigating Spectre variant 1.1, all accessors need to include
+ * verification of the address space.
+ */
+#define __put_user(x, ptr) put_user(x, ptr)
+
+#else
 #define __put_user(x, ptr)						\
 ({									\
 	long __pu_err = 0;						\
@@ -369,12 +411,6 @@ do {									\
 	__pu_err;							\
 })
 
-#define __put_user_error(x, ptr, err)					\
-({									\
-	__put_user_switch((x), (ptr), (err), __put_user_nocheck);	\
-	(void) 0;							\
-})
-
 #define __put_user_nocheck(x, __pu_ptr, __err, __size)			\
 	do {								\
 		unsigned long __pu_addr = (unsigned long)__pu_ptr;	\
@@ -454,6 +490,7 @@ do {									\
 	: "r" (x), "i" (-EFAULT)				\
 	: "cc")
 
+#endif /* !CONFIG_CPU_SPECTRE */
 
 #ifdef CONFIG_MMU
 extern unsigned long __must_check
diff --git a/arch/arm/kernel/bugs.c b/arch/arm/kernel/bugs.c
index 7be5113..d41d359 100644
--- a/arch/arm/kernel/bugs.c
+++ b/arch/arm/kernel/bugs.c
@@ -6,8 +6,8 @@
 void check_other_bugs(void)
 {
 #ifdef MULTI_CPU
-	if (processor.check_bugs)
-		processor.check_bugs();
+	if (cpu_check_bugs)
+		cpu_check_bugs();
 #endif
 }
 
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 8733012..7e662bd 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -122,6 +122,9 @@
 	.long	init_thread_union + THREAD_START_SP @ sp
 	.size	__mmap_switched_data, . - __mmap_switched_data
 
+	__FINIT
+	.text
+
 /*
  * This provides a C-API version of __lookup_processor_type
  */
@@ -133,9 +136,6 @@
 	ldmfd	sp!, {r4 - r6, r9, pc}
 ENDPROC(lookup_processor_type)
 
-	__FINIT
-	.text
-
 /*
  * Read processor ID register (CP#15, CR0), and look up in the linker-built
  * supported processor list.  Note that we can't use the absolute addresses
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 45b1bda..4c97aa1 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -124,6 +124,11 @@ EXPORT_SYMBOL(cold_boot);
 
 #ifdef MULTI_CPU
 struct processor processor __ro_after_init;
+#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+struct processor *cpu_vtable[NR_CPUS] = {
+	[0] = &processor,
+};
+#endif
 #endif
 #ifdef MULTI_TLB
 struct cpu_tlb_fns cpu_tlb __ro_after_init;
@@ -676,28 +681,33 @@ static void __init smp_build_mpidr_hash(void)
 }
 #endif
 
+/*
+ * locate processor in the list of supported processor types.  The linker
+ * builds this table for us from the entries in arch/arm/mm/proc-*.S
+ */
+struct proc_info_list *lookup_processor(u32 midr)
+{
+	struct proc_info_list *list = lookup_processor_type(midr);
+
+	if (!list) {
+		pr_err("CPU%u: configuration botched (ID %08x), CPU halted\n",
+		       smp_processor_id(), midr);
+		while (1)
+		/* can't use cpu_relax() here as it may require MMU setup */;
+	}
+
+	return list;
+}
+
 static void __init setup_processor(void)
 {
-	struct proc_info_list *list;
-
-	/*
-	 * locate processor in the list of supported processor
-	 * types.  The linker builds this table for us from the
-	 * entries in arch/arm/mm/proc-*.S
-	 */
-	list = lookup_processor_type(read_cpuid_id());
-	if (!list) {
-		pr_err("CPU configuration botched (ID %08x), unable to continue.\n",
-		       read_cpuid_id());
-		while (1);
-	}
+	unsigned int midr = read_cpuid_id();
+	struct proc_info_list *list = lookup_processor(midr);
 
 	cpu_name = list->cpu_name;
 	__cpu_architecture = __get_cpu_architecture();
 
-#ifdef MULTI_CPU
-	processor = *list->proc;
-#endif
+	init_proc_vtable(list->proc);
 #ifdef MULTI_TLB
 	cpu_tlb = *list->tlb;
 #endif
@@ -709,7 +719,7 @@ static void __init setup_processor(void)
 #endif
 
 	pr_info("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
-		cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
+		list->cpu_name, midr, midr & 15,
 		proc_arch[cpu_architecture()], get_cr());
 
 	snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index cdfe52b..02e6b6d 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -76,8 +76,6 @@ static int preserve_iwmmxt_context(struct iwmmxt_sigframe __user *frame)
 		kframe->magic = IWMMXT_MAGIC;
 		kframe->size = IWMMXT_STORAGE_SIZE;
 		iwmmxt_task_copy(current_thread_info(), &kframe->storage);
-
-		err = __copy_to_user(frame, kframe, sizeof(*frame));
 	} else {
 		/*
 		 * For bug-compatibility with older kernels, some space
@@ -85,10 +83,14 @@ static int preserve_iwmmxt_context(struct iwmmxt_sigframe __user *frame)
 		 * Set the magic and size appropriately so that properly
 		 * written userspace can skip it reliably:
 		 */
-		__put_user_error(DUMMY_MAGIC, &frame->magic, err);
-		__put_user_error(IWMMXT_STORAGE_SIZE, &frame->size, err);
+		*kframe = (struct iwmmxt_sigframe) {
+			.magic = DUMMY_MAGIC,
+			.size  = IWMMXT_STORAGE_SIZE,
+		};
 	}
 
+	err = __copy_to_user(frame, kframe, sizeof(*kframe));
+
 	return err;
 }
 
@@ -134,17 +136,18 @@ static int restore_iwmmxt_context(char __user **auxp)
 
 static int preserve_vfp_context(struct vfp_sigframe __user *frame)
 {
-	const unsigned long magic = VFP_MAGIC;
-	const unsigned long size = VFP_STORAGE_SIZE;
+	struct vfp_sigframe kframe;
 	int err = 0;
 
-	__put_user_error(magic, &frame->magic, err);
-	__put_user_error(size, &frame->size, err);
+	memset(&kframe, 0, sizeof(kframe));
+	kframe.magic = VFP_MAGIC;
+	kframe.size = VFP_STORAGE_SIZE;
 
+	err = vfp_preserve_user_clear_hwstate(&kframe.ufp, &kframe.ufp_exc);
 	if (err)
-		return -EFAULT;
+		return err;
 
-	return vfp_preserve_user_clear_hwstate(&frame->ufp, &frame->ufp_exc);
+	return __copy_to_user(frame, &kframe, sizeof(kframe));
 }
 
 static int restore_vfp_context(char __user **auxp)
@@ -296,30 +299,35 @@ static int
 setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
 {
 	struct aux_sigframe __user *aux;
+	struct sigcontext context;
 	int err = 0;
 
-	__put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
-	__put_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
-	__put_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
-	__put_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
-	__put_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
-	__put_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
-	__put_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
-	__put_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
-	__put_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
-	__put_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
-	__put_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
-	__put_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
-	__put_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
-	__put_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
-	__put_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
-	__put_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
-	__put_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
+	context = (struct sigcontext) {
+		.arm_r0        = regs->ARM_r0,
+		.arm_r1        = regs->ARM_r1,
+		.arm_r2        = regs->ARM_r2,
+		.arm_r3        = regs->ARM_r3,
+		.arm_r4        = regs->ARM_r4,
+		.arm_r5        = regs->ARM_r5,
+		.arm_r6        = regs->ARM_r6,
+		.arm_r7        = regs->ARM_r7,
+		.arm_r8        = regs->ARM_r8,
+		.arm_r9        = regs->ARM_r9,
+		.arm_r10       = regs->ARM_r10,
+		.arm_fp        = regs->ARM_fp,
+		.arm_ip        = regs->ARM_ip,
+		.arm_sp        = regs->ARM_sp,
+		.arm_lr        = regs->ARM_lr,
+		.arm_pc        = regs->ARM_pc,
+		.arm_cpsr      = regs->ARM_cpsr,
 
-	__put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, err);
-	__put_user_error(current->thread.error_code, &sf->uc.uc_mcontext.error_code, err);
-	__put_user_error(current->thread.address, &sf->uc.uc_mcontext.fault_address, err);
-	__put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
+		.trap_no       = current->thread.trap_no,
+		.error_code    = current->thread.error_code,
+		.fault_address = current->thread.address,
+		.oldmask       = set->sig[0],
+	};
+
+	err |= __copy_to_user(&sf->uc.uc_mcontext, &context, sizeof(context));
 
 	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
 
@@ -336,7 +344,7 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
 	if (err == 0)
 		err |= preserve_vfp_context(&aux->vfp);
 #endif
-	__put_user_error(0, &aux->end_magic, err);
+	err |= __put_user(0, &aux->end_magic);
 
 	return err;
 }
@@ -468,7 +476,7 @@ setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 	/*
 	 * Set uc.uc_flags to a value which sc.trap_no would never have.
 	 */
-	__put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);
+	err = __put_user(0x5ac3c35a, &frame->uc.uc_flags);
 
 	err |= setup_sigframe(frame, regs, set);
 	if (err == 0)
@@ -488,8 +496,8 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 
 	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
-	__put_user_error(0, &frame->sig.uc.uc_flags, err);
-	__put_user_error(NULL, &frame->sig.uc.uc_link, err);
+	err |= __put_user(0, &frame->sig.uc.uc_flags);
+	err |= __put_user(NULL, &frame->sig.uc.uc_link);
 
 	err |= __save_altstack(&frame->sig.uc.uc_stack, regs->ARM_sp);
 	err |= setup_sigframe(&frame->sig, regs, set);
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index d728afb..183f52c 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -42,6 +42,7 @@
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/procinfo.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
@@ -102,6 +103,30 @@ static unsigned long get_arch_pgd(pgd_t *pgd)
 #endif
 }
 
+#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+static int secondary_biglittle_prepare(unsigned int cpu)
+{
+	if (!cpu_vtable[cpu])
+		cpu_vtable[cpu] = kzalloc(sizeof(*cpu_vtable[cpu]), GFP_KERNEL);
+
+	return cpu_vtable[cpu] ? 0 : -ENOMEM;
+}
+
+static void secondary_biglittle_init(void)
+{
+	init_proc_vtable(lookup_processor(read_cpuid_id())->proc);
+}
+#else
+static int secondary_biglittle_prepare(unsigned int cpu)
+{
+	return 0;
+}
+
+static void secondary_biglittle_init(void)
+{
+}
+#endif
+
 int __cpu_up(unsigned int cpu, struct task_struct *idle)
 {
 	int ret;
@@ -109,6 +134,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
 	if (!smp_ops.smp_boot_secondary)
 		return -ENOSYS;
 
+	ret = secondary_biglittle_prepare(cpu);
+	if (ret)
+		return ret;
+
 	/*
 	 * We need to tell the secondary core where to find
 	 * its stack and the page tables.
@@ -360,6 +389,8 @@ asmlinkage void secondary_start_kernel(void)
 	struct mm_struct *mm = &init_mm;
 	unsigned int cpu;
 
+	secondary_biglittle_init();
+
 	/*
 	 * The identity mapping is uncached (strongly ordered), so
 	 * switch away from it before attempting any exclusive accesses.
@@ -706,6 +737,21 @@ void smp_send_stop(void)
 		pr_warn("SMP: failed to stop secondary CPUs\n");
 }
 
+/* In case panic() and panic() called at the same time on CPU1 and CPU2,
+ * and CPU 1 calls panic_smp_self_stop() before crash_smp_send_stop()
+ * CPU1 can't receive the ipi irqs from CPU2, CPU1 will be always online,
+ * kdump fails. So split out the panic_smp_self_stop() and add
+ * set_cpu_online(smp_processor_id(), false).
+ */
+void panic_smp_self_stop(void)
+{
+	pr_debug("CPU %u will stop doing anything useful since another CPU has paniced\n",
+	         smp_processor_id());
+	set_cpu_online(smp_processor_id(), false);
+	while (1)
+		cpu_relax();
+}
+
 /*
  * not supported here
  */
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index 4abe490..a876845 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -277,6 +277,7 @@ asmlinkage long sys_oabi_epoll_wait(int epfd,
 				    int maxevents, int timeout)
 {
 	struct epoll_event *kbuf;
+	struct oabi_epoll_event e;
 	mm_segment_t fs;
 	long ret, err, i;
 
@@ -295,8 +296,11 @@ asmlinkage long sys_oabi_epoll_wait(int epfd,
 	set_fs(fs);
 	err = 0;
 	for (i = 0; i < ret; i++) {
-		__put_user_error(kbuf[i].events, &events->events, err);
-		__put_user_error(kbuf[i].data,   &events->data,   err);
+		e.events = kbuf[i].events;
+		e.data = kbuf[i].data;
+		err = __copy_to_user(events, &e, sizeof(e));
+		if (err)
+			break;
 		events++;
 	}
 	kfree(kbuf);
diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S
index a826df3..6709a8d 100644
--- a/arch/arm/lib/copy_from_user.S
+++ b/arch/arm/lib/copy_from_user.S
@@ -93,11 +93,7 @@
 #ifdef CONFIG_CPU_SPECTRE
 	get_thread_info r3
 	ldr	r3, [r3, #TI_ADDR_LIMIT]
-	adds	ip, r1, r2	@ ip=addr+size
-	sub	r3, r3, #1	@ addr_limit - 1
-	cmpcc	ip, r3		@ if (addr+size > addr_limit - 1)
-	movcs	r1, #0		@ addr = NULL
-	csdb
+	uaccess_mask_range_ptr r1, r2, r3, ip
 #endif
 
 #include "copy_template.S"
diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S
index caf5019..970abe5 100644
--- a/arch/arm/lib/copy_to_user.S
+++ b/arch/arm/lib/copy_to_user.S
@@ -94,6 +94,11 @@
 
 ENTRY(__copy_to_user_std)
 WEAK(arm_copy_to_user)
+#ifdef CONFIG_CPU_SPECTRE
+	get_thread_info r3
+	ldr	r3, [r3, #TI_ADDR_LIMIT]
+	uaccess_mask_range_ptr r0, r2, r3, ip
+#endif
 
 #include "copy_template.S"
 
@@ -108,4 +113,3 @@
 	rsb	r0, r0, r2
 	copy_abort_end
 	.popsection
-
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c
index 9b4ed17..73dc736 100644
--- a/arch/arm/lib/uaccess_with_memcpy.c
+++ b/arch/arm/lib/uaccess_with_memcpy.c
@@ -152,7 +152,8 @@ arm_copy_to_user(void __user *to, const void *from, unsigned long n)
 		n = __copy_to_user_std(to, from, n);
 		uaccess_restore(ua_flags);
 	} else {
-		n = __copy_to_user_memcpy(to, from, n);
+		n = __copy_to_user_memcpy(uaccess_mask_range_ptr(to, n),
+					  from, n);
 	}
 	return n;
 }
diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index 318394e..5e11ad3 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -83,7 +83,7 @@ static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus,
 	} else /* remote PCI bus */
 		base = cnspci->cfg1_regs + ((busno & 0xf) << 20);
 
-	return base + (where & 0xffc) + (devfn << 12);
+	return base + where + (devfn << 12);
 }
 
 static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c
index c5a5c3a..edb888a 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sx.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sx.c
@@ -108,7 +108,7 @@ int __init imx6sx_cpuidle_init(void)
 	 * except for power up sw2iso which need to be
 	 * larger than LDO ramp up time.
 	 */
-	imx_gpc_set_arm_power_up_timing(2, 1);
+	imx_gpc_set_arm_power_up_timing(0xf, 1);
 	imx_gpc_set_arm_power_down_timing(1, 1);
 
 	return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index a109f648..0f916c2 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -393,7 +393,11 @@ static int __ref impd1_probe(struct lm_device *dev)
 					      sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
 					      GFP_KERNEL);
 			chipname = devm_kstrdup(&dev->dev, devname, GFP_KERNEL);
-			mmciname = kasprintf(GFP_KERNEL, "lm%x:00700", dev->id);
+			mmciname = devm_kasprintf(&dev->dev, GFP_KERNEL,
+						  "lm%x:00700", dev->id);
+			if (!lookup || !chipname || !mmciname)
+				return -ENOMEM;
+
 			lookup->dev_id = mmciname;
 			/*
 			 * Offsets on GPIO block 1:
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index c1cd80e..a904244 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -75,8 +75,7 @@ void __init n2100_map_io(void)
 /*
  * N2100 PCI.
  */
-static int __init
-n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq;
 
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 2dbd632..45c8f2e 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2497,7 +2497,7 @@ static int __init _init(struct omap_hwmod *oh, void *data)
  * a stub; implementing this properly requires iclk autoidle usecounting in
  * the clock code.   No return value.
  */
-static void __init _setup_iclk_autoidle(struct omap_hwmod *oh)
+static void _setup_iclk_autoidle(struct omap_hwmod *oh)
 {
 	struct omap_hwmod_ocp_if *os;
 
@@ -2528,7 +2528,7 @@ static void __init _setup_iclk_autoidle(struct omap_hwmod *oh)
  * reset.  Returns 0 upon success or a negative error code upon
  * failure.
  */
-static int __init _setup_reset(struct omap_hwmod *oh)
+static int _setup_reset(struct omap_hwmod *oh)
 {
 	int r;
 
@@ -2589,7 +2589,7 @@ static int __init _setup_reset(struct omap_hwmod *oh)
  *
  * No return value.
  */
-static void __init _setup_postsetup(struct omap_hwmod *oh)
+static void _setup_postsetup(struct omap_hwmod *oh)
 {
 	u8 postsetup_state;
 
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index 868448d..38ab308 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -547,7 +547,7 @@ static struct pxa3xx_u2d_platform_data cm_x300_u2d_platform_data = {
 	.exit		= cm_x300_u2d_exit,
 };
 
-static void cm_x300_init_u2d(void)
+static void __init cm_x300_init_u2d(void)
 {
 	pxa3xx_set_u2d_info(&cm_x300_u2d_platform_data);
 }
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index fae38fdc..5cd6b4b 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -183,7 +183,7 @@ static struct pxafb_mach_info littleton_lcd_info = {
 	.lcd_conn		= LCD_COLOR_TFT_16BPP,
 };
 
-static void littleton_init_lcd(void)
+static void __init littleton_init_lcd(void)
 {
 	pxa_set_fb_info(NULL, &littleton_lcd_info);
 }
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index ecbcaee..c293ea0 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -558,7 +558,7 @@ static struct pxaohci_platform_data zeus_ohci_platform_data = {
 	.flags		= ENABLE_PORT_ALL | POWER_SENSE_LOW,
 };
 
-static void zeus_register_ohci(void)
+static void __init zeus_register_ohci(void)
 {
 	/* Port 2 is shared between host and client interface. */
 	UP2OCR = UP2OCR_HXOE | UP2OCR_HXS | UP2OCR_DMPDE | UP2OCR_DPPDE;
diff --git a/arch/arm/mach-tango/pm.c b/arch/arm/mach-tango/pm.c
index 028e50c..a32c3b6 100644
--- a/arch/arm/mach-tango/pm.c
+++ b/arch/arm/mach-tango/pm.c
@@ -3,6 +3,7 @@
 #include <linux/suspend.h>
 #include <asm/suspend.h>
 #include "smc.h"
+#include "pm.h"
 
 static int tango_pm_powerdown(unsigned long arg)
 {
@@ -24,10 +25,7 @@ static const struct platform_suspend_ops tango_pm_ops = {
 	.valid = suspend_valid_only_mem,
 };
 
-static int __init tango_pm_init(void)
+void __init tango_pm_init(void)
 {
 	suspend_set_ops(&tango_pm_ops);
-	return 0;
 }
-
-late_initcall(tango_pm_init);
diff --git a/arch/arm/mach-tango/pm.h b/arch/arm/mach-tango/pm.h
new file mode 100644
index 0000000..35ea705
--- /dev/null
+++ b/arch/arm/mach-tango/pm.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifdef CONFIG_SUSPEND
+void __init tango_pm_init(void);
+#else
+#define tango_pm_init NULL
+#endif
diff --git a/arch/arm/mach-tango/setup.c b/arch/arm/mach-tango/setup.c
index 677dd7b..824f907 100644
--- a/arch/arm/mach-tango/setup.c
+++ b/arch/arm/mach-tango/setup.c
@@ -2,6 +2,7 @@
 #include <asm/mach/arch.h>
 #include <asm/hardware/cache-l2x0.h>
 #include "smc.h"
+#include "pm.h"
 
 static void tango_l2c_write(unsigned long val, unsigned int reg)
 {
@@ -15,4 +16,5 @@ DT_MACHINE_START(TANGO_DT, "Sigma Tango DT")
 	.dt_compat	= tango_dt_compat,
 	.l2c_aux_mask	= ~0,
 	.l2c_write_sec	= tango_l2c_write,
+	.init_late	= tango_pm_init,
 MACHINE_END
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index e74c237..204a630 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1832,7 +1832,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
 	int ret = 0;
 	unsigned int count;
 	struct scatterlist *s;
-	int prot;
+	int prot = 0;
 
 	size = PAGE_ALIGN(size);
 	*handle = ARM_MAPPING_ERROR;
@@ -1841,6 +1841,11 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
 	if (iova == ARM_MAPPING_ERROR)
 		return -ENOMEM;
 
+	/*
+	 * Check for coherency.
+	 */
+	prot |= is_coherent ? IOMMU_CACHE : 0;
+
 	for (count = 0, s = sg; count < (size >> PAGE_SHIFT); s = sg_next(s)) {
 		phys_addr_t phys = page_to_phys(sg_page(s));
 		unsigned int len = PAGE_ALIGN(s->offset + s->length);
@@ -1848,7 +1853,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
 		if (!is_coherent && (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
 			__dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
 
-		prot = __dma_info_to_prot(dir, attrs);
+		prot |= __dma_info_to_prot(dir, attrs);
 
 		ret = iommu_map(mapping->domain, iova, phys, len, prot);
 		if (ret < 0)
@@ -1952,9 +1957,23 @@ int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg,
 	dma_addr_t iova;
 	int prot = __dma_info_to_prot(dir, attrs);
 	bool coherent;
+	/*
+	 * This is used to check if there are any unaligned offset/size
+	 * given in the scatter list.
+	 */
+	bool unaligned_offset_size = false;
 
-	for_each_sg(sg, s, nents, i)
+	for_each_sg(sg, s, nents, i) {
 		total_length += s->length;
+		if ((s->offset & ~PAGE_MASK) || (s->length & ~PAGE_MASK)) {
+			unaligned_offset_size = true;
+			break;
+		}
+	}
+
+	if (unaligned_offset_size)
+		return __iommu_map_sg(dev, sg, nents, dir, attrs,
+				      is_dma_coherent(dev, attrs, false));
 
 	iova = __alloc_iova(mapping, total_length);
 	if (iova == ARM_MAPPING_ERROR)
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index 6157ce54..53d59cd 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -274,6 +274,13 @@
 	.endm
 
 .macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0, bugs=0
+/*
+ * If we are building for big.Little with branch predictor hardening,
+ * we need the processor function tables to remain available after boot.
+ */
+#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+	.section ".rodata"
+#endif
 	.type	\name\()_processor_functions, #object
 	.align 2
 ENTRY(\name\()_processor_functions)
@@ -309,6 +316,9 @@
 	.endif
 
 	.size	\name\()_processor_functions, . - \name\()_processor_functions
+#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+	.previous
+#endif
 .endm
 
 .macro define_cache_functions name:req
diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c
index 5544b82..9a07916 100644
--- a/arch/arm/mm/proc-v7-bugs.c
+++ b/arch/arm/mm/proc-v7-bugs.c
@@ -52,8 +52,6 @@ static void cpu_v7_spectre_init(void)
 	case ARM_CPU_PART_CORTEX_A17:
 	case ARM_CPU_PART_CORTEX_A73:
 	case ARM_CPU_PART_CORTEX_A75:
-		if (processor.switch_mm != cpu_v7_bpiall_switch_mm)
-			goto bl_error;
 		per_cpu(harden_branch_predictor_fn, cpu) =
 			harden_branch_predictor_bpiall;
 		spectre_v2_method = "BPIALL";
@@ -61,8 +59,6 @@ static void cpu_v7_spectre_init(void)
 
 	case ARM_CPU_PART_CORTEX_A15:
 	case ARM_CPU_PART_BRAHMA_B15:
-		if (processor.switch_mm != cpu_v7_iciallu_switch_mm)
-			goto bl_error;
 		per_cpu(harden_branch_predictor_fn, cpu) =
 			harden_branch_predictor_iciallu;
 		spectre_v2_method = "ICIALLU";
@@ -88,11 +84,9 @@ static void cpu_v7_spectre_init(void)
 					  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
 			if ((int)res.a0 != 0)
 				break;
-			if (processor.switch_mm != cpu_v7_hvc_switch_mm && cpu)
-				goto bl_error;
 			per_cpu(harden_branch_predictor_fn, cpu) =
 				call_hvc_arch_workaround_1;
-			processor.switch_mm = cpu_v7_hvc_switch_mm;
+			cpu_do_switch_mm = cpu_v7_hvc_switch_mm;
 			spectre_v2_method = "hypervisor";
 			break;
 
@@ -101,11 +95,9 @@ static void cpu_v7_spectre_init(void)
 					  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
 			if ((int)res.a0 != 0)
 				break;
-			if (processor.switch_mm != cpu_v7_smc_switch_mm && cpu)
-				goto bl_error;
 			per_cpu(harden_branch_predictor_fn, cpu) =
 				call_smc_arch_workaround_1;
-			processor.switch_mm = cpu_v7_smc_switch_mm;
+			cpu_do_switch_mm = cpu_v7_smc_switch_mm;
 			spectre_v2_method = "firmware";
 			break;
 
@@ -119,11 +111,6 @@ static void cpu_v7_spectre_init(void)
 	if (spectre_v2_method)
 		pr_info("CPU%u: Spectre v2: using %s workaround\n",
 			smp_processor_id(), spectre_v2_method);
-	return;
-
-bl_error:
-	pr_err("CPU%u: Spectre v2: incorrect context switching function, system vulnerable\n",
-		cpu);
 }
 #else
 static void cpu_v7_spectre_init(void)
diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c
index 2c118a6..0dc23fc 100644
--- a/arch/arm/probes/kprobes/opt-arm.c
+++ b/arch/arm/probes/kprobes/opt-arm.c
@@ -247,7 +247,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *or
 	}
 
 	/* Copy arch-dep-instance from template. */
-	memcpy(code, (unsigned char *)optprobe_template_entry,
+	memcpy(code, (unsigned long *)&optprobe_template_entry,
 			TMPL_END_IDX * sizeof(kprobe_opcode_t));
 
 	/* Adjust buffer according to instruction. */
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 6abcd4a..8e11223 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -554,12 +554,11 @@ void vfp_flush_hwstate(struct thread_info *thread)
  * Save the current VFP state into the provided structures and prepare
  * for entry into a new function (signal handler).
  */
-int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp,
-				    struct user_vfp_exc __user *ufp_exc)
+int vfp_preserve_user_clear_hwstate(struct user_vfp *ufp,
+				    struct user_vfp_exc *ufp_exc)
 {
 	struct thread_info *thread = current_thread_info();
 	struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
-	int err = 0;
 
 	/* Ensure that the saved hwstate is up-to-date. */
 	vfp_sync_hwstate(thread);
@@ -568,22 +567,19 @@ int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp,
 	 * Copy the floating point registers. There can be unused
 	 * registers see asm/hwcap.h for details.
 	 */
-	err |= __copy_to_user(&ufp->fpregs, &hwstate->fpregs,
-			      sizeof(hwstate->fpregs));
+	memcpy(&ufp->fpregs, &hwstate->fpregs, sizeof(hwstate->fpregs));
+
 	/*
 	 * Copy the status and control register.
 	 */
-	__put_user_error(hwstate->fpscr, &ufp->fpscr, err);
+	ufp->fpscr = hwstate->fpscr;
 
 	/*
 	 * Copy the exception registers.
 	 */
-	__put_user_error(hwstate->fpexc, &ufp_exc->fpexc, err);
-	__put_user_error(hwstate->fpinst, &ufp_exc->fpinst, err);
-	__put_user_error(hwstate->fpinst2, &ufp_exc->fpinst2, err);
-
-	if (err)
-		return -EFAULT;
+	ufp_exc->fpexc = hwstate->fpexc;
+	ufp_exc->fpinst = hwstate->fpinst;
+	ufp_exc->fpinst2 = hwstate->fpinst2;
 
 	/* Ensure that VFP is disabled. */
 	vfp_flush_hwstate(thread);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3be5f37..8077f07 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -508,7 +508,7 @@
 
 config ARM64_ERRATUM_1286807
 	bool "Cortex-A76: Modification of the translation table for a virtual address might lead to read-after-read ordering violation"
-	default y
+	default n
 	select ARM64_WORKAROUND_REPEAT_TLBI
 	help
 	  This option adds workaround for ARM Cortex-A76 erratum 1286807
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 3cf4346..91f4ff6 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -167,6 +167,14 @@
 	  This enables support for the SM6150 chipset. If you do not
 	  wish to build a kernel that runs on this chipset, say 'N' here.
 
+config ARCH_ATOLL
+	bool "Enable Support for Qualcomm Technologies, Inc. ATOLL"
+	depends on ARCH_QCOM
+	select COMMON_CLK_QCOM
+	help
+	  This enables support for the ATOLL chipset. If you do not
+	  wish to build a kernel that runs on this chipset, say 'N' here.
+
 config ARCH_QCS405
 	bool "Enable Support for Qualcomm Technologies, Inc. QCS405"
 	depends on ARCH_QCOM
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index f410011..0411e7a 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -18,7 +18,7 @@
 # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour
 # for relative relocs, since this leads to better Image compression
 # with the relocation offsets always being zero.
-LDFLAGS_vmlinux		+= -pie -shared -Bsymbolic \
+LDFLAGS_vmlinux		+= -shared -Bsymbolic -z notext -z norelro \
 			$(call ld-option, --no-apply-dynamic-relocs)
 endif
 
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index c58dabc..92912ab8 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -19,7 +19,8 @@
 		qcs405-iot-sku9.dtb \
 		qcs405-iot-sku10.dtb \
 		qcs405-iot-sku11.dtb \
-		qcs405-iot-sku12.dtb
+		qcs405-iot-sku12.dtb \
+		qcs401-iot-sku1.dtb
 else
 dtb-$(CONFIG_ARCH_QCS405) += qcs403-iot-sku1.dtb \
 			qcs403-iot-sku2.dtb \
@@ -94,19 +95,21 @@
 	sm8150p-hdk.dtb
 endif
 
-dtb-$(CONFIG_QTI_GVM) += sa8155-vm.dtb
+dtb-$(CONFIG_QTI_GVM) += sa8155-vm.dtb \
+	sa6155p-vm.dtb
 
 ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
 	dtbo-$(CONFIG_ARCH_SDMSHRIKE) += \
 		sdmshrike-cdp-overlay.dtbo \
 		sdmshrike-mtp-overlay.dtbo
 
-sdmshrike-cdp-overlay.dtbo-base := sdmshrike.dtb
-sdmshrike-mtp-overlay.dtbo-base := sdmshrike.dtb
+sdmshrike-cdp-overlay.dtbo-base := sdmshrike.dtb sdmshrike-v2.dtb
+sdmshrike-mtp-overlay.dtbo-base := sdmshrike.dtb sdmshrike-v2.dtb
 else
 dtb-$(CONFIG_ARCH_SDMSHRIKE)	+= sdmshrike-rumi.dtb \
 	sdmshrike-mtp.dtb \
-	sdmshrike-cdp.dtb
+	sdmshrike-cdp.dtb \
+	sdmshrike-v2-mtp.dtb
 endif
 
 ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
@@ -125,7 +128,9 @@
 		sa6155-adp-air-overlay.dtbo \
 		sa6155p-adp-air-overlay.dtbo \
 		sa6155p-v2-adp-star-overlay.dtbo \
-		sa6155p-v2-adp-air-overlay.dtbo
+		sa6155p-v2-adp-air-overlay.dtbo \
+		qcs610-iot-overlay.dtbo \
+		qcs410-iot-overlay.dtbo
 
 sm6150-rumi-overlay.dtbo-base := sm6150.dtb
 sm6150-qrd-overlay.dtbo-base := sm6150.dtb
@@ -142,6 +147,8 @@
 sa6155-adp-air-overlay.dtbo-base := sa6155.dtb
 sa6155p-adp-air-overlay.dtbo-base := sa6155p.dtb
 sa6155p-v2-adp-air-overlay.dtbo-base := sa6155p.dtb
+qcs610-iot-overlay.dtbo-base := qcs610.dtb
+qcs410-iot-overlay.dtbo-base := qcs410.dtb
 else
 dtb-$(CONFIG_ARCH_SM6150)	+= sm6150-rumi.dtb \
 	sm6150-qrd.dtb \
@@ -157,7 +164,9 @@
 	sa6155-adp-air.dtb \
 	sa6155p-adp-air.dtb \
 	sa6155p-v2-adp-star.dtb \
-	sa6155p-v2-adp-air.dtb
+	sa6155p-v2-adp-air.dtb \
+	qcs610-iot.dtb \
+	qcs410-iot.dtb
 
 endif
 
@@ -168,6 +177,7 @@
 		sdmmagpie-rumi-overlay.dtbo \
 		sdmmagpie-qrd-overlay.dtbo \
 		sdmmagpiep-idp-overlay.dtbo \
+		sdmmagpiep-atp-overlay.dtbo \
 		sdmmagpiep-qrd-overlay.dtbo \
 		sdmmagpie-external-codec-idp-overlay.dtbo \
 		sdmmagpie-usbc-idp-overlay.dtbo \
@@ -178,6 +188,7 @@
 sdmmagpie-rumi-overlay.dtbo-base := sdmmagpie.dtb
 sdmmagpie-qrd-overlay.dtbo-base := sdmmagpie.dtb
 sdmmagpiep-idp-overlay.dtbo-base := sdmmagpiep.dtb
+sdmmagpiep-atp-overlay.dtbo-base := sdmmagpiep.dtb
 sdmmagpiep-qrd-overlay.dtbo-base := sdmmagpiep.dtb
 sdmmagpie-external-codec-idp-overlay.dtbo-base := sdmmagpie.dtb
 sdmmagpie-usbc-idp-overlay.dtbo-base := sdmmagpie.dtb
@@ -188,6 +199,7 @@
 	sdmmagpie-atp.dtb \
 	sdmmagpie-qrd.dtb \
 	sdmmagpiep-idp.dtb \
+	sdmmagpiep-atp.dtb \
 	sdmmagpiep-qrd.dtb \
 	sdmmagpie-external-codec-idp.dtb \
 	sdmmagpie-usbc-idp.dtb \
@@ -218,6 +230,15 @@
 	trinket-usbc-idp.dtb
 endif
 
+ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
+	dtbo-$(CONFIG_ARCH_ATOLL) += \
+		atoll-rumi-overlay.dtbo\
+
+atoll-rumi-overlay.dtbo-base := atoll.dtb
+else
+dtb-$(CONFIG_ARCH_ATOLL)	+= atoll-rumi.dtb
+endif
+
 dtb-$(CONFIG_ARCH_SDXPRAIRIE) += sdxprairie-rumi.dtb \
 	sdxprairie-cdp.dtb \
 	sdxprairie-mtp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/atoll-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/atoll-pinctrl.dtsi
new file mode 100644
index 0000000..12ce68f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/atoll-pinctrl.dtsi
@@ -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.
+ */
+
+&soc {
+	tlmm: pinctrl@3400000 {
+		compatible = "qcom,atoll-pinctrl";
+		reg = <0x03400000 0x989000>, <0x17c000f0 0x60>;
+		reg-names = "pinctrl", "spi_cfg";
+		interrupts = <GIC_SPI 208 IRQ_TYPE_NONE>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/atoll-rumi-overlay.dts b/arch/arm64/boot/dts/qcom/atoll-rumi-overlay.dts
new file mode 100644
index 0000000..cac08cb
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/atoll-rumi-overlay.dts
@@ -0,0 +1,25 @@
+/* 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 <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "atoll-rumi.dtsi"
+
+/ {
+	model = "RUMI";
+	compatible = "qcom,atoll-rumi", "qcom,atoll", "qcom,rumi";
+	qcom,msm-id = <407 0x0>;
+	qcom,board-id = <15 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/atoll-rumi.dts b/arch/arm64/boot/dts/qcom/atoll-rumi.dts
new file mode 100644
index 0000000..211ad59
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/atoll-rumi.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/;
+
+#include "atoll.dtsi"
+#include "atoll-rumi.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. ATOLL PM6150 RUMI";
+	compatible = "qcom,atoll-rumi", "qcom,atoll", "qcom,rumi";
+	qcom,board-id = <15 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/atoll-rumi.dtsi b/arch/arm64/boot/dts/qcom/atoll-rumi.dtsi
new file mode 100644
index 0000000..84e7518
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/atoll-rumi.dtsi
@@ -0,0 +1,26 @@
+/* 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.
+ */
+
+&soc {
+
+	timer {
+		clock-frequency = <1000000>;
+	};
+
+	timer@17c20000 {
+		clock-frequency = <1000000>;
+	};
+
+	wdog: qcom,wdt@17c10000{
+		status = "disabled";
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/atoll.dts b/arch/arm64/boot/dts/qcom/atoll.dts
new file mode 100644
index 0000000..22d9bd7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/atoll.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/;
+
+#include "atoll.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. ATOLL SoC";
+	compatible = "qcom,atoll";
+	qcom,pmic-name = "PM6150";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/atoll.dtsi b/arch/arm64/boot/dts/qcom/atoll.dtsi
new file mode 100644
index 0000000..dec07df
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/atoll.dtsi
@@ -0,0 +1,723 @@
+/* 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 "skeleton64.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	model = "Qualcomm Technologies, Inc. ATOLL";
+	compatible = "qcom,atoll";
+	qcom,msm-name = "ATOLL";
+	qcom,msm-id = <407 0x0>;
+	interrupt-parent = <&intc>;
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		CPU0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+			      compatible = "arm,arch-cache";
+			      cache-size = <0x10000>;
+			      cache-level = <2>;
+			      next-level-cache = <&L3_0>;
+
+				L3_0: l3-cache {
+				      compatible = "arm,arch-cache";
+				      cache-size = <0x100000>;
+				      cache-level = <3>;
+				};
+			};
+
+			L1_I_0: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+
+			L1_D_0: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+
+			L2_TLB_0: l2-tlb {
+				qcom,dump-size = <0x5000>;
+			};
+		};
+
+		CPU1: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x100>;
+			enable-method = "psci";
+			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
+			next-level-cache = <&L2_100>;
+			L2_100: l2-cache {
+			      compatible = "arm,arch-cache";
+			      cache-size = <0x10000>;
+			      cache-level = <2>;
+			      next-level-cache = <&L3_0>;
+			};
+
+			L1_I_100: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+
+			L1_D_100: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+
+			L2_TLB_100: l2-tlb {
+				qcom,dump-size = <0x5000>;
+			};
+		};
+
+
+		CPU2: cpu@200 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x200>;
+			enable-method = "psci";
+			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
+			next-level-cache = <&L2_200>;
+			L2_200: l2-cache {
+			      compatible = "arm,arch-cache";
+			      cache-size = <0x10000>;
+			      cache-level = <2>;
+			      next-level-cache = <&L3_0>;
+			};
+
+			L1_I_200: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+
+			L1_D_200: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+
+			L2_TLB_200: l2-tlb {
+				qcom,dump-size = <0x5000>;
+			};
+		};
+
+		CPU3: cpu@300 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x300>;
+			enable-method = "psci";
+			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
+			next-level-cache = <&L2_300>;
+			L2_300: l2-cache {
+			      compatible = "arm,arch-cache";
+			      cache-size = <0x10000>;
+			      cache-level = <2>;
+			      next-level-cache = <&L3_0>;
+			};
+
+			L1_I_300: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+
+			L1_D_300: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+
+			L2_TLB_300: l2-tlb {
+				qcom,dump-size = <0x5000>;
+			};
+		};
+
+		CPU4: cpu@400 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x400>;
+			enable-method = "psci";
+			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
+			next-level-cache = <&L2_400>;
+			L2_400: l2-cache {
+			      compatible = "arm,arch-cache";
+			      cache-size = <0x10000>;
+			      cache-level = <2>;
+			      next-level-cache = <&L3_0>;
+			};
+
+			L1_I_400: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+
+			L1_D_400: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+
+			L2_TLB_400: l2-tlb {
+				qcom,dump-size = <0x5000>;
+			};
+		};
+
+		CPU5: cpu@500 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x500>;
+			enable-method = "psci";
+			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
+			next-level-cache = <&L2_500>;
+			L2_500: l2-cache {
+			      compatible = "arm,arch-cache";
+			      cache-size = <0x10000>;
+			      cache-level = <2>;
+			      next-level-cache = <&L3_0>;
+			};
+
+			L1_I_500: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+
+			L1_D_500: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+
+			L2_TLB_500: l2-tlb {
+				qcom,dump-size = <0x5000>;
+			};
+		};
+
+		CPU6: cpu@600 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x600>;
+			enable-method = "psci";
+			d-cache-size = <0x10000>;
+			i-cache-size = <0x10000>;
+			next-level-cache = <&L2_600>;
+			L2_600: l2-cache {
+			      compatible = "arm,arch-cache";
+			      cache-size = <0x40000>;
+			      cache-level = <2>;
+			      next-level-cache = <&L3_0>;
+			      qcom,dump-size = <0x48000>;
+			};
+
+			L1_I_600: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x11000>;
+			};
+
+			L1_D_600: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x12000>;
+			};
+
+			L1_ITLB_600: l1-itlb {
+				qcom,dump-size = <0x300>;
+			};
+
+			L1_DTLB_600: l1-dtlb {
+				qcom,dump-size = <0x480>;
+			};
+
+			L2_TLB_600: l2-tlb {
+				qcom,dump-size = <0x7800>;
+			};
+		};
+
+		CPU7: cpu@700 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x700>;
+			enable-method = "psci";
+			d-cache-size = <0x10000>;
+			i-cache-size = <0x10000>;
+			next-level-cache = <&L2_700>;
+			L2_700: l2-cache {
+			      compatible = "arm,arch-cache";
+			      cache-size = <0x40000>;
+			      cache-level = <2>;
+			      next-level-cache = <&L3_0>;
+			      qcom,dump-size = <0x48000>;
+			};
+
+			L1_I_700: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x11000>;
+			};
+
+			L1_D_700: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x12000>;
+			};
+
+			L1_ITLB_700: l1-itlb {
+				qcom,dump-size = <0x300>;
+			};
+
+			L1_DTLB_700: l1-dtlb {
+				qcom,dump-size = <0x480>;
+			};
+
+			L2_TLB_700: l2-tlb {
+				qcom,dump-size = <0x7800>;
+			};
+		};
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&CPU0>;
+				};
+
+				core1 {
+					cpu = <&CPU1>;
+				};
+
+				core2 {
+					cpu = <&CPU2>;
+				};
+
+				core3 {
+					cpu = <&CPU3>;
+				};
+
+				core4 {
+					cpu = <&CPU4>;
+				};
+
+				core5 {
+					cpu = <&CPU5>;
+				};
+
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&CPU6>;
+				};
+
+				core1 {
+					cpu = <&CPU7>;
+				};
+			};
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	chosen {
+		bootargs = "rcupdate.rcu_expedited=1 rcu_nocbs=0-7";
+	};
+
+	soc: soc { };
+
+};
+
+&soc {
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges = <0 0 0 0xffffffff>;
+	compatible = "simple-bus";
+
+	intc: interrupt-controller@17a00000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		#redistributor-regions = <1>;
+		redistributor-stride = <0x0 0x20000>;
+		reg = <0x17a00000 0x10000>,     /* GICD */
+			<0x17a60000 0x100000>;    /* GICR * 8 */
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-parent = <&intc>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 1 0xf08>,
+			     <GIC_PPI 2 0xf08>,
+			     <GIC_PPI 3 0xf08>,
+			     <GIC_PPI 0 0xf08>;
+		clock-frequency = <19200000>;
+	};
+
+	timer@17c20000{
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "arm,armv7-timer-mem";
+		reg = <0x17c20000 0x1000>;
+		clock-frequency = <19200000>;
+
+		frame@17c21000 {
+			frame-number = <0>;
+			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			reg = <0x17c21000 0x1000>,
+			      <0x17c22000 0x1000>;
+		};
+
+		frame@17c23000 {
+			frame-number = <1>;
+			interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+			reg = <0x17c23000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@17c25000 {
+			frame-number = <2>;
+			interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+			reg = <0x17c25000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@17c27000 {
+			frame-number = <3>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+			reg = <0x17c27000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@17c29000 {
+			frame-number = <4>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+			reg = <0x17c29000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@17c2b000 {
+			frame-number = <5>;
+			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+			reg = <0x17c2b000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@17c2d000 {
+			frame-number = <6>;
+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+			reg = <0x17c2d000 0x1000>;
+			status = "disabled";
+		};
+	};
+
+	cpu_pmu: cpu-pmu {
+		compatible = "arm,armv8-pmuv3";
+		qcom,irq-is-percpu;
+		interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	qcom,msm-imem@146aa000 {
+		compatible = "qcom,msm-imem";
+		reg = <0x146aa000 0x1000>;
+		ranges = <0x0 0x146aa000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mem_dump_table@10 {
+			compatible = "qcom,msm-imem-mem_dump_table";
+			reg = <0x10 8>;
+		};
+
+		restart_reason@65c {
+			compatible = "qcom,msm-imem-restart_reason";
+			reg = <0x65c 4>;
+		};
+
+		dload_type@1c {
+			compatible = "qcom,msm-imem-dload-type";
+			reg = <0x1c 0x4>;
+		};
+
+		boot_stats@6b0 {
+			compatible = "qcom,msm-imem-boot_stats";
+			reg = <0x6b0 32>;
+		};
+
+		kaslr_offset@6d0 {
+			compatible = "qcom,msm-imem-kaslr_offset";
+			reg = <0x6d0 12>;
+		};
+
+		pil@94c {
+			compatible = "qcom,msm-imem-pil";
+			reg = <0x94c 200>;
+		};
+
+		diag_dload@c8 {
+			compatible = "qcom,msm-imem-diag-dload";
+			reg = <0xc8 200>;
+		};
+	};
+
+	restart@c264000 {
+		compatible = "qcom,pshold";
+		reg = <0xc264000 0x4>,
+		      <0x1fd3000 0x4>;
+		reg-names = "pshold-base", "tcsr-boot-misc-detect";
+	};
+
+	qcom,msm-rtb {
+		compatible = "qcom,msm-rtb";
+		qcom,rtb-size = <0x100000>;
+	};
+
+	wdog: qcom,wdt@17c10000{
+		compatible = "qcom,msm-watchdog";
+		reg = <0x17c10000 0x1000>;
+		reg-names = "wdt-base";
+		interrupts = <GIC_SPI 0 IRQ_TYPE_NONE>,
+				<GIC_SPI 1 IRQ_TYPE_NONE>;
+		qcom,bark-time = <11000>;
+		qcom,pet-time = <9360>;
+		qcom,ipi-ping;
+		qcom,wakeup-enable;
+		qcom,scandump-sizes = <0x10100 0x10100 0x10100 0x10100
+				       0x10100 0x10100 0x25900 0x25900>;
+	};
+
+	qcom,chd_sliver {
+		compatible = "qcom,core-hang-detect";
+		label = "silver";
+		qcom,threshold-arr = <0x18000058 0x18010058
+				      0x18020058 0x18030058
+				      0x18040058 0x18050058>;
+		qcom,config-arr = <0x18000060 0x18010060
+				   0x18020060 0x18030060
+				   0x18040060 0x18050060>;
+	};
+
+	qcom,chd_gold {
+		compatible = "qcom,core-hang-detect";
+		label = "gold";
+		qcom,threshold-arr = <0x18060058 0x18070058>;
+		qcom,config-arr = <0x18060060 0x18070060>;
+	};
+
+	qcom,ghd {
+		compatible = "qcom,gladiator-hang-detect-v3";
+		qcom,threshold-arr = <0x17e0041C>;
+		qcom,config-reg = <0x17e00434>;
+	};
+
+	kryo-erp {
+		compatible = "arm,arm64-kryo-cpu-erp";
+		interrupts = <GIC_PPI 6 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+
+		interrupt-names = "l1-l2-faultirq",
+				  "l3-scu-faultirq";
+	};
+
+	qcom,llcc@9200000 {
+		compatible = "qcom,llcc-core", "syscon", "simple-mfd";
+		reg = <0x9200000 0x450000>;
+		reg-names = "llcc_base";
+		qcom,llcc-banks-off = <0x0>;
+		qcom,llcc-broadcast-off = <0x400000>;
+
+		llcc: qcom,atoll-llcc {
+			compatible = "qcom,atoll-llcc";
+			#cache-cells = <1>;
+			max-slices = <32>;
+			cap-based-alloc-and-pwr-collapse;
+		};
+
+		qcom,llcc-erp {
+			compatible = "qcom,llcc-erp";
+		};
+
+		qcom,llcc-amon {
+			compatible = "qcom,llcc-amon";
+		};
+
+		LLCC_1: llcc_1_dcache {
+			qcom,dump-size = <0x6c000>;
+		};
+	};
+
+	cpuss_dump {
+		compatible = "qcom,cpuss-dump";
+
+		qcom,l1_i_cache0 {
+			qcom,dump-node = <&L1_I_0>;
+			qcom,dump-id = <0x60>;
+		};
+
+		qcom,l1_i_cache100 {
+			qcom,dump-node = <&L1_I_100>;
+			qcom,dump-id = <0x61>;
+		};
+
+		qcom,l1_i_cache200 {
+			qcom,dump-node = <&L1_I_200>;
+			qcom,dump-id = <0x62>;
+		};
+
+		qcom,l1_i_cache300 {
+			qcom,dump-node = <&L1_I_300>;
+			qcom,dump-id = <0x63>;
+		};
+
+		qcom,l1_i_cache400 {
+			qcom,dump-node = <&L1_I_400>;
+			qcom,dump-id = <0x64>;
+		};
+
+		qcom,l1_i_cache500 {
+			qcom,dump-node = <&L1_I_500>;
+			qcom,dump-id = <0x65>;
+		};
+
+		qcom,l1_i_cache600 {
+			qcom,dump-node = <&L1_I_600>;
+			qcom,dump-id = <0x66>;
+		};
+
+		qcom,l1_i_cache700 {
+			qcom,dump-node = <&L1_I_700>;
+			qcom,dump-id = <0x67>;
+		};
+
+		qcom,l1_d_cache0 {
+			qcom,dump-node = <&L1_D_0>;
+			qcom,dump-id = <0x80>;
+		};
+
+		qcom,l1_d_cache100 {
+			qcom,dump-node = <&L1_D_100>;
+			qcom,dump-id = <0x81>;
+		};
+
+		qcom,l1_d_cache200 {
+			qcom,dump-node = <&L1_D_200>;
+			qcom,dump-id = <0x82>;
+		};
+
+		qcom,l1_d_cache300 {
+			qcom,dump-node = <&L1_D_300>;
+			qcom,dump-id = <0x83>;
+		};
+
+		qcom,l1_d_cache400 {
+			qcom,dump-node = <&L1_D_400>;
+			qcom,dump-id = <0x84>;
+		};
+
+		qcom,l1_d_cache500 {
+			qcom,dump-node = <&L1_D_500>;
+			qcom,dump-id = <0x85>;
+		};
+
+		qcom,l1_d_cache600 {
+			qcom,dump-node = <&L1_D_600>;
+			qcom,dump-id = <0x86>;
+		};
+
+		qcom,l1_d_cache700 {
+			qcom,dump-node = <&L1_D_700>;
+			qcom,dump-id = <0x87>;
+		};
+
+		qcom,l1_i_tlb_dump600 {
+			qcom,dump-node = <&L1_ITLB_600>;
+			qcom,dump-id = <0x26>;
+		};
+
+		qcom,l1_i_tlb_dump700 {
+			qcom,dump-node = <&L1_ITLB_700>;
+			qcom,dump-id = <0x27>;
+		};
+
+		qcom,l1_d_tlb_dump600 {
+			qcom,dump-node = <&L1_DTLB_600>;
+			qcom,dump-id = <0x46>;
+		};
+
+		qcom,l1_d_tlb_dump700 {
+			qcom,dump-node = <&L1_DTLB_700>;
+			qcom,dump-id = <0x47>;
+		};
+
+		qcom,l2_cache_dump600 {
+			qcom,dump-node = <&L2_600>;
+			qcom,dump-id = <0xc6>;
+		};
+
+		qcom,l2_cache_dump700 {
+			qcom,dump-node = <&L2_700>;
+			qcom,dump-id = <0xc7>;
+		};
+
+		qcom,l2_tlb_dump0 {
+			qcom,dump-node = <&L2_TLB_0>;
+			qcom,dump-id = <0x120>;
+		};
+
+		qcom,l2_tlb_dump100 {
+			qcom,dump-node = <&L2_TLB_100>;
+			qcom,dump-id = <0x121>;
+		};
+
+		qcom,l2_tlb_dump200 {
+			qcom,dump-node = <&L2_TLB_200>;
+			qcom,dump-id = <0x122>;
+		};
+
+		qcom,l2_tlb_dump300 {
+			qcom,dump-node = <&L2_TLB_300>;
+			qcom,dump-id = <0x123>;
+		};
+
+		qcom,l2_tlb_dump400 {
+			qcom,dump-node = <&L2_TLB_400>;
+			qcom,dump-id = <0x124>;
+		};
+
+		qcom,l2_tlb_dump500 {
+			qcom,dump-node = <&L2_TLB_500>;
+			qcom,dump-id = <0x125>;
+		};
+
+		qcom,l2_tlb_dump600 {
+			qcom,dump-node = <&L2_TLB_600>;
+			qcom,dump-id = <0x126>;
+		};
+
+		qcom,l2_tlb_dump700 {
+			qcom,dump-node = <&L2_TLB_700>;
+			qcom,dump-id = <0x127>;
+		};
+	};
+
+};
+
+#include "atoll-pinctrl.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-nt36672-truly-fhd-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-nt36672-truly-fhd-video.dtsi
new file mode 100644
index 0000000..c34131b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-nt36672-truly-fhd-video.dtsi
@@ -0,0 +1,282 @@
+/* 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.
+ */
+
+&mdss_mdp {
+	dsi_nt36672_truly_video: qcom,mdss_dsi_nt36672_truly_video {
+		qcom,mdss-dsi-panel-name =
+				"nt36672 truly fhd video mode dsi panel";
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-traffic-mode = "burst_mode";
+		qcom,mdss-dsi-te-pin-select = <1>;
+		qcom,mdss-dsi-te-dcs-command = <1>;
+		qcom,mdss-dsi-te-check-enable;
+		qcom,mdss-dsi-te-using-te-pin;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+		qcom,mdss-dsi-tx-eot-append;
+		qcom,mdss-dsi-post-init-delay = <1>;
+		qcom,mdss-dsi-dma-trigger = "trigger_sw";
+		qcom,mdss-dsi-mdp-trigger = "none";
+
+		qcom,mdss-dsi-display-timings {
+			timing@0{
+				qcom,mdss-dsi-panel-width = <1080>;
+				qcom,mdss-dsi-panel-height = <2520>;
+				qcom,mdss-dsi-h-front-porch = <28>;
+				qcom,mdss-dsi-h-back-porch = <176>;
+				qcom,mdss-dsi-h-pulse-width = <12>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <10>;
+				qcom,mdss-dsi-v-front-porch = <12>;
+				qcom,mdss-dsi-v-pulse-width = <4>;
+				qcom,mdss-dsi-h-sync-pulse = <0>;
+				qcom,mdss-dsi-h-left-border = <0>;
+				qcom,mdss-dsi-h-right-border = <0>;
+				qcom,mdss-dsi-v-top-border = <0>;
+				qcom,mdss-dsi-v-bottom-border = <0>;
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-on-command = [
+					29 01 00 00 00 00 02 FF 10
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 FF 20
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 0E B0
+					29 01 00 00 00 00 02 0F AE
+					29 01 00 00 00 00 02 62 93
+					29 01 00 00 00 00 02 6D 44
+					29 01 00 00 00 00 02 78 01
+					29 01 00 00 00 00 02 95 B9
+					29 01 00 00 00 00 02 96 B9
+					29 01 00 00 00 00 02 97 B9
+					29 01 00 00 00 00 02 98 B9
+					29 01 00 00 00 00 02 FF 24
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 00 1C
+					29 01 00 00 00 00 02 01 1C
+					29 01 00 00 00 00 02 02 1C
+					29 01 00 00 00 00 02 03 1C
+					29 01 00 00 00 00 02 04 20
+					29 01 00 00 00 00 02 05 00
+					29 01 00 00 00 00 02 06 09
+					29 01 00 00 00 00 02 07 0A
+					29 01 00 00 00 00 02 08 1E
+					29 01 00 00 00 00 02 09 0D
+					29 01 00 00 00 00 02 0A 0D
+					29 01 00 00 00 00 02 0B 25
+					29 01 00 00 00 00 02 0C 24
+					29 01 00 00 00 00 02 0D 01
+					29 01 00 00 00 00 02 0E 04
+					29 01 00 00 00 00 02 0F 04
+					29 01 00 00 00 00 02 10 03
+					29 01 00 00 00 00 02 11 03
+					29 01 00 00 00 00 02 12 14
+					29 01 00 00 00 00 02 13 14
+					29 01 00 00 00 00 02 14 12
+					29 01 00 00 00 00 02 15 12
+					29 01 00 00 00 00 02 16 10
+					29 01 00 00 00 00 02 17 1C
+					29 01 00 00 00 00 02 18 1C
+					29 01 00 00 00 00 02 19 1C
+					29 01 00 00 00 00 02 1A 1C
+					29 01 00 00 00 00 02 1B 20
+					29 01 00 00 00 00 02 1C 0D
+					29 01 00 00 00 00 02 1D 09
+					29 01 00 00 00 00 02 1E 0A
+					29 01 00 00 00 00 02 1F 1E
+					29 01 00 00 00 00 02 20 0D
+					29 01 00 00 00 00 02 21 0D
+					29 01 00 00 00 00 02 22 25
+					29 01 00 00 00 00 02 23 24
+					29 01 00 00 00 00 02 24 01
+					29 01 00 00 00 00 02 25 04
+					29 01 00 00 00 00 02 26 04
+					29 01 00 00 00 00 02 27 03
+					29 01 00 00 00 00 02 28 03
+					29 01 00 00 00 00 02 29 14
+					29 01 00 00 00 00 02 2A 14
+					29 01 00 00 00 00 02 2B 12
+					29 01 00 00 00 00 02 2D 12
+					29 01 00 00 00 00 02 2F 10
+					29 01 00 00 00 00 02 31 02
+					29 01 00 00 00 00 02 32 03
+					29 01 00 00 00 00 02 33 04
+					29 01 00 00 00 00 02 34 02
+					29 01 00 00 00 00 02 37 09
+					29 01 00 00 00 00 02 38 6A
+					29 01 00 00 00 00 02 39 6A
+					29 01 00 00 00 00 02 3F 6A
+					29 01 00 00 00 00 02 41 02
+					29 01 00 00 00 00 02 42 03
+					29 01 00 00 00 00 02 4C 10
+					29 01 00 00 00 00 02 4D 10
+					29 01 00 00 00 00 02 60 90
+					29 01 00 00 00 00 02 61 D8
+					29 01 00 00 00 00 02 72 00
+					29 01 00 00 00 00 02 73 00
+					29 01 00 00 00 00 02 74 00
+					29 01 00 00 00 00 02 75 00
+					29 01 00 00 00 00 02 79 23
+					29 01 00 00 00 00 02 7A 0D
+					29 01 00 00 00 00 02 7B 98
+					29 01 00 00 00 00 02 7C 80
+					29 01 00 00 00 00 02 7D 09
+					29 01 00 00 00 00 02 80 42
+					29 01 00 00 00 00 02 82 11
+					29 01 00 00 00 00 02 83 22
+					29 01 00 00 00 00 02 84 33
+					29 01 00 00 00 00 02 85 00
+					29 01 00 00 00 00 02 86 00
+					29 01 00 00 00 00 02 87 00
+					29 01 00 00 00 00 02 88 11
+					29 01 00 00 00 00 02 89 22
+					29 01 00 00 00 00 02 8A 33
+					29 01 00 00 00 00 02 8B 00
+					29 01 00 00 00 00 02 8C 00
+					29 01 00 00 00 00 02 8D 00
+					29 01 00 00 00 00 02 92 6D
+					29 01 00 00 00 00 02 9D B6
+					29 01 00 00 00 00 02 B3 02
+					29 01 00 00 00 00 02 B4 00
+					29 01 00 00 00 00 02 DC 44
+					29 01 00 00 00 00 02 DD 03
+					29 01 00 00 00 00 02 DF 3E
+					29 01 00 00 00 00 02 E0 3E
+					29 01 00 00 00 00 02 E1 22
+					29 01 00 00 00 00 02 E2 24
+					29 01 00 00 00 00 02 E3 09
+					29 01 00 00 00 00 02 E4 09
+					29 01 00 00 00 00 02 EB 0F
+					29 01 00 00 00 00 02 FF 25
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 21 18
+					29 01 00 00 00 00 02 22 18
+					29 01 00 00 00 00 02 24 6D
+					29 01 00 00 00 00 02 25 6D
+					29 01 00 00 00 00 02 2F 10
+					29 01 00 00 00 00 02 30 2D
+					29 01 00 00 00 00 02 38 2D
+					29 01 00 00 00 00 02 3F 21
+					29 01 00 00 00 00 02 40 65
+					29 01 00 00 00 00 02 4B 21
+					29 01 00 00 00 00 02 4C 65
+					29 01 00 00 00 00 02 58 22
+					29 01 00 00 00 00 02 59 04
+					29 01 00 00 00 00 02 5A 09
+					29 01 00 00 00 00 02 5B 09
+					29 01 00 00 00 00 02 5C 25
+					29 01 00 00 00 00 02 5E FF
+					29 01 00 00 00 00 02 5F 28
+					29 01 00 00 00 00 02 66 D8
+					29 01 00 00 00 00 02 67 2B
+					29 01 00 00 00 00 02 68 58
+					29 01 00 00 00 00 02 6B 00
+					29 01 00 00 00 00 02 6C 6D
+					29 01 00 00 00 00 02 77 72
+					29 01 00 00 00 00 02 BF 00
+					29 01 00 00 00 00 02 C3 01
+					29 01 00 00 00 00 02 FF 26
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 06 FF
+					29 01 00 00 00 00 02 0C 11
+					29 01 00 00 00 00 02 0F 09
+					29 01 00 00 00 00 02 10 0A
+					29 01 00 00 00 00 02 12 8C
+					29 01 00 00 00 00 02 1A 28
+					29 01 00 00 00 00 02 1C AF
+					29 01 00 00 00 00 02 1E AB
+					29 01 00 00 00 00 02 98 F1
+					29 01 00 00 00 00 02 A9 12
+					29 01 00 00 00 00 02 AA 10
+					29 01 00 00 00 00 02 AE 6A
+					29 01 00 00 00 00 02 FF 27
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 13 00
+					29 01 00 00 00 00 02 1E 24
+					29 01 00 00 00 00 02 FF F0
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 A2 00
+					29 01 00 00 00 00 02 FF 20
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 11 B0 00 00 00 3D 00
+						74 00 9A 00 B9 00 D1 00 E6 00 F8
+					29 01 00 00 00 00 11 B1 01 08 01 3B 01
+						5E 01 95 01 BB 01 F8 02 23 02 25
+					29 01 00 00 00 00 11 B2 02 51 02 84 02
+						AB 02 E1 02 FB 03 30 03 3E 03 4D
+					29 01 00 00 00 00 0D B3 03 5F 03 72 03
+						8A 03 A9 03 C9 03 FF
+					29 01 00 00 00 00 11 B4 00 00 00 3D 00
+						74 00 9A 00 B9 00 D1 00 E6 00 F8
+					29 01 00 00 00 00 11 B5 01 08 01 3B 01
+						5E 01 95 01 BB 01 F8 02 23 02 25
+					29 01 00 00 00 00 11 B6 02 51 02 84 02
+						AB 02 E1 02 FB 03 30 03 3E 03 4D
+					29 01 00 00 00 00 0D B7 03 5F 03 72 03
+						8A 03 A9 03 C9 03 FF
+					29 01 00 00 00 00 11 B8 00 00 00 3D 00
+						74 00 9A 00 B9 00 D1 00 E6 00 F8
+					29 01 00 00 00 00 11 B9 01 08 01 3B 01
+						5E 01 95 01 BB 01 F8 02 23 02 25
+					29 01 00 00 00 00 11 BA 02 51 02 84 02
+						AB 02 E1 02 FB 03 30 03 3E 03 4D
+					29 01 00 00 00 00 0D BB 03 5F 03 72 03
+						8A 03 A9 03 C9 03 FF
+					29 01 00 00 00 00 02 FF 21
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 11 B0 00 00 00 3D 00
+						74 00 9A 00 B9 00 D1 00 E6 00 F8
+					29 01 00 00 00 00 11 B1 01 08 01 3B 01
+						5E 01 95 01 BB 01 F8 02 23 02 25
+					29 01 00 00 00 00 11 B2 02 51 02 84 02
+						AB 02 E1 02 FB 03 30 03 3E 03 4D
+					29 01 00 00 00 00 0D B3 03 5F 03 72 03
+						8A 03 A9 03 C9 03 FF
+					29 01 00 00 00 00 11 B4 00 00 00 3D 00
+						74 00 9A 00 B9 00 D1 00 E6 00 F8
+					29 01 00 00 00 00 11 B5 01 08 01 3B 01
+						5E 01 95 01 BB 01 F8 02 23 02 25
+					29 01 00 00 00 00 11 B6 02 51 02 84 02
+						AB 02 E1 02 FB 03 30 03 3E 03 4D
+					29 01 00 00 00 00 0D B7 03 5F 03 72 03
+						8A 03 A9 03 C9 03 FF
+					29 01 00 00 00 00 11 B8 00 00 00 3D 00
+						74 00 9A 00 B9 00 D1 00 E6 00 F8
+					29 01 00 00 00 00 11 B9 01 08 01 3B 01
+						5E 01 95 01 BB 01 F8 02 23 02 25
+					29 01 00 00 00 00 11 BA 02 51 02 84 02
+						AB 02 E1 02 FB 03 30 03 3E 03 4D
+					29 01 00 00 00 00 0D BB 03 5F 03 72 03
+						8A 03 A9 03 C9 03 FF
+					29 01 00 00 00 00 02 FF 10
+					29 01 00 00 00 00 02 FB 01
+					39 01 00 00 00 00 02 51 FF
+					39 01 00 00 00 00 02 53 2C
+					05 01 00 00 78 00 02 11 00
+					05 01 00 00 32 00 02 29 00];
+				qcom,mdss-dsi-off-command = [05 01 00 00 14
+					00 02 28 00 05 01 00 00 78 00 02 10 00];
+				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+				qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-fhd-plus-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-fhd-plus-cmd.dtsi
index 3aa7f81..06823db 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-fhd-plus-cmd.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-fhd-plus-cmd.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
@@ -85,7 +85,7 @@
 				  39 01 00 00 00 00 06 b9 bf 11 40 00 30
 				  39 01 00 00 00 00 09 F8 00 08 10 08 2D
 					   00 00 2D
-				  15 01 00 00 00 00 02 55 0c
+				  15 01 00 00 00 00 02 55 00
 				  05 01 00 00 1e 00 02 11 00
 				  15 01 00 00 78 00 02 3d 01
 				  39 01 00 00 00 00 03 b0 a5 00
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi
index 3081bd6..ea8c4a8 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-cmd.dtsi
@@ -82,7 +82,7 @@
 					39 01 00 00 00 00 03 b0 a5 00
 					39 01 00 00 00 00 09 F8 00 08 10 08 2D
 					   00 00 2D
-					15 01 00 00 00 00 02 55 0c
+					15 01 00 00 00 00 02 55 00
 					05 01 00 00 1e 00 02 11 00
 					39 01 00 00 00 00 03 b0 a5 00
 					15 01 00 00 00 00 02 e0 18
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-video.dtsi
index 74ff912..5ad5736 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-sw43404-amoled-dsc-wqhd-video.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
@@ -55,7 +55,7 @@
 			  39 01 00 00 00 00 06 b2 00 5d 04 80 49
 			  15 01 00 00 00 00 02 3d 10
 			  15 01 00 00 00 00 02 36 00
-			  15 01 00 00 00 00 02 55 0c
+			  15 01 00 00 00 00 02 55 00
 			  39 01 00 00 00 00 09 f8 00 08 10 08 2d
 			     00 00 2d
 			  39 01 00 00 3c 00 03 51 00 00
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-td4330-truly-singlemipi-fhd-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-td4330-truly-singlemipi-fhd-cmd.dtsi
index daccd22..e0a480d 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-td4330-truly-singlemipi-fhd-cmd.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-td4330-truly-singlemipi-fhd-cmd.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
@@ -60,6 +60,7 @@
 				qcom,mdss-dsi-panel-framerate = <60>;
 				qcom,mdss-dsi-panel-jitter = <0x4 0x1>;
 				qcom,mdss-dsi-on-command = [
+					15 01 00 00 00 00 02 B0 04
 					15 01 00 00 00 00 02 B0 00
 					39 01 00 00 00 00 0D B6 30 6B
 						00 06 03 0A 13 1A 6C 18
@@ -85,17 +86,17 @@
 						2C 06 08 E8 00 06 00 00
 						08
 					39 01 00 00 00 00 24 C1 30 00 00
-						10 11 00 00 00 22 00 05
+						11 11 00 00 00 22 00 05
 						20 FA 00 08 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
 					39 01 00 00 00 00 79 C2 06 C0 6D
-						01 03 00 02 00 01 20 12
-						01 03 08 F0 00 00 00 00
+						01 03 00 02 02 01 20 12
+						01 03 08 F0 01 00 00 00
 						00 00 00 00 00 01 20 D9
-						04 04 01 00 01 00 28 F1
-						00 00 01 00 00 00 11 00
-						00 00 00 00 00 00 00 00
+						04 04 01 01 01 00 28 F1
+						00 00 01 08 00 00 11 00
+						28 F1 04 00 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 11 00 00 00
 						00 00 00 00 00 00 00 00
@@ -120,29 +121,17 @@
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00
-					39 01 00 00 00 00 62 C4 00 00 00
-						00 4F 00 3E 3F 4F 00 00
-						44 06 02 11 11 0F 0F 61
-						61 5F 5F 5D 5D 00 00 00
+					39 01 00 00 00 00 43 C4 00 00 00
 						00 4F 00 3E 3F 4F 00 00
 						44 06 02 10 10 0E 0E 61
+						61 5F 5F 5D 5D 00 00 00
+						00 4F 00 3E 3F 4F 00 00
+						44 06 02 11 11 0F 0F 61
 						61 5F 5F 5D 5D F0 FF FF
 						F0 FF FF E0 FF FF E0 FF
-						FF 10 00 00 10 00 00 00
-						00 00 00 00 00 00 00 00
-						00 00 00 00 00 00 00 00
-						00 00 00 00 00 00 50 00
-						00 00 00 00 00 00
+						FF 10 00 00 10 00 00
 					39 01 00 00 00 00 06 C5 08 00 00
 						00 00
-					39 01 00 00 00 00 3A C6 09 0A 08
-						FC FF FF FF 00 00 13 01
-						FF 0F 22 01 3A 3A 3A 00
-						00 00 01 05 09 28 28 22
-						01 3A 3A 3A 00 00 00 01
-						21 00 00 00 1C 01 00 00
-						00 00 00 00 00 00 00 00
-						00 00 20 20 00 00
 					39 01 00 00 00 00 3A C6 02 0A 08
 						FC FF FF FF 00 00 13 01
 						FF 0F 22 01 3A 3A 3A 00
@@ -162,6 +151,15 @@
 						E2 02 2E 02 6B 02 CF 02
 						39 02 D0 03 41 03 96 03
 						A0
+					39 01 00 00 00 00 42 C8 40 00 00
+						00 00 FF 00 00 00 00 00
+						FF 00 00 00 00 00 FF 00
+						00 00 00 00 FF 00 00 00
+						00 00 FF 00 00 00 00 FF
+						00 00 00 00 FF 00 00 00
+						00 FF 00 00 00 00 FF 00
+						00 00 00 FF 00 00 00 00
+						FF 00 00 00 00 FF
 					39 01 00 00 00 00 19 C9 00 00 00
 						00 FF 00 00 00 00 00 FF
 						00 00 00 00 00 FF 00 00
@@ -293,17 +291,18 @@
 						0F 00 03 40 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
-						00 00 00 00 00 00 00 00
+						00 00 00 00 00 03 00 02
+					15 01 00 00 00 00 02 35 00
 					15 01 00 00 00 00 02 B0 04
 					29 01 00 00 00 00 02 D6 00
-					15 01 00 00 00 00 02 35 00
+					15 01 00 00 00 00 02 B0 03
 					39 01 00 00 00 00 03 51 FF F0
 					15 01 00 00 00 00 02 53 0C
 					15 01 00 00 00 00 02 55 00
 					39 01 00 00 00 00 05 2A 00 00 04 37
 					39 01 00 00 00 00 05 2B 00 00 08 E7
 					39 01 00 00 00 00 05 30 00 00 02 A7
-					15 01 00 00 00 00 02 B0 04
+					15 01 00 00 00 00 02 B0 03
 					05 01 00 00 64 00 02 29 00
 					05 01 00 00 C8 00 02 11 00];
 				qcom,mdss-dsi-off-command = [
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-td4330-truly-singlemipi-fhd-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-td4330-truly-singlemipi-fhd-video.dtsi
index 3a83be2..466a7b7 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-td4330-truly-singlemipi-fhd-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-td4330-truly-singlemipi-fhd-video.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
@@ -50,51 +50,52 @@
 			timing@0 {
 				qcom,mdss-dsi-panel-width = <1080>;
 				qcom,mdss-dsi-panel-height = <2280>;
-				qcom,mdss-dsi-h-front-porch = <80>;
-				qcom,mdss-dsi-h-back-porch = <80>;
-				qcom,mdss-dsi-h-pulse-width = <20>;
+				qcom,mdss-dsi-h-front-porch = <75>;
+				qcom,mdss-dsi-h-back-porch = <20>;
+				qcom,mdss-dsi-h-pulse-width = <1>;
 				qcom,mdss-dsi-h-sync-skew = <0>;
-				qcom,mdss-dsi-v-back-porch = <13>;
-				qcom,mdss-dsi-v-front-porch = <16>;
-				qcom,mdss-dsi-v-pulse-width = <2>;
+				qcom,mdss-dsi-v-back-porch = <90>;
+				qcom,mdss-dsi-v-front-porch = <5>;
+				qcom,mdss-dsi-v-pulse-width = <1>;
 				qcom,mdss-dsi-panel-framerate = <60>;
 				qcom,mdss-dsi-on-command = [
+					15 01 00 00 00 00 02 B0 04
 					15 01 00 00 00 00 02 B0 00
-					39 01 00 00 00 00 0D B6 30 6B
-						00 06 03 0A 13 1A 6C 18
-						19 02
-					39 01 00 00 00 00 05 B7 11 00 00
+					29 01 00 00 00 00 0D B6 30
+						6B 00 06 03 0A 13
+						1A 6C 18 19 02
+					29 01 00 00 00 00 05 B7 11 00 00
 						00
-					39 01 00 00 00 00 08 B8 57 3D 19
+					29 01 00 00 00 00 08 B8 57 3D 19
 						BE 1E 0A 0A
-					39 01 00 00 00 00 08 B9 6F 3D 28
+					29 01 00 00 00 00 08 B9 6F 3D 28
 						BE 3C 14 0A
-					39 01 00 00 00 00 08 BA B5 33 41
+					29 01 00 00 00 00 08 BA B5 33 41
 						BE 64 23 0A
-					39 01 00 00 00 00 0C BB 44 26 C3
+					29 01 00 00 00 00 0C BB 44 26 C3
 						1F 19 06 03 C0 00 00 10
-					39 01 00 00 00 00 0C BC 32 4C C3
+					29 01 00 00 00 00 0C BC 32 4C C3
 						52 32 1F 03 F2 00 00 13
-					39 01 00 00 00 00 0C BD 24 68 C3
+					29 01 00 00 00 00 0C BD 24 68 C3
 						AA 3F 32 03 FF 00 00 25
-					39 01 00 00 00 00 0D BE 00 00 00
+					29 01 00 00 00 00 0D BE 00 00 00
 						00 00 00 00 00 00 00 00
 						00
-					39 01 00 00 00 00 0D C0 00 D9 01
+					29 01 00 00 00 00 0D C0 00 D9 01
 						2C 06 08 E8 00 06 00 00
 						08
-					39 01 00 00 00 00 24 C1 30 00 00
-						10 11 00 00 00 22 00 05
+					29 01 00 00 00 00 24 C1 30 00 00
+						11 11 00 00 00 22 00 05
 						20 FA 00 08 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
-					39 01 00 00 00 00 79 C2 06 C0 6D
-						01 03 00 02 00 01 20 12
-						01 03 08 F0 00 00 00 00
+					29 01 00 00 00 00 79 C2 06 C0 6D
+						01 03 00 02 02 01 20 12
+						01 03 08 F0 01 00 00 00
 						00 00 00 00 00 01 20 D9
-						04 04 01 00 01 00 28 F1
-						00 00 01 00 00 00 11 00
-						00 00 00 00 00 00 00 00
+						04 04 01 01 01 00 28 F1
+						00 00 01 08 00 00 11 00
+						28 F1 04 00 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 11 00 00 00
 						00 00 00 00 00 00 00 00
@@ -104,7 +105,7 @@
 						00 00 00 00 00 00 11 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00
-					39 01 00 00 00 00 6D C3 01 20 12
+					29 01 00 00 00 00 6D C3 01 20 12
 						01 8F 00 01 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
@@ -119,22 +120,18 @@
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00
-					39 01 00 00 00 00 62 C4 00 00 00
-						00 4F 00 3E 3F 4F 00 00
-						44 06 02 11 11 0F 0F 61
-						61 5F 5F 5D 5D 00 00 00
+					29 01 00 00 00 00 43 C4 00 00 00
 						00 4F 00 3E 3F 4F 00 00
 						44 06 02 10 10 0E 0E 61
+						61 5F 5F 5D 5D 00 00 00
+						00 4F 00 3E 3F 4F 00 00
+						44 06 02 11 11 0F 0F 61
 						61 5F 5F 5D 5D F0 FF FF
 						F0 FF FF E0 FF FF E0 FF
-						FF 10 00 00 10 00 00 00
-						00 00 00 00 00 00 00 00
-						00 00 00 00 00 00 00 00
-						00 00 00 00 00 00 50 00
-						00 00 00 00 00 00
-					39 01 00 00 00 00 06 C5 08 00 00
+						FF 10 00 00 10 00 00
+					29 01 00 00 00 00 06 C5 08 00 00
 						00 00
-					39 01 00 00 00 00 3A C6 09 0A 08
+					29 01 00 00 00 00 3A C6 02 0A 08
 						FC FF FF FF 00 00 13 01
 						FF 0F 22 01 3A 3A 3A 00
 						00 00 01 05 09 28 28 22
@@ -142,15 +139,7 @@
 						21 00 00 00 1C 01 00 00
 						00 00 00 00 00 00 00 00
 						00 00 20 20 00 00
-					39 01 00 00 00 00 3A C6 02 0A 08
-						FC FF FF FF 00 00 13 01
-						FF 0F 22 01 3A 3A 3A 00
-						00 00 01 05 09 28 28 22
-						01 3A 3A 3A 00 00 00 01
-						21 00 00 00 1C 01 00 00
-						00 00 00 00 00 00 00 00
-						00 00 20 20 00 00
-					39 01 00 00 00 00 4D C7 00 00 01
+					29 01 00 00 00 00 4D C7 00 00 01
 						11 02 15 02 AA 02 2E 02
 						B3 03 1A 02 5F 02 78 02
 						97 02 E2 02 2E 02 6B 02
@@ -161,11 +150,20 @@
 						E2 02 2E 02 6B 02 CF 02
 						39 02 D0 03 41 03 96 03
 						A0
-					39 01 00 00 00 00 19 C9 00 00 00
+					29 01 00 00 00 00 42 C8 40 00 00
+						00 00 FF 00 00 00 00 00
+						FF 00 00 00 00 00 FF 00
+						00 00 00 00 FF 00 00 00
+						00 00 FF 00 00 00 00 FF
+						00 00 00 00 FF 00 00 00
+						00 FF 00 00 00 00 FF 00
+						00 00 00 FF 00 00 00 00
+						FF 00 00 00 00 FF
+					29 01 00 00 00 00 19 C9 00 00 00
 						00 FF 00 00 00 00 00 FF
 						00 00 00 00 00 FF 00 00
 						00 00 00 FF 00
-					39 01 00 00 00 00 42 CA 1C FC FC
+					29 01 00 00 00 00 42 CA 1C FC FC
 						FC 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
@@ -174,26 +172,26 @@
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00
-					39 01 00 00 00 00 0C CB A0 00 F0
+					29 01 00 00 00 00 0C CB A0 00 F0
 						00 20 81 00 00 00 00 FF
-					39 01 00 00 00 00 0B CC 00 00 4D
+					29 01 00 00 00 00 0B CC 00 00 4D
 						8B 55 4D 8B AA 4D 8B
-					39 01 00 00 00 00 24 CE 5D 40 49
+					29 01 00 00 00 00 24 CE 5D 40 49
 						53 59 5E 63 68 6E 74 7E
 						8A 98 A8 BB D0 E7 FF 04
 						00 04 04 42 00 69 5A 40
 						11 F4 00 00 04 FA 00 00
-					39 01 00 00 00 00 12 D0 F3 96 11
+					29 01 00 00 00 00 12 D0 F3 96 11
 						B1 55 C9 00 F3 D4 11 F0
 						01 12 C8 02 20 11
-					39 01 00 00 00 00 23 D1 E3 E3 33
+					29 01 00 00 00 00 23 D1 E3 E3 33
 						33 07 03 3B 33 77 37 77
 						37 35 77 07 77 F7 33 73
 						07 33 33 03 33 1B 03 32
 						3D 0A 30 13 13 30 00
-					39 01 00 00 00 00 05 D2 00 00 07
+					29 01 00 00 00 00 05 D2 00 00 07
 						00
-					39 01 00 00 00 00 9A D3 00 00 00
+					29 01 00 00 00 00 9A D3 00 00 00
 						00 00 00 00 00 00 FF F7
 						FF FF F7 FF FF F7 FF FF
 						F7 FF FF F7 FF FF F7 FF
@@ -214,15 +212,15 @@
 						F7 FF FF F7 FF FF F7 FF
 						FF F7 FF FF F7 FF
 					15 01 00 00 00 00 02 E5 0F
-					39 01 00 00 00 00 09 D5 02 31 02
+					29 01 00 00 00 00 09 D5 02 31 02
 						31 02 31 02 31
 					15 01 00 00 00 00 02 D6 00
-					39 01 00 00 00 00 05 DD 30 06 23
+					29 01 00 00 00 00 05 DD 30 06 23
 						65
-					39 01 00 00 00 00 0D DE 00 00 00
+					29 01 00 00 00 00 0D DE 00 00 00
 						0F FF 00 00 00 00 00 00
 						10
-					39 01 00 00 00 00 99 DF 80 80 80
+					29 01 00 00 00 00 99 DF 80 80 80
 						FF FF FF FF FF FF FF 00
 						08 0F 08 08 D3 D3 D3 D3
 						D3 60 60 60 60 60 F5 F5
@@ -243,26 +241,26 @@
 						14 7F 15 01 4B 10 00 24
 						01 00 00 00 00
 					15 01 00 00 00 00 02 E3 FF
-					39 01 00 00 00 00 05 E5 03 7F 00
+					29 01 00 00 00 00 05 E5 03 7F 00
 						00
-					39 01 00 00 00 00 07 E6 00 00 00
+					29 01 00 00 00 00 07 E6 00 00 00
 						00 00 00
-					39 01 00 00 00 00 0B E7 50 00 00
+					29 01 00 00 00 00 0B E7 50 00 00
 						00 00 00 00 00 00 00
-					39 01 00 00 00 00 1E EA 01 02 47
-						40 47 40 00 00 05 00 14
-						C8 00 00 00 00 00 00 00
+					29 01 00 00 00 00 1E EA 01 02 47
+						40 47 40 00 00 05 00 12
+						86 00 00 00 00 00 00 00
 						00 04 C2 00 11 00 30 0D
 						90 86
-					39 01 00 00 00 00 08 EB 00 00 00
+					29 01 00 00 00 00 08 EB 00 00 00
 						00 01 00 11
-					39 01 00 00 00 00 04 EC 00 00 00
-					39 01 00 00 00 00 21 ED 01 01 02
+					29 01 00 00 00 00 04 EC 01 E0 00
+					29 01 00 00 00 00 21 ED 01 01 02
 						02 02 02 00 00 00 00 00
 						00 0A 00 00 00 00 10 00
 						18 00 00 00 B0 00 00 00
 						00 00 D0 10 00
-					39 01 00 00 00 00 61 EE 07 3F F0
+					29 01 00 00 00 00 61 EE 07 3F F0
 						03 00 F0 03 00 00 00 00
 						02 3F FC 00 00 00 00 00
 						00 00 00 00 00 3F 00 00
@@ -275,7 +273,7 @@
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00
-					39 01 00 00 00 00 8C EF 02 30 5D
+					29 01 00 00 00 00 8C EF 02 30 5D
 						09 70 00 00 00 00 2A 2A
 						2A 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
@@ -292,22 +290,20 @@
 						0F 00 03 40 00 00 00 00
 						00 00 00 00 00 00 00 00
 						00 00 00 00 00 00 00 00
-						00 00 00 00 00 00 00 00
-
-				15 01 00 00 00 00 02 B0 00
-				39 01 00 00 00 00 04 BE 00 13 02
+						00 00 00 00 00 03 00 02
+				15 01 00 00 00 00 02 35 00
 				15 01 00 00 00 00 02 B0 04
 				15 01 00 00 00 00 02 D6 00
+				29 01 00 00 00 00 02 B0 03
 				39 01 00 00 00 00 03 51 FF F0
 				15 01 00 00 00 00 02 53 0C
 				15 01 00 00 00 00 02 55 00
-				05 01 00 00 00 00 01 35
 				39 01 00 00 00 00 05 2A 00 00 04 37
 				39 01 00 00 00 00 05 2B 00 00 08 E7
 				39 01 00 00 00 00 05 30 00 00 02 A7
 				15 01 00 00 00 00 02 B0 04
-				05 01 00 00 C8 00 02 11 00
-				05 01 00 00 64 00 02 29 00];
+				05 01 00 00 64 00 02 29 00
+				05 01 00 00 C8 00 02 11 00];
 				qcom,mdss-dsi-off-command = [
 				  05 01 00 00 32 00 02 28 00
 				  05 01 00 00 96 00 02 10 00];
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-trinket.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-trinket.dtsi
index 5dfdfb6..6fab5f5 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-trinket.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-trinket.dtsi
@@ -23,16 +23,20 @@
 		#iommu-cells = <2>;
 		qcom,dynamic;
 		qcom,skip-init;
+		qcom,no-dynamic-asid;
 		qcom,use-3-lvl-tables;
 		#global-interrupts = <1>;
 		qcom,regulator-names = "vdd";
 		vdd-supply = <&gpu_cx_gdsc>;
+		qcom,deferred-regulator-disable-delay = <80>;
 		clocks = <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
 			 <&clock_gcc GCC_GPU_SNOC_DVM_GFX_CLK>,
-			 <&clock_gpucc GPU_CC_AHB_CLK>;
+			 <&clock_gpucc GPU_CC_AHB_CLK>,
+			 <&clock_gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>;
 		clock-names = "gcc_gpu_memnoc_gfx_clk",
 			      "gcc_gpu_snoc_dvm_gfx_clk",
-			      "gpu_cc_ahb_clk";
+			      "gpu_cc_ahb_clk",
+			      "gpu_cc_hlos1_vote_gpu_smmu_clk";
 		#size-cells = <1>;
 		#address-cells = <1>;
 		ranges;
diff --git a/arch/arm64/boot/dts/qcom/pm6125-rpm-regulator.dtsi b/arch/arm64/boot/dts/qcom/pm6125-rpm-regulator.dtsi
index 1a248dd..849b7ae 100644
--- a/arch/arm64/boot/dts/qcom/pm6125-rpm-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6125-rpm-regulator.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
@@ -99,6 +99,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <1>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -115,6 +116,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <2>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -131,6 +133,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <3>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -147,6 +150,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <4>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -163,6 +167,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <5>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -179,6 +184,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <6>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -195,6 +201,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <7>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -212,6 +219,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <8>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -228,6 +236,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <9>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -244,6 +253,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <10>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -260,6 +270,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <11>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -276,6 +287,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <12>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -292,6 +304,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <13>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -308,6 +321,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <14>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -324,6 +338,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <15>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -340,6 +355,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <16>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -356,6 +372,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <17>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -372,6 +389,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <18>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -388,6 +406,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <19>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -404,6 +423,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <20>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -420,6 +440,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <21>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -436,6 +457,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <22>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -452,6 +474,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <23>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -468,6 +491,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <24>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic5-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
diff --git a/arch/arm64/boot/dts/qcom/pm6150.dtsi b/arch/arm64/boot/dts/qcom/pm6150.dtsi
index 381b8bd..60fe030 100644
--- a/arch/arm64/boot/dts/qcom/pm6150.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6150.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
@@ -533,6 +533,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&pm6150_tz>;
+		wake-capable-sensor;
 
 		trips {
 			pm6150_trip0: trip0 {
@@ -558,6 +559,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&pm6150_bcl 0>;
+		wake-capable-sensor;
 
 		trips {
 			ibat_lvl0:ibat-lvl0 {
@@ -573,6 +575,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&pm6150_bcl 1>;
+		wake-capable-sensor;
 
 		trips {
 			ibat_lvl1:ibat-lvl1 {
@@ -588,6 +591,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_cap";
 		thermal-sensors = <&pm6150_bcl 2>;
+		wake-capable-sensor;
 		tracks-low;
 
 		trips {
@@ -604,6 +608,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_cap";
 		thermal-sensors = <&pm6150_bcl 3>;
+		wake-capable-sensor;
 		tracks-low;
 
 		trips {
@@ -620,6 +625,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_cap";
 		thermal-sensors = <&pm6150_bcl 4>;
+		wake-capable-sensor;
 		tracks-low;
 
 		trips {
@@ -636,6 +642,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_cap";
 		thermal-sensors = <&bcl_soc>;
+		wake-capable-sensor;
 		tracks-low;
 
 		trips {
diff --git a/arch/arm64/boot/dts/qcom/pm6150l.dtsi b/arch/arm64/boot/dts/qcom/pm6150l.dtsi
index da4099c..cfd475a 100644
--- a/arch/arm64/boot/dts/qcom/pm6150l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6150l.dtsi
@@ -431,6 +431,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&pm6150l_tz>;
+		wake-capable-sensor;
 
 		trips {
 			pm6150l_trip0: trip0 {
@@ -456,6 +457,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_cap";
 		thermal-sensors = <&pm6150l_bcl 2>;
+		wake-capable-sensor;
 		tracks-low;
 
 		trips {
@@ -472,6 +474,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_cap";
 		thermal-sensors = <&pm6150l_bcl 3>;
+		wake-capable-sensor;
 		tracks-low;
 
 		trips {
@@ -488,6 +491,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_cap";
 		thermal-sensors = <&pm6150l_bcl 4>;
+		wake-capable-sensor;
 		tracks-low;
 
 		trips {
diff --git a/arch/arm64/boot/dts/qcom/pm8008.dtsi b/arch/arm64/boot/dts/qcom/pm8008.dtsi
index 5a6222f..8e85687 100644
--- a/arch/arm64/boot/dts/qcom/pm8008.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8008.dtsi
@@ -12,7 +12,7 @@
 
 #include <dt-bindings/interrupt-controller/irq.h>
 
-qcom,pm8008@8 {
+pm8008_8: qcom,pm8008@8 {
 	compatible = "qcom,i2c-pmic";
 	reg = <0x8>;
 	#address-cells = <1>;
@@ -30,9 +30,19 @@
 		compatible = "qcom,qpnp-revid";
 		reg = <0x100>;
 	};
+
+	pm8008_gpios: pinctrl@c000 {
+		compatible = "qcom,spmi-gpio";
+		reg = <0xc000 0x200>;
+		interrupts = <0x0 0xc0 0 IRQ_TYPE_NONE>,
+				<0x0 0xc1 0 IRQ_TYPE_NONE>;
+		interrupt-names = "pm8008_gpio1", "pm8008_gpio2";
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
 };
 
-qcom,pm8008@9 {
+pm8008_9: qcom,pm8008@9 {
 	compatible = "qcom,i2c-pmic";
 	reg = <0x9>;
 	#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/pm8150l.dtsi b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
index e262faf..5e94780 100644
--- a/arch/arm64/boot/dts/qcom/pm8150l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150l.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
@@ -365,6 +365,14 @@
 			};
 		};
 
+		pm8150l_pwm: qcom,pwms@bc00 {
+			compatible = "qcom,pwm-lpg";
+			reg = <0xbc00 0x200>;
+			reg-names = "lpg-base";
+			#pwm-cells = <2>;
+			qcom,num-lpg-channels = <2>;
+		};
+
 		pm8150l_rgb_led: qcom,leds@d000 {
 			compatible = "qcom,tri-led";
 			reg = <0xd000 0x100>;
diff --git a/arch/arm64/boot/dts/qcom/pmi632.dtsi b/arch/arm64/boot/dts/qcom/pmi632.dtsi
index 719dfe5..6a7b742 100644
--- a/arch/arm64/boot/dts/qcom/pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi632.dtsi
@@ -29,9 +29,6 @@
 		pmi632_pon: qcom,power-on@800 {
 			compatible = "qcom,qpnp-power-on";
 			reg = <0x800 0x100>;
-
-			qcom,secondary-pon-reset;
-			qcom,s3-src = "kpdpwr";
 		};
 
 		pmi632_vadc: vadc@3100 {
diff --git a/arch/arm64/boot/dts/qcom/pms405-rpm-regulator.dtsi b/arch/arm64/boot/dts/qcom/pms405-rpm-regulator.dtsi
index 5b5c9d7..d3227fd 100644
--- a/arch/arm64/boot/dts/qcom/pms405-rpm-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/pms405-rpm-regulator.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
@@ -98,6 +98,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <1>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -114,6 +115,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <2>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -130,6 +132,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <3>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -146,6 +149,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <4>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -162,6 +166,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <5>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -178,6 +183,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <6>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -194,6 +200,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <7>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -210,6 +217,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <8>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -227,6 +235,7 @@
 		qcom,resource-name = "rwlm";
 		qcom,resource-id = <0>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -243,6 +252,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <10>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -259,6 +269,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <11>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -275,6 +286,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <12>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
@@ -291,6 +303,7 @@
 		qcom,resource-name = "ldoa";
 		qcom,resource-id = <13>;
 		qcom,regulator-type = <0>;
+		qcom,regulator-hw-type = "pmic4-ldo";
 		qcom,hpm-min-load = <10000>;
 		status = "disabled";
 
diff --git a/arch/arm64/boot/dts/qcom/qcs401-iot-sku1.dts b/arch/arm64/boot/dts/qcom/qcs401-iot-sku1.dts
new file mode 100644
index 0000000..d5ce85f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs401-iot-sku1.dts
@@ -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.
+ */
+
+/dts-v1/;
+
+#include "qcs401.dtsi"
+#include "qcs405-audio-overlay.dtsi"
+#include "qcs405-circular-pca9956.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS401 EVB2 1000 IOT";
+	compatible = "qcom,qcs401-iot", "qcom,qcs401", "qcom,iot";
+	qcom,board-id = <0x010020 0x3>;
+
+	cpus {
+		/delete-node/ cpu@102;
+		/delete-node/ cpu@103;
+
+		cpu-map {
+			cluster0 {
+				/delete-node/ core2;
+				/delete-node/ core3;
+			};
+		};
+	};
+};
+
+&soc {
+	cpuss_dump {
+		/delete-node/ qcom,l1_i_cache102;
+		/delete-node/ qcom,l1_i_cache103;
+		/delete-node/ qcom,l1_d_cache102;
+		/delete-node/ qcom,l1_d_cache103;
+	};
+
+	qcom,spm@b012000 {
+		qcom,cpu-vctl-list = <&CPU0 &CPU1>;
+	};
+
+	qcom,lpm-levels {
+		qcom,pm-cluster@0{
+			qcom,pm-cpu {
+				qcom,cpu = <&CPU0 &CPU1>;
+			};
+		};
+	};
+
+	/delete-node/ cti@61ba000;
+	/delete-node/ cti@61bb000;
+	/delete-node/ etm@61be000;
+	/delete-node/ etm@61bf000;
+	funnel@61a1000 {
+		ports {
+			/delete-node/ port@3;
+			/delete-node/ port@4;
+		};
+	};
+};
+
+&thermal_zones {
+	cpuss-max-step {
+		cooling-maps {
+			/delete-node/ cpu2_cdev;
+			/delete-node/ cpu3_cdev;
+		};
+	};
+
+	/delete-node/ cpuss-2-step;
+	/delete-node/ cpuss-3-step;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/qcs401.dtsi b/arch/arm64/boot/dts/qcom/qcs401.dtsi
new file mode 100644
index 0000000..39c7712
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs401.dtsi
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#include "qcs405.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS401";
+	qcom,msm-name = "QCS401";
+	qcom,msm-id = <371 0x0>;
+};
+
+&soc {
+	/delete-node/ qcom,msm-cpufreq;
+
+	msm_cpufreq: qcom,msm-cpufreq {
+		compatible = "qcom,msm-cpufreq";
+		clock-names = "cpu0_clk";
+		clocks = <&clock_cpu APCS_MUX_CLK>;
+
+		qcom,cpufreq-table =
+			 < 1094400 >,
+			 < 1248000 >,
+			 < 1401600 >;
+	};
+
+	/delete-node/ qcom,cpu0-computemon;
+
+	cpu0_computemon: qcom,cpu0-computemon {
+		compatible = "qcom,arm-cpu-mon";
+		qcom,cpulist = <&CPU0 &CPU1>;
+		qcom,target-dev = <&cpu0_cpu_ddr_latfloor>;
+		qcom,core-dev-table =
+			< 1094400 MHZ_TO_MBPS( 297, 8) >,
+			< 1248000 MHZ_TO_MBPS( 597, 8) >,
+			< 1401600 MHZ_TO_MBPS( 710, 8) >;
+	};
+};
+
diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts
index b0c067b..bcf65cf 100644
--- a/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts
+++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku1.dts
@@ -82,3 +82,7 @@
 &qnand_1 {
 	status = "ok";
 };
+
+&qseecom_mem {
+	size = <0 0x400000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts
index 09bb106..4220f8e 100644
--- a/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts
+++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku2.dts
@@ -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
@@ -111,7 +111,8 @@
 };
 
 &usb_ss_phy {
-	status = "disabled";
+	status = "ok";
+	qcom,keep-powerdown;
 };
 
 &usb2_phy1 {
diff --git a/arch/arm64/boot/dts/qcom/qcs403-iot-sku3.dts b/arch/arm64/boot/dts/qcom/qcs403-iot-sku3.dts
index b9634fe..637d94c 100644
--- a/arch/arm64/boot/dts/qcom/qcs403-iot-sku3.dts
+++ b/arch/arm64/boot/dts/qcom/qcs403-iot-sku3.dts
@@ -117,7 +117,8 @@
 };
 
 &usb_ss_phy {
-	status = "disabled";
+	status = "ok";
+	qcom,keep-powerdown;
 };
 
 &usb2_phy1 {
diff --git a/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi b/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi
index 7a94f6d..7bc6666 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs405-audio.dtsi
@@ -17,6 +17,7 @@
 &msm_audio_ion {
 	iommus = <&apps_smmu 0x0801 0x0>;
 	qcom,smmu-sid-mask = /bits/ 64 <0xf>;
+	qcom,non-hyp-assign;
 };
 
 &soc {
diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku10.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku10.dts
index daad9fe5..f573c43 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku10.dts
+++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku10.dts
@@ -49,3 +49,14 @@
 	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 };
+
+&soc {
+	spi@78b5000 {
+		status = "ok";
+		spi@0 {
+			compatible = "qcom,spi-msm-codec-slave";
+			reg = <0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku12.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku12.dts
index d234548..9546c43 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku12.dts
+++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku12.dts
@@ -23,3 +23,14 @@
 	compatible = "qcom,qcs405-iot", "qcom,qcs405", "qcom,iot";
 	qcom,board-id = <0x080020 0x1>;
 };
+
+&soc {
+	spi@78b5000 {
+		status = "ok";
+		spi@0 {
+			compatible = "qcom,spi-msm-codec-slave";
+			reg = <0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts
index 066fd00..d7dd2c7 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts
+++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku2.dts
@@ -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
@@ -82,6 +82,16 @@
 		qcom,mdss-fb-map = <&mdss_fb0>;
 	};
 
+	spi@78b5000 {
+		status = "okay";
+
+		spi@0 {
+			compatible = "qcom,spi-msm-codec-slave";
+			reg = <0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+
 	spi@7af5000 {  /* BLSP1 QUP2 */
 		status = "ok";
 		mdss_spi_client: qcom,mdss_spi_client {
@@ -172,6 +182,8 @@
 };
 
 &sdhc_2 {
+	/delete-property/ qcom,nonhotplug;
+
 	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
diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts
index 235dc40..bd92c17 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts
+++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku5.dts
@@ -14,7 +14,7 @@
 /dts-v1/;
 
 #include "qcs405.dtsi"
-#include "qcs405-audio-overlay.dtsi"
+#include "qcs405-nowcd-audio-overlay.dtsi"
 #include "qcs405-geni-ir-overlay.dtsi"
 #include "qcs405-circular-pca9956.dtsi"
 #include "qcs405-mdss-panels.dtsi"
@@ -86,4 +86,12 @@
 	gpio_keys {
 		status = "disabled";
 	};
+	spi@78b5000 {
+		status = "ok";
+		spi@0 {
+			compatible = "qcom,spi-msm-codec-slave";
+			reg = <0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts
index c6b124d..227b8e7 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts
+++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku6.dts
@@ -50,3 +50,14 @@
 	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 };
+
+&soc {
+	spi@78b5000 {
+		status = "ok";
+		spi@0 {
+			compatible = "qcom,spi-msm-codec-slave";
+			reg = <0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts
index 879b5c4..8fa169c 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts
+++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku7.dts
@@ -50,3 +50,14 @@
 	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 };
+
+&soc {
+	spi@78b5000 {
+		status = "ok";
+		spi@0 {
+			compatible = "qcom,spi-msm-codec-slave";
+			reg = <0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts
index 5d8a785d..0f99af0 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts
+++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku8.dts
@@ -50,3 +50,14 @@
 	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 };
+
+&soc {
+	spi@78b5000 {
+		status = "ok";
+		spi@0 {
+			compatible = "qcom,spi-msm-codec-slave";
+			reg = <0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs405-iot-sku9.dts b/arch/arm64/boot/dts/qcom/qcs405-iot-sku9.dts
index 775a158..4e35792 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-iot-sku9.dts
+++ b/arch/arm64/boot/dts/qcom/qcs405-iot-sku9.dts
@@ -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
@@ -60,7 +60,8 @@
 };
 
 &usb_ss_phy {
-	status = "disabled";
+	status = "ok";
+	qcom,keep-powerdown;
 };
 
 &usb2_phy1 {
diff --git a/arch/arm64/boot/dts/qcom/qcs405-linear-pca9956.dtsi b/arch/arm64/boot/dts/qcom/qcs405-linear-pca9956.dtsi
index 6d7d469..aa18e3b 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-linear-pca9956.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs405-linear-pca9956.dtsi
@@ -151,99 +151,99 @@
 		pca9956b,ledout5 = <0xFF>;
 		pca9956b,defaultiref = <0x2f>;
 		out0@0 {
-			label = "ledsec9_b";
+			label = "ledsec13_b";
 			reg = <0x0>;
 		};
 		out1@1 {
-			label = "ledsec9_g";
+			label = "ledsec13_g";
 			reg = <0x1>;
 		};
 		out2@2 {
-			label = "ledsec9_r";
+			label = "ledsec13_r";
 			reg = <0x2>;
 		};
 		out3@3 {
-			label = "ledsec10_b";
+			label = "ledsec14_b";
 			reg = <0x3>;
 		};
 		out4@4 {
-			label = "ledsec10_g";
+			label = "ledsec14_g";
 			reg = <0x4>;
 		};
 		out5@5 {
-			label = "ledsec10_r";
+			label = "ledsec14_r";
 			reg = <0x5>;
 		};
 		out6@6 {
-			label = "ledsec11_b";
+			label = "ledsec15_b";
 			reg = <0x6>;
 		};
 		out7@7 {
-			label = "ledsec11_g";
+			label = "ledsec15_g";
 			reg = <0x7>;
 		};
 		out8@8 {
-			label = "ledsec11_r";
+			label = "ledsec15_r";
 			reg = <0x8>;
 		};
 		out9@9 {
-			label = "ledsec12_b";
+			label = "ledsec16_b";
 			reg = <0x9>;
 		};
 		out10@10 {
-			label = "ledsec12_g";
+			label = "ledsec16_g";
 			reg = <0xA>;
 		};
 		out11@11 {
-			label = "ledsec12_r";
+			label = "ledsec16_r";
 			reg = <0xB>;
 		};
 		out12@12 {
-			label = "ledsec13_b";
+			label = "ledsec9_b";
 			reg = <0xC>;
 		};
 		out13@13 {
-			label = "ledsec13_g";
+			label = "ledsec9_g";
 			reg = <0xD>;
 		};
 		out14@14 {
-			label = "ledsec13_r";
+			label = "ledsec9_r";
 			reg = <0xE>;
 		};
 		out15@15 {
-			label = "ledsec14_b";
+			label = "ledsec10_b";
 			reg = <0xF>;
 		};
 		out16@16 {
-			label = "ledsec14_g";
+			label = "ledsec10_g";
 			reg = <0x10>;
 		};
 		out17@17 {
-			label = "ledsec14_r";
+			label = "ledsec10_r";
 			reg = <0x11>;
 		};
 		out18@18 {
-			label = "ledsec15_b";
+			label = "ledsec11_b";
 			reg = <0x12>;
 		};
 		out19@19 {
-			label = "ledsec15_g";
+			label = "ledsec11_g";
 			reg = <0x13>;
 		};
 		out20@20 {
-			label = "ledsec15_r";
+			label = "ledsec11_r";
 			reg = <0x14>;
 		};
 		out21@21 {
-			label = "ledsec16_b";
+			label = "ledsec12_b";
 			reg = <0x15>;
 		};
 		out22@22 {
-			label = "ledsec16_g";
+			label = "ledsec12_g";
 			reg = <0x16>;
 		};
 		out23@23 {
-			label = "ledsec16_r";
+			label = "ledsec12_r";
 			reg = <0x17>;
 		};
 	};
diff --git a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi b/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi
index acf1b64..b9ca3ff 100644
--- a/arch/arm64/boot/dts/qcom/qcs405-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs405-usb.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
@@ -113,7 +113,7 @@
 		vdda18-supply = <&pms405_l5>;
 		qcom,vdd-voltage-level = <0 1050000 1050000>;
 
-		clocks = <&clock_rpmcc RPM_SMD_LN_BB_CLK>,
+		clocks = <&clock_cmn_blk_pll CMN_BLK_PLL>,
 			 <&clock_gcc GCC_USB_HS_PHY_CFG_AHB_CLK>,
 			 <&clock_gcc GCC_USB3_PHY_PIPE_CLK>;
 		clock-names = "ref_clk", "cfg_ahb_clk", "pipe_clk";
diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi
index db92cc07..ffe6d1f 100644
--- a/arch/arm64/boot/dts/qcom/qcs405.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi
@@ -15,6 +15,7 @@
 #include "skeleton64.dtsi"
 #include <dt-bindings/clock/qcom,gcc-qcs405.h>
 #include <dt-bindings/clock/qcom,cpu-qcs405.h>
+#include <dt-bindings/clock/qcom,cmn-blk-pll.h>
 #include <dt-bindings/clock/qcom,rpmcc.h>
 #include <dt-bindings/regulator/qcom,rpm-smd-regulator.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -315,6 +316,19 @@
 		#reset-cells = <1>;
 	};
 
+	clock_cmn_blk_pll: qcom,cmn_blk_pll@2f780 {
+		compatible = "qcom,cmn_blk_pll";
+		reg = <0x2f780 0x4>;
+		reg-names = "cmn_blk";
+		clocks = <&clock_gcc GCC_BIAS_PLL_MISC_RESET_CLK>,
+			<&clock_gcc GCC_BIAS_PLL_AHB_CLK>,
+			<&clock_gcc GCC_BIAS_PLL_AON_CLK>;
+		clock-names = "misc_reset_clk", "ahb_clk", "aon_clk";
+		resets = <&clock_gcc GCC_BIAS_PLL_BCR>;
+		reset-names = "cmn_blk_pll_reset";
+		#clock-cells = <1>;
+	};
+
 	clock_gcc_mdss: qcom,gcc-mdss@1800000 {
 		compatible = "qcom,gcc-mdss-qcs405";
 		reg = <0x1800000 0x80000>;
@@ -1001,6 +1015,74 @@
 		};
 	};
 
+	qcom_crypto: qcrypto@720000 {
+		 compatible = "qcom,qcrypto";
+		 reg = <0x720000 0x20000>,
+		     <0x704000 0x20000>;
+		 reg-names = "crypto-base","crypto-bam-base";
+		 interrupts = <0 206 0>;
+		 qcom,bam-pipe-pair = <2>;
+		 qcom,ce-hw-instance = <0>;
+		 qcom,ce-device = <0>;
+		 qcom,bam-ee = <0>;
+		 qcom,ce-hw-shared;
+		 qcom,clk-mgmt-sus-res;
+		 qcom,msm-bus,name = "qcrypto-noc";
+		 qcom,msm-bus,num-cases = <2>;
+		 qcom,msm-bus,num-paths = <1>;
+		 qcom,msm-bus,vectors-KBps =
+			 <55 512 0 0>,
+			 <55 512 393600 393600>;
+		clock-names =
+			"core_clk_src", "core_clk",
+			"iface_clk", "bus_clk";
+		clocks =
+			<&clock_rpmcc QCRYPTO_CE1_CLK>,
+			<&clock_rpmcc QCRYPTO_CE1_CLK>,
+			<&clock_rpmcc QCRYPTO_CE1_CLK>,
+			<&clock_rpmcc QCRYPTO_CE1_CLK>;
+		 qcom,use-sw-aes-cbc-ecb-ctr-algo;
+		 qcom,use-sw-aes-xts-algo;
+		 qcom,use-sw-aes-ccm-algo;
+		 qcom,use-sw-ahash-algo;
+		 qcom,use-sw-hmac-algo;
+		 qcom,use-sw-aead-algo;
+		 qcom,smmu-s1-enable;
+		 iommus = <&apps_smmu 0x0064 0x0011>,
+			<&apps_smmu 0x0074 0x0011>;
+	     };
+
+	qcom_cedev: qcedev@720000 {
+		compatible = "qcom,qcedev";
+		reg = <0x720000 0x20000>,
+		    <0x704000 0x20000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 206 0>;
+		qcom,ce-device = <0>;
+		qcom,bam-ee = <0>;
+		qcom,ce-hw-shared;
+		qcom,clk-mgmt-sus-res;
+		qcom,bam-pipe-pair = <3>;
+		qcom,ce-hw-instance = <0>;
+		qcom,msm-bus,name = "qcedev-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<55 512 0 0>,
+			<55 512 393600 393600>;
+		clock-names =
+			"core_clk_src", "core_clk",
+			"iface_clk", "bus_clk";
+		clocks =
+			<&clock_rpmcc QCEDEV_CE1_CLK>,
+			<&clock_rpmcc QCEDEV_CE1_CLK>,
+			<&clock_rpmcc QCEDEV_CE1_CLK>,
+			<&clock_rpmcc QCEDEV_CE1_CLK>;
+		qcom,smmu-s1-enable;
+		iommus = <&apps_smmu 0x0066 0x0011>,
+		       <&apps_smmu 0x0076 0x0011>;
+	    };
+
 	qcom_tzlog: tz-log@8600720 {
 		compatible = "qcom,tz-log";
 		reg = <0x08600720 0x2000>;
@@ -1055,6 +1137,9 @@
 		qcom,hlos-num-ce-hw-instances = <1>;
 		qcom,hlos-ce-hw-instance = <0>;
 		qcom,qsee-ce-hw-instance = <0>;
+		qcom,disk-encrypt-pipe-pair = <2>;
+		qcom,support-fde;
+		qcom,fde-key-size;
 		qcom,no-clock-support;
 		qcom,msm-bus,name = "qseecom-noc";
 		qcom,msm-bus,num-cases = <4>;
@@ -1215,6 +1300,8 @@
 			<&clock_gcc GCC_SDCC2_APPS_CLK>;
 		clock-names = "iface_clk", "core_clk";
 
+		qcom,nonhotplug;
+
 		/* VDD is an external regulator eLDO5 */
 		vdd-io-supply = <&pms405_l11>;
 		qcom,vdd-io-voltage-level = <1800000 2950000>;
diff --git a/arch/arm64/boot/dts/qcom/qcs410-iot-overlay.dts b/arch/arm64/boot/dts/qcom/qcs410-iot-overlay.dts
new file mode 100644
index 0000000..8f774b5
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs410-iot-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/;
+
+#include "qcs410-iot.dtsi"
+
+/ {
+	model = "IOT";
+	compatible = "qcom,qcs410-iot", "qcom,qcs410", "qcom,iot";
+	qcom,msm-id = <406 0x0>;
+	qcom,board-id = <32 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs410-iot.dts b/arch/arm64/boot/dts/qcom/qcs410-iot.dts
new file mode 100644
index 0000000..bac1561
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs410-iot.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/;
+
+#include "qcs410.dtsi"
+#include "qcs410-iot.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS410 IOT";
+	compatible = "qcom,qcs410-iot", "qcom,qcs410", "qcom,iot";
+	qcom,board-id = <32 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi b/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi
new file mode 100644
index 0000000..2ffb6a6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi
@@ -0,0 +1,16 @@
+/* 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.
+ */
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS410 IOT";
+	compatible = "qcom,qcs410-iot", "qcom,qcs410", "qcom,iot";
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs410.dts b/arch/arm64/boot/dts/qcom/qcs410.dts
new file mode 100644
index 0000000..e0b4e468
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs410.dts
@@ -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.
+ */
+
+/dts-v1/;
+
+#include "qcs410.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS410 SoC";
+	compatible = "qcom,qcs410";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs410.dtsi b/arch/arm64/boot/dts/qcom/qcs410.dtsi
new file mode 100644
index 0000000..0e9baa1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs410.dtsi
@@ -0,0 +1,137 @@
+/* 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 "sm6150.dtsi"
+#include "sm6150-pm.dtsi"
+#include "sm6150-thermal-overlay.dtsi"
+#include "sm6150-thermal.dtsi"
+#include "sm6150-coresight.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS410 SoC";
+	qcom,msm-name = "QCS410";
+	qcom,msm-id = <406 0>;
+
+	cpus {
+		/delete-node/ cpu@200;
+		/delete-node/ cpu@300;
+		/delete-node/ cpu@400;
+		/delete-node/ cpu@500;
+
+		cpu-map {
+			cluster0 {
+				/delete-node/ core2;
+				/delete-node/ core3;
+				/delete-node/ core4;
+				/delete-node/ core5;
+			};
+		};
+	};
+};
+
+&soc {
+	qcom,lpm-levels {
+		qcom,pm-cluster@0 {
+			 qcom,pm-cpu@0 {
+				qcom,cpu = <&CPU0 &CPU1>;
+			};
+		};
+	};
+
+	dsu_pmu@0 {
+		cpus = <&CPU0>, <&CPU1>, <&CPU6>, <&CPU7>;
+	};
+
+	qcom,chd_silver {
+		compatible = "qcom,core-hang-detect";
+		label = "silver";
+		qcom,threshold-arr = <0x18000058 0x18010058>;
+		qcom,config-arr = <0x18000060 0x18010060>;
+	};
+
+	/delete-node/ cti@7220000;
+	/delete-node/ cti@7320000;
+	/delete-node/ cti@7420000;
+	/delete-node/ cti@7520000;
+	/delete-node/ etm@7240000;
+	/delete-node/ etm@7340000;
+	/delete-node/ etm@7440000;
+	/delete-node/ etm@7540000;
+	cpuss_dump {
+		/delete-node/ qcom,l1_i_cache200;
+		/delete-node/ qcom,l1_i_cache300;
+		/delete-node/ qcom,l1_i_cache400;
+		/delete-node/ qcom,l1_i_cache500;
+		/delete-node/ qcom,l1_d_cache200;
+		/delete-node/ qcom,l1_d_cache300;
+		/delete-node/ qcom,l1_d_cache400;
+		/delete-node/ qcom,l1_d_cache500;
+		/delete-node/ qcom,l2_tlb_dump200;
+		/delete-node/ qcom,l2_tlb_dump300;
+		/delete-node/ qcom,l2_tlb_dump400;
+		/delete-node/ qcom,l2_tlb_dump500;
+	};
+
+	qcom,cpu0-cpu-l3-latmon {
+		qcom,cpulist = <&CPU0 &CPU1>;
+	};
+
+	qcom,cpu0-cpu-llcc-latmon {
+		qcom,cpulist = <&CPU0 &CPU1>;
+	};
+
+	qcom,cpu0-llcc-ddr-latmon {
+		qcom,cpulist = <&CPU0 &CPU1>;
+	};
+
+	qcom,cpu0-computemon {
+		qcom,cpulist = <&CPU0 &CPU1>;
+	};
+
+	funnel@7800000 {
+			ports {
+				/delete-node/ port@3;
+				/delete-node/ port@4;
+				/delete-node/ port@5;
+				/delete-node/ port@6;
+			};
+	};
+};
+
+&thermal_zones {
+	pm6150l-tz {
+		cooling-maps {
+			/delete-node/ trip0_cpu2;
+			/delete-node/ trip0_cpu3;
+			/delete-node/ trip0_cpu4;
+			/delete-node/ trip0_cpu5;
+			/delete-node/ trip1_cpu2;
+			/delete-node/ trip1_cpu3;
+			/delete-node/ trip1_cpu4;
+			/delete-node/ trip1_cpu5;
+		};
+	};
+	cpuss-0-step {
+		/delete-node/ cooling-maps;
+	};
+	cpuss-1-step {
+		/delete-node/ cooling-maps;
+	};
+	quiet-therm-step {
+		cooling-maps {
+			/delete-node/ skin_cpu2;
+			/delete-node/ skin_cpu3;
+			/delete-node/ skin_cpu4;
+			/delete-node/ skin_cpu5;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs610-iot-overlay.dts b/arch/arm64/boot/dts/qcom/qcs610-iot-overlay.dts
new file mode 100644
index 0000000..44af227
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs610-iot-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/;
+
+#include "qcs610-iot.dtsi"
+
+/ {
+	model = "IOT";
+	compatible = "qcom,qcs610-iot", "qcom,qcs610", "qcom,iot";
+	qcom,msm-id = <401 0x0>;
+	qcom,board-id = <32 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs610-iot.dts b/arch/arm64/boot/dts/qcom/qcs610-iot.dts
new file mode 100644
index 0000000..15dcd26
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs610-iot.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/;
+
+#include "qcs610.dtsi"
+#include "qcs610-iot.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS610 IOT";
+	compatible = "qcom,qcs610-iot", "qcom,qcs610", "qcom,iot";
+	qcom,board-id = <32 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi b/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi
new file mode 100644
index 0000000..df6f191
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs610-iot.dtsi
@@ -0,0 +1,18 @@
+/* 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.
+ */
+
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS610 IOT";
+	compatible = "qcom,qcs610-iot", "qcom,qcs610", "qcom,iot";
+	qcom,board-id = <32 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs610.dts b/arch/arm64/boot/dts/qcom/qcs610.dts
new file mode 100644
index 0000000..d870642
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs610.dts
@@ -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.
+ */
+
+/dts-v1/;
+
+#include "qcs610.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS610 SoC";
+	compatible = "qcom,qcs610";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs610.dtsi b/arch/arm64/boot/dts/qcom/qcs610.dtsi
new file mode 100644
index 0000000..39f0aed
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs610.dtsi
@@ -0,0 +1,19 @@
+/* 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 "sm6150.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS610";
+	qcom,msm-name = "QCS610";
+	qcom,msm-id = <401 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sa6155-adp-air-overlay.dts b/arch/arm64/boot/dts/qcom/sa6155-adp-air-overlay.dts
index 33fc370..72a605e 100644
--- a/arch/arm64/boot/dts/qcom/sa6155-adp-air-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155-adp-air-overlay.dts
@@ -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,5 +21,5 @@
 	model = "Qualcomm Technologies, Inc. SA6155 ADP-AIR";
 	compatible = "qcom,sa6155-adp-air", "qcom,sa6155", "qcom,adp-air";
 	qcom,msm-id = <384 0x0>;
-	qcom,board-id = <0x03000019 0>;
+	qcom,board-id = <0x03010019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155-adp-air.dts b/arch/arm64/boot/dts/qcom/sa6155-adp-air.dts
index dd9f327..bff3d52 100644
--- a/arch/arm64/boot/dts/qcom/sa6155-adp-air.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155-adp-air.dts
@@ -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
@@ -17,5 +17,5 @@
 / {
 	model = "Qualcomm Technologies, Inc. SA6155 ADP-AIR";
 	compatible = "qcom,sa6155-adp-air", "qcom,sa6155", "qcom,adp-air";
-	qcom,board-id = <0x03000019 0>;
+	qcom,board-id = <0x03010019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155-adp-air.dtsi b/arch/arm64/boot/dts/qcom/sa6155-adp-air.dtsi
index 5bbcabd..8f36a86 100644
--- a/arch/arm64/boot/dts/qcom/sa6155-adp-air.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa6155-adp-air.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
@@ -90,7 +90,8 @@
 		"dev-emac-rgmii_rxd2_state", "dev-emac-rgmii_rxd3_state",
 		"dev-emac-rgmii_rxc_state", "dev-emac-rgmii_rx_ctl_state",
 		"dev-emac-phy_intr", "dev-emac-phy_reset_state",
-		"dev-emac_pin_pps_0";
+		"dev-emac_pin_pps_0", "dev-emac-rgmii_rxc_suspend_state",
+		"dev-emac-rgmii_rxc_resume_state";
 
 		pinctrl-0 = <&emac_mdc>;
 		pinctrl-1 = <&emac_mdio>;
@@ -109,6 +110,8 @@
 		pinctrl-14 = <&emac_phy_intr>;
 		pinctrl-15 = <&emac_phy_reset_state>;
 		pinctrl-16 = <&emac_pin_pps_0>;
+		pinctrl-17 = <&emac_rgmii_rxc_suspend>;
+		pinctrl-18 = <&emac_rgmii_rxc_resume>;
 
 		io-macro-info {
 			io-macro-bypass-mode = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sa6155-adp-star-overlay.dts b/arch/arm64/boot/dts/qcom/sa6155-adp-star-overlay.dts
index 3593457..4eb2f21 100644
--- a/arch/arm64/boot/dts/qcom/sa6155-adp-star-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155-adp-star-overlay.dts
@@ -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,5 +21,5 @@
 	model = "Qualcomm Technologies, Inc. SA6155 ADP-STAR";
 	compatible = "qcom,sa6155-adp-star", "qcom,sa6155", "qcom,adp-star";
 	qcom,msm-id = <384 0x0>;
-	qcom,board-id = <25 0>;
+	qcom,board-id = <0x10019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155-adp-star.dts b/arch/arm64/boot/dts/qcom/sa6155-adp-star.dts
index 1cea61a..488ca5c 100644
--- a/arch/arm64/boot/dts/qcom/sa6155-adp-star.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155-adp-star.dts
@@ -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
@@ -17,5 +17,5 @@
 / {
 	model = "Qualcomm Technologies, Inc. SA6155 ADP-STAR";
 	compatible = "qcom,sa6155-adp-star", "qcom,sa6155", "qcom,adp-star";
-	qcom,board-id = <25 0>;
+	qcom,board-id = <0x10019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155-adp-star.dtsi b/arch/arm64/boot/dts/qcom/sa6155-adp-star.dtsi
index 2680c0e..05403d3 100644
--- a/arch/arm64/boot/dts/qcom/sa6155-adp-star.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa6155-adp-star.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
@@ -90,7 +90,8 @@
 		"dev-emac-rgmii_rxd2_state", "dev-emac-rgmii_rxd3_state",
 		"dev-emac-rgmii_rxc_state", "dev-emac-rgmii_rx_ctl_state",
 		"dev-emac-phy_intr", "dev-emac-phy_reset_state",
-		"dev-emac_pin_pps_0";
+		"dev-emac_pin_pps_0", "dev-emac-rgmii_rxc_suspend_state",
+		"dev-emac-rgmii_rxc_resume_state";
 
 		pinctrl-0 = <&emac_mdc>;
 		pinctrl-1 = <&emac_mdio>;
@@ -109,6 +110,8 @@
 		pinctrl-14 = <&emac_phy_intr>;
 		pinctrl-15 = <&emac_phy_reset_state>;
 		pinctrl-16 = <&emac_pin_pps_0>;
+		pinctrl-17 = <&emac_rgmii_rxc_suspend>;
+		pinctrl-18 = <&emac_rgmii_rxc_resume>;
 
 		io-macro-info {
 			io-macro-bypass-mode = <0>;
@@ -191,15 +194,30 @@
 };
 
 &usb0 {
+	qcom,default-mode-none;
 	qcom,host-poweroff-in-pm-suspend;
 };
 
+&qusb_phy0 {
+	qcom,usb-hs-ac-bitmask = <0x30>;
+	qcom,usb-hs-ac-value = <0x10>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb0_hs_ac_en_default>;
+};
+
 &usb1 {
 	status = "ok";
 	qcom,default-mode-host;
 	qcom,host-poweroff-in-pm-suspend;
 };
 
+&qusb_phy1 {
+	qcom,usb-hs-ac-bitmask = <0xc0>;
+	qcom,usb-hs-ac-value = <0x40>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb1_hs_ac_en_default>;
+};
+
 &qupv3_se0_2uart {
 	status = "ok";
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155-audio.dtsi b/arch/arm64/boot/dts/qcom/sa6155-audio.dtsi
index 98508e0..6e7f890 100644
--- a/arch/arm64/boot/dts/qcom/sa6155-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa6155-audio.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
@@ -10,6 +10,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+#include "sm6150-lpi.dtsi"
 
 &soc {
 	qcom,msm-dai-tdm-pri-rx {
@@ -254,7 +255,7 @@
 		qcom,msm-cpudai-tdm-group-id = <37168>;
 		qcom,msm-cpudai-tdm-group-num-ports = <4>;
 		qcom,msm-cpudai-tdm-group-port-id = <36912 36914 36916 36918>;
-		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-rate = <24576000>;
 		qcom,msm-cpudai-tdm-clk-internal = <1>;
 		qcom,msm-cpudai-tdm-sync-mode = <1>;
 		qcom,msm-cpudai-tdm-sync-src = <1>;
@@ -396,6 +397,14 @@
 			qcom,msm-cpudai-tdm-data-align = <0>;
 		};
 	};
+
+	dai_pri_auxpcm: qcom,msm-pri-auxpcm {
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&pri_aux_pcm_sck_active &pri_aux_pcm_ws_active
+			&pri_aux_pcm_data0_active &pri_aux_pcm_data1_active>;
+		pinctrl-1 = <&pri_aux_pcm_sck_sleep &pri_aux_pcm_ws_sleep
+			&pri_aux_pcm_data0_sleep &pri_aux_pcm_data1_sleep>;
+	};
 };
 
 &audio_apr {
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-adp-air-overlay.dts b/arch/arm64/boot/dts/qcom/sa6155p-adp-air-overlay.dts
index 6d79a17..2d61e9f8 100644
--- a/arch/arm64/boot/dts/qcom/sa6155p-adp-air-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155p-adp-air-overlay.dts
@@ -22,5 +22,5 @@
 	model = "Qualcomm Technologies, Inc. SA6155P ADP-AIR";
 	compatible = "qcom,sa6155p-adp-air", "qcom,sa6155p", "qcom,adp-air";
 	qcom,msm-id = <377 0x0>, <380 0>;
-	qcom,board-id = <0x03000019 0>;
+	qcom,board-id = <0x03010019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-adp-air.dts b/arch/arm64/boot/dts/qcom/sa6155p-adp-air.dts
index 42eeeed..45096df 100644
--- a/arch/arm64/boot/dts/qcom/sa6155p-adp-air.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155p-adp-air.dts
@@ -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
@@ -18,5 +18,5 @@
 / {
 	model = "Qualcomm Technologies, Inc. SA6155P ADP-AIR";
 	compatible = "qcom,sa6155p-adp-air", "qcom,sa6155p", "qcom,adp-air";
-	qcom,board-id = <0x03000019 0>;
+	qcom,board-id = <0x03010019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-adp-star-overlay.dts b/arch/arm64/boot/dts/qcom/sa6155p-adp-star-overlay.dts
index 4e52cf4..af524de 100644
--- a/arch/arm64/boot/dts/qcom/sa6155p-adp-star-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155p-adp-star-overlay.dts
@@ -22,5 +22,5 @@
 	model = "Qualcomm Technologies, Inc. SA6155P ADP-STAR";
 	compatible = "qcom,sa6155p-adp-star", "qcom,sa6155p", "qcom,adp-star";
 	qcom,msm-id = <377 0x0>, <380 0>;
-	qcom,board-id = <25 0>;
+	qcom,board-id = <0x10019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-adp-star.dts b/arch/arm64/boot/dts/qcom/sa6155p-adp-star.dts
index 3ff625a..745b4a8 100644
--- a/arch/arm64/boot/dts/qcom/sa6155p-adp-star.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155p-adp-star.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* 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
@@ -18,5 +18,5 @@
 / {
 	model = "Qualcomm Technologies, Inc. SA6155P ADP-STAR";
 	compatible = "qcom,sa6155p-adp-star", "qcom,sa6155p", "qcom,adp-star";
-	qcom,board-id = <25 0>;
+	qcom,board-id = <0x10019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-air-overlay.dts b/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-air-overlay.dts
index 40b2766..7e1af62 100644
--- a/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-air-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-air-overlay.dts
@@ -22,5 +22,5 @@
 	model = "Qualcomm Technologies, Inc. SA6155P ADP-AIR V2";
 	compatible = "qcom,sa6155p-adp-air", "qcom,sa6155p", "qcom,adp-air";
 	qcom,msm-id = <377 0x0>, <380 0>;
-	qcom,board-id = <0x03010019 0>;
+	qcom,board-id = <0x03020019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-air.dts b/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-air.dts
index 28050b4..9227291 100644
--- a/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-air.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-air.dts
@@ -18,5 +18,5 @@
 / {
 	model = "Qualcomm Technologies, Inc. SA6155P ADP-AIR V2";
 	compatible = "qcom,sa6155p-adp-air", "qcom,sa6155p", "qcom,adp-air";
-	qcom,board-id = <0x03010019 0>;
+	qcom,board-id = <0x03020019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-star-overlay.dts b/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-star-overlay.dts
index 9207b50..c2d16fa 100644
--- a/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-star-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-star-overlay.dts
@@ -22,5 +22,5 @@
 	model = "Qualcomm Technologies, Inc. SA6155P ADP-STAR V2";
 	compatible = "qcom,sa6155p-adp-star", "qcom,sa6155p", "qcom,adp-star";
 	qcom,msm-id = <377 0x0>, <380 0>;
-	qcom,board-id = <0x010019 0>;
+	qcom,board-id = <0x020019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-star.dts b/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-star.dts
index 45338ae..00a8980 100644
--- a/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-star.dts
+++ b/arch/arm64/boot/dts/qcom/sa6155p-v2-adp-star.dts
@@ -18,5 +18,5 @@
 / {
 	model = "Qualcomm Technologies, Inc. SA6155P ADP-STAR V2";
 	compatible = "qcom,sa6155p-adp-star", "qcom,sa6155p", "qcom,adp-star";
-	qcom,board-id = <0x010019 0>;
+	qcom,board-id = <0x020019 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-vm-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sa6155p-vm-pinctrl.dtsi
new file mode 100644
index 0000000..cd591f8e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa6155p-vm-pinctrl.dtsi
@@ -0,0 +1,1783 @@
+/* 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.
+ */
+
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+
+&soc {
+	tlmm: pinctrl@03000000 {
+		compatible = "qcom,sm6150-pinctrl";
+		reg = <0x03000000 0xdc2000>, <0x17c000f0 0x60>;
+		reg-names = "pinctrl", "spi_cfg";
+		interrupts = <0 208 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		ufs_dev_reset_assert: ufs_dev_reset_assert {
+			config {
+				pins = "ufs_reset";
+				bias-pull-down;		/* default: pull down */
+				/*
+				 * UFS_RESET driver strengths are having
+				 * different values/steps compared to typical
+				 * GPIO drive strengths.
+				 *
+				 * Following table clarifies:
+				 *
+				 * HDRV value | UFS_RESET | Typical GPIO
+				 *   (dec)    |   (mA)    |    (mA)
+				 *     0      |   0.8     |    2
+				 *     1      |   1.55    |    4
+				 *     2      |   2.35    |    6
+				 *     3      |   3.1     |    8
+				 *     4      |   3.9     |    10
+				 *     5      |   4.65    |    12
+				 *     6      |   5.4     |    14
+				 *     7      |   6.15    |    16
+				 *
+				 * POR value for UFS_RESET HDRV is 3 which means
+				 * 3.1mA and we want to use that. Hence just
+				 * specify 8mA to "drive-strength" binding and
+				 * that should result into writing 3 to HDRV
+				 * field.
+				 */
+				drive-strength = <8>;	/* default: 3.1 mA */
+				output-low; /* active low reset */
+			};
+		};
+
+		ufs_dev_reset_deassert: ufs_dev_reset_deassert {
+			config {
+				pins = "ufs_reset";
+				bias-pull-down;		/* default: pull down */
+				/*
+				 * default: 3.1 mA
+				 * check comments under ufs_dev_reset_assert
+				 */
+				drive-strength = <8>;
+				output-high; /* active low reset */
+			};
+		};
+
+		/* QUPv3_0 South SE mappings */
+		/* SE 0 pin mappings */
+		qupv3_se0_2uart_pins: qupv3_se0_2uart_pins {
+			qupv3_se0_2uart_active: qupv3_se0_2uart_active {
+				mux {
+					pins = "gpio16", "gpio17";
+					function = "qup00";
+				};
+
+				config {
+					pins = "gpio16", "gpio17";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se0_2uart_sleep: qupv3_se0_2uart_sleep {
+				mux {
+					pins = "gpio16", "gpio17";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio16", "gpio17";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		/* SE 1 pin mappings */
+		qupv3_se1_i2c_pins: qupv3_se1_i2c_pins {
+			qupv3_se1_i2c_active: qupv3_se1_i2c_active {
+				mux {
+					pins = "gpio4", "gpio5";
+					function = "qup01";
+				};
+
+				config {
+					pins = "gpio4", "gpio5";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se1_i2c_sleep: qupv3_se1_i2c_sleep {
+				mux {
+					pins = "gpio4", "gpio5";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio4", "gpio5";
+					drive-strength = <2>;
+					bias-no-pull;
+				};
+			};
+		};
+
+		/* SE 2 pin mappings */
+		qupv3_se2_i2c_pins: qupv3_se2_i2c_pins {
+			qupv3_se2_i2c_active: qupv3_se2_i2c_active {
+				mux {
+					pins = "gpio0", "gpio1";
+					function = "qup02";
+				};
+
+				config {
+					pins = "gpio0", "gpio1";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se2_i2c_sleep: qupv3_se2_i2c_sleep {
+				mux {
+					pins = "gpio0", "gpio1";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio0", "gpio1";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		qupv3_se2_spi_pins: qupv3_se2_spi_pins {
+			qupv3_se2_spi_active: qupv3_se2_spi_active {
+				mux {
+					pins = "gpio0", "gpio1", "gpio2",
+								"gpio3";
+					function = "qup02";
+				};
+
+				config {
+					pins = "gpio0", "gpio1", "gpio2",
+								"gpio3";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se2_spi_sleep: qupv3_se2_spi_sleep {
+				mux {
+					pins = "gpio0", "gpio1", "gpio2",
+								"gpio3";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio0", "gpio1", "gpio2",
+								"gpio3";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+		};
+
+		fpc_reset_int {
+			fpc_reset_low: reset_low {
+				mux {
+					pins = "gpio101";
+					function = "fpc_reset_gpio_low";
+				};
+				config {
+					pins = "gpio101";
+					drive-strength = <2>;
+					bias-disable;
+					output-low;
+					};
+			};
+
+			fpc_reset_high: reset_high {
+				mux {
+					pins = "gpio101";
+					function = "fpc_reset_gpio_high";
+				};
+
+				config {
+					pins = "gpio101";
+					drive-strength = <2>;
+					bias-disable;
+					output-high;
+				};
+			};
+
+			fpc_int_low: int_low {
+				mux {
+					pins = "gpio93";
+				};
+				config {
+					pins = "gpio93";
+					drive-strength = <2>;
+					bias-pull-down;
+					input-enable;
+				};
+			};
+		};
+
+		/* SE 3 pin mappings */
+		qupv3_se3_i2c_pins: qupv3_se3_i2c_pins {
+			qupv3_se3_i2c_active: qupv3_se3_i2c_active {
+				mux {
+					pins = "gpio18", "gpio19";
+					function = "qup03";
+				};
+
+				config {
+					pins = "gpio18", "gpio19";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se3_i2c_sleep: qupv3_se3_i2c_sleep {
+				mux {
+					pins = "gpio18", "gpio19";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio18", "gpio19";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		/* QUPv3_1 North instances */
+		/* SE 4 pin mappings */
+		qupv3_se4_i2c_pins: qupv3_se4_i2c_pins {
+			qupv3_se4_i2c_active: qupv3_se4_i2c_active {
+				mux {
+					pins = "gpio20", "gpio21";
+					function = "qup10";
+				};
+
+				config {
+					pins = "gpio20", "gpio21";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se4_i2c_sleep: qupv3_se4_i2c_sleep {
+				mux {
+					pins = "gpio20", "gpio21";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio20", "gpio21";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		qupv3_se4_spi_pins: qupv3_se4_spi_pins {
+			qupv3_se4_spi_active: qupv3_se4_spi_active {
+				mux {
+					pins = "gpio20", "gpio21", "gpio22",
+								"gpio23";
+					function = "qup10";
+				};
+
+				config {
+					pins = "gpio20", "gpio21", "gpio22",
+								"gpio23";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se4_spi_sleep: qupv3_se4_spi_sleep {
+				mux {
+					pins = "gpio20", "gpio21", "gpio22",
+								"gpio23";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio20", "gpio21", "gpio22",
+								"gpio23";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+		};
+
+		/* SE 5 pin mappings */
+		qupv3_se5_i2c_pins: qupv3_se5_i2c_pins {
+			qupv3_se5_i2c_active: qupv3_se5_i2c_active {
+				mux {
+					pins = "gpio14", "gpio15";
+					function = "qup11";
+				};
+
+				config {
+					pins = "gpio14", "gpio15";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se5_i2c_sleep: qupv3_se5_i2c_sleep {
+				mux {
+					pins = "gpio14", "gpio15";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio14", "gpio15";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		nfc {
+			nfc_int_active: nfc_int_active {
+				/* active state */
+				mux {
+					/* GPIO 86 NFC Read Interrupt */
+					pins = "gpio86";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio86";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
+			};
+
+			nfc_int_suspend: nfc_int_suspend {
+				/* sleep state */
+				mux {
+					/* GPIO 86 NFC Read Interrupt */
+					pins = "gpio86";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio86";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
+			};
+
+			nfc_enable_active: nfc_enable_active {
+				/* active state */
+				mux {
+					/* 84: Enable 85: Firmware */
+					pins = "gpio84", "gpio85";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio84", "gpio85";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
+			};
+
+			nfc_enable_suspend: nfc_enable_suspend {
+				/* sleep state */
+				mux {
+					/* 84: Enable 85: Firmware */
+					pins = "gpio84", "gpio85";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio84", "gpio85";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable;
+				};
+			};
+
+			nfc_clk_req_active: nfc_clk_req_active {
+				/* active state */
+				mux {
+					/* GPIO 50: NFC CLOCK REQUEST */
+					pins = "gpio50";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio50";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
+			};
+
+			nfc_clk_req_suspend: nfc_clk_req_suspend {
+				/* sleep state */
+				mux {
+					/* GPIO 50: NFC CLOCK REQUEST */
+					pins = "gpio50";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio50";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable;
+				};
+			};
+		};
+
+		/* SE 6 pin mappings */
+		qupv3_se6_i2c_pins: qupv3_se6_i2c_pins {
+			qupv3_se6_i2c_active: qupv3_se6_i2c_active {
+				mux {
+					pins = "gpio6", "gpio7";
+					function = "qup12";
+				};
+
+				config {
+					pins = "gpio6", "gpio7";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se6_i2c_sleep: qupv3_se6_i2c_sleep {
+				mux {
+					pins = "gpio6", "gpio7";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio6", "gpio7";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		qupv3_se6_spi_pins: qupv3_se6_spi_pins {
+			qupv3_se6_spi_active: qupv3_se6_spi_active {
+				mux {
+					pins = "gpio6", "gpio7", "gpio8",
+								"gpio9";
+					function = "qup12";
+				};
+
+				config {
+					pins = "gpio6", "gpio7", "gpio8",
+								"gpio9";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se6_spi_sleep: qupv3_se6_spi_sleep {
+				mux {
+					pins = "gpio6", "gpio7", "gpio8",
+								"gpio9";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio6", "gpio7", "gpio8",
+								"gpio9";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+		};
+
+		/* SE 7 pin mappings */
+		qupv3_se7_i2c_pins: qupv3_se7_i2c_pins {
+			qupv3_se7_i2c_active: qupv3_se7_i2c_active {
+				mux {
+					pins = "gpio10", "gpio11";
+					function = "qup13";
+				};
+
+				config {
+					pins = "gpio10", "gpio11";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se7_i2c_sleep: qupv3_se7_i2c_sleep {
+				mux {
+					pins = "gpio10", "gpio11";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio10", "gpio11";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		qupv3_se7_spi_pins: qupv3_se7_spi_pins {
+			qupv3_se7_spi_active: qupv3_se7_spi_active {
+				mux {
+					pins = "gpio10", "gpio11", "gpio12",
+								"gpio13";
+					function = "qup13";
+				};
+
+				config {
+					pins = "gpio10", "gpio11", "gpio12",
+								"gpio13";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se7_spi_sleep: qupv3_se7_spi_sleep {
+				mux {
+					pins = "gpio10", "gpio11", "gpio12",
+								"gpio13";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio10", "gpio11", "gpio12",
+								"gpio13";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+		};
+
+		qupv3_se7_4uart_pins: qupv3_se7_4uart_pins {
+			qupv3_se7_ctsrx: qupv3_se7_ctsrx {
+				mux {
+					pins = "gpio10", "gpio13";
+					function = "qup13";
+				};
+
+				config {
+					pins = "gpio10", "gpio13";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			qupv3_se7_rts: qupv3_se7_rts {
+				mux {
+					pins = "gpio11";
+					function = "qup13";
+				};
+
+				config {
+					pins = "gpio11";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+
+			qupv3_se7_tx: qupv3_se7_tx {
+				mux {
+					pins = "gpio12";
+					function = "qup13";
+				};
+
+				config {
+					pins = "gpio12";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		pmx_sde: pmx_sde {
+			sde_dsi_active: sde_dsi_active {
+				mux {
+					pins = "gpio91";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio91";
+					drive-strength = <8>;   /* 8 mA */
+					bias-disable = <0>;   /* no pull */
+				};
+			};
+
+			sde_dsi_suspend: sde_dsi_suspend {
+				mux {
+					pins = "gpio91";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio91";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+		};
+
+		fsa_usbc_ana_en_n@114 {
+			fsa_usbc_ana_en: fsa_usbc_ana_en {
+				mux {
+					pins = "gpio114";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio114";
+					drive-strength = <2>;
+					bias-disable;
+					output-low;
+				};
+			};
+		};
+
+		pmx_sde_te {
+			sde_te_active: sde_te_active {
+				mux {
+					pins = "gpio90";
+					function = "mdp_vsync";
+				};
+
+				config {
+					pins = "gpio90";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+
+			sde_te_suspend: sde_te_suspend {
+				mux {
+					pins = "gpio90";
+					function = "mdp_vsync";
+				};
+
+				config {
+					pins = "gpio90";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+		};
+
+		sde_dp_usbplug_cc_active: sde_dp_usbplug_cc_active {
+			mux {
+				pins = "gpio104";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio104";
+				bias-disable;
+				drive-strength = <16>;
+			};
+		};
+
+		sde_dp_usbplug_cc_suspend: sde_dp_usbplug_cc_suspend {
+			mux {
+				pins = "gpio104";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio104";
+				bias-pull-down;
+				drive-strength = <2>;
+			};
+		};
+
+		sde_dp_switch_active: sde_dp_switch_active {
+			mux {
+				pins = "gpio49";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio49";
+				bias-pull-up;		/* pull up */
+				output-high;
+				drive-strength = <2>;
+			};
+		};
+
+		sde_dp_switch_suspend: sde_dp_switch_suspend {
+			mux {
+				pins = "gpio49";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio49";
+				bias-pull-down;
+				output-low;
+				drive-strength = <2>;
+			};
+		};
+
+		sde_dp_connector_enable: sde_dp_connector_enable {
+			mux {
+				pins = "gpio44";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio44";
+				bias-pull-up;
+				output-high;
+				drive-strength = <2>;
+			};
+		};
+
+		sde_dp_hotplug_ctrl: sde_dp_hotplug_ctrl {
+			mux {
+				pins = "gpio103";
+				function = "debug_hot";
+			};
+
+			config {
+				pins = "gpio103";
+				bias-disable;
+				input-enable;
+				drive-strength = <2>;
+			};
+		};
+
+		sde_dp_hotplug_tlmm: sde_dp_hotplug_tlmm {
+			mux {
+				pins = "gpio103";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio103";
+				bias-disable;
+				input-enable;
+				drive-strength = <2>;
+			};
+		};
+
+
+
+		/* SDC pin type */
+		sdc1_clk_on: sdc1_clk_on {
+			config {
+				pins = "sdc1_clk";
+				bias-disable;		/* NO pull */
+				drive-strength = <16>;	/* 16 MA */
+			};
+		};
+
+		sdc1_clk_off: sdc1_clk_off {
+			config {
+				pins = "sdc1_clk";
+				bias-disable;		/* NO pull */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc1_cmd_on: sdc1_cmd_on {
+			config {
+				pins = "sdc1_cmd";
+				bias-pull-up;		/* pull up */
+				drive-strength = <10>;	/* 10 MA */
+			};
+		};
+
+		sdc1_cmd_off: sdc1_cmd_off {
+			config {
+				pins = "sdc1_cmd";
+				num-grp-pins = <1>;
+				bias-pull-up;		/* pull up */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc1_data_on: sdc1_data_on {
+			config {
+				pins = "sdc1_data";
+				bias-pull-up;		/* pull up */
+				drive-strength = <10>;	/* 10 MA */
+			};
+		};
+
+		sdc1_data_off: sdc1_data_off {
+			config {
+				pins = "sdc1_data";
+				bias-pull-up;		/* pull up */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc1_rclk_on: sdc1_rclk_on {
+			config {
+				pins = "sdc1_rclk";
+				bias-pull-down; /* pull down */
+			};
+		};
+
+		sdc1_rclk_off: sdc1_rclk_off {
+			config {
+				pins = "sdc1_rclk";
+				bias-pull-down; /* pull down */
+			};
+		};
+
+		sdc2_clk_on: sdc2_clk_on {
+			config {
+				pins = "sdc2_clk";
+				bias-disable;		/* NO pull */
+				drive-strength = <16>;	/* 16 MA */
+			};
+		};
+
+		sdc2_clk_off: sdc2_clk_off {
+			config {
+				pins = "sdc2_clk";
+				bias-disable;		/* NO pull */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc2_cmd_on: sdc2_cmd_on {
+			config {
+				pins = "sdc2_cmd";
+				bias-pull-up;		/* pull up */
+				drive-strength = <10>;	/* 10 MA */
+			};
+		};
+
+		sdc2_cmd_off: sdc2_cmd_off {
+			config {
+				pins = "sdc2_cmd";
+				bias-pull-up;		/* pull up */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc2_data_on: sdc2_data_on {
+			config {
+				pins = "sdc2_data";
+				bias-pull-up;		/* pull up */
+				drive-strength = <10>;	/* 10 MA */
+			};
+		};
+
+		sdc2_data_off: sdc2_data_off {
+			config {
+				pins = "sdc2_data";
+				bias-pull-up;		/* pull up */
+				drive-strength = <2>;	/* 2 MA */
+			};
+		};
+
+		sdc2_cd_on: cd_on {
+			mux {
+				pins = "gpio99";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio99";
+				drive-strength = <2>;
+				bias-pull-up;
+			};
+		};
+
+		sdc2_cd_off: cd_off {
+			mux {
+				pins = "gpio99";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio99";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		cnss_pins {
+			cnss_wlan_en_active: cnss_wlan_en_active {
+				mux {
+					pins = "gpio98";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio98";
+					drive-strength = <16>;
+					output-high;
+					bias-pull-up;
+				};
+			};
+			cnss_wlan_en_sleep: cnss_wlan_en_sleep {
+				mux {
+					pins = "gpio98";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio98";
+					drive-strength = <2>;
+					output-low;
+					bias-pull-down;
+				};
+			};
+		};
+
+		wsa_swr_clk_pin {
+			wsa_swr_clk_sleep: wsa_swr_clk_sleep {
+				mux {
+					pins = "gpio111";
+					function = "WSA_CLK";
+				};
+
+				config {
+					pins = "gpio111";
+					drive-strength = <2>;
+					bias-bus-hold;
+				};
+			};
+
+			wsa_swr_clk_active: wsa_swr_clk_active {
+				mux {
+					pins = "gpio111";
+					function = "WSA_CLK";
+				};
+
+				config {
+					pins = "gpio111";
+					drive-strength = <2>;
+					bias-bus-hold;
+				};
+			};
+		};
+
+		wsa_swr_data_pin {
+			wsa_swr_data_sleep: wsa_swr_data_sleep {
+				mux {
+					pins = "gpio110";
+					function = "WSA_DATA";
+				};
+
+				config {
+					pins = "gpio110";
+					drive-strength = <4>;
+					bias-bus-hold;
+				};
+			};
+
+			wsa_swr_data_active: wsa_swr_data_active {
+				mux {
+					pins = "gpio110";
+					function = "WSA_DATA";
+				};
+
+				config {
+					pins = "gpio110";
+					drive-strength = <4>;
+					bias-bus-hold;
+				};
+			};
+		};
+
+		/* WSA speaker reset pins */
+		spkr_1_sd_n {
+			spkr_1_sd_n_sleep: spkr_1_sd_n_sleep {
+				mux {
+					pins = "gpio108";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio108";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;
+					input-enable;
+				};
+			};
+
+			spkr_1_sd_n_active: spkr_1_sd_n_active {
+				mux {
+					pins = "gpio108";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio108";
+					drive-strength = <16>;   /* 16 mA */
+					bias-disable;
+					output-high;
+				};
+			};
+		};
+
+		spkr_2_sd_n {
+			spkr_2_sd_n_sleep: spkr_2_sd_n_sleep {
+				mux {
+					pins = "gpio109";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio109";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;
+					input-enable;
+				};
+			};
+
+			spkr_2_sd_n_active: spkr_2_sd_n_active {
+				mux {
+					pins = "gpio109";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio109";
+					drive-strength = <16>;   /* 16 mA */
+					bias-disable;
+					output-high;
+				};
+			};
+		};
+
+		wcd9xxx_intr {
+			wcd_intr_default: wcd_intr_default{
+				mux {
+					pins = "gpio122";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio122";
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down; /* pull down */
+					input-enable;
+				};
+			};
+		};
+
+		ter_i2s_sck_ws {
+			ter_i2s_sck_sleep: ter_i2s_sck_sleep {
+				mux {
+					pins = "gpio115", "gpio116";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio115", "gpio116";
+					drive-strength = <2>;   /* 2 mA */
+				};
+			};
+
+			ter_i2s_sck_active: ter_i2s_sck_active {
+				mux {
+					pins = "gpio115", "gpio116";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio115", "gpio116";
+					drive-strength = <8>;   /* 8 mA */
+					input-enable;
+				};
+			};
+		};
+
+		ter_i2s_data0 {
+			ter_i2s_data0_sleep: ter_i2s_data0_sleep {
+				mux {
+					pins = "gpio117";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio117";
+					drive-strength = <2>;   /* 2 mA */
+				};
+			};
+
+			ter_i2s_data0_active: ter_i2s_data0_active {
+				mux {
+					pins = "gpio117";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio117";
+					drive-strength = <8>;   /* 8 mA */
+					input-enable;
+				};
+			};
+		};
+
+		ter_i2s_data1 {
+			ter_i2s_data1_sleep: ter_i2s_data1_sleep {
+				mux {
+					pins = "gpio118";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio118";
+					drive-strength = <2>;   /* 2 mA */
+				};
+			};
+
+			ter_i2s_data1_active: ter_i2s_data1_active {
+				mux {
+					pins = "gpio118";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio118";
+					drive-strength = <8>;   /* 8 mA */
+					output-high;
+				};
+			};
+		};
+
+		pcie0 {
+			pcie0_clkreq_default: pcie0_clkreq_default {
+				mux {
+					pins = "gpio90";
+					function = "pcie_clk";
+				};
+
+				config {
+					pins = "gpio90";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+
+			pcie0_perst_default: pcie0_perst_default {
+				mux {
+					pins = "gpio101";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio101";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+
+			pcie0_wake_default: pcie0_wake_default {
+				mux {
+					pins = "gpio100";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio100";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		pmx_ts_int_active {
+			ts_int_active: ts_int_active {
+				mux {
+					pins = "gpio89";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio89";
+					drive-strength = <8>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		pmx_ts_int_suspend {
+			ts_int_suspend: ts_int_suspend {
+				mux {
+					pins = "gpio89";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio89";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		pmx_ts_reset_active {
+			ts_reset_active: ts_reset_active {
+				mux {
+					pins = "gpio88";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio88";
+					drive-strength = <8>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		pmx_ts_reset_suspend {
+			ts_reset_suspend: ts_reset_suspend {
+				mux {
+					pins = "gpio88";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio88";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		pmx_ts_release {
+			ts_release: ts_release {
+				mux {
+					pins = "gpio89", "gpio88";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio89", "gpio88";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		cci0_active: cci0_active {
+			mux {
+				/* CLK, DATA */
+				pins = "gpio32", "gpio33";
+				function = "cci_i2c";
+			};
+
+			config {
+				pins = "gpio32", "gpio33";
+				bias-pull-up; /* PULL UP*/
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cci0_suspend: cci0_suspend {
+			mux {
+				/* CLK, DATA */
+				pins = "gpio32", "gpio33";
+				function = "cci_i2c";
+			};
+
+			config {
+				pins = "gpio32", "gpio33";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cci1_active: cci1_active {
+			mux {
+				/* CLK, DATA */
+				pins = "gpio34", "gpio35";
+				function = "cci_i2c";
+			};
+
+			config {
+				pins = "gpio34", "gpio35";
+				bias-pull-up; /* PULL UP*/
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cci1_suspend: cci1_suspend {
+			mux {
+				/* CLK, DATA */
+				pins = "gpio34", "gpio35";
+				function = "cci_i2c";
+			};
+
+			config {
+				pins = "gpio34", "gpio35";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk0_active: cam_sensor_mclk0_active {
+			/* MCLK0 */
+			mux {
+				pins = "gpio28";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio28";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk0_suspend: cam_sensor_mclk0_suspend {
+			/* MCLK0 */
+			mux {
+				pins = "gpio28";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio28";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear_active: cam_sensor_rear_active {
+			/* RESET */
+			mux {
+				pins = "gpio47";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio47";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear_suspend: cam_sensor_rear_suspend {
+			/* RESET */
+			mux {
+				pins = "gpio47";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio47";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+				output-low;
+			};
+		};
+
+		cam_sensor_front_active: cam_sensor_front_active {
+			/* RESET  */
+			mux {
+				pins = "gpio37";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio37";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_front_suspend: cam_sensor_front_suspend {
+			/* RESET */
+			mux {
+				pins = "gpio37";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio37";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+				output-low;
+			};
+		};
+
+		cam_sensor_rear2_active: cam_sensor_rear2_active {
+			/* RESET */
+			mux {
+				pins = "gpio45";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio45";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear2_suspend: cam_sensor_rear2_suspend {
+			/* RESET */
+			mux {
+				pins = "gpio45";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio45";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+				output-low;
+			};
+		};
+
+		cam_sensor_mclk1_active: cam_sensor_mclk1_active {
+			/* MCLK1 */
+			mux {
+				pins = "gpio29";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio29";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk1_suspend: cam_sensor_mclk1_suspend {
+			/* MCLK1 */
+			mux {
+				pins = "gpio29";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio29";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk2_active: cam_sensor_mclk2_active {
+			/* MCLK2 */
+			mux {
+				pins = "gpio30";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio30";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk2_suspend: cam_sensor_mclk2_suspend {
+			/* MCLK2 */
+			mux {
+				pins = "gpio30";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio30";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		flash_led3_front {
+			flash_led3_front_en: flash_led3_front_en {
+				mux {
+					pins = "gpio38";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio38";
+					drive_strength = <2>;
+					output-high;
+					bias-disable;
+				};
+			};
+
+			flash_led3_front_dis: flash_led3_front_dis {
+				mux {
+					pins = "gpio38";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio38";
+					drive_strength = <2>;
+					output-low;
+					bias-disable;
+				};
+			};
+		};
+		emac {
+			emac_mdc: emac_mdc {
+				mux {
+					pins = "gpio113";
+					function = "rgmii_mdc";
+				};
+
+				config {
+					pins = "gpio113";
+					bias-pull-up;
+				};
+			};
+			emac_mdio: emac_mdio {
+				mux {
+					pins = "gpio114";
+					function = "rgmii_mdio";
+				};
+
+				config {
+					pins = "gpio114";
+					bias-pull-up;
+				};
+			};
+
+			emac_rgmii_txd0: emac_rgmii_txd0 {
+				mux {
+					pins = "gpio96";
+					function = "rgmii_txd0";
+				};
+
+				config {
+					pins = "gpio96";
+					bias-pull-up;
+					drive-strength = <16>;
+				};
+			};
+
+			emac_rgmii_txd1: emac_rgmii_txd1 {
+				mux {
+					pins = "gpio95";
+					function = "rgmii_txd1";
+				};
+
+				config {
+					pins = "gpio95";
+					bias-pull-up;
+					drive-strength = <16>;
+				};
+			};
+
+			emac_rgmii_txd2: emac_rgmii_txd2 {
+				mux {
+					pins = "gpio94";
+					function = "rgmii_txd2";
+				};
+
+				config {
+					pins = "gpio94";
+					bias-pull-up;
+					drive-strength = <16>;
+				};
+			};
+			emac_rgmii_txd3: emac_rgmii_txd3 {
+				mux {
+					pins = "gpio93";
+					function = "rgmii_txd3";
+				};
+
+				config {
+					pins = "gpio93";
+					bias-pull-up;
+					drive-strength = <16>;
+				};
+			};
+			emac_rgmii_txc: emac_rgmii_txc {
+				mux {
+					pins = "gpio92";
+					function = "rgmii_txc";
+				};
+
+				config {
+					pins = "gpio92";
+					bias-pull-up;
+					drive-strength = <16>;
+				};
+			};
+			emac_rgmii_tx_ctl: emac_rgmii_tx_ctl {
+				mux {
+					pins = "gpio97";
+					function = "rgmii_tx";
+				};
+
+				config {
+					pins = "gpio97";
+					bias-pull-up;
+					drive-strength = <16>;
+				};
+			};
+
+
+			emac_rgmii_rxd0: emac_rgmii_rxd0 {
+				mux {
+					pins = "gpio83";
+					function = "rgmii_rxd0";
+				};
+
+				config {
+					pins = "gpio83";
+					bias-disable;  /* NO pull */
+					drive-strength = <2>;  /* 2MA */
+				};
+			};
+
+			emac_rgmii_rxd1: emac_rgmii_rxd1 {
+				mux {
+					pins = "gpio82";
+					function = "rgmii_rxd1";
+				};
+
+				config {
+					pins = "gpio82";
+					bias-disable;  /* NO pull */
+					drive-strength = <2>;
+				};
+			};
+
+			emac_rgmii_rxd2: emac_rgmii_rxd2 {
+				mux {
+					pins = "gpio81";
+					function = "rgmii_rxd2";
+				};
+
+				config {
+					pins = "gpio81";
+					bias-disable;	/* NO pull */
+					drive-strength = <2>;
+				};
+			};
+			emac_rgmii_rxd3: emac_rgmii_rxd3 {
+				mux {
+					pins = "gpio103";
+					function = "rgmii_rxd3";
+				};
+
+				config {
+					pins = "gpio103";
+					bias-disable;	/* NO pull */
+					drive-strength = <2>;
+				};
+			};
+			emac_rgmii_rxc: emac_rgmii_rxc {
+				mux {
+					pins = "gpio102";
+					function = "rgmii_rxc";
+				};
+
+				config {
+					pins = "gpio102";
+					bias-disable;	/* NO pull */
+					drive-strength = <2>;
+				};
+			};
+			emac_rgmii_rx_ctl: emac_rgmii_rx_ctl {
+				mux {
+					pins = "gpio112";
+					function = "rgmii_rx";
+				};
+
+				config {
+					pins = "gpio112";
+					bias-disable;  /* NO pull */
+					drive-strength = <2>;
+				};
+			};
+			emac_phy_intr: emac_phy_intr {
+				mux {
+					pins = "gpio121";
+					function = "emac_phy";
+				};
+
+				config {
+					pins = "gpio121";
+					bias-disable;  /* NO pull */
+					drive-strength = <2>;
+				};
+			};
+			emac_phy_reset_state: emac_phy_reset_state {
+				mux {
+					pins = "gpio104";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio104";
+					bias-pull-up;
+					drive-strength = <16>;
+				};
+			};
+			emac_pin_pps_0: emac_pin_pps_0 {
+				mux {
+					pins = "gpio91";
+					function = "rgmii_sync";
+				};
+
+				config {
+					pins = "gpio91";
+					bias-pull-up;
+					drive-strength = <16>;
+				};
+			};
+		};
+
+		bt_en_active: bt_en_active {
+			mux {
+				pins = "gpio85";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio85";
+				drive-strength = <2>;
+				bias-pull-down;
+			};
+		};
+
+		usb0_hs_ac_en_default: usb0_hs_ac_en_default {
+			mux {
+				pins = "gpio88";
+				function = "usb0_hs_ac";
+			};
+
+			config {
+				pins = "gpio88";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		usb1_hs_ac_en_default: usb1_hs_ac_en_default {
+			mux {
+				pins = "gpio89";
+				function = "usb1_hs_ac";
+			};
+
+			config {
+				pins = "gpio89";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+	};
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-vm.dts b/arch/arm64/boot/dts/qcom/sa6155p-vm.dts
new file mode 100644
index 0000000..9ba381f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa6155p-vm.dts
@@ -0,0 +1,23 @@
+/*
+ * 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 "sa6155p-vm.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SA6155P Virtual Machine";
+	compatible = "qcom,sa6155p";
+	qcom,pmic-name = "PM6150";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sa6155p-vm.dtsi b/arch/arm64/boot/dts/qcom/sa6155p-vm.dtsi
new file mode 100644
index 0000000..371a322
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa6155p-vm.dtsi
@@ -0,0 +1,171 @@
+/*
+ * 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 "skeleton64.dtsi"
+#include <dt-bindings/clock/qcom,gcc-sm6150.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	model = "Qualcomm Technologies, Inc. SA6155P Virtual Machine";
+	qcom,msm-name = "SA6155P";
+	qcom,msm-id = <377 0x0>;
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	chosen {
+		bootargs = "rcupdate.rcu_expedited=1 rcu_nocbs=0-7 cgroup.memory=nokmem,nosocket";
+	};
+
+	soc: soc { };
+
+	reserved_memory: reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* global autoconfigured region for contiguous allocations */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
+			reusable;
+			alignment = <0x0 0x400000>;
+			size = <0x0 0x2000000>;
+			linux,cma-default;
+		};
+
+		pmem_shared: pmem_shared_region@a0000000 {
+			reg = <0x0 0xa0000000 0x0 0x20000000>;
+			label = "pmem_shared_mem";
+		};
+	};
+
+	firmware: firmware {
+		android {
+			compatible = "android,firmware";
+			vbmeta {
+				compatible = "android,vbmeta";
+				parts = "vbmeta,boot,system,vendor,dtbo";
+			};
+			fstab {
+				compatible = "android,fstab";
+				vendor {
+					compatible = "android,vendor";
+					dev="/dev/block/platform/vdevs/1c0f0000.virtio_blk/vdc";
+					type = "ext4";
+					mnt_flags = "ro,barrier=1,discard";
+					fsmgr_flags = "wait";
+					status = "ok";
+				};
+			};
+		};
+	};
+};
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	virtual-interrupt-parent = "gic";
+	ranges = <0 0 0 0xffffffff>;
+	compatible = "simple-bus";
+
+	clock_gcc: qcom,gcc {
+		compatible = "qcom,dummycc";
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	qcom,ion {
+		compatible = "qcom,msm-ion";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		system_heap: qcom,ion-heap@25 {
+			reg = <25>;
+			qcom,ion-heap-type = "SYSTEM";
+		};
+	};
+
+	qcom,hab {
+		compatible = "qcom,hab";
+		vmid = <2>;
+
+		mmidgrp100: mmidgrp100 {
+			grp-start-id = <100>;
+			role = "fe";
+			remote-vmids = <0>;
+		};
+
+		mmidgrp200: mmidgrp200 {
+			grp-start-id = <200>;
+			role = "fe";
+			remote-vmids = <0>;
+		};
+
+		mmidgrp300: mmidgrp300 {
+			grp-start-id = <300>;
+			role = "fe";
+			remote-vmids = <0>;
+		};
+
+		mmidgrp400: mmidgrp400 {
+			grp-start-id = <400>;
+			role = "fe";
+			remote-vmids = <0>;
+		};
+
+		mmidgrp500: mmidgrp500 {
+			grp-start-id = <500>;
+			role = "fe";
+			remote-vmids = <0>;
+		};
+
+		mmidgrp600: mmidgrp600 {
+			grp-start-id = <600>;
+			role = "fe";
+			remote-vmids = <0>;
+		};
+
+		mmidgrp700: mmidgrp700 {
+			grp-start-id = <700>;
+			role = "fe";
+			remote-vmids = <0>;
+		};
+
+		mmidgrp800: mmidgrp800 {
+			grp-start-id = <800>;
+			role = "fe";
+			remote-vmids = <0>;
+		};
+
+		mmidgrp900: mmidgrp900 {
+			grp-start-id = <900>;
+			role = "fe";
+			remote-vmids = <0>;
+		};
+
+		mmidgrp1000: mmidgrp1000 {
+			grp-start-id = <1000>;
+			role = "fe";
+			remote-vmids = <0>;
+		};
+	};
+	sde_kms_hyp: qcom,sde_kms_hyp@ae00000 {
+		compatible = "qcom,sde-kms-hyp";
+		qcom,client-id = "7815";
+	};
+};
+#include "sa6155p-vm-pinctrl.dtsi"
+#include "sm6150-slpi-pinctrl.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-alcor-display.dtsi b/arch/arm64/boot/dts/qcom/sa8155-adp-alcor-display.dtsi
new file mode 100644
index 0000000..ab266f1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa8155-adp-alcor-display.dtsi
@@ -0,0 +1,88 @@
+/* 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.
+ */
+
+&tlmm {
+	dp_hpd_cfg_pins: dp_hpd_cfg_pins {
+		mux {
+			pins = "gpio48";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio48";
+			drive-strength = <2>;
+			bias-pull-down;
+		};
+	};
+
+	dp_redriver_en: dp_redriver_en {
+		mux {
+			pins = "gpio47";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio47";
+			drive-strength = <2>;
+			bias-disable;
+			output-high;
+		};
+	};
+};
+
+&sde_dp {
+	qcom,ext-disp = <&ext_disp>;
+	qcom,dp-hpd-gpio = <&tlmm 48 0>;
+	pinctrl-names = "mdss_dp_active", "mdss_dp_sleep",
+			"mdss_dp_hpd_active";
+	pinctrl-0 = <&dp_hpd_cfg_pins &dp_redriver_en>;
+	pinctrl-1 = <&dp_hpd_cfg_pins &dp_redriver_en>;
+	pinctrl-2 = <&dp_hpd_cfg_pins &dp_redriver_en>;
+
+	qcom,core-supply-entries {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		qcom,core-supply-entry@0 {
+			reg = <0>;
+			qcom,supply-name = "refgen";
+			qcom,supply-min-voltage = <0>;
+			qcom,supply-max-voltage = <0>;
+			qcom,supply-enable-load = <0>;
+			qcom,supply-disable-load = <0>;
+		};
+	};
+};
+
+&soc {
+	refgen: refgen-regulator@88e7000 {
+		compatible = "qcom,refgen-regulator";
+		reg = <0x88e7000 0x60>;
+		regulator-name = "refgen";
+		regulator-enable-ramp-delay = <5>;
+	};
+
+	sde_wb: qcom,wb-display@0 {
+		compatible = "qcom,wb-display";
+		cell-index = <0>;
+		label = "wb_display";
+	};
+
+	ext_disp: qcom,msm-ext-disp {
+		compatible = "qcom,msm-ext-disp";
+
+		ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx {
+			compatible = "qcom,msm-ext-disp-audio-codec-rx";
+		};
+	};
+};
+
+&mdss_mdp {
+	connectors = <&sde_rscc &sde_dp &sde_wb>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-alcor-overlay.dts b/arch/arm64/boot/dts/qcom/sa8155-adp-alcor-overlay.dts
index 2c6abde..b720b0e 100644
--- a/arch/arm64/boot/dts/qcom/sa8155-adp-alcor-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155-adp-alcor-overlay.dts
@@ -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
@@ -13,7 +13,7 @@
 /dts-v1/;
 /plugin/;
 
-#include "sa8155-adp-common.dtsi"
+#include "sa8155-adp-alcor.dtsi"
 
 / {
 	model = "ADP-ALCOR";
diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-alcor.dts b/arch/arm64/boot/dts/qcom/sa8155-adp-alcor.dts
index e99e9db..5b52009 100644
--- a/arch/arm64/boot/dts/qcom/sa8155-adp-alcor.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155-adp-alcor.dts
@@ -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
@@ -13,7 +13,7 @@
 /dts-v1/;
 
 #include "sa8155-v2.dtsi"
-#include "sa8155-adp-common.dtsi"
+#include "sa8155-adp-alcor.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SA8155 ADP ALCOR";
diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-alcor.dtsi b/arch/arm64/boot/dts/qcom/sa8155-adp-alcor.dtsi
new file mode 100644
index 0000000..2c48865
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa8155-adp-alcor.dtsi
@@ -0,0 +1,14 @@
+/* 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 "sa8155-adp-common.dtsi"
+#include "sa8155-adp-alcor-display.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-common.dtsi b/arch/arm64/boot/dts/qcom/sa8155-adp-common.dtsi
index ab11186..afa8a15 100644
--- a/arch/arm64/boot/dts/qcom/sa8155-adp-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8155-adp-common.dtsi
@@ -45,6 +45,37 @@
 &qupv3_se4_i2c {
 	status = "ok";
 };
+
+&qupv3_se10_i2c {
+	status = "ok";
+	asm330@6a {
+		compatible = "st,asm330lhh";
+		reg = <0x6a>;
+		vio-supply = <&pm8150_2_l7>;
+		vdd-supply = <&pm8150_2_l16>;
+		interrupt-parent = <&tlmm>;
+		interrupts = <41 IRQ_TYPE_EDGE_RISING>,
+				<42 IRQ_TYPE_EDGE_RISING>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sensor_int1_default
+			&sensor_int2_default>;
+		sensor_int1_default: sensor_int1_default {
+			pins = "gpio41";
+			drive-strength = <16>;
+			bias-pull-up;
+		};
+		sensor_int2_default: sensor_int2_default {
+			pins = "gpio42";
+			drive-strength = <16>;
+			bias-pull-up;
+		};
+	};
+};
+
+&qupv3_se20_i2c {
+	status = "ok";
+};
+
 &pil_modem {
 	status = "disabled";
 };
@@ -82,11 +113,11 @@
 	};
 
 	qcom,rmnet-ipa {
-		status = "ok";
+		status = "disabled";
 	};
 
 	qcom,ipa_fws {
-		status = "ok";
+		status = "disabled";
 	};
 
 	qcom,msm-cdsp-loader {
@@ -98,7 +129,7 @@
 	};
 
 	ipa_hw: qcom,ipa@1e00000 {
-		status = "ok";
+		status = "disabled";
 	};
 
 	gpio_keys {
@@ -182,7 +213,12 @@
 };
 
 &usb0 {
+	qcom,default-mode-none;
 	qcom,host-poweroff-in-pm-suspend;
+	dwc3@a600000 {
+		usb-phy = <&usb2_phy0>, <&usb_nop_phy>;
+		maximum-speed = "high-speed";
+	};
 };
 
 &usb2_phy0 {
@@ -193,6 +229,10 @@
 	pinctrl-0 = <&usb2phy_ac_en1_default>;
 };
 
+&usb_qmp_dp_phy {
+	status = "disabled";
+};
+
 &usb1 {
 	status = "ok";
 	qcom,default-mode-host;
diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-star-display.dtsi b/arch/arm64/boot/dts/qcom/sa8155-adp-star-display.dtsi
new file mode 100644
index 0000000..0db9ec2
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa8155-adp-star-display.dtsi
@@ -0,0 +1,311 @@
+/* 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 <dt-bindings/clock/mdss-10nm-pll-clk.h>
+
+&tlmm {
+	ioexp_intr_active: ioexp_intr_active {
+		mux {
+			pins = "gpio48";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio48";
+			drive-strength = <2>;
+			bias-pull-up;
+		};
+	};
+
+	ioexp_reset_active: ioexp_reset_active {
+		mux {
+			pins = "gpio30";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio30";
+			drive-strength = <2>;
+			bias-disable;
+			output-high;
+		};
+	};
+};
+
+&sde_dp {
+	qcom,ext-disp = <&ext_disp>;
+	qcom,dp-hpd-gpio = <&ioexp 8 0>;
+
+	pinctrl-names = "mdss_dp_active", "mdss_dp_sleep";
+	pinctrl-0 = <&dp_hpd_cfg_pins>;
+	pinctrl-1 = <&dp_hpd_cfg_pins>;
+
+	qcom,core-supply-entries {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		qcom,core-supply-entry@0 {
+			reg = <0>;
+			qcom,supply-name = "refgen";
+			qcom,supply-min-voltage = <0>;
+			qcom,supply-max-voltage = <0>;
+			qcom,supply-enable-load = <0>;
+			qcom,supply-disable-load = <0>;
+		};
+	};
+};
+
+&qupv3_se15_i2c {
+	status = "ok";
+
+	pinctrl-0 = <&qupv3_se15_i2c_active
+		&ioexp_intr_active
+		&ioexp_reset_active>;
+
+	ioexp: gpio@3e {
+		#gpio-cells = <2>;
+		#interrupt-cells = <2>;
+		compatible = "semtech,sx1509q";
+		reg = <0x3e>;
+		interrupt-parent = <&tlmm>;
+		interrupts = <48 0>;
+		gpio-controller;
+		interrupt-controller;
+		semtech,probe-reset;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&dsi1_hpd_cfg_pins
+			&dsi1_cdet_cfg_pins
+			&dsi2_hpd_cfg_pins
+			&dsi2_cdet_cfg_pins
+			&dp_hpd_cfg_pins>;
+
+		dsi1_hpd_cfg_pins: gpio0-cfg {
+			pins = "gpio0";
+			bias-pull-up;
+		};
+
+		dsi1_cdet_cfg_pins: gpio1-cfg {
+			pins = "gpio1";
+			bias-pull-down;
+		};
+
+		dsi2_hpd_cfg_pins: gpio2-cfg {
+			pins = "gpio2";
+			bias-pull-up;
+		};
+
+		dsi2_cdet_cfg_pins: gpio3-cfg {
+			pins = "gpio3";
+			bias-pull-down;
+		};
+
+		dp_hpd_cfg_pins: gpio8-cfg {
+			pins = "gpio8";
+			bias-pull-down;
+		};
+	};
+
+	i2c-mux@77 {
+		compatible = "nxp,pca9542";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			anx_7625_1: anx7625@2c {
+				compatible = "analogix,anx7625";
+				reg = <0x2c>;
+				interrupt-parent = <&ioexp>;
+				interrupts = <0 0>;
+				cbl_det-gpio = <&ioexp 1 0>;
+				power_en-gpio = <&tlmm 47 0>;
+				reset_n-gpio = <&tlmm 49 0>;
+			};
+		};
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			anx_7625_2: anx7625@2c {
+				compatible = "analogix,anx7625";
+				reg = <0x2c>;
+				interrupt-parent = <&ioexp>;
+				interrupts = <2 0>;
+				cbl_det-gpio = <&ioexp 3 0>;
+				power_en-gpio = <&tlmm 87 0>;
+				reset_n-gpio = <&tlmm 29 0>;
+			};
+		};
+	};
+};
+
+&anx_7625_1 {
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			anx_7625_1_in: endpoint {
+				remote-endpoint = <&dsi_anx_7625_1_out>;
+			};
+		};
+	};
+};
+
+&anx_7625_2 {
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			anx_7625_2_in: endpoint {
+				remote-endpoint = <&dsi_anx_7625_2_out>;
+			};
+		};
+	};
+};
+
+#include "dsi-panel-ext-bridge-1080p.dtsi"
+
+&dsi_ext_bridge_1080p {
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1E 08 07 24 22
+				08 08 05 02 04 00 19 17];
+		};
+	};
+};
+
+&soc {
+	dsi_anx_7625_1: qcom,dsi-display@17 {
+		label = "dsi_anx_7625_1";
+		qcom,dsi-display-active;
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl-num = <0>;
+		qcom,dsi-phy-num = <0>;
+		qcom,dsi-select-clocks = "mux_byte_clk0", "mux_pixel_clk0";
+
+		qcom,dsi-panel = <&dsi_ext_bridge_1080p>;
+	};
+
+	dsi_anx_7625_2: qcom,dsi-display@18 {
+		label = "dsi_anx_7625_2";
+		qcom,dsi-display-active;
+		qcom,display-type = "secondary";
+
+		qcom,dsi-ctrl-num = <1>;
+		qcom,dsi-phy-num = <1>;
+		qcom,dsi-select-clocks = "mux_byte_clk1", "mux_pixel_clk1";
+
+		qcom,dsi-panel = <&dsi_ext_bridge_1080p>;
+	};
+
+	dsi_dp1: qcom,dsi-display@1 {
+		compatible = "qcom,dsi-display";
+		label = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
+		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
+
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			 <&mdss_dsi0_pll PCLK_MUX_0_CLK>,
+			 <&mdss_dsi1_pll BYTECLK_MUX_1_CLK>,
+			 <&mdss_dsi1_pll PCLK_MUX_1_CLK>;
+		clock-names = "mux_byte_clk0", "mux_pixel_clk0",
+			      "mux_byte_clk1", "mux_pixel_clk1";
+
+		qcom,dsi-display-list =
+			<&dsi_anx_7625_1>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				dsi_anx_7625_1_out: endpoint {
+					remote-endpoint = <&anx_7625_1_in>;
+				};
+			};
+		};
+	};
+
+	dsi_dp2: qcom,dsi-display@2 {
+		compatible = "qcom,dsi-display";
+		label = "secondary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
+		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
+
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			 <&mdss_dsi0_pll PCLK_MUX_0_CLK>,
+			 <&mdss_dsi1_pll BYTECLK_MUX_1_CLK>,
+			 <&mdss_dsi1_pll PCLK_MUX_1_CLK>;
+		clock-names = "mux_byte_clk0", "mux_pixel_clk0",
+			      "mux_byte_clk1", "mux_pixel_clk1";
+
+		qcom,dsi-display-list =
+			<&dsi_anx_7625_2>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				dsi_anx_7625_2_out: endpoint {
+					remote-endpoint = <&anx_7625_2_in>;
+				};
+			};
+		};
+	};
+
+	refgen: refgen-regulator@88e7000 {
+		compatible = "qcom,refgen-regulator";
+		reg = <0x88e7000 0x60>;
+		regulator-name = "refgen";
+		regulator-enable-ramp-delay = <5>;
+	};
+
+	sde_wb: qcom,wb-display@0 {
+		compatible = "qcom,wb-display";
+		cell-index = <0>;
+		label = "wb_display";
+	};
+
+	ext_disp: qcom,msm-ext-disp {
+		compatible = "qcom,msm-ext-disp";
+
+		ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx {
+			compatible = "qcom,msm-ext-disp-audio-codec-rx";
+		};
+	};
+};
+
+&mdss_dsi_phy0 {
+	qcom,panel-force-clock-lane-hs;
+};
+
+&mdss_dsi_phy1 {
+	qcom,panel-force-clock-lane-hs;
+};
+
+&mdss_mdp {
+	connectors = <&sde_rscc &dsi_dp1 &dsi_dp2 &sde_dp &sde_wb>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi b/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi
index fa61fa9..340c9ed 100644
--- a/arch/arm64/boot/dts/qcom/sa8155-adp-star.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8155-adp-star.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
@@ -11,5 +11,5 @@
  */
 
 #include "sa8155-adp-common.dtsi"
-#include "sm8150-camera-sensor-adp-star.dtsi"
+#include "sa8155-adp-star-display.dtsi"
 
diff --git a/arch/arm64/boot/dts/qcom/sa8155-audio.dtsi b/arch/arm64/boot/dts/qcom/sa8155-audio.dtsi
index 51f1f88..9912fec 100644
--- a/arch/arm64/boot/dts/qcom/sa8155-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8155-audio.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
@@ -274,6 +274,7 @@
 		qcom,msm-cpudai-tdm-group-id = <37168>;
 		qcom,msm-cpudai-tdm-group-num-ports = <4>;
 		qcom,msm-cpudai-tdm-group-port-id = <36912 36914 36916 36918>;
+		qcom,msm-cpudai-tdm-lane-mask = /bits/ 16 <3>;
 		qcom,msm-cpudai-tdm-clk-rate = <24576000>;
 		qcom,msm-cpudai-tdm-clk-internal = <1>;
 		qcom,msm-cpudai-tdm-sync-mode = <1>;
@@ -314,6 +315,7 @@
 		qcom,msm-cpudai-tdm-group-id = <37169>;
 		qcom,msm-cpudai-tdm-group-num-ports = <4>;
 		qcom,msm-cpudai-tdm-group-port-id = <36913 36915 36917 36919>;
+		qcom,msm-cpudai-tdm-lane-mask = /bits/ 16 <12>;
 		qcom,msm-cpudai-tdm-clk-rate = <24576000>;
 		qcom,msm-cpudai-tdm-clk-internal = <1>;
 		qcom,msm-cpudai-tdm-sync-mode = <1>;
@@ -439,6 +441,10 @@
 };
 
 &audio_apr {
+	q6core: qcom,q6core-audio {
+		compatible = "qcom,q6core-audio";
+	};
+
 	snd_9360: sound-pahu {
 		status = "disabled";
 	};
@@ -446,7 +452,9 @@
 	snd_934x: sound-tavil {
 		status = "disabled";
 	};
+};
 
+&q6core {
 	sound-adp-star {
 		compatible = "qcom,sa8155-asoc-snd-adp-star";
 		qcom,model = "sa8155-adp-star-snd-card";
@@ -534,6 +542,7 @@
 				"msm-dai-q6-tdm.36935";
 		asoc-codec = <&stub_codec>;
 		asoc-codec-names = "msm-stub-codec.1";
+		qcom,msm_audio_ssr_devs = <&audio_apr>, <&q6core>;
 	};
 };
 
diff --git a/arch/arm64/boot/dts/qcom/sm8150-camera-sensor-adp-star.dtsi b/arch/arm64/boot/dts/qcom/sa8155-camera-sensor.dtsi
similarity index 100%
rename from arch/arm64/boot/dts/qcom/sm8150-camera-sensor-adp-star.dtsi
rename to arch/arm64/boot/dts/qcom/sa8155-camera-sensor.dtsi
diff --git a/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air-overlay.dts b/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air-overlay.dts
index 5bd264f..8c51bb3 100644
--- a/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air-overlay.dts
@@ -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
@@ -14,6 +14,7 @@
 /plugin/;
 
 #include "sa8155-adp-common.dtsi"
+#include "sa8155-adp-star-display.dtsi"
 
 / {
 	model = "ADP-AIR";
diff --git a/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air.dts b/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air.dts
index c0cdac4..0cdfaf5 100644
--- a/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155-v2-adp-air.dts
@@ -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
@@ -14,6 +14,7 @@
 
 #include "sa8155-v2.dtsi"
 #include "sa8155-adp-common.dtsi"
+#include "sa8155-adp-star-display.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SA8155 V2 ADP AIR";
diff --git a/arch/arm64/boot/dts/qcom/sa8155-vm-audio.dtsi b/arch/arm64/boot/dts/qcom/sa8155-vm-audio.dtsi
new file mode 100644
index 0000000..22e31ee
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa8155-vm-audio.dtsi
@@ -0,0 +1,517 @@
+/*
+ * 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 "msm-audio-lpass.dtsi"
+
+&soc {
+	qcom,msm-dai-tdm-pri-rx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37120>;
+		qcom,msm-cpudai-tdm-group-num-ports = <4>;
+		qcom,msm-cpudai-tdm-group-port-id = <36864 36866 36868 36870>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-internal = <1>;
+		qcom,msm-cpudai-tdm-sync-mode = <0>;
+		qcom,msm-cpudai-tdm-sync-src = <1>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <0>;
+		qcom,msm-cpudai-tdm-data-delay = <1>;
+		qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>;
+		dai_pri_tdm_rx_0: qcom,msm-dai-q6-tdm-pri-rx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36864>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_pri_tdm_rx_1: qcom,msm-dai-q6-tdm-pri-rx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36866>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_pri_tdm_rx_2: qcom,msm-dai-q6-tdm-pri-rx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36868>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_pri_tdm_rx_3: qcom,msm-dai-q6-tdm-pri-rx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36870>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	qcom,msm-dai-tdm-pri-tx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37121>;
+		qcom,msm-cpudai-tdm-group-num-ports = <4>;
+		qcom,msm-cpudai-tdm-group-port-id = <36865 36867 36869 36871>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-internal = <1>;
+		qcom,msm-cpudai-tdm-sync-mode = <0>;
+		qcom,msm-cpudai-tdm-sync-src = <1>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <0>;
+		qcom,msm-cpudai-tdm-data-delay = <1>;
+		qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>;
+		dai_pri_tdm_tx_0: qcom,msm-dai-q6-tdm-pri-tx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36865>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_pri_tdm_tx_1: qcom,msm-dai-q6-tdm-pri-tx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36867>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_pri_tdm_tx_2: qcom,msm-dai-q6-tdm-pri-tx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36869>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_pri_tdm_tx_3: qcom,msm-dai-q6-tdm-pri-tx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36871>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	qcom,msm-dai-tdm-sec-rx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37136>;
+		qcom,msm-cpudai-tdm-group-num-ports = <5>;
+		qcom,msm-cpudai-tdm-group-port-id = <36880 36882 36884
+							36886 36894>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-internal = <1>;
+		qcom,msm-cpudai-tdm-sync-mode = <1>;
+		qcom,msm-cpudai-tdm-sync-src = <1>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <0>;
+		qcom,msm-cpudai-tdm-data-delay = <0>;
+		dai_sec_tdm_rx_0: qcom,msm-dai-q6-tdm-sec-rx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36880>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_sec_tdm_rx_1: qcom,msm-dai-q6-tdm-sec-rx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36882>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_sec_tdm_rx_2: qcom,msm-dai-q6-tdm-sec-rx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36884>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_sec_tdm_rx_3: qcom,msm-dai-q6-tdm-sec-rx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36886>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_sec_tdm_rx_7: qcom,msm-dai-q6-tdm-sec-rx-7 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36894>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	qcom,msm-dai-tdm-sec-tx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37137>;
+		qcom,msm-cpudai-tdm-group-num-ports = <4>;
+		qcom,msm-cpudai-tdm-group-port-id = <36881 36883 36885 36887>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-internal = <1>;
+		qcom,msm-cpudai-tdm-sync-mode = <1>;
+		qcom,msm-cpudai-tdm-sync-src = <1>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <0>;
+		qcom,msm-cpudai-tdm-data-delay = <0>;
+		dai_sec_tdm_tx_0: qcom,msm-dai-q6-tdm-sec-tx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36881>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_sec_tdm_tx_1: qcom,msm-dai-q6-tdm-sec-tx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36883>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_sec_tdm_tx_2: qcom,msm-dai-q6-tdm-sec-tx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36885>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_sec_tdm_tx_3: qcom,msm-dai-q6-tdm-sec-tx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36887>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	qcom,msm-dai-tdm-tert-rx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37152>;
+		qcom,msm-cpudai-tdm-group-num-ports = <5>;
+		qcom,msm-cpudai-tdm-group-port-id = <36896 36898 36900
+							36902 36904>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-internal = <0>;
+		qcom,msm-cpudai-tdm-sync-mode = <1>;
+		qcom,msm-cpudai-tdm-sync-src = <0>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <0>;
+		qcom,msm-cpudai-tdm-data-delay = <0>;
+		dai_tert_tdm_rx_0: qcom,msm-dai-q6-tdm-tert-rx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36896>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_tert_tdm_rx_1: qcom,msm-dai-q6-tdm-tert-rx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36898>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_tert_tdm_rx_2: qcom,msm-dai-q6-tdm-tert-rx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36900>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_tert_tdm_rx_3: qcom,msm-dai-q6-tdm-tert-rx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36902>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_tert_tdm_rx_4: qcom,msm-dai-q6-tdm-tert-rx-4 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36904>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	qcom,msm-dai-tdm-tert-tx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37153>;
+		qcom,msm-cpudai-tdm-group-num-ports = <5>;
+		qcom,msm-cpudai-tdm-group-port-id = <36897 36899 36901
+							36903 36911>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-internal = <0>;
+		qcom,msm-cpudai-tdm-sync-mode = <1>;
+		qcom,msm-cpudai-tdm-sync-src = <0>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <0>;
+		qcom,msm-cpudai-tdm-data-delay = <0>;
+		dai_tert_tdm_tx_0: qcom,msm-dai-q6-tdm-tert-tx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36897>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_tert_tdm_tx_1: qcom,msm-dai-q6-tdm-tert-tx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36899>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_tert_tdm_tx_2: qcom,msm-dai-q6-tdm-tert-tx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36901>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_tert_tdm_tx_3: qcom,msm-dai-q6-tdm-tert-tx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36903>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_tert_tdm_tx_7: qcom,msm-dai-q6-tdm-tert-tx-7 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36911>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	qcom,msm-dai-tdm-quat-rx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37168>;
+		qcom,msm-cpudai-tdm-group-num-ports = <4>;
+		qcom,msm-cpudai-tdm-group-port-id = <36912 36914 36916 36918>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-internal = <1>;
+		qcom,msm-cpudai-tdm-sync-mode = <1>;
+		qcom,msm-cpudai-tdm-sync-src = <1>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <0>;
+		qcom,msm-cpudai-tdm-data-delay = <0>;
+		dai_quat_tdm_rx_0: qcom,msm-dai-q6-tdm-quat-rx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36912>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quat_tdm_rx_1: qcom,msm-dai-q6-tdm-quat-rx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36914>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quat_tdm_rx_2: qcom,msm-dai-q6-tdm-quat-rx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36916>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quat_tdm_rx_3: qcom,msm-dai-q6-tdm-quat-rx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36918>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	qcom,msm-dai-tdm-quat-tx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37169>;
+		qcom,msm-cpudai-tdm-group-num-ports = <4>;
+		qcom,msm-cpudai-tdm-group-port-id = <36913 36915 36917 36919>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-internal = <1>;
+		qcom,msm-cpudai-tdm-sync-mode = <1>;
+		qcom,msm-cpudai-tdm-sync-src = <1>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <0>;
+		qcom,msm-cpudai-tdm-data-delay = <0>;
+		dai_quat_tdm_tx_0: qcom,msm-dai-q6-tdm-quat-tx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36913>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quat_tdm_tx_1: qcom,msm-dai-q6-tdm-quat-tx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36915>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quat_tdm_tx_2: qcom,msm-dai-q6-tdm-quat-tx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36917>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quat_tdm_tx_3: qcom,msm-dai-q6-tdm-quat-tx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36919>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	qcom,msm-dai-tdm-quin-rx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37184>;
+		qcom,msm-cpudai-tdm-group-num-ports = <4>;
+		qcom,msm-cpudai-tdm-group-port-id = <36928 36930 36932 36934>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-internal = <1>;
+		qcom,msm-cpudai-tdm-sync-mode = <1>;
+		qcom,msm-cpudai-tdm-sync-src = <1>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <0>;
+		qcom,msm-cpudai-tdm-data-delay = <0>;
+		dai_quin_tdm_rx_0: qcom,msm-dai-q6-tdm-quin-rx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36928>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quin_tdm_rx_1: qcom,msm-dai-q6-tdm-quin-rx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36930>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quin_tdm_rx_2: qcom,msm-dai-q6-tdm-quin-rx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36932>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quin_tdm_rx_3: qcom,msm-dai-q6-tdm-quin-rx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36934>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	qcom,msm-dai-tdm-quin-tx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37185>;
+		qcom,msm-cpudai-tdm-group-num-ports = <4>;
+		qcom,msm-cpudai-tdm-group-port-id = <36929 36931 36933 36935>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-clk-internal = <1>;
+		qcom,msm-cpudai-tdm-sync-mode = <1>;
+		qcom,msm-cpudai-tdm-sync-src = <1>;
+		qcom,msm-cpudai-tdm-data-out = <0>;
+		qcom,msm-cpudai-tdm-invert-sync = <0>;
+		qcom,msm-cpudai-tdm-data-delay = <0>;
+		dai_quin_tdm_tx_0: qcom,msm-dai-q6-tdm-quin-tx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36929>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quin_tdm_tx_1: qcom,msm-dai-q6-tdm-quin-tx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36931>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quin_tdm_tx_2: qcom,msm-dai-q6-tdm-quin-tx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36933>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+
+		dai_quin_tdm_tx_3: qcom,msm-dai-q6-tdm-quin-tx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36935>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	qcom,avtimer@170f7000 {
+		compatible = "qcom,avtimer";
+		reg = <0x170f700c 0x4>,
+		      <0x170f7010 0x4>;
+		reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+		qcom,clk-div = <192>;
+		qcom,clk-mult = <10>;
+	};
+};
+
+&audio_apr {
+	q6core: qcom,q6core-audio {
+		compatible = "qcom,q6core-audio";
+	};
+};
+
+&q6core {
+	sound-adp-star {
+		compatible = "qcom,sa8155-asoc-snd-adp-star";
+		qcom,model = "sa8155-adp-star-snd-card";
+		qcom,mi2s-audio-intf;
+		qcom,auxpcm-audio-intf;
+		qcom,msm-mi2s-master = <1>, <1>, <1>, <1>, <1>;
+
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&compr>,
+				<&pcm_noirq>, <&loopback1>, <&pcm_dtmf>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-pcm-dsp.2", "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-compr-dsp",
+				"msm-pcm-dsp-noirq", "msm-pcm-loopback.1",
+				"msm-pcm-dtmf";
+		asoc-cpu = <&dai_hdmi>, <&dai_dp>,
+				<&dai_mi2s0>, <&dai_mi2s1>,
+				<&dai_mi2s2>, <&dai_mi2s3>,
+				<&dai_mi2s4>, <&dai_pri_auxpcm>,
+				<&dai_sec_auxpcm>, <&dai_tert_auxpcm>,
+				<&dai_quat_auxpcm>, <&dai_quin_auxpcm>,
+				<&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>,
+				<&usb_audio_rx>, <&usb_audio_tx>,
+				<&dai_pri_tdm_rx_0>, <&dai_pri_tdm_rx_1>,
+				<&dai_pri_tdm_rx_2>, <&dai_pri_tdm_rx_3>,
+				<&dai_pri_tdm_tx_0>, <&dai_pri_tdm_tx_1>,
+				<&dai_pri_tdm_tx_2>, <&dai_pri_tdm_tx_3>,
+				<&dai_sec_tdm_rx_0>, <&dai_sec_tdm_rx_1>,
+				<&dai_sec_tdm_rx_2>, <&dai_sec_tdm_rx_3>,
+				<&dai_sec_tdm_rx_7>, <&dai_sec_tdm_tx_0>,
+				<&dai_sec_tdm_tx_1>, <&dai_sec_tdm_tx_2>,
+				<&dai_sec_tdm_tx_3>, <&dai_tert_tdm_rx_0>,
+				<&dai_tert_tdm_rx_1>, <&dai_tert_tdm_rx_2>,
+				<&dai_tert_tdm_rx_3>, <&dai_tert_tdm_rx_4>,
+				<&dai_tert_tdm_tx_0>, <&dai_tert_tdm_tx_1>,
+				<&dai_tert_tdm_tx_2>, <&dai_tert_tdm_tx_3>,
+				<&dai_tert_tdm_tx_7>, <&dai_quat_tdm_rx_0>,
+				<&dai_quat_tdm_rx_1>, <&dai_quat_tdm_rx_2>,
+				<&dai_quat_tdm_rx_3>, <&dai_quat_tdm_tx_0>,
+				<&dai_quat_tdm_tx_1>, <&dai_quat_tdm_tx_2>,
+				<&dai_quat_tdm_tx_3>, <&dai_quin_tdm_rx_0>,
+				<&dai_quin_tdm_rx_1>, <&dai_quin_tdm_rx_2>,
+				<&dai_quin_tdm_rx_3>, <&dai_quin_tdm_tx_0>,
+				<&dai_quin_tdm_tx_1>, <&dai_quin_tdm_tx_2>,
+				<&dai_quin_tdm_tx_3>;
+		asoc-cpu-names = "msm-dai-q6-hdmi.8",  "msm-dai-q6-dp.24608",
+				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-mi2s.4", "msm-dai-q6-auxpcm.1",
+				"msm-dai-q6-auxpcm.2", "msm-dai-q6-auxpcm.3",
+				"msm-dai-q6-auxpcm.4", "msm-dai-q6-auxpcm.5",
+				"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",
+				"msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673",
+				"msm-dai-q6-tdm.36864", "msm-dai-q6-tdm.36866",
+				"msm-dai-q6-tdm.36868", "msm-dai-q6-tdm.36870",
+				"msm-dai-q6-tdm.36865", "msm-dai-q6-tdm.36867",
+				"msm-dai-q6-tdm.36869", "msm-dai-q6-tdm.36871",
+				"msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36882",
+				"msm-dai-q6-tdm.36884", "msm-dai-q6-tdm.36886",
+				"msm-dai-q6-tdm.36894", "msm-dai-q6-tdm.36881",
+				"msm-dai-q6-tdm.36883", "msm-dai-q6-tdm.36885",
+				"msm-dai-q6-tdm.36887", "msm-dai-q6-tdm.36896",
+				"msm-dai-q6-tdm.36898", "msm-dai-q6-tdm.36900",
+				"msm-dai-q6-tdm.36902", "msm-dai-q6-tdm.36904",
+				"msm-dai-q6-tdm.36897", "msm-dai-q6-tdm.36899",
+				"msm-dai-q6-tdm.36901", "msm-dai-q6-tdm.36903",
+				"msm-dai-q6-tdm.36911", "msm-dai-q6-tdm.36912",
+				"msm-dai-q6-tdm.36914", "msm-dai-q6-tdm.36916",
+				"msm-dai-q6-tdm.36918", "msm-dai-q6-tdm.36913",
+				"msm-dai-q6-tdm.36915", "msm-dai-q6-tdm.36917",
+				"msm-dai-q6-tdm.36919", "msm-dai-q6-tdm.36928",
+				"msm-dai-q6-tdm.36930", "msm-dai-q6-tdm.36932",
+				"msm-dai-q6-tdm.36934", "msm-dai-q6-tdm.36929",
+				"msm-dai-q6-tdm.36931", "msm-dai-q6-tdm.36933",
+				"msm-dai-q6-tdm.36935";
+		asoc-codec = <&stub_codec>;
+		asoc-codec-names = "msm-stub-codec.1";
+		qcom,msm_audio_ssr_devs = <&audio_apr>, <&q6core>;
+	};
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sa8155-vm-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sa8155-vm-qupv3.dtsi
new file mode 100644
index 0000000..16622e1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa8155-vm-qupv3.dtsi
@@ -0,0 +1,958 @@
+/* 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 <dt-bindings/msm/msm-bus-ids.h>
+
+&soc {
+	/* QUPv3 South Instances */
+	qupv3_0: qcom,qupv3_0_geni_se@8c0000 {
+		compatible = "qcom,qupv3-geni-se";
+		reg = <0x8c0000 0x6000>;
+		qcom,bus-mas-id = <MSM_BUS_MASTER_QUP_0>;
+		qcom,bus-slv-id = <MSM_BUS_SLAVE_EBI_CH0>;
+		qcom,iommu-s1-bypass;
+
+		iommu_qupv3_0_geni_se_cb: qcom,iommu_qupv3_0_geni_se_cb {
+			compatible = "qcom,qupv3-geni-se-cb";
+			iommus = <&apps_smmu 0xc3 0x0>;
+		};
+	};
+
+	/* I2C */
+	qupv3_se0_i2c: i2c@880000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x880000 0x4000>;
+		interrupts = <GIC_SPI 601 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S0_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se0_i2c_active>;
+		pinctrl-1 = <&qupv3_se0_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se1_i2c: i2c@884000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x884000 0x4000>;
+		interrupts = <GIC_SPI 602 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S1_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se1_i2c_active>;
+		pinctrl-1 = <&qupv3_se1_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se2_i2c: i2c@888000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x888000 0x4000>;
+		interrupts = <GIC_SPI 603 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S2_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se2_i2c_active>;
+		pinctrl-1 = <&qupv3_se2_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se3_i2c: i2c@88c000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x88c000 0x4000>;
+		interrupts = <GIC_SPI 604 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S3_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se3_i2c_active>;
+		pinctrl-1 = <&qupv3_se3_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se4_i2c: i2c@890000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x890000 0x4000>;
+		interrupts = <GIC_SPI 605 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S4_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se4_i2c_active>;
+		pinctrl-1 = <&qupv3_se4_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se5_i2c: i2c@894000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x894000 0x4000>;
+		interrupts = <GIC_SPI 606 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S5_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se5_i2c_active>;
+		pinctrl-1 = <&qupv3_se5_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se6_i2c: i2c@898000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x898000 0x4000>;
+		interrupts = <GIC_SPI 607 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S6_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se6_i2c_active>;
+		pinctrl-1 = <&qupv3_se6_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se7_i2c: i2c@89c000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x89c000 0x4000>;
+		interrupts = <GIC_SPI 608 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S7_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se7_i2c_active>;
+		pinctrl-1 = <&qupv3_se7_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	/* SPI */
+	qupv3_se0_spi: spi@880000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x880000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S0_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se0_spi_active>;
+		pinctrl-1 = <&qupv3_se0_spi_sleep>;
+		interrupts = <GIC_SPI 601 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se1_spi: spi@884000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x884000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S1_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se1_spi_active>;
+		pinctrl-1 = <&qupv3_se1_spi_sleep>;
+		interrupts = <GIC_SPI 602 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se2_spi: spi@888000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x888000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S2_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se2_spi_active>;
+		pinctrl-1 = <&qupv3_se2_spi_sleep>;
+		interrupts = <GIC_SPI 603 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se3_spi: spi@88c000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x88c000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S3_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se3_spi_active>;
+		pinctrl-1 = <&qupv3_se3_spi_sleep &qupv3_se3_spi_miso_sleep>;
+		interrupts = <GIC_SPI 604 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se4_spi: spi@890000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x890000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S4_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se4_spi_active>;
+		pinctrl-1 = <&qupv3_se4_spi_sleep>;
+		interrupts = <GIC_SPI 605 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se5_spi: spi@894000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x894000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S5_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se5_spi_active>;
+		pinctrl-1 = <&qupv3_se5_spi_sleep>;
+		interrupts = <GIC_SPI 606 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se6_spi: spi@898000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x898000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S6_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se6_spi_active>;
+		pinctrl-1 = <&qupv3_se6_spi_sleep>;
+		interrupts = <GIC_SPI 607 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	qupv3_se7_spi: spi@89c000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x89c000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP0_S7_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se7_spi_active>;
+		pinctrl-1 = <&qupv3_se7_spi_sleep>;
+		interrupts = <GIC_SPI 608 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_0>;
+		status = "disabled";
+	};
+
+	/* QUPv3 North & East Instances
+	 * North 0 : SE 8
+	 * North 1 : SE 9
+	 * North 2 : SE 10
+	 * North 3 : SE 11
+	 * North 4 : SE 12
+	 * North 5 : SE 16
+	 * East 0 : SE 17
+	 * East 1 : SE 18
+	 * East 2 : SE 19
+	 * East 3 : SE 13
+	 * East 4 : SE 14
+	 * East 5 : SE 15
+	 */
+	qupv3_1: qcom,qupv3_1_geni_se@ac0000 {
+		compatible = "qcom,qupv3-geni-se";
+		reg = <0xac0000 0x6000>;
+		qcom,bus-mas-id = <MSM_BUS_MASTER_QUP_1>;
+		qcom,bus-slv-id = <MSM_BUS_SLAVE_EBI_CH0>;
+		qcom,iommu-s1-bypass;
+
+		iommu_qupv3_1_geni_se_cb: qcom,iommu_qupv3_1_geni_se_cb {
+			compatible = "qcom,qupv3-geni-se-cb";
+			iommus = <&apps_smmu 0x603 0x0>;
+		};
+	};
+
+	/* 2-wire UART */
+
+	/* Debug UART Instance for CDP/MTP platform */
+	qupv3_se12_2uart: qcom,qup_uart@0xa90000 {
+		compatible = "qcom,msm-geni-console";
+		reg = <0xa90000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S4_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se12_2uart_active>;
+		pinctrl-1 = <&qupv3_se12_2uart_sleep>;
+		interrupts = <GIC_SPI 357 0>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	/* 4-wire UART */
+	qupv3_se13_4uart: qcom,qup_uart@0xc8c000 {
+		compatible = "qcom,msm-geni-serial-hs";
+		reg = <0xc8c000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S3_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se13_ctsrx>, <&qupv3_se13_rts>,
+						<&qupv3_se13_tx>;
+		pinctrl-1 = <&qupv3_se13_ctsrx>, <&qupv3_se13_rts>,
+						<&qupv3_se13_tx>;
+		interrupts = <GIC_SPI 585 0>;
+		qcom,wrapper-core = <&qupv3_2>;
+		qcom,wakeup-byte = <0xFD>;
+		status = "disabled";
+	};
+
+	/* I2C */
+	qupv3_se8_i2c: i2c@a80000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xa80000 0x4000>;
+		interrupts = <GIC_SPI 353 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S0_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se8_i2c_active>;
+		pinctrl-1 = <&qupv3_se8_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se9_i2c: i2c@a84000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xa84000 0x4000>;
+		interrupts = <GIC_SPI 354 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S1_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se9_i2c_active>;
+		pinctrl-1 = <&qupv3_se9_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se10_i2c: i2c@a88000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xa88000 0x4000>;
+		interrupts = <GIC_SPI 355 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S2_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se10_i2c_active>;
+		pinctrl-1 = <&qupv3_se10_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se11_i2c: i2c@a8c000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xa8c000 0x4000>;
+		interrupts = <GIC_SPI 356 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S3_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se11_i2c_active>;
+		pinctrl-1 = <&qupv3_se11_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se12_i2c: i2c@a90000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xa90000 0x4000>;
+		interrupts = <GIC_SPI 357 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S4_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se12_i2c_active>;
+		pinctrl-1 = <&qupv3_se12_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se13_i2c: i2c@c8c000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xc8c000 0x4000>;
+		interrupts = <GIC_SPI 585 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S3_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se13_i2c_active>;
+		pinctrl-1 = <&qupv3_se13_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	/* SPI */
+	qupv3_se8_spi: spi@a80000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xa80000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S0_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se8_spi_active>;
+		pinctrl-1 = <&qupv3_se8_spi_active>;
+		interrupts = <GIC_SPI 353 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se9_spi: spi@a84000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xa84000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S1_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se9_spi_active>;
+		pinctrl-1 = <&qupv3_se9_spi_sleep>;
+		interrupts = <GIC_SPI 354 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se10_spi: spi@a88000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xa88000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S2_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se10_spi_active>;
+		pinctrl-1 = <&qupv3_se10_spi_sleep>;
+		interrupts = <GIC_SPI 355 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se11_spi: spi@a8c000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xa8c000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S3_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se11_spi_active>;
+		pinctrl-1 = <&qupv3_se11_spi_sleep>;
+		interrupts = <GIC_SPI 356 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se12_spi: spi@a90000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xa90000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S4_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se12_spi_active>;
+		pinctrl-1 = <&qupv3_se12_spi_sleep>;
+		interrupts = <GIC_SPI 357 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se13_spi: spi@c8c000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xc8c000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S3_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se13_spi_active>;
+		pinctrl-1 = <&qupv3_se13_spi_sleep>;
+		interrupts = <GIC_SPI 585 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	/* QUPv3 East Instances */
+	qupv3_2: qcom,qupv3_2_geni_se@cc0000 {
+		compatible = "qcom,qupv3-geni-se";
+		reg = <0xcc0000 0x6000>;
+		qcom,bus-mas-id = <MSM_BUS_MASTER_QUP_2>;
+		qcom,bus-slv-id = <MSM_BUS_SLAVE_EBI_CH0>;
+		qcom,iommu-s1-bypass;
+
+		iommu_qupv3_2_geni_se_cb: qcom,iommu_qupv3_2_geni_se_cb {
+			compatible = "qcom,qupv3-geni-se-cb";
+			iommus = <&apps_smmu 0x7a3 0x0>;
+		};
+	};
+
+	/* I2C */
+	qupv3_se14_i2c: i2c@0xc90000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xc90000 0x4000>;
+		interrupts = <GIC_SPI 586 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S4_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se14_i2c_active>;
+		pinctrl-1 = <&qupv3_se14_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	qupv3_se15_i2c: i2c@0xc94000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xc94000 0x4000>;
+		interrupts = <GIC_SPI 587 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S5_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se15_i2c_active>;
+		pinctrl-1 = <&qupv3_se15_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	qupv3_se16_i2c: i2c@0xa94000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xa94000 0x4000>;
+		interrupts = <GIC_SPI 358 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S5_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se16_i2c_active>;
+		pinctrl-1 = <&qupv3_se16_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se17_i2c: i2c@0xc80000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xc80000 0x4000>;
+		interrupts = <GIC_SPI 373 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S0_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se17_i2c_active>;
+		pinctrl-1 = <&qupv3_se17_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	qupv3_se18_i2c: i2c@0xc84000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xc84000 0x4000>;
+		interrupts = <GIC_SPI 583 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S1_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se18_i2c_active>;
+		pinctrl-1 = <&qupv3_se18_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	qupv3_se19_i2c: i2c@0xc88000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0xc88000 0x4000>;
+		interrupts = <GIC_SPI 584 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S2_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se19_i2c_active>;
+		pinctrl-1 = <&qupv3_se19_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	/* SPI */
+	qupv3_se14_spi: spi@c90000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xc90000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S4_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se14_spi_active>;
+		pinctrl-1 = <&qupv3_se14_spi_sleep>;
+		interrupts = <GIC_SPI 586 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	qupv3_se15_spi: spi@c90000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xc90000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S5_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se15_spi_active>;
+		pinctrl-1 = <&qupv3_se15_spi_sleep>;
+		interrupts = <GIC_SPI 587 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	qupv3_se16_spi: spi@a94000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xa94000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP1_S5_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se16_spi_active>;
+		pinctrl-1 = <&qupv3_se16_spi_sleep>;
+		interrupts = <GIC_SPI 358 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_1>;
+		status = "disabled";
+	};
+
+	qupv3_se17_spi: spi@c80000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xc80000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S0_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se17_spi_active>;
+		pinctrl-1 = <&qupv3_se17_spi_sleep>;
+		interrupts = <GIC_SPI 373 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	qupv3_se18_spi: spi@c84000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xc84000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S1_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se18_spi_active>;
+		pinctrl-1 = <&qupv3_se18_spi_sleep>;
+		interrupts = <GIC_SPI 583 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	qupv3_se19_spi: spi@c88000 {
+		compatible = "qcom,spi-geni";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xc88000 0x4000>;
+		reg-names = "se_phys";
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt GCC_QUPV3_WRAP2_S2_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_M_AHB_CLK>,
+			<&clock_virt GCC_QUPV3_WRAP_2_S_AHB_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se19_spi_active>;
+		pinctrl-1 = <&qupv3_se19_spi_sleep>;
+		interrupts = <GIC_SPI 584 0>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_2>;
+		status = "disabled";
+	};
+
+	 /* QUPv3 SSC Instances */
+	qupv3_3: qcom,qupv3_3_geni_se@26c0000 {
+		compatible = "qcom,qupv3-geni-se";
+		reg = <0x26c0000 0x6000>;
+		qcom,bus-mas-id = <MSM_BUS_MASTER_SENSORS_AHB>;
+		qcom,bus-slv-id = <MSM_BUS_SLAVE_EBI_CH0>;
+		qcom,iommu-s1-bypass;
+
+		iommu_qupv3_3_geni_se_cb: qcom,iommu_qupv3_3_geni_se_cb {
+			compatible = "qcom,qupv3-geni-se-cb";
+			iommus = <&apps_smmu 0x4e3 0x0>;
+		};
+	};
+
+	/* I2C */
+	qupv3_se20_i2c: i2c@2680000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x2680000 0x4000>;
+		interrupts = <GIC_SPI 442 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt_scc SCC_QUPV3_SE0_CLK>,
+			<&clock_virt_scc SCC_QUPV3_M_HCLK_CLK>,
+			<&clock_virt_scc SCC_QUPV3_S_HCLK_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se20_i2c_active>;
+		pinctrl-1 = <&qupv3_se20_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_3>;
+		status = "disabled";
+	};
+
+	qupv3_se21_i2c: i2c@2684000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x2684000 0x4000>;
+		interrupts = <GIC_SPI 443 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt_scc SCC_QUPV3_SE1_CLK>,
+			<&clock_virt_scc SCC_QUPV3_M_HCLK_CLK>,
+			<&clock_virt_scc SCC_QUPV3_S_HCLK_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se21_i2c_active>;
+		pinctrl-1 = <&qupv3_se21_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_3>;
+		status = "disabled";
+	};
+
+	qupv3_se22_i2c: i2c@2688000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x2688000 0x4000>;
+		interrupts = <GIC_SPI 444 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt_scc SCC_QUPV3_SE2_CLK>,
+			<&clock_virt_scc SCC_QUPV3_M_HCLK_CLK>,
+			<&clock_virt_scc SCC_QUPV3_S_HCLK_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se22_i2c_active>;
+		pinctrl-1 = <&qupv3_se22_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_3>;
+		status = "disabled";
+	};
+
+	qupv3_se23_i2c: i2c@268c000 {
+		compatible = "qcom,i2c-geni";
+		reg = <0x268c000 0x4000>;
+		interrupts = <GIC_SPI 445 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt_scc SCC_QUPV3_SE3_CLK>,
+			<&clock_virt_scc SCC_QUPV3_M_HCLK_CLK>,
+			<&clock_virt_scc SCC_QUPV3_S_HCLK_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se23_i2c_active>;
+		pinctrl-1 = <&qupv3_se23_i2c_sleep>;
+		qcom,wrapper-core = <&qupv3_3>;
+		status = "disabled";
+	};
+
+	/* SPI */
+	qupv3_se21_spi: spi@2684000 {
+		compatible = "qcom,spi-geni";
+		reg = <0x2684000 0x4000>;
+		reg-names = "se_phys";
+		interrupts = <GIC_SPI 443 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt_scc SCC_QUPV3_SE1_CLK>,
+			<&clock_virt_scc SCC_QUPV3_M_HCLK_CLK>,
+			<&clock_virt_scc SCC_QUPV3_S_HCLK_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se21_spi_active>;
+		pinctrl-1 = <&qupv3_se21_spi_sleep>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_3>;
+		status = "disabled";
+	};
+
+	qupv3_se22_spi: spi@2688000 {
+		compatible = "qcom,spi-geni";
+		reg = <0x2688000 0x4000>;
+		reg-names = "se_phys";
+		interrupts = <GIC_SPI 444 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "se-clk", "m-ahb", "s-ahb";
+		clocks = <&clock_virt_scc SCC_QUPV3_SE2_CLK>,
+			<&clock_virt_scc SCC_QUPV3_M_HCLK_CLK>,
+			<&clock_virt_scc SCC_QUPV3_S_HCLK_CLK>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&qupv3_se22_spi_active>;
+		pinctrl-1 = <&qupv3_se22_spi_sleep>;
+		spi-max-frequency = <50000000>;
+		qcom,wrapper-core = <&qupv3_3>;
+		qcom,disable-dma;
+		status = "disabled";
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8155-vm-usb.dtsi b/arch/arm64/boot/dts/qcom/sa8155-vm-usb.dtsi
new file mode 100644
index 0000000..5e79647
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa8155-vm-usb.dtsi
@@ -0,0 +1,542 @@
+/* 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 <dt-bindings/clock/qcom,gcc-sm8150.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/msm/msm-bus-ids.h>
+#include <dt-bindings/phy/qcom,sm8150-qmp-usb3.h>
+
+&soc {
+	/* Primary USB port related controller */
+	usb0: ssusb@a600000 {
+		compatible = "qcom,dwc-usb3-msm";
+		reg = <0x0a600000 0x100000>;
+		reg-names = "core_base";
+
+		iommus = <&apps_smmu 0x140 0x0>;
+		qcom,smmu-s1-bypass;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		interrupts = <0 489 0>, <0 130 0>, <0 486 0>, <0 488 0>;
+		interrupt-names = "dp_hs_phy_irq", "pwr_event_irq",
+				"ss_phy_irq", "dm_hs_phy_irq";
+		qcom,use-pdc-interrupts;
+
+		USB3_GDSC-supply = <&usb30_prim_gdsc>;
+		dpdm-supply = <&usb2_phy0>;
+		clocks = <&clock_virt GCC_USB30_PRIM_MASTER_CLK>,
+			<&clock_virt GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
+			<&clock_virt GCC_AGGRE_USB3_PRIM_AXI_CLK>,
+			<&clock_virt GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+			<&clock_virt GCC_USB30_PRIM_SLEEP_CLK>,
+			<&clock_virt GCC_USB3_PRIM_CLKREF_CLK>;
+		clock-names = "core_clk", "iface_clk", "bus_aggr_clk",
+					"utmi_clk", "sleep_clk", "xo";
+
+		resets = <&clock_virt GCC_USB30_PRIM_BCR>;
+		reset-names = "core_reset";
+
+		qcom,core-clk-rate = <200000000>;
+		qcom,core-clk-rate-hs = <66666667>;
+		qcom,num-gsi-evt-buffs = <0x3>;
+		qcom,gsi-reg-offset =
+			<0x0fc /* GSI_GENERAL_CFG */
+			 0x110 /* GSI_DBL_ADDR_L */
+			 0x120 /* GSI_DBL_ADDR_H */
+			 0x130 /* GSI_RING_BASE_ADDR_L */
+			 0x144 /* GSI_RING_BASE_ADDR_H */
+			 0x1a4>; /* GSI_IF_STS */
+		qcom,dwc-usb3-msm-tx-fifo-size = <27696>;
+
+		status = "disabled";
+
+		dwc3@a600000 {
+			compatible = "snps,dwc3";
+			reg = <0x0a600000 0xcd00>;
+			interrupts = <0 133 0>;
+			usb-phy = <&usb2_phy0>, <&usb_nop_phy>;
+			linux,sysdev_is_parent;
+			snps,disable-clk-gating;
+			snps,has-lpm-erratum;
+			snps,hird-threshold = /bits/ 8 <0x10>;
+			snps,ssp-u3-u0-quirk;
+			snps,usb3-u1u2-disable;
+			usb-core-id = <0>;
+			tx-fifo-resize;
+			maximum-speed = "high-speed";
+			dr_mode = "otg";
+		};
+
+		usbbam: qcom,usbbam@a704000 {
+			compatible = "qcom,usb-bam-msm";
+			reg = <0xa704000 0x17000>;
+			interrupts = <0 132 0>;
+
+			qcom,usb-bam-fifo-baseaddr = <0x146bb000>;
+			qcom,usb-bam-num-pipes = <4>;
+			qcom,disable-clk-gating;
+			qcom,usb-bam-override-threshold = <0x4001>;
+			qcom,usb-bam-max-mbps-highspeed = <400>;
+			qcom,usb-bam-max-mbps-superspeed = <3600>;
+			qcom,reset-bam-on-connect;
+
+			status = "disabled";
+
+			qcom,pipe0 {
+				label = "ssusb-qdss-in-0";
+				qcom,usb-bam-mem-type = <2>;
+				qcom,dir = <1>;
+				qcom,pipe-num = <0>;
+				qcom,peer-bam = <0>;
+				qcom,peer-bam-physical-address = <0x6064000>;
+				qcom,src-bam-pipe-index = <0>;
+				qcom,dst-bam-pipe-index = <0>;
+				qcom,data-fifo-offset = <0x0>;
+				qcom,data-fifo-size = <0x1800>;
+				qcom,descriptor-fifo-offset = <0x1800>;
+				qcom,descriptor-fifo-size = <0x800>;
+			};
+		};
+	};
+
+	/* Primary USB port related High Speed PHY */
+	usb2_phy0: hsphy@88e2000 {
+		compatible = "qcom,usb-hsphy-snps-femto";
+		reg = <0x88e2000 0x110>,
+		    <0x007801f8 0x4>;
+		reg-names = "hsusb_phy_base",
+			"phy_rcal_reg";
+
+		vdd-supply = <&pm8150_l5>;
+		vdda18-supply = <&pm8150_l12>;
+		vdda33-supply = <&pm8150_l2>;
+		qcom,vdd-voltage-level = <0 880000 880000>;
+
+		clocks = <&clock_gcc RPMH_CXO_CLK>;
+		clock-names = "ref_clk_src";
+
+		resets = <&clock_virt GCC_QUSB2PHY_PRIM_BCR>;
+		reset-names = "phy_reset";
+		qcom,param-override-seq = <0x43 0x70>;
+		qcom,rcal-mask = <0x1e00000>;
+
+		status = "disabled";
+	};
+
+	/* Primary USB port related QMP USB DP Combo PHY */
+	usb_qmp_dp_phy: ssphy@88e8000 {
+		compatible = "qcom,usb-ssphy-qmp-dp-combo";
+		reg = <0x88e8000 0x3000>;
+		reg-names = "qmp_phy_base";
+
+		vdd-supply = <&pm8150_l5>;
+		qcom,vdd-voltage-level = <0 880000 880000>;
+		qcom,vdd-max-load-uA = <47000>;
+		core-supply = <&pm8150l_l3>;
+		qcom,vbus-valid-override;
+		qcom,link-training-reset;
+		qcom,qmp-phy-init-seq =
+		    /* <reg_offset, value, delay> */
+		    <USB3_DP_QSERDES_COM_SSC_EN_CENTER 0x01 0
+		     USB3_DP_QSERDES_COM_SSC_PER1 0x31 0
+		     USB3_DP_QSERDES_COM_SSC_PER2 0x01 0
+		     USB3_DP_QSERDES_COM_SSC_STEP_SIZE1_MODE0 0xde 0
+		     USB3_DP_QSERDES_COM_SSC_STEP_SIZE2_MODE0 0x07 0
+		     USB3_DP_QSERDES_COM_SSC_STEP_SIZE1_MODE1 0xde 0
+		     USB3_DP_QSERDES_COM_SSC_STEP_SIZE2_MODE1 0x07 0
+		     USB3_DP_QSERDES_COM_SYSCLK_BUF_ENABLE 0x0a 0
+		     USB3_DP_QSERDES_COM_CP_CTRL_MODE0 0x06 0
+		     USB3_DP_QSERDES_COM_CP_CTRL_MODE1 0x06 0
+		     USB3_DP_QSERDES_COM_PLL_RCTRL_MODE0 0x16 0
+		     USB3_DP_QSERDES_COM_PLL_RCTRL_MODE1 0x16 0
+		     USB3_DP_QSERDES_COM_PLL_CCTRL_MODE0 0x36 0
+		     USB3_DP_QSERDES_COM_PLL_CCTRL_MODE1 0x36 0
+		     USB3_DP_QSERDES_COM_SYSCLK_EN_SEL 0x1a 0
+		     USB3_DP_QSERDES_COM_LOCK_CMP_EN 0x04 0
+		     USB3_DP_QSERDES_COM_LOCK_CMP1_MODE0 0x14 0
+		     USB3_DP_QSERDES_COM_LOCK_CMP2_MODE0 0x34 0
+		     USB3_DP_QSERDES_COM_LOCK_CMP1_MODE1 0x34 0
+		     USB3_DP_QSERDES_COM_LOCK_CMP2_MODE1 0x82 0
+		     USB3_DP_QSERDES_COM_DEC_START_MODE0 0x82 0
+		     USB3_DP_QSERDES_COM_DEC_START_MODE1 0x82 0
+		     USB3_DP_QSERDES_COM_DIV_FRAC_START1_MODE0 0xab 0
+		     USB3_DP_QSERDES_COM_DIV_FRAC_START2_MODE0 0xea 0
+		     USB3_DP_QSERDES_COM_DIV_FRAC_START3_MODE0 0x02 0
+		     USB3_DP_QSERDES_COM_DIV_FRAC_START1_MODE1 0xab 0
+		     USB3_DP_QSERDES_COM_DIV_FRAC_START2_MODE1 0xea 0
+		     USB3_DP_QSERDES_COM_DIV_FRAC_START3_MODE1 0x02 0
+		     USB3_DP_QSERDES_COM_VCO_TUNE1_MODE0 0x24 0
+		     USB3_DP_QSERDES_COM_VCO_TUNE1_MODE1 0x24 0
+		     USB3_DP_QSERDES_COM_VCO_TUNE2_MODE1 0x02 0
+		     USB3_DP_QSERDES_COM_HSCLK_SEL 0x01 0
+		     USB3_DP_QSERDES_COM_CORECLK_DIV_MODE1 0x08 0
+		     USB3_DP_QSERDES_COM_SVS_MODE_CLK_SEL 0x5 0
+		     USB3_DP_QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0xca 0
+		     USB3_DP_QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1e 0
+		     USB3_DP_QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0xca 0
+		     USB3_DP_QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1e 0
+		     USB3_DP_QSERDES_COM_BIN_VCOCAL_HSCLK_SEL 0x11 0
+		     USB3_DP_QSERDES_COM_VCO_TUNE_MAP 0x02 0
+		     USB3_DP_QSERDES_COM_CMN_IPTRIM 0x20 0
+		     USB3_DP_QSERDES_TXA_LANE_MODE_1 0x05 0
+		     USB3_DP_QSERDES_TXA_RCV_DETECT_LVL_2 0x12 0
+		     USB3_DP_QSERDES_TXA_RES_CODE_LANE_TX 0xe4 0
+		     USB3_DP_QSERDES_TXA_RES_CODE_LANE_RX 0xd0 0
+		     USB3_DP_QSERDES_RXA_UCDR_SO_GAIN 0x04 0
+		     USB3_DP_QSERDES_RXA_UCDR_FASTLOCK_FO_GAIN 0x2f 0
+		     USB3_DP_QSERDES_RXA_UCDR_SO_SATURATION_AND_ENABLE 0x7f 0
+		     USB3_DP_QSERDES_RXA_UCDR_FASTLOCK_COUNT_LOW 0xff 0
+		     USB3_DP_QSERDES_RXA_UCDR_FASTLOCK_COUNT_HIGH 0x0f 0
+		     USB3_DP_QSERDES_RXA_UCDR_PI_CONTROLS 0x99 0
+		     USB3_DP_QSERDES_RXA_UCDR_SB2_THRESH1 0x04 0
+		     USB3_DP_QSERDES_RXA_UCDR_SB2_THRESH2 0x08 0
+		     USB3_DP_QSERDES_RXA_UCDR_SB2_GAIN1 0x05 0
+		     USB3_DP_QSERDES_RXA_UCDR_SB2_GAIN2 0x05 0
+		     USB3_DP_QSERDES_RXA_VGA_CAL_CNTRL1 0x54 0
+		     USB3_DP_QSERDES_RXA_VGA_CAL_CNTRL2 0x08 0
+		     USB3_DP_QSERDES_RXA_GM_CAL 0x1f 0
+		     USB3_DP_QSERDES_RXA_RX_EQU_ADAPTOR_CNTRL2 0x0f 0
+		     USB3_DP_QSERDES_RXA_RX_EQU_ADAPTOR_CNTRL3 0x4a 0
+		     USB3_DP_QSERDES_RXA_RX_EQU_ADAPTOR_CNTRL4 0x0a 0
+		     USB3_DP_QSERDES_RXA_RX_IDAC_TSETTLE_LOW 0xc0 0
+		     USB3_DP_QSERDES_RXA_RX_IDAC_TSETTLE_HIGH 0x00 0
+		     USB3_DP_QSERDES_RXA_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x77 0
+		     USB3_DP_QSERDES_RXA_RX_OFFSET_ADAPTOR_CNTRL2 0x80 0
+		     USB3_DP_QSERDES_RXA_SIGDET_CNTRL 0x04 0
+		     USB3_DP_QSERDES_RXA_SIGDET_DEGLITCH_CNTRL 0x0e 0
+		     USB3_DP_QSERDES_RXA_RX_MODE_00_LOW 0x3f 0
+		     USB3_DP_QSERDES_RXA_RX_MODE_00_HIGH 0x7f 0
+		     USB3_DP_QSERDES_RXA_RX_MODE_00_HIGH2 0x7f 0
+		     USB3_DP_QSERDES_RXA_RX_MODE_00_HIGH3 0x3f 0
+		     USB3_DP_QSERDES_RXA_RX_MODE_00_HIGH4 0xa4 0
+		     USB3_DP_QSERDES_RXA_RX_MODE_01_LOW 0xdc 0
+		     USB3_DP_QSERDES_RXA_RX_MODE_01_HIGH 0xdc 0
+		     USB3_DP_QSERDES_RXA_RX_MODE_01_HIGH2 0x5c 0
+		     USB3_DP_QSERDES_RXA_RX_MODE_01_HIGH3 0x0b 0
+		     USB3_DP_QSERDES_RXA_RX_MODE_01_HIGH4 0xb3 0
+		     USB3_DP_QSERDES_RXA_DFE_EN_TIMER 0x04 0
+		     USB3_DP_QSERDES_RXA_DFE_CTLE_POST_CAL_OFFSET 0x30 0
+		     USB3_DP_QSERDES_TXB_LANE_MODE_1 0x05 0
+		     USB3_DP_QSERDES_TXB_RCV_DETECT_LVL_2 0x12 0
+		     USB3_DP_QSERDES_TXB_RES_CODE_LANE_TX 0xe4 0
+		     USB3_DP_QSERDES_TXB_RES_CODE_LANE_RX 0xd0 0
+		     USB3_DP_QSERDES_RXB_UCDR_SO_GAIN 0x04 0
+		     USB3_DP_QSERDES_RXB_UCDR_FASTLOCK_FO_GAIN 0x2f 0
+		     USB3_DP_QSERDES_RXB_UCDR_SO_SATURATION_AND_ENABLE 0x7f 0
+		     USB3_DP_QSERDES_RXB_UCDR_FASTLOCK_COUNT_LOW 0xff 0
+		     USB3_DP_QSERDES_RXB_UCDR_FASTLOCK_COUNT_HIGH 0x0f 0
+		     USB3_DP_QSERDES_RXB_UCDR_PI_CONTROLS 0x99 0
+		     USB3_DP_QSERDES_RXB_UCDR_SB2_THRESH1 0x04 0
+		     USB3_DP_QSERDES_RXB_UCDR_SB2_THRESH2 0x08 0
+		     USB3_DP_QSERDES_RXB_UCDR_SB2_GAIN1 0x05 0
+		     USB3_DP_QSERDES_RXB_UCDR_SB2_GAIN2 0x05 0
+		     USB3_DP_QSERDES_RXB_VGA_CAL_CNTRL1 0x54 0
+		     USB3_DP_QSERDES_RXB_VGA_CAL_CNTRL2 0x08 0
+		     USB3_DP_QSERDES_RXB_GM_CAL 0x1f 0
+		     USB3_DP_QSERDES_RXB_RX_EQU_ADAPTOR_CNTRL2 0x0f 0
+		     USB3_DP_QSERDES_RXB_RX_EQU_ADAPTOR_CNTRL3 0x4a 0
+		     USB3_DP_QSERDES_RXB_RX_EQU_ADAPTOR_CNTRL4 0x0a 0
+		     USB3_DP_QSERDES_RXB_RX_IDAC_TSETTLE_LOW 0xc0 0
+		     USB3_DP_QSERDES_RXB_RX_IDAC_TSETTLE_HIGH 0x00 0
+		     USB3_DP_QSERDES_RXB_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x77 0
+		     USB3_DP_QSERDES_RXB_RX_OFFSET_ADAPTOR_CNTRL2 0x80 0
+		     USB3_DP_QSERDES_RXB_SIGDET_CNTRL 0x04 0
+		     USB3_DP_QSERDES_RXB_SIGDET_DEGLITCH_CNTRL 0x0e 0
+		     USB3_DP_QSERDES_RXB_RX_MODE_00_LOW 0x3f 0
+		     USB3_DP_QSERDES_RXB_RX_MODE_00_HIGH 0x7f 0
+		     USB3_DP_QSERDES_RXB_RX_MODE_00_HIGH2 0x7f 0
+		     USB3_DP_QSERDES_RXB_RX_MODE_00_HIGH3 0x3f 0
+		     USB3_DP_QSERDES_RXB_RX_MODE_00_HIGH4 0xa4 0
+		     USB3_DP_QSERDES_RXB_RX_MODE_01_LOW 0xdc 0
+		     USB3_DP_QSERDES_RXB_RX_MODE_01_HIGH 0xdc 0
+		     USB3_DP_QSERDES_RXB_RX_MODE_01_HIGH2 0x5c 0
+		     USB3_DP_QSERDES_RXB_RX_MODE_01_HIGH3 0x0b 0
+		     USB3_DP_QSERDES_RXB_RX_MODE_01_HIGH4 0xb3 0
+		     USB3_DP_QSERDES_RXB_DFE_EN_TIMER 0x04 0
+		     USB3_DP_QSERDES_RXB_DFE_CTLE_POST_CAL_OFFSET 0x30 0
+		     USB3_DP_PCS_LOCK_DETECT_CONFIG1 0xd0 0
+		     USB3_DP_PCS_LOCK_DETECT_CONFIG2 0x17 0
+		     USB3_DP_PCS_LOCK_DETECT_CONFIG3 0x20 0
+		     USB3_DP_PCS_RX_SIGDET_LVL 0xaa 0
+		     USB3_DP_PCS_ALIGN_DETECT_CONFIG1 0x88 0
+		     USB3_DP_PCS_ALIGN_DETECT_CONFIG2 0x13 0
+		     USB3_DP_PCS_EQ_CONFIG1 0x0d 0
+		     USB3_DP_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL 0xf8 0
+		     USB3_DP_PCS_USB3_RXEQTRAINING_DFE_TIME_S2 0x07 0
+		     USB3_DP_PCS_EQ_CONFIG5 0x02 0
+		     0xffffffff 0xffffffff 0x00>;
+
+		qcom,qmp-phy-reg-offset =
+			<USB3_DP_PCS_PCS_STATUS1
+			 USB3_DP_PCS_USB3_AUTONOMOUS_MODE_CTRL
+			 USB3_DP_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR
+			 USB3_DP_PCS_POWER_DOWN_CONTROL
+			 USB3_DP_PCS_SW_RESET
+			 USB3_DP_PCS_START_CONTROL
+			 0xffff /* USB3_PHY_PCS_MISC_TYPEC_CTRL */
+			 0x2a18 /* USB3_DP_DP_PHY_PD_CTL */
+			 USB3_DP_COM_POWER_DOWN_CTRL
+			 USB3_DP_COM_SW_RESET
+			 USB3_DP_COM_RESET_OVRD_CTRL
+			 USB3_DP_COM_PHY_MODE_CTRL
+			 USB3_DP_COM_TYPEC_CTRL
+			 USB3_DP_COM_SWI_CTRL
+			 USB3_DP_PCS_CLAMP_ENABLE
+			 USB3_DP_PCS_PCS_STATUS2
+			 USB3_DP_PCS_INSIG_SW_CTRL3
+			 USB3_DP_PCS_INSIG_MX_CTRL3>;
+
+		clocks = <&clock_virt GCC_USB3_PRIM_PHY_AUX_CLK>,
+			<&clock_virt GCC_USB3_PRIM_PHY_PIPE_CLK>,
+			<&clock_gcc RPMH_CXO_CLK>,
+			<&clock_virt GCC_USB3_PRIM_CLKREF_CLK>,
+			<&clock_virt GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
+		clock-names = "aux_clk", "pipe_clk", "ref_clk_src",
+				"ref_clk", "com_aux_clk";
+
+		resets = <&clock_virt GCC_USB3_DP_PHY_PRIM_BCR>,
+			<&clock_virt GCC_USB3_PHY_PRIM_BCR>;
+		reset-names = "global_phy_reset", "phy_reset";
+
+		status = "disabled";
+	};
+
+	usb_audio_qmi_dev {
+		compatible = "qcom,usb-audio-qmi-dev";
+		iommus = <&apps_smmu 0x1b2f 0x0>;
+		qcom,usb-audio-stream-id = <0xf>;
+		qcom,usb-audio-intr-num = <2>;
+		status = "disabled";
+	};
+
+	usb_nop_phy: usb_nop_phy {
+		compatible = "usb-nop-xceiv";
+	};
+
+	/* Secondary USB port related controller */
+	usb1: ssusb@a800000 {
+		compatible = "qcom,dwc-usb3-msm";
+		reg = <0x0a800000 0x100000>;
+		reg-names = "core_base";
+
+		iommus = <&apps_smmu 0x160 0x0>;
+		qcom,smmu-s1-bypass;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		interrupts = <0 491 0>, <0 135 0>, <0 487 0>, <0 490 0>;
+		interrupt-names = "dp_hs_phy_irq", "pwr_event_irq",
+				"ss_phy_irq", "dm_hs_phy_irq";
+		qcom,use-pdc-interrupts;
+
+		USB3_GDSC-supply = <&usb30_sec_gdsc>;
+		clocks = <&clock_virt GCC_USB30_SEC_MASTER_CLK>,
+			<&clock_virt GCC_CFG_NOC_USB3_SEC_AXI_CLK>,
+			<&clock_virt GCC_AGGRE_USB3_SEC_AXI_CLK>,
+			<&clock_virt GCC_USB30_SEC_MOCK_UTMI_CLK>,
+			<&clock_virt GCC_USB30_SEC_SLEEP_CLK>,
+			 <&clock_virt GCC_USB3_SEC_CLKREF_CLK>;
+		clock-names = "core_clk", "iface_clk", "bus_aggr_clk",
+					"utmi_clk", "sleep_clk", "xo";
+
+		resets = <&clock_virt GCC_USB30_SEC_BCR>;
+		reset-names = "core_reset";
+
+		qcom,core-clk-rate = <200000000>;
+		qcom,core-clk-rate-hs = <66666667>;
+		qcom,num-gsi-evt-buffs = <0x3>;
+		qcom,gsi-reg-offset =
+			<0x0fc /* GSI_GENERAL_CFG */
+			 0x110 /* GSI_DBL_ADDR_L */
+			 0x120 /* GSI_DBL_ADDR_H */
+			 0x130 /* GSI_RING_BASE_ADDR_L */
+			 0x144 /* GSI_RING_BASE_ADDR_H */
+			 0x1a4>; /* GSI_IF_STS */
+		qcom,dwc-usb3-msm-tx-fifo-size = <27696>;
+		qcom,charging-disabled;
+
+		status = "disabled";
+
+		dwc3@a800000 {
+			compatible = "snps,dwc3";
+			reg = <0x0a800000 0xcd00>;
+			interrupts = <0 138 0>;
+			usb-phy = <&usb2_phy1>, <&usb_qmp_phy>;
+			linux,sysdev_is_parent;
+			snps,disable-clk-gating;
+			snps,has-lpm-erratum;
+			snps,hird-threshold = /bits/ 8 <0x10>;
+			snps,usb3_lpm_capable;
+			usb-core-id = <1>;
+			tx-fifo-resize;
+			maximum-speed = "super-speed";
+			dr_mode = "otg";
+		};
+	};
+
+	/* Primary USB port related High Speed PHY */
+	usb2_phy1: hsphy@88e3000 {
+		compatible = "qcom,usb-hsphy-snps-femto";
+		reg = <0x88e3000 0x110>,
+		   <0x007801f8 0x4>;
+		reg-names = "hsusb_phy_base",
+			"phy_rcal_reg";
+
+		vdd-supply = <&pm8150_l5>;
+		vdda18-supply = <&pm8150_l12>;
+		vdda33-supply = <&pm8150_l2>;
+		qcom,vdd-voltage-level = <0 880000 880000>;
+
+		clocks = <&clock_gcc RPMH_CXO_CLK>;
+		clock-names = "ref_clk_src";
+
+		resets = <&clock_virt GCC_QUSB2PHY_SEC_BCR>;
+		reset-names = "phy_reset";
+		qcom,rcal-mask = <0x1e00000>;
+
+		status = "disabled";
+	};
+
+	/* Secondary USB port related QMP PHY */
+	usb_qmp_phy: ssphy@88eb000 {
+		compatible = "qcom,usb-ssphy-qmp-v2";
+		reg = <0x88eb000 0x1000>,
+		    <0x088eb88c 0x4>;
+		reg-names = "qmp_phy_base",
+			"pcs_clamp_enable_reg";
+
+		vdd-supply = <&pm8150_l5>;
+		qcom,vdd-voltage-level = <0 880000 880000>;
+		qcom,vdd-max-load-uA = <47000>;
+		core-supply = <&pm8150l_l3>;
+		qcom,vbus-valid-override;
+		qcom,qmp-phy-init-seq =
+		    /* <reg_offset, value, delay> */
+		    <USB3_UNI_QSERDES_COM_SYSCLK_EN_SEL 0x1a 0
+		     USB3_UNI_QSERDES_COM_BIN_VCOCAL_HSCLK_SEL 0x11 0
+		     USB3_UNI_QSERDES_COM_HSCLK_SEL 0x01 0
+		     USB3_UNI_QSERDES_COM_DEC_START_MODE0 0x82 0
+		     USB3_UNI_QSERDES_COM_DIV_FRAC_START1_MODE0 0xab 0
+		     USB3_UNI_QSERDES_COM_DIV_FRAC_START2_MODE0 0xea 0
+		     USB3_UNI_QSERDES_COM_DIV_FRAC_START3_MODE0 0x02 0
+		     USB3_UNI_QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0xca 0
+		     USB3_UNI_QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1e 0
+		     USB3_UNI_QSERDES_COM_CP_CTRL_MODE0 0x06 0
+		     USB3_UNI_QSERDES_COM_PLL_RCTRL_MODE0 0x16 0
+		     USB3_UNI_QSERDES_COM_PLL_CCTRL_MODE0 0x36 0
+		     USB3_UNI_QSERDES_COM_VCO_TUNE1_MODE0 0x24 0
+		     USB3_UNI_QSERDES_COM_LOCK_CMP2_MODE0 0x34 0
+		     USB3_UNI_QSERDES_COM_LOCK_CMP1_MODE0 0x14 0
+		     USB3_UNI_QSERDES_COM_LOCK_CMP_EN 0x04 0
+		     USB3_UNI_QSERDES_COM_SYSCLK_BUF_ENABLE 0x0a 0
+		     USB3_UNI_QSERDES_COM_VCO_TUNE2_MODE1 0x02 0
+		     USB3_UNI_QSERDES_COM_VCO_TUNE1_MODE1 0x24 0
+		     USB3_UNI_QSERDES_COM_CORECLK_DIV_MODE1 0x08 0
+		     USB3_UNI_QSERDES_COM_DEC_START_MODE1 0x82 0
+		     USB3_UNI_QSERDES_COM_DIV_FRAC_START1_MODE1 0xab 0
+		     USB3_UNI_QSERDES_COM_DIV_FRAC_START2_MODE1 0xea 0
+		     USB3_UNI_QSERDES_COM_DIV_FRAC_START3_MODE1 0x02 0
+		     USB3_UNI_QSERDES_COM_LOCK_CMP2_MODE1 0x82 0
+		     USB3_UNI_QSERDES_COM_LOCK_CMP1_MODE1 0x34 0
+		     USB3_UNI_QSERDES_COM_CP_CTRL_MODE1 0x06 0
+		     USB3_UNI_QSERDES_COM_PLL_RCTRL_MODE1 0x16 0
+		     USB3_UNI_QSERDES_COM_PLL_CCTRL_MODE1 0x36 0
+		     USB3_UNI_QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0xca 0
+		     USB3_UNI_QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1e 0
+		     USB3_UNI_QSERDES_COM_SSC_EN_CENTER 0x01 0
+		     USB3_UNI_QSERDES_COM_SSC_PER1 0x31 0
+		     USB3_UNI_QSERDES_COM_SSC_PER2 0x01 0
+		     USB3_UNI_QSERDES_COM_SSC_STEP_SIZE1_MODE1 0xde 0
+		     USB3_UNI_QSERDES_COM_SSC_STEP_SIZE2_MODE1 0x07 0
+		     USB3_UNI_QSERDES_COM_SSC_STEP_SIZE1_MODE0 0xde 0
+		     USB3_UNI_QSERDES_COM_SSC_STEP_SIZE2_MODE0 0x07 0
+		     USB3_UNI_QSERDES_COM_VCO_TUNE_MAP 0x02 0
+		     USB3_UNI_QSERDES_COM_CMN_IPTRIM 0x20 0
+		     USB3_UNI_QSERDES_RX_RX_MODE_00_HIGH4 0x8a 0
+		     USB3_UNI_QSERDES_RX_RX_MODE_00_HIGH3 0x3f 0
+		     USB3_UNI_QSERDES_RX_RX_MODE_00_HIGH2 0x3f 0
+		     USB3_UNI_QSERDES_RX_RX_MODE_00_HIGH 0xbf 0
+		     USB3_UNI_QSERDES_RX_RX_MODE_00_LOW 0x3f 0
+		     USB3_UNI_QSERDES_RX_RX_MODE_01_HIGH4 0xb3 0
+		     USB3_UNI_QSERDES_RX_RX_MODE_01_HIGH3 0x0b 0
+		     USB3_UNI_QSERDES_RX_RX_MODE_01_HIGH2 0x5c 0
+		     USB3_UNI_QSERDES_RX_RX_MODE_01_HIGH 0xdc 0
+		     USB3_UNI_QSERDES_RX_RX_MODE_01_LOW 0xdc 0
+		     USB3_UNI_QSERDES_RX_UCDR_PI_CONTROLS 0x99 0
+		     USB3_UNI_QSERDES_RX_UCDR_SB2_THRESH1 0x04 0
+		     USB3_UNI_QSERDES_RX_UCDR_SB2_THRESH2 0x08 0
+		     USB3_UNI_QSERDES_RX_UCDR_SB2_GAIN1 0x05 0
+		     USB3_UNI_QSERDES_RX_UCDR_SB2_GAIN2 0x05 0
+		     USB3_UNI_QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x2f 0
+		     USB3_UNI_QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW 0xff 0
+		     USB3_UNI_QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH 0x0f 0
+		     USB3_UNI_QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x7f 0
+		     USB3_UNI_QSERDES_RX_VGA_CAL_CNTRL1 0x54 0
+		     USB3_UNI_QSERDES_RX_VGA_CAL_CNTRL2 0x08 0
+		     USB3_UNI_QSERDES_RX_GM_CAL 0x1f 0
+		     USB3_UNI_QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x0f 0
+		     USB3_UNI_QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x4a 0
+		     USB3_UNI_QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x0a 0
+		     USB3_UNI_QSERDES_RX_DFE_EN_TIMER 0x04 0
+		     USB3_UNI_QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x77 0
+		     USB3_UNI_QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x80 0
+		     USB3_UNI_QSERDES_RX_SIGDET_CNTRL 0x04 0
+		     USB3_UNI_QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x0e 0
+		     USB3_UNI_QSERDES_RX_RX_IDAC_TSETTLE_HIGH 0x00 0
+		     USB3_UNI_QSERDES_RX_RX_IDAC_TSETTLE_LOW 0xc0 0
+		     USB3_UNI_QSERDES_RX_DFE_CTLE_POST_CAL_OFFSET 0x30 0
+		     USB3_UNI_QSERDES_RX_UCDR_SO_GAIN 0x04 0
+		     USB3_UNI_QSERDES_TX_RCV_DETECT_LVL_2 0x12 0
+		     USB3_UNI_QSERDES_TX_LANE_MODE_1 0x05 0
+		     USB3_UNI_QSERDES_TX_RES_CODE_LANE_TX 0xe4 0
+		     USB3_UNI_QSERDES_TX_RES_CODE_LANE_RX 0xd0 0
+		     USB3_UNI_PCS_LOCK_DETECT_CONFIG1 0xd0 0
+		     USB3_UNI_PCS_LOCK_DETECT_CONFIG2 0x17 0
+		     USB3_UNI_PCS_LOCK_DETECT_CONFIG3 0x20 0
+		     USB3_UNI_PCS_RCVR_DTCT_DLY_P1U2_L 0xe7 0
+		     USB3_UNI_PCS_RCVR_DTCT_DLY_P1U2_H 0x03 0
+		     USB3_UNI_PCS_RX_SIGDET_LVL 0xaa 0
+		     USB3_UNI_PCS_USB3_RXEQTRAINING_DFE_TIME_S2 0x07 0
+		     USB3_UNI_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL 0xf8 0
+		     USB3_UNI_PCS_ALIGN_DETECT_CONFIG1 0x88 0
+		     USB3_UNI_PCS_ALIGN_DETECT_CONFIG2 0x13 0
+		     USB3_UNI_PCS_EQ_CONFIG1 0x0d 0
+		     USB3_UNI_PCS_REFGEN_REQ_CONFIG1 0x21 0
+		     USB3_UNI_PCS_PCS_TX_RX_CONFIG 0x08 0
+		     0xffffffff 0xffffffff 0x00>;
+
+		qcom,qmp-phy-reg-offset =
+				<USB3_UNI_PCS_PCS_STATUS1
+				 USB3_UNI_PCS_USB3_AUTONOMOUS_MODE_CTRL
+				 USB3_UNI_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR
+				 USB3_UNI_PCS_POWER_DOWN_CONTROL
+				 USB3_UNI_PCS_SW_RESET
+				 USB3_UNI_PCS_START_CONTROL>;
+
+		clocks = <&clock_virt GCC_USB3_SEC_PHY_AUX_CLK>,
+			 <&clock_virt GCC_USB3_SEC_PHY_PIPE_CLK>,
+			 <&clock_gcc RPMH_CXO_CLK>,
+			 <&clock_virt GCC_USB3_SEC_CLKREF_CLK>,
+			 <&clock_virt GCC_USB3_SEC_PHY_COM_AUX_CLK>;
+		clock-names = "aux_clk", "pipe_clk", "ref_clk_src",
+				"ref_clk", "com_aux_clk";
+
+		resets = <&clock_virt GCC_USB3_PHY_SEC_BCR>,
+			<&clock_virt GCC_USB3PHY_PHY_SEC_BCR>;
+		reset-names = "phy_reset", "phy_phy_reset";
+
+		status = "disabled";
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8155-vm.dts b/arch/arm64/boot/dts/qcom/sa8155-vm.dts
index 3be217dc..db9167e 100644
--- a/arch/arm64/boot/dts/qcom/sa8155-vm.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155-vm.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  */
 
 /dts-v1/;
@@ -13,3 +13,19 @@
 	qcom,pmic-name = "PM8150";
 	qcom,board-id = <0 0>;
 };
+
+&slpi_tlmm {
+	status = "ok";
+};
+
+&apps_smmu {
+	status = "ok";
+};
+
+&usb0 {
+	status = "ok";
+};
+
+&usb2_phy0 {
+	status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8155-vm.dtsi b/arch/arm64/boot/dts/qcom/sa8155-vm.dtsi
index c5a9d7d..b06ce3c 100644
--- a/arch/arm64/boot/dts/qcom/sa8155-vm.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8155-vm.dtsi
@@ -5,6 +5,7 @@
 
 #include "skeleton64.dtsi"
 #include <dt-bindings/clock/qcom,gcc-sm8150.h>
+#include <dt-bindings/clock/qcom,scc-sm8150.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
@@ -73,6 +74,18 @@
 	ranges = <0 0 0 0xffffffff>;
 	compatible = "simple-bus";
 
+	clock_virt: qcom,virt-gcc {
+		compatible = "qcom,virt-clk-sm8150-gcc";
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	clock_virt_scc: qcom,virt-scc {
+		compatible = "qcom,virt-clk-sm8150-scc";
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
 	clock_gcc: qcom,gcc {
 		compatible = "qcom,dummycc";
 		#clock-cells = <1>;
@@ -159,6 +172,166 @@
 		compatible = "qcom,sde-kms-hyp";
 		qcom,client-id = "7815";
 	};
+
+	apps_smmu: apps-smmu@0x15000000 {
+		compatible = "qcom,qsmmu-v500";
+		reg = <0x15000000 0x100000>,
+			<0x15182000 0x20>;
+		reg-names = "base", "tcu-base";
+		#iommu-cells = <2>;
+		qcom,skip-init;
+		qcom,use-3-lvl-tables;
+		qcom,disable-atos;
+		#global-interrupts = <1>;
+		#size-cells = <1>;
+		#address-cells = <1>;
+		ranges;
+		interrupts =	<GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 395 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 396 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 407 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 408 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 409 IRQ_TYPE_LEVEL_HIGH>;
+
+		status = "disabled";
+	};
+
+	qcom,sps {
+		compatible = "qcom,msm-sps-4k";
+		qcom,pipe-attr-ee;
+		status = "disabled";
+	};
+
+	pm8150_l2: regulator-pm8150-l2 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "pm8150_l2";
+		regulator-min-microvolt = <3072000>;
+		regulator-max-microvolt = <3072000>;
+		qcom,init-voltage = <3072000>;
+		status = "okay";
+	};
+
+	pm8150_l5: regulator-pm8150-l5 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "pm8150_l5";
+		regulator-min-microvolt = <880000>;
+		regulator-max-microvolt = <880000>;
+		qcom,proxy-consumer-enable;
+		qcom,proxy-consumer-current = <23800>;
+		qcom,init-voltage = <880000>;
+		status = "okay";
+	};
+
+	pm8150_l12: regulator-pm8150-l12 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "pm8150_l12";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		qcom,init-voltage = <1800000>;
+		status = "okay";
+	};
+
+	pm8150l_l3: regulator-pm8150l-l3 {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "pm8150l_l3";
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+		qcom,proxy-consumer-enable;
+		qcom,proxy-consumer-current = <51800>;
+		qcom,init-voltage = <1200000>;
+		status = "okay";
+	};
+
+	usb30_prim_gdsc: usb30_prim_gdsc {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "usb30_prim_gdsc";
+		status = "okay";
+	};
+
+	usb30_sec_gdsc: usb30_sec_gdsc {
+		compatible = "qcom,stub-regulator";
+		regulator-name = "usb30_sec_gdsc";
+		status = "okay";
+	};
 };
 
-#include "sa8155-vm-pinctrl.dtsi"
+#include "sm8150-pinctrl.dtsi"
+#include "sm8150-slpi-pinctrl.dtsi"
+#include "sa8155-vm-qupv3.dtsi"
+#include "sa8155-vm-usb.dtsi"
+#include "sa8155-vm-audio.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sa8155.dtsi b/arch/arm64/boot/dts/qcom/sa8155.dtsi
index cc4c054..7871e9de 100644
--- a/arch/arm64/boot/dts/qcom/sa8155.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8155.dtsi
@@ -10,6 +10,12 @@
  * GNU General Public License for more details.
  */
 
+/ {
+	aliases {
+		i2c7 = &qupv3_se20_i2c;
+	};
+};
+
 /* Remove regulator nodes specific to SA8155 */
 &soc {
 	/delete-node/ regulator-pm8150-s4;
@@ -74,7 +80,7 @@
 		qca,bt-vdd-vh-supply = <&pm8150_2_l15>;
 
 		qca,bt-vdd-vl-voltage-level = <1055000 1055000>;
-		qca,bt-vdd-vm-voltage-level = <1350000 1350000>;
+		qca,bt-vdd-vm-voltage-level = <1370000 1370000>;
 		qca,bt-vdd-5c-voltage-level = <2040000 2040000>;
 		qca,bt-vdd-vh-voltage-level = <1900000 1900000>;
 
@@ -353,290 +359,24 @@
 			/delete-node/ mmcx_vdd_cdev;
 		};
 	};
-};
 
-&tlmm {
-	ioexp_intr_active: ioexp_intr_active {
-		mux {
-			pins = "gpio48";
-			function = "gpio";
-		};
-		config {
-			pins = "gpio48";
-			drive-strength = <2>;
-			bias-pull-up;
-		};
-	};
-
-	ioexp_reset_active: ioexp_reset_active {
-		mux {
-			pins = "gpio30";
-			function = "gpio";
-		};
-		config {
-			pins = "gpio30";
-			drive-strength = <2>;
-			bias-disable;
-			output-high;
-		};
-	};
-};
-
-&sde_dp {
-	qcom,ext-disp = <&ext_disp>;
-	qcom,dp-hpd-gpio = <&ioexp 8 0>;
-
-	pinctrl-names = "mdss_dp_active", "mdss_dp_sleep";
-	pinctrl-0 = <&dp_hpd_cfg_pins>;
-	pinctrl-1 = <&dp_hpd_cfg_pins>;
-
-	qcom,core-supply-entries {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		qcom,core-supply-entry@0 {
-			reg = <0>;
-			qcom,supply-name = "refgen";
-			qcom,supply-min-voltage = <0>;
-			qcom,supply-max-voltage = <0>;
-			qcom,supply-enable-load = <0>;
-			qcom,supply-disable-load = <0>;
-		};
-	};
-};
-
-&qupv3_se15_i2c {
-	status = "ok";
-
-	pinctrl-0 = <&qupv3_se15_i2c_active
-		&ioexp_intr_active
-		&ioexp_reset_active>;
-
-	ioexp: gpio@3e {
-		#gpio-cells = <2>;
-		#interrupt-cells = <2>;
-		compatible = "semtech,sx1509q";
-		reg = <0x3e>;
-		interrupt-parent = <&tlmm>;
-		interrupts = <48 0>;
-		gpio-controller;
-		interrupt-controller;
-		semtech,probe-reset;
-
-		pinctrl-names = "default";
-		pinctrl-0 = <&dsi1_hpd_cfg_pins
-			&dsi1_cdet_cfg_pins
-			&dsi2_hpd_cfg_pins
-			&dsi2_cdet_cfg_pins>;
-
-		dsi1_hpd_cfg_pins: gpio0-cfg {
-			pins = "gpio0";
-			bias-pull-up;
-		};
-
-		dsi1_cdet_cfg_pins: gpio1-cfg {
-			pins = "gpio1";
-			bias-pull-down;
-		};
-
-		dsi2_hpd_cfg_pins: gpio2-cfg {
-			pins = "gpio2";
-			bias-pull-up;
-		};
-
-		dsi2_cdet_cfg_pins: gpio3-cfg {
-			pins = "gpio3";
-			bias-pull-down;
-		};
-
-		dp_hpd_cfg_pins: gpio8-cfg {
-			pins = "gpio8";
-			bias-pull-down;
-		};
-	};
-
-	i2c-mux@77 {
-		compatible = "nxp,pca9542";
-		reg = <0x77>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		i2c@0 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <0>;
-
-			anx_7625_1: anx7625@2c {
-				compatible = "analogix,anx7625";
-				reg = <0x2c>;
-				interrupt-parent = <&ioexp>;
-				interrupts = <0 0>;
-				cbl_det-gpio = <&ioexp 1 0>;
-				power_en-gpio = <&tlmm 47 0>;
-				reset_n-gpio = <&tlmm 49 0>;
-			};
-		};
-
-		i2c@1 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <1>;
-
-			anx_7625_2: anx7625@2c {
-				compatible = "analogix,anx7625";
-				reg = <0x2c>;
-				interrupt-parent = <&ioexp>;
-				interrupts = <2 0>;
-				cbl_det-gpio = <&ioexp 3 0>;
-				power_en-gpio = <&tlmm 87 0>;
-				reset_n-gpio = <&tlmm 29 0>;
-			};
-		};
-	};
-};
-
-&anx_7625_1 {
-	ports {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		port@0 {
-			reg = <0>;
-			anx_7625_1_in: endpoint {
-				remote-endpoint = <&dsi_anx_7625_1_out>;
-			};
-		};
-	};
-};
-
-&anx_7625_2 {
-	ports {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		port@0 {
-			reg = <0>;
-			anx_7625_2_in: endpoint {
-				remote-endpoint = <&dsi_anx_7625_2_out>;
-			};
-		};
-	};
-};
-
-#include "dsi-panel-ext-bridge-1080p.dtsi"
-
-&soc {
-	dsi_anx_7625_1: qcom,dsi-display@17 {
-		label = "dsi_anx_7625_1";
-		qcom,dsi-display-active;
-		qcom,display-type = "primary";
-
-		qcom,dsi-ctrl-num = <0>;
-		qcom,dsi-phy-num = <0>;
-		qcom,dsi-select-clocks = "mux_byte_clk0", "mux_pixel_clk0";
-
-		qcom,dsi-panel = <&dsi_ext_bridge_1080p>;
-	};
-
-	dsi_anx_7625_2: qcom,dsi-display@18 {
-		label = "dsi_anx_7625_2";
-		qcom,dsi-display-active;
-		qcom,display-type = "secondary";
-
-		qcom,dsi-ctrl-num = <1>;
-		qcom,dsi-phy-num = <1>;
-		qcom,dsi-select-clocks = "mux_byte_clk1", "mux_pixel_clk1";
-
-		qcom,dsi-panel = <&dsi_ext_bridge_1080p>;
-	};
-
-	dsi_dp1: qcom,dsi-display@1 {
-		compatible = "qcom,dsi-display";
-		label = "primary";
-
-		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
-		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
-
-		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
-			 <&mdss_dsi0_pll PCLK_MUX_0_CLK>,
-			 <&mdss_dsi1_pll BYTECLK_MUX_1_CLK>,
-			 <&mdss_dsi1_pll PCLK_MUX_1_CLK>;
-		clock-names = "mux_byte_clk0", "mux_pixel_clk0",
-			      "mux_byte_clk1", "mux_pixel_clk1";
-
-		qcom,dsi-display-list =
-			<&dsi_anx_7625_1>;
-
-		ports {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			port@0 {
-				reg = <0>;
-				dsi_anx_7625_1_out: endpoint {
-					remote-endpoint = <&anx_7625_1_in>;
-				};
+	lmh-dcvs-01 {
+		trips {
+			active-config {
+				temperature = <105000>;
+				hysteresis = <40000>;
 			};
 		};
 	};
 
-	dsi_dp2: qcom,dsi-display@2 {
-		compatible = "qcom,dsi-display";
-		label = "secondary";
-
-		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
-		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
-
-		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
-			 <&mdss_dsi0_pll PCLK_MUX_0_CLK>,
-			 <&mdss_dsi1_pll BYTECLK_MUX_1_CLK>,
-			 <&mdss_dsi1_pll PCLK_MUX_1_CLK>;
-		clock-names = "mux_byte_clk0", "mux_pixel_clk0",
-			      "mux_byte_clk1", "mux_pixel_clk1";
-
-		qcom,dsi-display-list =
-			<&dsi_anx_7625_2>;
-
-		ports {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			port@0 {
-				reg = <0>;
-				dsi_anx_7625_2_out: endpoint {
-					remote-endpoint = <&anx_7625_2_in>;
-				};
+	lmh-dcvs-00 {
+		trips {
+			active-config {
+				temperature = <105000>;
+				hysteresis = <40000>;
 			};
 		};
 	};
-
-	refgen: refgen-regulator@88e7000 {
-		compatible = "qcom,refgen-regulator";
-		reg = <0x88e7000 0x60>;
-		regulator-name = "refgen";
-		regulator-enable-ramp-delay = <5>;
-	};
-
-	sde_wb: qcom,wb-display@0 {
-		compatible = "qcom,wb-display";
-		cell-index = <0>;
-		label = "wb_display";
-	};
-
-	ext_disp: qcom,msm-ext-disp {
-		compatible = "qcom,msm-ext-disp";
-
-		ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx {
-			compatible = "qcom,msm-ext-disp-audio-codec-rx";
-		};
-	};
-};
-
-&mdss_dsi_phy0 {
-	qcom,panel-force-clock-lane-hs;
-};
-
-&mdss_dsi_phy1 {
-	qcom,panel-force-clock-lane-hs;
 };
 
 &mdss_dsi0_pll {
@@ -648,7 +388,6 @@
 };
 
 &mdss_mdp {
-	connectors = <&sde_rscc &dsi_dp1 &dsi_dp2 &sde_dp &sde_wb>;
 	qcom,sde-mixer-display-pref = "primary", "none", "none",
 				"none", "none", "none";
 };
@@ -809,9 +548,9 @@
 			wlan_vregs = "vdd-wlan-aon", "vdd-wlan-rfa1",
 				   "vdd-wlan-rfa2", "vdd-wlan-rfa3";
 			qcom,vdd-wlan-aon-info = <1055000 1055000 0 0>;
-			qcom,vdd-wlan-rfa1-info = <1350000 1350000 0 0>;
+			qcom,vdd-wlan-rfa1-info = <1370000 1370000 0 0>;
 			qcom,vdd-wlan-rfa2-info = <2040000 2040000 0 0>;
-			qcom,vdd-wlan-rfa3-info = <1900000 1900000 0 0>;
+			qcom,vdd-wlan-rfa3-info = <1900000 1900000 450000 0>;
 
 			qcom,wlan-ramdump-dynamic = <0x400000>;
 			mhi,max-channels = <30>;
@@ -907,7 +646,123 @@
 				};
 			};
 		};
+		chip_cfg@2 {
+			reg = <0xa0000000 0x10000000>,
+			    <0xb0000000 0x10000>;
+			reg-names = "smmu_iova_base", "smmu_iova_ipa";
+
+			supported-ids = <0x1102>;
+			wlan_vregs = "vdd-wlan-aon", "vdd-wlan-rfa1",
+				   "vdd-wlan-rfa2", "vdd-wlan-rfa3";
+			qcom,vdd-wlan-aon-info = <1055000 1055000 0 0>;
+			qcom,vdd-wlan-rfa1-info = <1350000 1350000 0 0>;
+			qcom,vdd-wlan-rfa2-info = <2040000 2040000 0 0>;
+			qcom,vdd-wlan-rfa3-info = <1900000 1900000 0 0>;
+
+			qcom,wlan-ramdump-dynamic = <0x300000>;
+			mhi,max-channels = <30>;
+			mhi,timeout = <10000>;
+
+			mhi_channels {
+				mhi_chan@0 {
+					reg = <0>;
+					label = "LOOPBACK";
+					mhi,num-elements = <32>;
+					mhi,event-ring = <1>;
+					mhi,chan-dir = <1>;
+					mhi,data-type = <0>;
+					mhi,doorbell-mode = <2>;
+					mhi,ee = <0x14>;
+				};
+
+				mhi_chan@1 {
+					reg = <1>;
+					label = "LOOPBACK";
+					mhi,num-elements = <32>;
+					mhi,event-ring = <1>;
+					mhi,chan-dir = <2>;
+					mhi,data-type = <0>;
+					mhi,doorbell-mode = <2>;
+					mhi,ee = <0x14>;
+				};
+
+				mhi_chan@4 {
+					reg = <4>;
+					label = "DIAG";
+					mhi,num-elements = <32>;
+					mhi,event-ring = <1>;
+					mhi,chan-dir = <1>;
+					mhi,data-type = <0>;
+					mhi,doorbell-mode = <2>;
+					mhi,ee = <0x14>;
+				};
+
+				mhi_chan@5 {
+					reg = <5>;
+					label = "DIAG";
+					mhi,num-elements = <32>;
+					mhi,event-ring = <1>;
+					mhi,chan-dir = <2>;
+					mhi,data-type = <0>;
+					mhi,doorbell-mode = <2>;
+					mhi,ee = <0x14>;
+				};
+
+				mhi_chan@16 {
+					reg = <16>;
+					label = "IPCR";
+					mhi,num-elements = <32>;
+					mhi,event-ring = <1>;
+					mhi,chan-dir = <1>;
+					mhi,data-type = <1>;
+					mhi,doorbell-mode = <2>;
+					mhi,ee = <0x14>;
+					mhi,auto-start;
+				};
+
+				mhi_chan@17 {
+					reg = <17>;
+					label = "IPCR";
+					mhi,num-elements = <32>;
+					mhi,event-ring = <1>;
+					mhi,chan-dir = <2>;
+					mhi,data-type = <0>;
+					mhi,doorbell-mode = <2>;
+					mhi,ee = <0x14>;
+					mhi,auto-queue;
+					mhi,auto-start;
+				};
+			};
+
+			mhi_events {
+				mhi_event@0 {
+					mhi,num-elements = <32>;
+					mhi,intmod = <1>;
+					mhi,msi = <1>;
+					mhi,priority = <1>;
+					mhi,brstmode = <2>;
+					mhi,data-type = <1>;
+				};
+
+				mhi_event@1 {
+					mhi,num-elements = <256>;
+					mhi,intmod = <1>;
+					mhi,msi = <2>;
+					mhi,priority = <1>;
+					mhi,brstmode = <2>;
+				};
+			};
+		};
+	};
+
+	qcom,rmnet-ipa {
+		status="disabled";
 	};
 };
 
+&ipa_hw {
+	status="disabled";
+};
+
 #include "sa8155-audio.dtsi"
+#include "sa8155-camera-sensor.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sa8155p-adp-alcor-overlay.dts b/arch/arm64/boot/dts/qcom/sa8155p-adp-alcor-overlay.dts
index fc16f29..339ee49 100644
--- a/arch/arm64/boot/dts/qcom/sa8155p-adp-alcor-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155p-adp-alcor-overlay.dts
@@ -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
@@ -13,7 +13,7 @@
 /dts-v1/;
 /plugin/;
 
-#include "sa8155-adp-common.dtsi"
+#include "sa8155-adp-alcor.dtsi"
 
 / {
 	model = "ADP-ALCOR";
diff --git a/arch/arm64/boot/dts/qcom/sa8155p-adp-alcor.dts b/arch/arm64/boot/dts/qcom/sa8155p-adp-alcor.dts
index a022f3b..eddf12f 100644
--- a/arch/arm64/boot/dts/qcom/sa8155p-adp-alcor.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155p-adp-alcor.dts
@@ -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
@@ -13,7 +13,7 @@
 /dts-v1/;
 
 #include "sa8155p-v2.dtsi"
-#include "sa8155-adp-common.dtsi"
+#include "sa8155-adp-alcor.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SA8155P ADP ALCOR";
diff --git a/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air-overlay.dts b/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air-overlay.dts
index 74b4b7e..c89b831 100644
--- a/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air-overlay.dts
@@ -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
@@ -14,6 +14,7 @@
 /plugin/;
 
 #include "sa8155-adp-common.dtsi"
+#include "sa8155-adp-star-display.dtsi"
 
 / {
 	model = "ADP-AIR";
diff --git a/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air.dts b/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air.dts
index 19f6a23..fd1abc71 100644
--- a/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155p-v2-adp-air.dts
@@ -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
@@ -14,6 +14,7 @@
 
 #include "sa8155p-v2.dtsi"
 #include "sa8155-adp-common.dtsi"
+#include "sa8155-adp-star-display.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SA8155P V2 ADP AIR";
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-atp-overlay.dts b/arch/arm64/boot/dts/qcom/sdmmagpie-atp-overlay.dts
index fd31bd8..53555bb 100644
--- a/arch/arm64/boot/dts/qcom/sdmmagpie-atp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdmmagpie-atp-overlay.dts
@@ -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
@@ -17,7 +17,8 @@
 #include <dt-bindings/clock/qcom,camcc-sdmmagpie.h>
 
 #include "sdmmagpie-atp.dtsi"
-#include "sdmmagpie-audio-overlay.dtsi"
+#include "sdmmagpie-ext-codec-audio-overlay.dtsi"
+#include "sdmmagpie-external-codec.dtsi"
 
 / {
 	model = "ATP";
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-coresight.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-coresight.dtsi
index ce3e038..aa01e22 100644
--- a/arch/arm64/boot/dts/qcom/sdmmagpie-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdmmagpie-coresight.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
@@ -1619,6 +1619,34 @@
 						<&tpdm_center_out_tpda>;
 				};
 			};
+
+			port@14 {
+				reg = <17>;
+				tpda_in_tpdm_qdss: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_qdss_out_tpda>;
+				};
+			};
+		};
+	};
+
+	tpdm_qdss: tpdm@6006000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+		reg = <0x6006000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-qdss";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		port {
+			tpdm_qdss_out_tpda: endpoint {
+				remote-endpoint =
+					<&tpda_in_tpdm_qdss>;
+			};
 		};
 	};
 
@@ -1919,10 +1947,17 @@
 
 		coresight-name = "coresight-funnel-gfx";
 
-		clocks = <&clock_aop QDSS_CLK>;
-		clock-names = "apb_pclk";
+		clocks = <&clock_aop QDSS_CLK>,
+			<&clock_gpucc GPU_CC_CX_APB_CLK>;
+		clock-names = "apb_pclk", "gpu_apb_clk";
+		qcom,proxy-clks = "gpu_apb_clk";
 
-		status = "disabled";
+		/* GDSC regulator names */
+		regulator-names = "vddcx", "vdd";
+		/* GDSC oxili regulators */
+		vddcx-supply = <&gpu_cx_gdsc>;
+		vdd-supply = <&gpu_gx_gdsc>;
+		qcom,proxy-regs = "vddcx", "vdd";
 
 		ports {
 			#address-cells = <1>;
@@ -1953,10 +1988,19 @@
 		reg = <0x6940000 0x1000>;
 		reg-names = "tpdm-base";
 
-		coresight-name = "coresight-tpdm-gfx";
+		coresight-name = "coresight-tpdm-gpu";
 
-		clocks = <&clock_aop QDSS_CLK>;
-		clock-names = "apb_pclk";
+		clocks = <&clock_aop QDSS_CLK>,
+			<&clock_gpucc GPU_CC_CX_APB_CLK>;
+		clock-names = "apb_pclk", "gpu_apb_clk";
+		qcom,tpdm-clks = "gpu_apb_clk";
+
+		/* GDSC regulator names */
+		regulator-names = "vddcx", "vdd";
+		/* GDSC oxili regulators */
+		vddcx-supply = <&gpu_cx_gdsc>;
+		vdd-supply = <&gpu_gx_gdsc>;
+		qcom,tpdm-regs = "vddcx", "vdd";
 
 		qcom,msr-fix-req;
 
@@ -2058,10 +2102,10 @@
 		};
 	};
 
-	tpdm_center: tpdm@6c28000 {
+	tpdm_center: tpdm@6b44000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b968>;
-		reg = <0x6c28000 0x1000>;
+		reg = <0x6b44000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-center";
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-qrd.dtsi
index f78baa7..92ffe56 100644
--- a/arch/arm64/boot/dts/qcom/sdmmagpie-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdmmagpie-qrd.dtsi
@@ -237,37 +237,37 @@
 };
 
 &dsi_sim_cmd {
-	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
 	qcom,platform-reset-gpio = <&pm6150l_gpios 9 0>;
 };
 
 &dsi_sim_vid {
-	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
 	qcom,platform-reset-gpio = <&pm6150l_gpios 9 0>;
 };
 
 &dsi_dual_sim_cmd {
-	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
 	qcom,platform-reset-gpio = <&pm6150l_gpios 9 0>;
 };
 
 &dsi_dual_sim_vid {
-	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
 	qcom,platform-reset-gpio = <&pm6150l_gpios 9 0>;
 };
 
 &dsi_sim_dsc_375_cmd {
-	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
 	qcom,platform-reset-gpio = <&pm6150l_gpios 9 0>;
 };
 
 &dsi_dual_sim_dsc_375_cmd {
-	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
 	qcom,platform-reset-gpio = <&pm6150l_gpios 9 0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-thermal.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-thermal.dtsi
index bf64f31..d426faa 100644
--- a/arch/arm64/boot/dts/qcom/sdmmagpie-thermal.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdmmagpie-thermal.dtsi
@@ -102,6 +102,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&tsens0 0>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -121,6 +122,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&tsens0 1>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -140,6 +142,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&tsens0 2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -159,6 +162,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&tsens0 3>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -178,6 +182,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 4>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -197,6 +202,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 5>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -216,6 +222,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 6>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -235,6 +242,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 7>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -254,6 +262,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 8>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -273,6 +282,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 9>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -292,6 +302,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 10>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -311,6 +322,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 11>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -330,6 +342,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 12>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -349,6 +362,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 13>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -368,6 +382,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 14>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -387,6 +402,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 0>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -406,6 +422,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 1>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -425,6 +442,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 2>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -444,6 +462,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 3>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -463,6 +482,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 4>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -482,6 +502,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 5>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -501,6 +522,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 6>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -520,6 +542,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 7>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -539,6 +562,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 8>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -558,6 +582,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 9>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -577,6 +602,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150_adc_tm ADC_XO_THERM_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -591,6 +617,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150_adc_tm ADC_AMUX_THM2_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -605,6 +632,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150_adc_tm ADC_AMUX_THM3_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -619,6 +647,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150_adc_tm ADC_AMUX_THM4_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -633,6 +662,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150l_adc_tm ADC_AMUX_THM1_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -647,6 +677,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150l_adc_tm ADC_AMUX_THM3_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -661,6 +692,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150l_adc_tm ADC_GPIO4_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -675,6 +707,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&lmh_dcvs0>;
+		wake-capable-sensor;
 
 		trips {
 			active-config {
@@ -690,6 +723,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&lmh_dcvs1>;
+		wake-capable-sensor;
 
 		trips {
 			active-config {
@@ -704,6 +738,7 @@
 		polling-delay-passive = <10>;
 		polling-delay = <100>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			gpu_trip: gpu-trip {
 				temperature = <95000>;
@@ -724,6 +759,7 @@
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			silver-trip {
 				temperature = <120000>;
@@ -737,6 +773,7 @@
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			gold-trip {
 				temperature = <120000>;
@@ -751,6 +788,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 1>;
+		wake-capable-sensor;
 		trips {
 			cpu0_config: cpu0-config {
 				temperature = <110000>;
@@ -773,6 +811,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 2>;
+		wake-capable-sensor;
 		trips {
 			cpu1_config: cpu1-config {
 				temperature = <110000>;
@@ -795,6 +834,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 3>;
+		wake-capable-sensor;
 		trips {
 			cpu2_config: cpu2-config {
 				temperature = <110000>;
@@ -817,6 +857,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 4>;
+		wake-capable-sensor;
 		trips {
 			cpu3_config: cpu3-config {
 				temperature = <110000>;
@@ -839,6 +880,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 5>;
+		wake-capable-sensor;
 		trips {
 			cpu4_config: cpu4-config {
 				temperature = <110000>;
@@ -861,6 +903,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 6>;
+		wake-capable-sensor;
 		trips {
 			cpu5_config: cpu5-config {
 				temperature = <110000>;
@@ -883,6 +926,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 9>;
+		wake-capable-sensor;
 		trips {
 			cpu6_0_config: cpu6-0-config {
 				temperature = <110000>;
@@ -905,6 +949,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 10>;
+		wake-capable-sensor;
 		trips {
 			cpu6_1_config: cpu6-1-config {
 				temperature = <110000>;
@@ -927,6 +972,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 11>;
+		wake-capable-sensor;
 		trips {
 			cpu7_0_config: cpu7-0-config {
 				temperature = <110000>;
@@ -949,6 +995,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 12>;
+		wake-capable-sensor;
 		trips {
 			cpu7_1_config: cpu7-1-config {
 				temperature = <110000>;
@@ -971,6 +1018,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 0>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			aoss0_trip: aoss0-trip {
@@ -1021,6 +1069,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 1>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cpu_0_0_trip: cpu-0-0-trip {
@@ -1071,6 +1120,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 9>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cpu_1_0_trip: cpu-1-0-trip {
@@ -1121,6 +1171,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 13>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			gpuss_0_trip: gpuss-0-trip {
@@ -1171,6 +1222,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens1 1>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cwlan_trip: cwlan-trip {
@@ -1221,6 +1273,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens1 2>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			audio_trip: audio-trip {
@@ -1271,6 +1324,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens1 3>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			ddr_trip: ddr-trip {
@@ -1321,6 +1375,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens1 4>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			q6_hvx_trip: q6-hvx-trip {
@@ -1371,6 +1426,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens1 5>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			camera_trip: camera-trip {
@@ -1421,6 +1477,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens1 6>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			mdm_core_trip: mdm-core-trip {
@@ -1471,6 +1528,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens1 7>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			mdm_dsp_trip: mdm-dsp-lowf-trip {
@@ -1521,6 +1579,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens1 8>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			npu_trip: npu-trip {
@@ -1571,6 +1630,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens1 9>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			video_trip: video-trip {
@@ -1621,6 +1681,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 8>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			npu_trip0: npu-trip0 {
 				temperature = <95000>;
@@ -1643,6 +1704,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens1 4>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			q6_hvx_trip0: q6-hvx-trip0 {
 				temperature = <95000>;
@@ -1686,6 +1748,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&pm6150_adc_tm ADC_AMUX_THM4_PU2>;
+		wake-capable-sensor;
 		trips {
 			batt_trip0: batt-trip0 {
 				temperature = <43000>;
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie-vidc.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie-vidc.dtsi
index 263383f..92b370c 100644
--- a/arch/arm64/boot/dts/qcom/sdmmagpie-vidc.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdmmagpie-vidc.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
@@ -197,7 +197,7 @@
 			label = "venus_sec_bitstream";
 			iommus = <&apps_smmu 0x1081 0x4>;
 			buffer-types = <0x241>;
-			virtual-addr-pool = <0x0 0xe0000000>;
+			virtual-addr-pool = <0x500000 0xdfb00000>;
 			qcom,secure-context-bank;
 		};
 
@@ -206,7 +206,7 @@
 			label = "venus_sec_pixel";
 			iommus = <&apps_smmu 0x1083 0x20>;
 			buffer-types = <0x106>;
-			virtual-addr-pool = <0x0 0xe0000000>;
+			virtual-addr-pool = <0x500000 0xdfb00000>;
 			qcom,secure-context-bank;
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi
index 97f52f6..972a2cfd 100644
--- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi
@@ -2771,6 +2771,7 @@
 		qcom,smmu-fast-map;
 		qcom,use-ipa-pm;
 		qcom,bandwidth-vote-for-ipa;
+		qcom,ipa-endp-delay-wa;
 		qcom,msm-bus,name = "ipa";
 		qcom,msm-bus,num-cases = <5>;
 		qcom,msm-bus,num-paths = <4>;
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpiep-atp-overlay.dts b/arch/arm64/boot/dts/qcom/sdmmagpiep-atp-overlay.dts
new file mode 100644
index 0000000..fc84bd3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdmmagpiep-atp-overlay.dts
@@ -0,0 +1,26 @@
+/* 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 <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/qcom,camcc-sdmmagpie.h>
+
+#include "sdmmagpie-atp.dtsi"
+
+/ {
+	model = "ATP";
+	compatible = "qcom,sdmmagpiep-atp", "qcom,sdmmagpiep", "qcom,atp";
+	qcom,msm-id = <366 0x0>;
+	qcom,board-id = <33 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdmmagpiep-atp.dts b/arch/arm64/boot/dts/qcom/sdmmagpiep-atp.dts
new file mode 100644
index 0000000..48d4c02
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdmmagpiep-atp.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/;
+
+#include "sdmmagpiep.dtsi"
+#include "sdmmagpie-atp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDMMAGPIEP PM6150 ATP";
+	compatible = "qcom,sdmmagpiep-atp", "qcom,sdmmagpiep", "qcom,atp";
+	qcom,board-id = <33 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdmshrike-v2-mtp.dts b/arch/arm64/boot/dts/qcom/sdmshrike-v2-mtp.dts
new file mode 100644
index 0000000..55d1e7f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdmshrike-v2-mtp.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/;
+
+#include "sdmshrike-v2.dtsi"
+#include "sdmshrike-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDMSHRIKE V2 MTP";
+	compatible = "qcom,sdmshrike-mtp", "qcom,sdmshrike", "qcom,mtp";
+	qcom,board-id = <8 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdmshrike-v2.dts b/arch/arm64/boot/dts/qcom/sdmshrike-v2.dts
new file mode 100644
index 0000000..4d26944
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdmshrike-v2.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/;
+
+#include "sdmshrike-v2.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDMSHRIKE v2 SoC";
+	compatible = "qcom,sdmshrike";
+	qcom,pmic-name = "PM8150";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdmshrike-v2.dtsi b/arch/arm64/boot/dts/qcom/sdmshrike-v2.dtsi
new file mode 100644
index 0000000..04f3498
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdmshrike-v2.dtsi
@@ -0,0 +1,25 @@
+/* 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 "sdmshrike.dtsi"
+/ {
+	model = "Qualcomm Technologies, Inc. SDMSHRIKE V2";
+	qcom,msm-name = "SDMSHRIKE V2";
+	qcom,msm-id = <340 0x20000>;
+};
+
+/* GPU overrides */
+&msm_gpu {
+	/* Updated chip ID */
+	qcom,chipid = <0x6080001>;
+
+};
diff --git a/arch/arm64/boot/dts/qcom/sdmshrike.dtsi b/arch/arm64/boot/dts/qcom/sdmshrike.dtsi
index 640f478..370700a 100644
--- a/arch/arm64/boot/dts/qcom/sdmshrike.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdmshrike.dtsi
@@ -21,6 +21,9 @@
 #include <dt-bindings/clock/qcom,aop-qmp.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/soc/qcom,tcs-mbox.h>
+#include <dt-bindings/msm/msm-bus-ids.h>
+
+#define MHZ_TO_MBPS(mhz, w) ((mhz * 1000000 * w) / (1024 * 1024))
 
 / {
 	model = "Qualcomm Technologies, Inc. SDMSHRIKE";
@@ -676,6 +679,274 @@
 		};
 	};
 
+	llcc_pmu: llcc-pmu@90cc000 {
+		compatible = "qcom,qcom-llcc-pmu";
+		reg = <0x090cc000 0x300>, <0x09648000 0x200>;
+		reg-names = "lagg-base", "beac-base";
+	};
+
+	cpu_cpu_llcc_bw: qcom,cpu-cpu-llcc-bw {
+		compatible = "qcom,devbw";
+		governor = "performance";
+		qcom,src-dst-ports =
+			<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_LLCC>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			< MHZ_TO_MBPS(150, 16) >, /*  2288 MB/s */
+			< MHZ_TO_MBPS(200, 16) >, /*  4577 MB/s */
+			< MHZ_TO_MBPS(403, 16) >, /*  6149 MB/s */
+			< MHZ_TO_MBPS(533, 16) >, /*  8132 MB/s */
+			< MHZ_TO_MBPS(666, 16) >, /* 10162 MB/s */
+			< MHZ_TO_MBPS(777, 16) >; /* 11856 MB/s */
+	};
+
+	cpu_cpu_llcc_bwmon: qcom,cpu-cpu-llcc-bwmon@90b6400 {
+		compatible = "qcom,bimc-bwmon4";
+		reg = <0x90b6400 0x300>, <0x90b6300 0x200>;
+		reg-names = "base", "global_base";
+		interrupts = <GIC_SPI 581 IRQ_TYPE_LEVEL_HIGH>;
+		qcom,mport = <0>;
+		qcom,hw-timer-hz = <19200000>;
+		qcom,target-dev = <&cpu_cpu_llcc_bw>;
+		qcom,count-unit = <0x10000>;
+	};
+
+	cpu_llcc_ddr_bw: qcom,cpu-llcc-ddr-bw {
+		compatible = "qcom,devbw";
+		governor = "performance";
+		qcom,src-dst-ports =
+			<MSM_BUS_MASTER_LLCC MSM_BUS_SLAVE_EBI_CH0>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			< MHZ_TO_MBPS( 200, 4) >, /* 762 MB/s */
+			< MHZ_TO_MBPS( 300, 4) >, /* 1144 MB/s */
+			< MHZ_TO_MBPS( 451, 4) >, /* 1720 MB/s */
+			< MHZ_TO_MBPS( 547, 4) >, /* 2086 MB/s */
+			< MHZ_TO_MBPS( 681, 4) >, /* 2597 MB/s */
+			< MHZ_TO_MBPS( 768, 4) >, /* 2929 MB/s */
+			< MHZ_TO_MBPS(1017, 4) >, /* 3879 MB/s */
+			< MHZ_TO_MBPS(1296, 4) >, /* 4943 MB/s */
+			< MHZ_TO_MBPS(1555, 4) >, /* 5931 MB/s */
+			< MHZ_TO_MBPS(1804, 4) >, /* 6881 MB/s */
+			< MHZ_TO_MBPS(2092, 4) >; /* 7980 MB/s */
+	};
+
+	cpu_llcc_ddr_bwmon: qcom,cpu-llcc-ddr-bwmon@90cd000 {
+		compatible = "qcom,bimc-bwmon5";
+		reg = <0x90cd000 0x1000>;
+		reg-names = "base";
+		interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+		qcom,hw-timer-hz = <19200000>;
+		qcom,target-dev = <&cpu_llcc_ddr_bw>;
+		qcom,count-unit = <0x10000>;
+	};
+
+	cdsp_cdsp_l3_lat: qcom,cdsp-cdsp-l3-lat {
+		compatible = "devfreq-simple-dev";
+		clock-names = "devfreq_clk";
+		clocks = <&clock_cpucc L3_MISC_VOTE_CLK>;
+		governor = "powersave";
+	};
+
+	cpu0_cpu_l3_lat: qcom,cpu0-cpu-l3-lat {
+		compatible = "devfreq-simple-dev";
+		clock-names = "devfreq_clk";
+		clocks = <&clock_cpucc L3_CLUSTER0_VOTE_CLK>;
+		governor = "performance";
+	};
+
+	cpu0_cpu_l3_latmon: qcom,cpu0-cpu-l3-latmon {
+		compatible = "qcom,arm-memlat-mon";
+		qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>;
+		qcom,target-dev = <&cpu0_cpu_l3_lat>;
+		qcom,cachemiss-ev = <0x17>;
+		qcom,core-dev-table =
+			<  300000  300000000 >,
+			<  576000  576000000 >,
+			<  672000  768000000 >,
+			<  864000  960000000 >,
+			< 1171200 1228800000 >,
+			< 1267200 1344000000 >;
+	};
+
+	cpu4_cpu_l3_lat: qcom,cpu4-cpu-l3-lat {
+		compatible = "devfreq-simple-dev";
+		clock-names = "devfreq_clk";
+		clocks = <&clock_cpucc L3_CLUSTER1_VOTE_CLK>;
+		governor = "performance";
+	};
+
+	cpu4_cpu_l3_latmon: qcom,cpu4-cpu-l3-latmon {
+		compatible = "qcom,arm-memlat-mon";
+		qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>;
+		qcom,target-dev = <&cpu4_cpu_l3_lat>;
+		qcom,cachemiss-ev = <0x17>;
+		qcom,core-dev-table =
+			<  300000  300000000 >,
+			<  576000  576000000 >,
+			<  768000  768000000 >,
+			<  960000  960000000 >,
+			< 1248000 1228800000 >,
+			< 1593600 1344000000 >;
+	};
+
+	cpu0_cpu_llcc_lat: qcom,cpu0-cpu-llcc-lat {
+		compatible = "qcom,devbw";
+		governor = "performance";
+		qcom,src-dst-ports =
+			<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_LLCC>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			< MHZ_TO_MBPS(150, 16) >, /*  2288 MB/s */
+			< MHZ_TO_MBPS(200, 16) >, /*  4577 MB/s */
+			< MHZ_TO_MBPS(403, 16) >, /*  6149 MB/s */
+			< MHZ_TO_MBPS(533, 16) >, /*  8132 MB/s */
+			< MHZ_TO_MBPS(666, 16) >, /* 10162 MB/s */
+			< MHZ_TO_MBPS(777, 16) >; /* 11856 MB/s */
+	};
+
+	cpu0_cpu_llcc_latmon: qcom,cpu0-cpu-llcc-latmon {
+		compatible = "qcom,arm-memlat-mon";
+		qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>;
+		qcom,target-dev = <&cpu0_cpu_llcc_lat>;
+		qcom,cachemiss-ev = <0x2A>;
+		qcom,core-dev-table =
+			<  300000 MHZ_TO_MBPS(150, 16) >,
+			<  576000 MHZ_TO_MBPS(200, 16) >,
+			<  672000 MHZ_TO_MBPS(403, 16) >,
+			<  864000 MHZ_TO_MBPS(533, 16) >,
+			< 1171200 MHZ_TO_MBPS(666, 16) >,
+			< 1267200 MHZ_TO_MBPS(777, 16) >;
+	};
+
+	cpu4_cpu_llcc_lat: qcom,cpu4-cpu-llcc-lat {
+		compatible = "qcom,devbw";
+		governor = "performance";
+		qcom,src-dst-ports =
+			<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_LLCC>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			< MHZ_TO_MBPS(150, 16) >, /*  2288 MB/s */
+			< MHZ_TO_MBPS(200, 16) >, /*  4577 MB/s */
+			< MHZ_TO_MBPS(403, 16) >, /*  6149 MB/s */
+			< MHZ_TO_MBPS(533, 16) >, /*  8132 MB/s */
+			< MHZ_TO_MBPS(666, 16) >, /* 10162 MB/s */
+			< MHZ_TO_MBPS(777, 16) >; /* 11856 MB/s */
+	};
+
+	cpu4_cpu_llcc_latmon: qcom,cpu4-cpu-llcc-latmon {
+		compatible = "qcom,arm-memlat-mon";
+		qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>;
+		qcom,target-dev = <&cpu4_cpu_llcc_lat>;
+		qcom,cachemiss-ev = <0x2A>;
+		qcom,core-dev-table =
+			<  300000 MHZ_TO_MBPS(150, 16) >,
+			<  576000 MHZ_TO_MBPS(200, 16) >,
+			<  768000 MHZ_TO_MBPS(403, 16) >,
+			<  960000 MHZ_TO_MBPS(533, 16) >,
+			< 1248000 MHZ_TO_MBPS(666, 16) >,
+			< 1593600 MHZ_TO_MBPS(777, 16) >;
+	};
+
+	cpu0_llcc_ddr_lat: qcom,cpu0-llcc-ddr-lat {
+		compatible = "qcom,devbw";
+		governor = "performance";
+		qcom,src-dst-ports =
+			<MSM_BUS_MASTER_LLCC MSM_BUS_SLAVE_EBI_CH0>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			< MHZ_TO_MBPS( 200, 4) >, /* 762 MB/s */
+			< MHZ_TO_MBPS( 300, 4) >, /* 1144 MB/s */
+			< MHZ_TO_MBPS( 451, 4) >, /* 1720 MB/s */
+			< MHZ_TO_MBPS( 547, 4) >, /* 2086 MB/s */
+			< MHZ_TO_MBPS( 681, 4) >, /* 2597 MB/s */
+			< MHZ_TO_MBPS( 768, 4) >, /* 2929 MB/s */
+			< MHZ_TO_MBPS(1017, 4) >, /* 3879 MB/s */
+			< MHZ_TO_MBPS(1296, 4) >, /* 4943 MB/s */
+			< MHZ_TO_MBPS(1555, 4) >, /* 5931 MB/s */
+			< MHZ_TO_MBPS(1804, 4) >, /* 6881 MB/s */
+			< MHZ_TO_MBPS(2092, 4) >; /* 7980 MB/s */
+	};
+
+	cpu0_llcc_ddr_latmon: qcom,cpu0-llcc-ddr-latmon {
+		compatible = "qcom,arm-memlat-mon";
+		qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>;
+		qcom,target-dev = <&cpu0_llcc_ddr_lat>;
+		qcom,cachemiss-ev = <0x1000>;
+		qcom,core-dev-table =
+			<  300000 MHZ_TO_MBPS( 200, 4) >,
+			<  576000 MHZ_TO_MBPS( 451, 4) >,
+			<  672000 MHZ_TO_MBPS( 768, 4) >,
+			<  864000 MHZ_TO_MBPS(1017, 4) >,
+			< 1171200 MHZ_TO_MBPS(1555, 4) >,
+			< 1267200 MHZ_TO_MBPS(1804, 4) >;
+	};
+
+	cpu4_llcc_ddr_lat: qcom,cpu4-llcc-ddr-lat {
+		compatible = "qcom,devbw";
+		governor = "performance";
+		qcom,src-dst-ports =
+			<MSM_BUS_MASTER_LLCC MSM_BUS_SLAVE_EBI_CH0>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			< MHZ_TO_MBPS( 200, 4) >, /* 762 MB/s */
+			< MHZ_TO_MBPS( 300, 4) >, /* 1144 MB/s */
+			< MHZ_TO_MBPS( 451, 4) >, /* 1720 MB/s */
+			< MHZ_TO_MBPS( 547, 4) >, /* 2086 MB/s */
+			< MHZ_TO_MBPS( 681, 4) >, /* 2597 MB/s */
+			< MHZ_TO_MBPS( 768, 4) >, /* 2929 MB/s */
+			< MHZ_TO_MBPS(1017, 4) >, /* 3879 MB/s */
+			< MHZ_TO_MBPS(1296, 4) >, /* 4943 MB/s */
+			< MHZ_TO_MBPS(1555, 4) >, /* 5931 MB/s */
+			< MHZ_TO_MBPS(1804, 4) >, /* 6881 MB/s */
+			< MHZ_TO_MBPS(2092, 4) >; /* 7980 MB/s */
+	};
+
+	cpu4_llcc_ddr_latmon: qcom,cpu4-llcc-ddr-latmon {
+		compatible = "qcom,arm-memlat-mon";
+		qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>;
+		qcom,target-dev = <&cpu4_llcc_ddr_lat>;
+		qcom,cachemiss-ev = <0x1000>;
+		qcom,core-dev-table =
+			<  300000 MHZ_TO_MBPS( 200, 4) >,
+			<  576000 MHZ_TO_MBPS( 451, 4) >,
+			<  768000 MHZ_TO_MBPS( 768, 4) >,
+			<  960000 MHZ_TO_MBPS(1017, 4) >,
+			< 1248000 MHZ_TO_MBPS(1555, 4) >,
+			< 1593600 MHZ_TO_MBPS(1804, 4) >,
+			< 1689600 MHZ_TO_MBPS(2092, 4) >;
+	};
+
+	cpu4_cpu_ddr_latfloor: qcom,cpu4-cpu-ddr-latfloor {
+		compatible = "qcom,devbw";
+		governor = "performance";
+		qcom,src-dst-ports =
+			<MSM_BUS_MASTER_LLCC MSM_BUS_SLAVE_EBI_CH0>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			< MHZ_TO_MBPS( 200, 4) >, /* 762 MB/s */
+			< MHZ_TO_MBPS( 300, 4) >, /* 1144 MB/s */
+			< MHZ_TO_MBPS( 451, 4) >, /* 1720 MB/s */
+			< MHZ_TO_MBPS( 547, 4) >, /* 2086 MB/s */
+			< MHZ_TO_MBPS( 681, 4) >, /* 2597 MB/s */
+			< MHZ_TO_MBPS( 768, 4) >, /* 2929 MB/s */
+			< MHZ_TO_MBPS(1017, 4) >, /* 3879 MB/s */
+			< MHZ_TO_MBPS(1296, 4) >, /* 4943 MB/s */
+			< MHZ_TO_MBPS(1555, 4) >, /* 5931 MB/s */
+			< MHZ_TO_MBPS(1804, 4) >, /* 6881 MB/s */
+			< MHZ_TO_MBPS(2092, 4) >; /* 7980 MB/s */
+	};
+
+	cpu4_computemon: qcom,cpu4-computemon {
+		compatible = "qcom,arm-cpu-mon";
+		qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>;
+		qcom,target-dev = <&cpu4_cpu_ddr_latfloor>;
+		qcom,core-dev-table =
+			< 1593600 MHZ_TO_MBPS( 200, 4) >,
+			< 2016000 MHZ_TO_MBPS(1017, 4) >,
+			< 2054400 MHZ_TO_MBPS(2092, 4) >;
+	};
+
 	qcom,chd_silver {
 		compatible = "qcom,core-hang-detect";
 		label = "silver";
@@ -1050,6 +1321,7 @@
 			<0x18325800 0x1400>;
 		reg-names = "osm_l3_base", "osm_pwrcl_base",
 			"osm_perfcl_base";
+		l3-devs = <&cpu0_cpu_l3_lat &cpu4_cpu_l3_lat &cdsp_cdsp_l3_lat>;
 		#clock-cells = <1>;
 	};
 
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-aqc.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-aqc.dtsi
index 0e9495a..d61b505 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-aqc.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-aqc.dtsi
@@ -16,11 +16,73 @@
 
 		compatible = "aquantia,aqc-107";
 
-		qcom,smmu;
-		qcom,smmu-iova-base = /bits/ 64 <0x0>;
-		qcom,smmu-iova-size = /bits/ 64 <0x80000000>;
+		pci-ids =
+			"1d6a:0001",
+			"1d6a:d107",
+			"1d6a:07b1",
+			"1d6a:87b1",
+			"1d6a:d108",
+			"1d6a:08b1",
+			"1d6a:88b1",
+			"1d6a:d109",
+			"1d6a:09b1",
+			"1d6a:89b1",
+			"1d6a:d100",
+			"1d6a:00b1",
+			"1d6a:80b1",
+			"1d6a:11b1",
+			"1d6a:91b1",
+			"1d6a:51b1",
+			"1d6a:12b1",
+			"1d6a:92b1",
+			"1d6a:52b1";
 
-		qcom,smmu-attr-s1-bypass;
+		qcom,smmu;
+
+		/* IOVA range is restricted to avoid conflicts with PCI BAR
+		 * space and IOVA spaces used by peripherals that are currently
+		 * attached to IPA.
+		 */
+		qcom,smmu-iova-base = /bits/ 64 <0x80000000>;
+		qcom,smmu-iova-size = /bits/ 64 <0x10000000>;
+
+		qcom,smmu-attr-atomic;
+		qcom,smmu-attr-fastmap;
+
+		/* AQC IPA offload driver */
+
+		qcom,rx-proxy = <&atd_proxy_host>,
+				<&atd_proxy_uc>;
+
+		qcom,rx-gsi-mod-count = <250>;
+		qcom,rx-gsi-mod-timer = <5000>;
+
+		qcom,tx-gsi-mod-count = <250>;
+		qcom,tx-gsi-mod-timer = <5000>;
+
+		qcom,rx-mod-usecs = <50>;
+
+		qcom,use-pci-direct;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		atd_proxy_host: host_proxy@17a00040 {
+			reg = <0x17800200 0>;
+			reg-names = "intc-ispendr-n";
+
+			interrupt-parent = <&intc>;
+			interrupts = <GIC_SPI 292 IRQ_TYPE_EDGE_RISING>;
+
+			qcom,proxy-agent = "host";
+			qcom,proxy-method = "msi";
+		};
+
+		atd_proxy_uc: uc_proxy@1ec2080 {
+			qcom,proxy-agent = "uc";
+			qcom,proxy-method = "msi";
+			qcom,proxy-msi-addr = /bits/ 64 <0x01ec2080>;
+			qcom,proxy-msi-data = /bits/ 32 <0x636f6d6d>;
+		};
 	};
 };
-
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-cdp-256.dts b/arch/arm64/boot/dts/qcom/sdxprairie-cdp-256.dts
index e1b05ad..5603023 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-cdp-256.dts
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-cdp-256.dts
@@ -25,3 +25,7 @@
 &qnand_1 {
 	status = "ok";
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-cdp-256.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-cdp-256.dtsi
index 958d72a..8b9bd06 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-cdp-256.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-cdp-256.dtsi
@@ -173,3 +173,10 @@
 		thermal-governor = "user_space";
 	};
 };
+
+&soc {
+	bluetooth: bt_qca6390 {
+		compatible = "qca,qca6390";
+		qca,bt-reset-gpio = <&pmxprairie_gpios 6 0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dts b/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dts
index e1d4eaf..795a7f2 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dts
@@ -25,3 +25,7 @@
 &qnand_1 {
 	status = "ok";
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dtsi
index 0144c89..f9fda8c 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-cdp.dtsi
@@ -174,6 +174,13 @@
 	};
 };
 
+&soc {
+	bluetooth: bt_qca6390 {
+		compatible = "qca,qca6390";
+		qca,bt-reset-gpio = <&pmxprairie_gpios 6 0>;
+	};
+};
+
 &pm8150b_charger {
 	qcom,batteryless-platform;
 	io-channels = <&pm8150b_vadc ADC_USB_IN_V_16>,
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-coresight.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-coresight.dtsi
index 5723a01..d0f3e3d 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-coresight.dtsi
@@ -530,10 +530,88 @@
 			};
 			port@2 {
 				reg = <1>;
-				funnel_modem_dl_in_modem_etm0: endpoint {
+				funnel_modem_dl_in_modem_etm1: endpoint {
 					slave-mode;
 					remote-endpoint =
-					<&modem_etm0_out_funnel_modem_dl>;
+					<&modem_etm1_out_funnel_modem_dl>;
+				};
+			};
+			port@3 {
+				reg = <3>;
+				funnel_modem_dl_in_funnel_scal_dup: endpoint {
+					slave-mode;
+					remote-endpoint =
+					<&funnel_scal_dup_out_funnel_modem_dl>;
+				};
+			};
+		};
+	};
+
+	funnel_scal: funnel@680c000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x680c000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-modem-q6";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_scal_out_funnel_scal_dup: endpoint {
+					remote-endpoint =
+					<&funnel_scal_dup_in_funnel_scal>;
+				};
+			};
+			port@1 {
+				reg = <0>;
+				funnel_scal_in_modem_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+					<&modem_etm0_out_funnel_scal>;
+				};
+			};
+		};
+	};
+
+	funnel_scal_dup: funnel@680a000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x680a000 0x1>,
+				<0x680c000 0x1000>;
+		reg-names = "funnel-base-dummy", "funnel-base-real";
+
+		coresight-name = "coresight-funnel-modem-duplicate";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+		qcom,duplicate-funnel;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_scal_dup_out_funnel_modem_dl: endpoint {
+					remote-endpoint =
+					<&funnel_modem_dl_in_funnel_scal_dup>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				funnel_scal_dup_in_funnel_scal: endpoint {
+					slave-mode;
+					remote-endpoint =
+					<&funnel_scal_out_funnel_scal_dup>;
 				};
 			};
 		};
@@ -1164,9 +1242,24 @@
 		qcom,inst-id = <2>;
 
 		port {
-			modem_etm0_out_funnel_modem_dl: endpoint {
+			modem_etm0_out_funnel_scal: endpoint {
 				remote-endpoint =
-					<&funnel_modem_dl_in_modem_etm0>;
+					<&funnel_scal_in_modem_etm0>;
+			};
+		};
+	};
+
+
+	modem_etm1 {
+		compatible = "qcom,coresight-remote-etm";
+
+		coresight-name = "coresight-modem-etm1";
+		qcom,inst-id = <2>;
+
+		port {
+			modem_etm1_out_funnel_modem_dl: endpoint {
+				remote-endpoint =
+					<&funnel_modem_dl_in_modem_etm1>;
 			};
 		};
 	};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-mtp-256.dts b/arch/arm64/boot/dts/qcom/sdxprairie-mtp-256.dts
index 2c67cce..c679f5c 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-mtp-256.dts
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-mtp-256.dts
@@ -25,3 +25,7 @@
 &qnand_1 {
 	status = "ok";
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-mtp-256.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-mtp-256.dtsi
index ec1ba09..901214a 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-mtp-256.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-mtp-256.dtsi
@@ -181,6 +181,13 @@
 	};
 };
 
+&soc {
+	bluetooth: bt_qca6390 {
+		compatible = "qca,qca6390";
+		qca,bt-reset-gpio = <&pmxprairie_gpios 6 0>;
+	};
+};
+
 &pm8150b_charger {
 	qcom,sec-charger-config = <0>;
 	qcom,auto-recharge-soc = <98>;
@@ -188,12 +195,14 @@
 		      <&pm8150b_vadc ADC_USB_IN_I>,
 		      <&pm8150b_vadc ADC_SBUx>,
 		      <&pm8150b_vadc ADC_VPH_PWR>,
-		      <&pm8150b_vadc ADC_CHG_TEMP>;
+		      <&pm8150b_vadc ADC_CHG_TEMP>,
+		      <&pm8150b_vadc ADC_USB_IN_V_16>;
 	io-channel-names = "mid_voltage",
 			   "usb_in_current",
 			   "sbux_res",
 			   "vph_voltage",
-			   "chg_temp";
+			   "chg_temp",
+			   "usb_in_voltage";
 	qcom,battery-data = <&sdxprairie_mtp_batterydata>;
 	qcom,step-charging-enable;
 	qcom,wd-bark-time-secs = <16>;
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-mtp-aqc.dts b/arch/arm64/boot/dts/qcom/sdxprairie-mtp-aqc.dts
index 4f8f76f..5faa08d 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-mtp-aqc.dts
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-mtp-aqc.dts
@@ -25,3 +25,7 @@
 &qnand_1 {
 	status = "ok";
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dts b/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dts
index 3f2ee52..9c2a429 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dts
@@ -25,3 +25,7 @@
 &qnand_1 {
 	status = "ok";
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dtsi
index 12a23d1..7c19334 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-mtp.dtsi
@@ -181,6 +181,13 @@
 	};
 };
 
+&soc {
+	bluetooth: bt_qca6390 {
+		compatible = "qca,qca6390";
+		qca,bt-reset-gpio = <&pmxprairie_gpios 6 0>;
+	};
+};
+
 &pm8150b_charger {
 	qcom,sec-charger-config = <0>;
 	qcom,auto-recharge-soc = <98>;
@@ -188,18 +195,19 @@
 		      <&pm8150b_vadc ADC_USB_IN_I>,
 		      <&pm8150b_vadc ADC_SBUx>,
 		      <&pm8150b_vadc ADC_VPH_PWR>,
-		      <&pm8150b_vadc ADC_CHG_TEMP>;
+		      <&pm8150b_vadc ADC_CHG_TEMP>,
+		      <&pm8150b_vadc ADC_USB_IN_V_16>;
 	io-channel-names = "mid_voltage",
 			   "usb_in_current",
 			   "sbux_res",
 			   "vph_voltage",
-			   "chg_temp";
+			   "chg_temp",
+			   "usb_in_voltage";
 	qcom,battery-data = <&sdxprairie_mtp_batterydata>;
 	qcom,step-charging-enable;
 	qcom,wd-bark-time-secs = <16>;
 	qcom,suspend-input-on-debug-batt;
 	qcom,hvdcp-autonomous-enable;
-	qcom,usb-pd-disable;
 	qcom,hw-die-temp-mitigation;
 	qcom,hw-connector-mitigation;
 	qcom,hw-skin-temp-mitigation;
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-pcie-ep-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-pcie-ep-mtp.dtsi
index 4f853cca..f0dfb1e 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-pcie-ep-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-pcie-ep-mtp.dtsi
@@ -20,3 +20,23 @@
 &restart_pshold {
 	qcom,force-warm-reboot;
 };
+
+&cnss_qca6390 {
+	status = "disabled";
+};
+
+&ipa_hw {
+	qcom,use-ipa-in-mhi-mode;
+};
+
+&pcie0 {
+	status = "disabled";
+};
+
+&pcie_ep {
+	status = "ok";
+};
+
+&mhi_device {
+	status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-pcie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-pcie.dtsi
index 4e00c29..679a15f 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-pcie.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-pcie.dtsi
@@ -45,6 +45,7 @@
 				0 0 0 4 &intc 0 140 0>;
 
 		qcom,phy-sequence = <0x1240 0x03 0x0
+				0x1010 0x00 0x0
 				0x101c 0x31 0x0
 				0x1020 0x01 0x0
 				0x1024 0xce 0x0
@@ -74,7 +75,7 @@
 				0x10dc 0x55 0x0
 				0x10e0 0x05 0x0
 				0x110c 0x02 0x0
-				0x1154 0x32 0x0
+				0x1154 0x34 0x0
 				0x1158 0x12 0x0
 				0x115c 0x00 0x0
 				0x1168 0x05 0x0
@@ -88,55 +89,74 @@
 				0x11bc 0x22 0x0
 				0x106c 0x0a 0x0
 				0x1070 0x10 0x0
+				0x11a4 0x05 0x0
+				0x11a8 0x0f 0x0
+				0x008c 0x06 0x0
+				0x00e0 0x01 0x0
+				0x00c4 0x01 0x0
 				0x0258 0x16 0x0
+				0x0378 0x83 0x0
+				0x0360 0xe2 0x0
+				0x0364 0x04 0x0
+				0x0368 0x30 0x0
+				0x0370 0xff 0x0
+				0x03cc 0x42 0x0
+				0x03d0 0x0d 0x0
+				0x03d4 0x77 0x0
+				0x03d8 0x2d 0x0
+				0x03dc 0x39 0x0
+				0x03e0 0x9f 0x0
+				0x03e4 0x0f 0x0
+				0x03e8 0x63 0x0
+				0x03ec 0xbf 0x0
+				0x03f0 0x79 0x0
+				0x03f4 0x4f 0x0
+				0x03f8 0x0f 0x0
+				0x03fc 0xd5 0x0
+				0x02ac 0x7f 0x0
+				0x0310 0x55 0x0
+				0x0334 0x0c 0x0
+				0x0338 0x00 0x0
+				0x0350 0x0f 0x0
+				0x088c 0x06 0x0
+				0x08e0 0x01 0x0
+				0x08c4 0x01 0x0
 				0x0a58 0x16 0x0
+				0x0b78 0x83 0x0
+				0x0b60 0xe2 0x0
+				0x0b64 0x04 0x0
+				0x0b68 0x30 0x0
+				0x0b70 0xff 0x0
+				0x0bcc 0x42 0x0
+				0x0bd0 0x0d 0x0
+				0x0bd4 0x77 0x0
+				0x0bd8 0x2d 0x0
+				0x0bdc 0x39 0x0
+				0x0be0 0x9f 0x0
+				0x0be4 0x0f 0x0
+				0x0be8 0x63 0x0
+				0x0bec 0xbf 0x0
+				0x0bf0 0x79 0x0
+				0x0bf4 0x4f 0x0
+				0x0bf8 0x0f 0x0
+				0x0bfc 0xd5 0x0
+				0x0aac 0x7f 0x0
+				0x0b10 0x55 0x0
+				0x0b34 0x0c 0x0
+				0x0b38 0x00 0x0
+				0x0b50 0x0f 0x0
 				0x161c 0xc1 0x0
 				0x1690 0x00 0x0
-				0x13e4 0x02 0x0
-				0x1708 0x02 0x0
-				0x16a0 0x14 0x0
+				0x13e4 0x03 0x0
+				0x1708 0x03 0x0
+				0x16a0 0x16 0x0
+				0x13e0 0x16 0x0
 				0x13d8 0x01 0x0
 				0x16fc 0x01 0x0
 				0x13dc 0x00 0x0
 				0x1700 0x00 0x0
-				0x13e0 0x16 0x0
-				0x16f0 0x13 0x0
-				0x16f4 0x13 0x0
-				0x0b78 0x83 0x0
-				0x0b60 0xe2 0x0
-				0x0b64 0x04 0x0
-				0x0b70 0xff 0x0
-				0x0378 0x83 0x0
-				0x0360 0xe2 0x0
-				0x0364 0x04 0x0
-				0x0370 0xff 0x0
-				0x0088 0x05 0x0
-				0x008c 0x06 0x0
-				0x034c 0x14 0x0
-				0x0350 0xbf 0x0
-				0x03f8 0x0f 0x0
-				0x0888 0x05 0x0
-				0x088c 0x06 0x0
-				0x0b4c 0x14 0x0
-				0x0b50 0xbf 0x0
-				0x0bf8 0x0f 0x0
-				0x1060 0x28 0x0
-				0x0368 0x00 0x0
-				0x0b68 0x00 0x0
-				0x0424 0x10 0x0
-				0x0c24 0x10 0x0
-				0x043c 0x10 0x0
-				0x0c3c 0x10 0x0
-				0x0310 0x00 0x0
-				0x0310 0x00 0x0
-				0x00e4 0x25 0x0
-				0x08e4 0x25 0x0
-				0x000c 0x20 0x0
-				0x080c 0x20 0x0
-				0x0b70 0x3f 0x0
-				0x0b74 0x00 0x0
-				0x0370 0x3f 0x0
-				0x0374 0x00 0x0
+				0x1828 0x50 0x0
+				0x1c28 0x50 0x0
 				0x1200 0x00 0x0
 				0x1244 0x03 0x0>;
 
@@ -166,7 +186,7 @@
 
 		qcom,slv-addr-space-size = <0x40000000>;
 
-		qcom,pcie-phy-ver = <0x1000>;
+		qcom,pcie-phy-ver = <0x1096>;
 		qcom,use-19p2mhz-aux-clk;
 		qcom,phy-status-offset = <0x1214>;
 		qcom,phy-status-bit = <7>;
@@ -215,6 +235,7 @@
 
 		pcie0_rp: pcie0_rp {
 			reg = <0 0 0 0 0>;
+			pci-ids = "17cb:010c";
 		};
 	};
 
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi
index 60bdb5a..30e8c5b 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-pinctrl.dtsi
@@ -1330,6 +1330,44 @@
 			};
 		};
 
+		pcie_ep {
+			pcie_ep_clkreq_default: pcie_ep_clkreq_default {
+				mux {
+					pins = "gpio56";
+					function = "pcie_clkreq";
+				};
+				config {
+					pins = "gpio56";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			pcie_ep_perst_default: pcie_ep_perst_default {
+				mux {
+					pins = "gpio57";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio57";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+
+			pcie_ep_wake_default: pcie_ep_wake_default {
+				mux {
+					pins = "gpio53";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio53";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
 		cnss_pins {
 			cnss_wlan_en_active: cnss_wlan_en_active {
 				mux {
@@ -1435,32 +1473,5 @@
 			};
 		};
 
-		emac {
-			emac_pin_pps_0: emac_pin_pps_0 {
-				mux {
-					pins = "gpio106";
-					function = "emac_PPS0";
-				};
-
-				config {
-					pins = "gpio106";
-					drive-strength = <8>;   /* 8 mA */
-					bias-disable;	/* NO PULL*/
-				};
-			};
-
-			emac_pin_pps_1: emac_pin_pps_1 {
-				mux {
-					pins = "gpio95";
-					function = "emac_PPS1";
-				};
-
-				config {
-					pins = "gpio95";
-					drive-strength = <8>;	/* 8 mA */
-					bias-disable;	/* NO PULL*/
-				};
-			};
-		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-pmic-overlay.dtsi
index 1d2f47f..a523e7a 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-pmic-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-pmic-overlay.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
@@ -16,7 +16,7 @@
 #include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
 
 &pm8150b_charger {
-	/delete-property/ dpdm-supply;
+	dpdm-supply = <&usb2_phy>;
 
 	smb5_vconn: qcom,smb5-vconn {
 		regulator-name = "smb5-vconn";
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-regulator.dtsi
index 2aafd00..c863b32 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-regulator.dtsi
@@ -102,6 +102,14 @@
 			qcom,init-voltage-level =
 				<RPMH_REGULATOR_LEVEL_RETENTION>;
 		};
+
+		mx_cdev: mx-cdev-lvl {
+			compatible = "qcom,regulator-cooling-device";
+			regulator-cdev-supply = <&VDD_MX_LEVEL>;
+			regulator-levels = <RPMH_REGULATOR_LEVEL_NOM
+					RPMH_REGULATOR_LEVEL_OFF>;
+			#cooling-cells = <2>;
+		};
 	};
 
 	/* PMXPRAIRIE S5 = VDD_CX supply */
@@ -137,6 +145,13 @@
 				<RPMH_REGULATOR_LEVEL_RETENTION>;
 			qcom,min-dropout-voltage-level = <(-1)>;
 		};
+
+		cx_cdev: regulator-cdev {
+			compatible = "qcom,rpmh-reg-cdev";
+			mboxes = <&qmp_aop 0>;
+			qcom,reg-resource-name = "cx";
+			#cooling-cells = <2>;
+		};
 	};
 
 	rpmh-regulator-ldoe1 {
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dts b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dts
index 75d1832..b944d19 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dts
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dts
@@ -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
@@ -25,3 +25,7 @@
 &qnand_1 {
 	status = "ok";
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi
index 2a7ec3c..49158a8 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-rumi.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-rumi.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
@@ -82,3 +82,10 @@
 &usb2_phy {
 	status = "disabled";
 };
+
+&soc {
+	bluetooth: bt_qca6390 {
+		compatible = "qca,qca6390";
+		qca,bt-reset-gpio = <&pmxprairie_gpios 6 0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-thermal.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-thermal.dtsi
new file mode 100644
index 0000000..8cee489
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-thermal.dtsi
@@ -0,0 +1,428 @@
+/* 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 <dt-bindings/thermal/thermal.h>
+
+&soc {
+	qmi-tmd-devices {
+		compatible = "qcom,qmi-cooling-devices";
+
+		modem {
+			qcom,instance-id = <0x0>;
+
+			modem_pa: modem_pa {
+				qcom,qmi-dev-name = "pa";
+				#cooling-cells = <2>;
+			};
+
+			modem_proc: modem_proc {
+				qcom,qmi-dev-name = "modem";
+				#cooling-cells = <2>;
+			};
+
+			modem_current: modem_current {
+				qcom,qmi-dev-name = "modem_current";
+				#cooling-cells = <2>;
+			};
+
+			modem_skin: modem_skin {
+				qcom,qmi-dev-name = "modem_skin";
+				#cooling-cells = <2>;
+			};
+
+			modem_vdd: modem_vdd {
+				qcom,qmi-dev-name = "cpuv_restriction_cold";
+				#cooling-cells = <2>;
+			};
+		};
+
+	};
+
+	qmi_sensor: qmi-ts-sensors {
+		compatible = "qcom,qmi-sensors";
+		#thermal-sensor-cells = <1>;
+
+		modem {
+			qcom,instance-id = <0x0>;
+			qcom,qmi-sensor-names = "pa",
+						"pa_1",
+						"qfe_pa0",
+						"qfe_wtr0";
+		};
+	};
+};
+
+&thermal_zones {
+	aoss0-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "user_space";
+		thermal-sensors = <&tsens0 0>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+			active-config1 {
+				temperature = <115000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+	};
+
+	mdm-q6-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "user_space";
+		thermal-sensors = <&tsens0 1>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+			active-config1 {
+				temperature = <115000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+	};
+
+	ipa-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "user_space";
+		thermal-sensors = <&tsens0 2>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+			active-config1 {
+				temperature = <115000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+	};
+
+	cpu0-a7-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "user_space";
+		thermal-sensors = <&tsens0 3>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+			active-config1 {
+				temperature = <115000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+	};
+
+	mdm-5g-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 4>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+			active-config1 {
+				temperature = <115000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+	};
+
+	mdm-vpe-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 5>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+			active-config1 {
+				temperature = <115000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+	};
+
+	mdm-core-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 6>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+			active-config1 {
+				temperature = <115000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+	};
+
+	aoss0-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 0>;
+		tracks-low;
+		trips {
+			aoss0_trip: active-config0 {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_cdev {
+				trip = <&aoss0_trip>;
+				cooling-device = <&CPU0 1 1>;
+			};
+			modem_vdd_cdev {
+				trip = <&aoss0_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+			cx_vdd_cdev {
+				trip = <&aoss0_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&aoss0_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
+		};
+	};
+
+	mdm-q6-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 1>;
+		tracks-low;
+		trips {
+			mdm_q6_trip: active-config0 {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_cdev {
+				trip = <&mdm_q6_trip>;
+				cooling-device = <&CPU0 1 1>;
+			};
+			modem_vdd_cdev {
+				trip = <&mdm_q6_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+			cx_vdd_cdev {
+				trip = <&mdm_q6_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&mdm_q6_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
+		};
+	};
+
+	ipa-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 2>;
+		tracks-low;
+		trips {
+			ipa_trip: active-config0 {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_cdev {
+				trip = <&ipa_trip>;
+				cooling-device = <&CPU0 1 1>;
+			};
+			modem_vdd_cdev {
+				trip = <&ipa_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+			cx_vdd_cdev {
+				trip = <&ipa_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&ipa_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
+		};
+	};
+
+	cpu0-a7-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 3>;
+		tracks-low;
+		trips {
+			cpu0_trip: active-config0 {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_cdev {
+				trip = <&cpu0_trip>;
+				cooling-device = <&CPU0 1 1>;
+			};
+			modem_vdd_cdev {
+				trip = <&cpu0_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+			cx_vdd_cdev {
+				trip = <&cpu0_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&cpu0_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
+		};
+	};
+
+	mdm-5g-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 4>;
+		thermal-governor = "low_limits_floor";
+		tracks-low;
+		trips {
+			mdm_5g_trip: active-config0 {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_cdev {
+				trip = <&mdm_5g_trip>;
+				cooling-device = <&CPU0 1 1>;
+			};
+			modem_vdd_cdev {
+				trip = <&mdm_5g_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+			cx_vdd_cdev {
+				trip = <&mdm_5g_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&mdm_5g_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
+		};
+	};
+
+	mdm-vpe-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 5>;
+		thermal-governor = "low_limits_floor";
+		tracks-low;
+		trips {
+			mdm_vpe_trip: active-config0 {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_cdev {
+				trip = <&mdm_vpe_trip>;
+				cooling-device = <&CPU0 1 1>;
+			};
+			modem_vdd_cdev {
+				trip = <&mdm_vpe_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+			cx_vdd_cdev {
+				trip = <&mdm_vpe_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&mdm_vpe_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
+		};
+	};
+
+	mdm-core-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 6>;
+		thermal-governor = "low_limits_floor";
+		tracks-low;
+		trips {
+			mdm_core_trip: active-config0 {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_cdev {
+				trip = <&mdm_core_trip>;
+				cooling-device = <&CPU0 1 1>;
+			};
+			modem_vdd_cdev {
+				trip = <&mdm_core_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+			cx_vdd_cdev {
+				trip = <&mdm_core_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			mx_vdd_cdev {
+				trip = <&mdm_core_trip>;
+				cooling-device = <&mx_cdev 0 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-usb.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-usb.dtsi
index 792f278..fc407c4 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie-usb.dtsi
@@ -25,12 +25,13 @@
 		#size-cells = <1>;
 		ranges;
 
-		interrupts = <0 157 0>, <0 130 0>, <0 158 0>;
+		interrupts = <0 157 0>, <0 130 0>, <0 158 0>, <0 198 0>;
 		interrupt-names = "dp_hs_phy_irq", "pwr_event_irq",
-				"dm_hs_phy_irq";
+				"dm_hs_phy_irq", "ss_phy_irq";
 		qcom,use-pdc-interrupts;
 
 		USB3_GDSC-supply = <&gdsc_usb30>;
+		dpdm-supply = <&usb2_phy>;
 		clocks = <&clock_gcc GCC_USB30_MASTER_CLK>,
 			<&clock_gcc GCC_USB30_SLV_AHB_CLK>,
 			<&clock_gcc GCC_USB30_MSTR_AXI_CLK>,
@@ -99,7 +100,7 @@
 			reg = <0xa704000 0x17000>;
 			interrupts = <0 132 0>;
 
-			qcom,usb-bam-fifo-baseaddr = <0x146bb000>;
+			qcom,usb-bam-fifo-baseaddr = <0x1468b000>;
 			qcom,usb-bam-num-pipes = <4>;
 			qcom,disable-clk-gating;
 			qcom,usb-bam-override-threshold = <0x4001>;
diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi
index 56dd19e..04a9f1d 100644
--- a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi
@@ -40,12 +40,6 @@
 		#size-cells = <1>;
 		ranges;
 
-		mpss_debug_mem: mpss_debug_region@90c00000 {
-			no-map;
-			reg = <0x90c00000 0x800000>;
-			label = "mpss_debug_mem";
-		};
-
 		tz_apps_mem: tz_apps_region@0x90000000 {
 			no-map;
 			reg = <0x90000000 0xc00000>;
@@ -70,6 +64,12 @@
 			label = "peripheral2_mem";
 		};
 
+		secdata_mem: secdata_region@8fcfd000 {
+			no-map;
+			reg = <0x8fcfd000 0x1000>;
+			label = "secdata_mem";
+		};
+
 		ac_db_mem: ac_db_region@8fc80000 {
 			no-map;
 			reg = <0x8fc80000 0x40000>;
@@ -82,10 +82,16 @@
 			label = "hyp_mem";
 		};
 
-		mpss_adsp_mem: mpss_adsp_region@83c00000 {
+		mpss_debug_mem: mpss_debug_region@8ef00000 {
+			no-map;
+			reg = <0x8ef00000 0x800000>;
+			label = "mpss_debug_mem";
+		};
+
+		mpss_adsp_mem: mpss_adsp_region@83400000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0x83c00000 0xbb00000>;
+			reg = <0x83400000 0xbb00000>;
 			label = "mpss_adsp_mem";
 		};
 
@@ -131,6 +137,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x0>;
 			enable-method = "psci";
+			#cooling-cells = <2>;
 		};
 	};
 
@@ -326,9 +333,9 @@
 
 	clock_debugcc: qcom,cc-debug {
 		compatible = "qcom,debugcc-sdxprairie";
-		qcom,cc-count = <2>;
 		qcom,gcc = <&clock_gcc>;
 		qcom,cpucc = <&cpucc_debug>;
+		qcom,mccc = <&mccc_debug>;
 		clock-names = "xo_clk_src";
 		clocks = <&clock_rpmh RPMH_CXO_CLK>;
 		#clock-cells = <1>;
@@ -336,9 +343,8 @@
 
 	clock_cpu: qcom,clock-cpu@17808100 {
 		compatible = "qcom,cpu-sdxprairie";
-		clocks = <&clock_rpmh RPMH_CXO_CLK>,
-			 <&clock_gcc GPLL0>;
-		clock-names = "bi_tcxo", "gpll0";
+		clocks = <&clock_rpmh RPMH_CXO_CLK>;
+		clock-names = "bi_tcxo";
 		reg = <0x17810008 0x8>,
 			<0x17808100 0x44>;
 		reg-names = "apcs_cmd" , "apcs_pll";
@@ -349,7 +355,7 @@
 			<  345600000 RPMH_REGULATOR_LEVEL_LOW_SVS>,
 			<  576000000 RPMH_REGULATOR_LEVEL_SVS>,
 			< 1094400000 RPMH_REGULATOR_LEVEL_NOM>,
-			< 1497600000 RPMH_REGULATOR_LEVEL_TURBO>;
+			< 1555200000 RPMH_REGULATOR_LEVEL_TURBO>;
 		#clock-cells = <1>;
 	};
 
@@ -358,6 +364,11 @@
 		reg = <0x1781101c 0x4>;
 	};
 
+	mccc_debug: syscon@90b0000 {
+		compatible = "syscon";
+		reg = <0x90b0000 0x800>;
+	};
+
 	spmi_bus: qcom,spmi@c440000 {
 		compatible = "qcom,spmi-pmic-arb";
 		reg = <0xc440000 0xd00>,
@@ -500,6 +511,15 @@
 		qcom,rmnet-ipa-ssr;
 	};
 
+	dcc: dcc_v2@10a2000 {
+		compatible = "qcom,dcc-v2";
+		reg = <0x10a2000 0x1000>,
+			<0x10ae800 0x1800>;
+		reg-names = "dcc-base", "dcc-ram-base";
+
+		dcc-ram-offset = <0x800>;
+	};
+
 	qcom,ipa_fws {
 		compatible = "qcom,pil-tz-generic";
 		qcom,pas-id = <0xf>;
@@ -514,6 +534,7 @@
 
 	ipa_hw: qcom,ipa@01e00000 {
 		compatible = "qcom,ipa";
+		mboxes = <&qmp_aop 0>;
 		reg = <0x1e00000 0x84000>,
 		      <0x1e04000 0x23000>;
 		reg-names = "ipa-base", "gsi-base";
@@ -525,7 +546,7 @@
 		qcom,ipa-hw-mode = <0>;
 		qcom,ee = <0>;
 		qcom,use-ipa-tethering-bridge;
-		qcom,mhi-event-ring-id-limits = <9 10>; /* start and end */
+		qcom,mhi-event-ring-id-limits = <9 11>; /* start and end */
 		qcom,modem-cfg-emb-pipe-flt;
 		qcom,use-ipa-pm;
 		qcom,arm-smmu;
@@ -533,6 +554,7 @@
 		qcom,wlan-ce-db-over-pcie;
 		qcom,bandwidth-vote-for-ipa;
 		qcom,msm-bus,name = "ipa";
+		qcom,ipa-wdi3-over-gsi;
 		qcom,msm-bus,num-cases = <5>;
 		qcom,msm-bus,num-paths = <5>;
 		qcom,msm-bus,vectors-KBps =
@@ -587,7 +609,7 @@
 			qcom,additional-mapping =
 				/* modem tables in IMEM */
 				<0x14688000 0x14688000 0x3000>;
-			qcom,ipa-q6-smem-size = <16384>;
+			qcom,ipa-q6-smem-size = <26624>;
 		};
 
 		ipa_smmu_wlan: ipa_smmu_wlan {
@@ -820,8 +842,8 @@
 				<125 512 393600 393600>;
 		qcom,no-clock-support;
 		qcom,smmu-s1-enable;
-		iommus = <&apps_smmu 0x0066 0x0013>,
-			<&apps_smmu 0x0076 0x0013>;
+		iommus = <&apps_smmu 0x0066 0x0011>,
+			<&apps_smmu 0x0076 0x0011>;
 	};
 
 	qcom_crypto: qcrypto@1de0000 {
@@ -849,8 +871,8 @@
 		qcom,use-sw-hmac-algo;
 		qcom,no-clock-support;
 		qcom,smmu-s1-enable;
-		iommus = <&apps_smmu 0x0064 0x0013>,
-			<&apps_smmu 0x0074 0x0013>;
+		iommus = <&apps_smmu 0x0064 0x0011>,
+			<&apps_smmu 0x0074 0x0011>;
 	};
 
 	mem_dump {
@@ -983,7 +1005,7 @@
 				<  345600 >,
 				<  576000 >,
 				< 1094400 >,
-				< 1497600 >;
+				< 1555200 >;
 	};
 
 	ddr_bw_opp_table: ddr-bw-opp-table {
@@ -1019,7 +1041,7 @@
 				< 1497600 MHZ_TO_MBPS(1804, 4)>;
 	};
 
-	qcom,cnss-qca6390@a0000000 {
+	cnss_qca6390: qcom,cnss-qca6390@a0000000 {
 		compatible = "qcom,cnss-qca6390";
 		reg = <0xa0000000 0x10000000>,
 		      <0xb0000000 0x10000>;
@@ -1030,6 +1052,8 @@
 		pinctrl-1 = <&cnss_wlan_en_sleep>;
 		qcom,wlan-rc-num = <0>;
 		qcom,wlan-ramdump-dynamic = <0x400000>;
+		pcie-disable-l1;
+		pcie-disable-l1ss;
 
 		mhi,max-channels = <30>;
 		mhi,timeout = <10000>;
@@ -1126,6 +1150,161 @@
 
 		mhi_devices {
 		};
+
+	};
+
+	pcie_ep: qcom,pcie@40002000 {
+		compatible = "qcom,pcie-ep";
+
+		reg = <0x40002000 0x1000>,
+			<0x40000000 0xf1d>,
+			<0x40000f20 0xa8>,
+			<0x40001000 0x1000>,
+			<0x40002000 0x2000>,
+			<0x01c00000 0x3000>,
+			<0x01c06000 0x2000>,
+			<0x01c03000 0x1000>,
+			<0x01fcb000 0x1000>;
+		reg-names = "msi", "dm_core", "elbi", "iatu", "edma", "parf",
+				"phy", "mmio", "tcsr_pcie_perst_en";
+
+		#address-cells = <0>;
+		interrupt-parent = <&pcie_ep>;
+		interrupts = <0>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 140 0>;
+		interrupt-names = "int_global";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pcie_ep_clkreq_default &pcie_ep_perst_default
+			&pcie_ep_wake_default>;
+
+		clkreq-gpio = <&tlmm 56 0>;
+		perst-gpio = <&tlmm 57 0>;
+		wake-gpio = <&tlmm 53 0>;
+
+		gdsc-vdd-supply = <&gdsc_pcie>;
+		vreg-1.8-supply = <&pmxprairie_l1>;
+		vreg-0.9-supply = <&pmxprairie_l4>;
+
+		qcom,vreg-1.8-voltage-level = <1200000 1200000 24000>;
+		qcom,vreg-0.9-voltage-level = <872000 872000 24000>;
+
+		clocks = <&clock_gcc GCC_PCIE_PIPE_CLK>,
+			<&clock_gcc GCC_PCIE_CFG_AHB_CLK>,
+			<&clock_gcc GCC_PCIE_MSTR_AXI_CLK>,
+			<&clock_gcc GCC_PCIE_SLV_AXI_CLK>,
+			<&clock_gcc GCC_PCIE_AUX_CLK>,
+			<&clock_gcc GCC_PCIE_0_CLKREF_CLK>,
+			<&clock_gcc GCC_PCIE_SLEEP_CLK>,
+			<&clock_gcc GCC_PCIE_SLV_Q2A_AXI_CLK>;
+
+		clock-names = "pcie_pipe_clk", "pcie_cfg_ahb_clk",
+				"pcie_mstr_axi_clk", "pcie_slv_axi_clk",
+				"pcie_aux_clk", "pcie_ldo",
+				"pcie_sleep_clk",
+				"pcie_slv_q2a_axi_clk";
+
+		resets = <&clock_gcc GCC_PCIE_BCR>,
+			<&clock_gcc GCC_PCIE_PHY_BCR>;
+
+		reset-names = "pcie_core_reset",
+				"pcie_phy_reset";
+
+		qcom,msm-bus,name = "pcie-ep";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<45 512 0 0>,
+				<45 512 500 800>;
+
+		qcom,pcie-vendor-id = /bits/ 16 <0x17cb>;
+		qcom,pcie-device-id = /bits/ 16 <0x0306>;
+		qcom,pcie-link-speed = <2>;
+		qcom,pcie-phy-ver = <6>;
+		qcom,pcie-active-config;
+		qcom,pcie-aggregated-irq;
+		qcom,pcie-mhi-a7-irq;
+		qcom,phy-status-reg = <0x814>;
+
+		qcom,phy-init = <0x1240 0x001 0x0 0x1
+				0x100c 0x002 0x0 0x1
+				0x1044 0x018 0x0 0x1
+				0x104c 0x007 0x0 0x1
+				0x1058 0x00f 0x0 0x1
+				0x1074 0x006 0x0 0x1
+				0x1078 0x028 0x0 0x1
+				0x107c 0x016 0x0 0x1
+				0x1080 0x00d 0x0 0x1
+				0x1084 0x036 0x0 0x1
+				0x1088 0x000 0x0 0x1
+				0x1094 0x000 0x0 0x1
+				0x10a4 0x046 0x0 0x1
+				0x10a8 0x004 0x0 0x1
+				0x10ac 0x07f 0x0 0x1
+				0x10b0 0x002 0x0 0x1
+				0x10b4 0x0ff 0x0 0x1
+				0x10b8 0x004 0x0 0x1
+				0x10bc 0x025 0x0 0x1
+				0x10c4 0x028 0x0 0x1
+				0x10d4 0x008 0x0 0x1
+				0x10f4 0x0fb 0x0 0x1
+				0x10f8 0x003 0x0 0x1
+				0x110c 0x002 0x0 0x1
+				0x1158 0x012 0x0 0x1
+				0x115c 0x000 0x0 0x1
+				0x1168 0x005 0x0 0x1
+				0x116c 0x004 0x0 0x1
+				0x119c 0x088 0x0 0x1
+				0x11a0 0x003 0x0 0x1
+				0x11ac 0x056 0x0 0x1
+				0x11b0 0x01d 0x0 0x1
+				0x11b4 0x04b 0x0 0x1
+				0x11b8 0x01f 0x0 0x1
+				0x11bc 0x022 0x0 0x1
+				0x0258 0x016 0x0 0x1
+				0x0378 0x083 0x0 0x1
+				0x0360 0x0e2 0x0 0x1
+				0x0364 0x004 0x0 0x1
+				0x0368 0x030 0x0 0x1
+				0x0370 0x0ff 0x0 0x1
+				0x0a58 0x016 0x0 0x1
+				0x0b78 0x083 0x0 0x1
+				0x0b60 0x0e2 0x0 0x1
+				0x0b64 0x004 0x0 0x1
+				0x0b68 0x030 0x0 0x1
+				0x0b70 0x0ff 0x0 0x1
+				0x13e4 0x003 0x0 0x1
+				0x1708 0x003 0x0 0x1
+				0x13e0 0x016 0x0 0x1
+				0x13d8 0x001 0x0 0x1
+				0x16fc 0x001 0x0 0x1
+				0x13dc 0x000 0x0 0x1
+				0x1700 0x000 0x0 0x1
+				0x1828 0x050 0x0 0x1
+				0x1c28 0x050 0x0 0x1
+				0x1200 0x000 0x0 0x1
+				0x1244 0x003 0x0 0x1>;
+
+		status = "disabled";
+	};
+
+	mhi_device: mhi_dev@1c03000 {
+		compatible = "qcom,msm-mhi-dev";
+		reg = <0x1c03000 0x1000>,
+			<0x1e15000 0x4>,
+			<0x1e15148 0x4>;
+			reg-names = "mhi_mmio_base", "ipa_uc_mbox_crdb",
+			"ipa_uc_mbox_erdb";
+			qcom,mhi-ep-msi = <0>;
+			qcom,mhi-version = <0x1000000>;
+			qcom,use-ipa-software-channel;
+			interrupts = <0 145 0>;
+			interrupt-names = "mhi-device-inta";
+			qcom,mhi-ifc-id = <0x030617cb>;
+			qcom,mhi-interrupt;
+		status = "disabled";
 	};
 
 	sdhc_1: sdhci@8804000 {
@@ -1215,10 +1394,6 @@
 		gdsc_emac-supply = <&gdsc_emac>;
 		mboxes = <&qmp_aop 0>;
 		mbox-names = "emac_aop";
-		pinctrl-names = "dev-emac_pin_pps_0",
-			"dev-emac_pin_pps_1";
-		pinctrl-0 = <&emac_pin_pps_0>;
-		pinctrl-1 = <&emac_pin_pps_1>;
 
 		io-macro-info {
 			io-macro-bypass-mode = <0>;
@@ -1245,6 +1420,7 @@
 #include "sdxprairie-pcie.dtsi"
 #include "sdxprairie-coresight.dtsi"
 #include "sdxprairie-aqc.dtsi"
+#include "sdxprairie-thermal.dtsi"
 
 &gdsc_usb30 {
 	status = "ok";
@@ -1258,110 +1434,33 @@
 	status = "ok";
 };
 
-&thermal_zones {
-	aoss0-usr {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "user_space";
-		thermal-sensors = <&tsens0 0>;
-		trips {
-			active-config0 {
-				temperature = <125000>;
-				hysteresis = <1000>;
-				type = "passive";
-			};
-		};
-	};
-
-	mdm-q6-usr {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "user_space";
-		thermal-sensors = <&tsens0 1>;
-		trips {
-			active-config0 {
-				temperature = <125000>;
-				hysteresis = <1000>;
-				type = "passive";
-			};
-		};
-	};
-
-	ipa-usr {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "user_space";
-		thermal-sensors = <&tsens0 2>;
-		trips {
-			active-config0 {
-				temperature = <125000>;
-				hysteresis = <1000>;
-				type = "passive";
-			};
-		};
-	};
-
-	cpu0-a7-usr {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "user_space";
-		thermal-sensors = <&tsens0 3>;
-		trips {
-			active-config0 {
-				temperature = <125000>;
-				hysteresis = <1000>;
-				type = "passive";
-			};
-		};
-	};
-
-	mdm-5g-usr {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-sensors = <&tsens0 4>;
-		thermal-governor = "user_space";
-		trips {
-			active-config0 {
-				temperature = <125000>;
-				hysteresis = <1000>;
-				type = "passive";
-			};
-		};
-	};
-
-	mdm-vpe-usr {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-sensors = <&tsens0 5>;
-		thermal-governor = "user_space";
-		trips {
-			active-config0 {
-				temperature = <125000>;
-				hysteresis = <1000>;
-				type = "passive";
-			};
-		};
-	};
-
-	mdm-core-usr {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-sensors = <&tsens0 6>;
-		thermal-governor = "user_space";
-		trips {
-			active-config0 {
-				temperature = <125000>;
-				hysteresis = <1000>;
-				type = "passive";
-			};
-		};
-	};
-};
-
 &pcie0_rp {
 	cnss: qcom,qca6390@0 {
 		reg = <0 0 0 0 0>;
+		pci-ids = "17cb:1101";
 
 		memory-region = <&cnss_wlan_mem>;
 	};
 };
+
+&soc {
+	ess-instance {
+		num_devices = <0x1>;
+		ess-switch@0 {
+			compatible = "qcom,ess-switch-qca83xx";
+			qcom,switch-access-mode = "mdio";
+			qcom,ar8327-initvals = <
+				0x00004 0x4200000   /* PAD0_MODE */
+				0x00008 0x0         /* PAD5_MODE */
+				0x000e4 0xaa545     /* MAC_POWER_SEL */
+				0x000e0 0xc74164de  /* SGMII_CTRL */
+				0x0007c 0x4e        /* PORT0_STATUS */
+				0x00094 0x4e        /* PORT6_STATUS */
+			>;
+			qcom,link-intr-gpio = <84>;
+			qcom,switch-cpu-bmp = <0x01>;    /* cpu port bitmap */
+			qcom,switch-lan-bmp = <0x3e>;    /* lan port bitmap */
+			qcom,switch-wan-bmp = <0x0>;     /* wan port bitmap */
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sm6150-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sm6150-audio-overlay.dtsi
index 41c0731..96489b8 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-audio-overlay.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
@@ -18,6 +18,8 @@
 &bolero {
 	qcom,num-macros = <4>;
 	qcom,va-without-decimation;
+	slew_rate_reg1 = <0x62B6F000 0x0>;
+	slew_rate_reg2 = <0x62B6F004 0x0>;
 	tx_macro: tx-macro@62ec0000 {
 		compatible = "qcom,tx-macro";
 		reg = <0x62ec0000 0x0>;
diff --git a/arch/arm64/boot/dts/qcom/sm6150-gpu.dtsi b/arch/arm64/boot/dts/qcom/sm6150-gpu.dtsi
index 38f0e13..70a4481 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-gpu.dtsi
@@ -70,7 +70,7 @@
 
 		clock-names = "core_clk", "rbbmtimer_clk", "mem_clk",
 				"iface_clk", "mem_iface_clk",
-				"gpu_cc_hlos1_vote_gpu_smmu_clk", "gmu_clk";
+				"smmu_vote", "gmu_clk";
 
 		/* Bus Scale Settings */
 		qcom,gpubw-dev = <&gpubw>;
@@ -603,8 +603,7 @@
 			<&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
 			<&clock_gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>;
 
-		clock-names = "mem_clk", "mem_iface_clk",
-				"gpu_cc_hlos1_vote_gpu_smmu_clk";
+		clock-names = "mem_clk", "mem_iface_clk", "smmu_vote";
 
 		qcom,secure_align_mask = <0xfff>;
 		qcom,retention;
@@ -647,7 +646,6 @@
 
 		clock-names = "gmu", "rbbmtimer", "mem",
 				"iface", "mem_iface",
-				"gpu_cc_hlos1_vote_gpu_smmu_clk",
-				"core";
+				"smmu_vote", "core";
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi
index 9ed76fe..9bf9abf 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-pinctrl.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
@@ -1197,6 +1197,114 @@
 			};
 		};
 
+		pri_aux_pcm_sck {
+			pri_aux_pcm_sck_sleep: pri_aux_pcm_sck_sleep {
+				mux {
+					pins = "gpio108";
+					function = "mi2s_1";
+				};
+
+				config {
+					pins = "gpio108";
+					drive-strength = <2>;   /* 2 mA */
+				};
+			};
+
+			pri_aux_pcm_sck_active: pri_aux_pcm_sck_active {
+				mux {
+					pins = "gpio108";
+					function = "mi2s_1";
+				};
+
+				config {
+					pins = "gpio108";
+					drive-strength = <8>;   /* 8 mA */
+					input-enable;
+				};
+			};
+		};
+
+		pri_aux_pcm_ws {
+			pri_aux_pcm_ws_sleep: pri_aux_pcm_ws_sleep {
+				mux {
+					pins = "gpio109";
+					function = "mi2s_1";
+				};
+
+				config {
+					pins = "gpio109";
+					drive-strength = <2>;   /* 2 mA */
+				};
+			};
+
+			pri_aux_pcm_ws_active: pri_aux_pcm_ws_active {
+				mux {
+					pins = "gpio109";
+					function = "mi2s_1";
+				};
+
+				config {
+					pins = "gpio109";
+					drive-strength = <8>;   /* 8 mA */
+					input-enable;
+				};
+			};
+		};
+
+		pri_aux_pcm_data0 {
+			pri_aux_pcm_data0_sleep: pri_aux_pcm_data0_sleep {
+				mux {
+					pins = "gpio110";
+					function = "mi2s_1";
+				};
+
+				config {
+					pins = "gpio110";
+					drive-strength = <2>;   /* 2 mA */
+				};
+			};
+
+			pri_aux_pcm_data0_active: pri_aux_pcm_data0_active {
+				mux {
+					pins = "gpio110";
+					function = "mi2s_1";
+				};
+
+				config {
+					pins = "gpio110";
+					drive-strength = <8>;   /* 8 mA */
+					input-enable;
+				};
+			};
+		};
+
+		pri_aux_pcm_data1 {
+			pri_aux_pcm_data1_sleep: pri_aux_pcm_data1_sleep {
+				mux {
+					pins = "gpio111";
+					function = "mi2s_1";
+				};
+
+				config {
+					pins = "gpio111";
+					drive-strength = <2>;   /* 2 mA */
+				};
+			};
+
+			pri_aux_pcm_data1_active: pri_aux_pcm_data1_active {
+				mux {
+					pins = "gpio111";
+					function = "mi2s_1";
+				};
+
+				config {
+					pins = "gpio111";
+					drive-strength = <8>;   /* 8 mA */
+					output-high;
+				};
+			};
+		};
+
 		pmx_ts_int_active {
 			ts_int_active: ts_int_active {
 				mux {
@@ -1690,6 +1798,29 @@
 					drive-strength = <2>;
 				};
 			};
+			emac_rgmii_rxc_suspend: emac_rgmii_rxc_suspend {
+				mux {
+					pins = "gpio102";
+					function = "rgmii_rxc";
+				};
+
+				config {
+					pins = "gpio102";
+					input-disable;
+				};
+			};
+			emac_rgmii_rxc_resume: emac_rgmii_rxc_resume {
+				mux {
+					pins = "gpio102";
+					function = "rgmii_rxc";
+				};
+
+				config {
+					pins = "gpio102";
+					input-enable;
+					bias-disable;/* NO pull */
+				};
+			};
 			emac_rgmii_rx_ctl: emac_rgmii_rx_ctl {
 				mux {
 					pins = "gpio112";
@@ -1752,9 +1883,36 @@
 				bias-pull-down;
 			};
 		};
+
+		usb0_hs_ac_en_default: usb0_hs_ac_en_default {
+			mux {
+				pins = "gpio88";
+				function = "usb0_hs_ac";
+			};
+
+			config {
+				pins = "gpio88";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		usb1_hs_ac_en_default: usb1_hs_ac_en_default {
+			mux {
+				pins = "gpio89";
+				function = "usb1_hs_ac";
+			};
+
+			config {
+				pins = "gpio89";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
 	};
 };
 
+
 &pm6150_gpios {
 	wcd934x_mclk {
 		wcd934x_mclk_default: wcd934x_mclk_default{
@@ -1800,3 +1958,4 @@
 
 	};
 };
+
diff --git a/arch/arm64/boot/dts/qcom/sm6150-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sm6150-qrd-overlay.dts
index 0ad6d57..174fd45 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-qrd-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sm6150-qrd-overlay.dts
@@ -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
@@ -52,7 +52,13 @@
 		"IN3_AUX", "AUX_OUT",
 		"TX SWR_ADC0", "ADC1_OUTPUT",
 		"TX SWR_ADC2", "ADC2_OUTPUT",
-		"TX SWR_ADC3", "ADC3_OUTPUT",
+		"WSA SRC0_INP", "SRC0",
+		"WSA_TX DEC0_INP", "TX DEC0 MUX",
+		"WSA_TX DEC1_INP", "TX DEC1 MUX",
+		"RX_TX DEC0_INP", "TX DEC0 MUX",
+		"RX_TX DEC1_INP", "TX DEC1 MUX",
+		"RX_TX DEC2_INP", "TX DEC2 MUX",
+		"RX_TX DEC3_INP", "TX DEC3 MUX",
 		"SpkrLeft IN", "WSA_SPK1 OUT",
 		"WSA_SPK1 OUT", "VA_MCLK";
 	qcom,wsa-max-devs = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sm6150-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sm6150-qupv3.dtsi
index 3e452d8..ce13188 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-qupv3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-qupv3.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
@@ -460,6 +460,7 @@
 		pinctrl-1 = <&qupv3_se9_spi_sleep>;
 		spi-max-frequency = <50000000>;
 		qcom,wrapper-core = <&qupv3_2>;
+		qcom,disable-dma;
 		status = "disabled";
 	};
 
@@ -479,6 +480,7 @@
 		pinctrl-1 = <&qupv3_se10_spi_sleep>;
 		spi-max-frequency = <50000000>;
 		qcom,wrapper-core = <&qupv3_2>;
+		qcom,disable-dma;
 		status = "disabled";
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sm6150-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sm6150-sde-display.dtsi
index 33a0a4e..f3d7739 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-sde-display.dtsi
@@ -124,7 +124,9 @@
 
 		qcom,dsi-ctrl-num = <0>;
 		qcom,dsi-phy-num = <0>;
-		qcom,dsi-select-clocks = "mux_byte_clk0", "mux_pixel_clk0";
+		qcom,dsi-select-clocks = "mux_byte_clk0", "mux_pixel_clk0",
+			"src_byte_clk0", "src_pixel_clk0",
+			"shadow_byte_clk0", "shadow_pixel_clk0";
 
 		qcom,dsi-panel = <&dsi_hx83112a_truly_video>;
 	};
@@ -213,8 +215,14 @@
 		qcom,dsi-phy = <&mdss_dsi_phy0>;
 
 		clocks = <&mdss_dsi0_pll BYTE0_MUX_CLK>,
-			 <&mdss_dsi0_pll PIX0_MUX_CLK>;
-		clock-names = "mux_byte_clk0", "mux_pixel_clk0";
+			 <&mdss_dsi0_pll PIX0_MUX_CLK>,
+			 <&mdss_dsi0_pll BYTE0_SRC_CLK>,
+			 <&mdss_dsi0_pll PIX0_SRC_CLK>,
+			 <&mdss_dsi0_pll SHADOW_BYTE0_SRC_CLK>,
+			 <&mdss_dsi0_pll SHADOW_PIX0_SRC_CLK>;
+		clock-names = "mux_byte_clk0", "mux_pixel_clk0",
+			"src_byte_clk0", "src_pixel_clk0",
+			"shadow_byte_clk0", "shadow_pixel_clk0";
 		pinctrl-names = "panel_active", "panel_suspend";
 		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
 		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
@@ -358,6 +366,9 @@
 	qcom,mdss-dsi-panel-status-value = <0x9d 0x9d 0x9d 0x9d>;
 	qcom,mdss-dsi-panel-on-check-value = <0x9d 0x9d 0x9d 0x9d>;
 	qcom,mdss-dsi-panel-status-read-length = <4>;
+	qcom,dsi-dyn-clk-enable;
+	qcom,dsi-dyn-clk-list =
+		<924736320 909324048 913177120 917030184 920883256 928589392>;
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings =
diff --git a/arch/arm64/boot/dts/qcom/sm6150-sde-pll.dtsi b/arch/arm64/boot/dts/qcom/sm6150-sde-pll.dtsi
index ee21295..87b524f 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-sde-pll.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-sde-pll.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
@@ -17,11 +17,14 @@
 		cell-index = <0>;
 		#clock-cells = <1>;
 		reg = <0xae94400 0x588>,
-		      <0xaf03000 0x8>;
-		reg-names = "pll_base", "gdsc_base";
+		      <0xaf03000 0x8>,
+		      <0xae94200 0x100>;
+		reg-names = "pll_base", "gdsc_base",
+			"dynamic_pll_base";
 		clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>;
 		clock-names = "iface_clk";
 		clock-rate = <0>;
+		memory-region = <&dfps_data_memory>;
 		gdsc-supply = <&mdss_core_gdsc>;
 		qcom,dsi-pll-ssc-en;
 		qcom,dsi-pll-ssc-mode = "down-spread";
diff --git a/arch/arm64/boot/dts/qcom/sm6150-sde.dtsi b/arch/arm64/boot/dts/qcom/sm6150-sde.dtsi
index 33bfc6c..3fdf0fe 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-sde.dtsi
@@ -423,8 +423,10 @@
 		label = "dsi-phy-0";
 		cell-index = <0>;
 		reg = <0xae94400 0x588>,
-		    <0xae01400 0x100>;
-		reg-names = "dsi_phy", "phy_clamp_base";
+		    <0xae01400 0x100>,
+		    <0xae94200 0x100>;
+		reg-names = "dsi_phy", "phy_clamp_base",
+			"dyn_refresh_base";
 		vdda-0p9-supply = <&pm6150_l4>;
 		qcom,platform-strength-ctrl = [ff 06
 						ff 06
diff --git a/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi b/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi
index 26794a3b..d9862a9 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-thermal.dtsi
@@ -100,6 +100,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&tsens0 0>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -124,6 +125,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&tsens0 1>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -148,6 +150,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&tsens0 2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -172,6 +175,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&tsens0 3>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -196,6 +200,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 4>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -220,6 +225,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 5>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -244,6 +250,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 6>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -268,6 +275,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 7>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -292,6 +300,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 8>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -316,6 +325,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 9>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -340,6 +350,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 10>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -364,6 +375,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 11>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -388,6 +400,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 12>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -412,6 +425,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 13>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -436,6 +450,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 14>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -460,6 +475,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 15>;
 		thermal-governor = "user_space";
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -484,6 +500,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&lmh_dcvs0>;
+		wake-capable-sensor;
 
 		trips {
 			active-config {
@@ -499,6 +516,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&lmh_dcvs1>;
+		wake-capable-sensor;
 
 		trips {
 			active-config {
@@ -514,6 +532,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 9>;
+		wake-capable-sensor;
 		trips {
 			gpu_trip: gpu-trip {
 				temperature = <95000>;
@@ -557,6 +576,7 @@
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			silver-trip {
 				temperature = <120000>;
@@ -570,6 +590,7 @@
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			gold-trip {
 				temperature = <120000>;
@@ -584,6 +605,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 1>;
+		wake-capable-sensor;
 		trips {
 			cpu45_config: cpu45-config {
 				temperature = <110000>;
@@ -612,6 +634,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&tsens0 2>;
+		wake-capable-sensor;
 		trips {
 			cpu23_config: cpu23-config {
 				temperature = <110000>;
@@ -640,6 +663,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 3>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			cpu01_config: cpu01-config {
 				temperature = <110000>;
@@ -668,6 +692,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 5>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			cpu6_0_config: cpu6-0-config {
 				temperature = <110000>;
@@ -690,6 +715,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 6>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			cpu6_1_config: cpu6-1-config {
 				temperature = <110000>;
@@ -712,6 +738,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 7>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			cpu7_0_config: cpu7-0-config {
 				temperature = <110000>;
@@ -734,6 +761,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 8>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			cpu7_1_config: cpu7-1-config {
 				temperature = <110000>;
@@ -756,6 +784,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 0>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			aoss0_trip: aoss0-trip {
@@ -806,6 +835,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 1>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cpuss_0_trip: cpuss-0-trip {
@@ -856,6 +886,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 2>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cpuss_1_trip: cpuss-1-trip {
@@ -906,6 +937,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 3>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cpuss_2_trip: cpuss-2-trip {
@@ -956,6 +988,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 4>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cpuss_3_trip: cpuss-3-trip {
@@ -1006,6 +1039,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 5>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cpu_1_0_trip: cpu-1-0-trip {
@@ -1056,6 +1090,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 6>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cpu_1_1_trip: cpu-1-1-trip {
@@ -1106,6 +1141,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 7>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cpu_1_2_trip: cpu-1-2-trip {
@@ -1156,6 +1192,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 8>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			cpu_1_3_trip: cpu-1-3-trip {
@@ -1206,6 +1243,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 9>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			gpu_lowf_trip: gpu-lowf-trip {
@@ -1256,6 +1294,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 10>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			q6_hvx_trip: q6-hvx-lowf-trip {
@@ -1306,6 +1345,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 11>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			mdm_core_trip: mdm-core-trip {
@@ -1356,6 +1396,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 12>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			camera_trip: camera-trip {
@@ -1406,6 +1447,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 13>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			wlan_trip: wlan-trip {
@@ -1456,6 +1498,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 14>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			display_trip: display-trip {
@@ -1506,6 +1549,7 @@
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
 		thermal-sensors = <&tsens0 15>;
+		wake-capable-sensor;
 		tracks-low;
 		trips {
 			video_trip: video-trip {
@@ -1556,6 +1600,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 10>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			q6_hvx_cxip: q6-hvx-config {
 				temperature = <95000>;
@@ -1609,6 +1654,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 11>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			mdm_core_cx_mon: mdm-core-cx-mon {
 				temperature = <100000>;
@@ -1642,6 +1688,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 12>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			camera_cx_mon: camera-cx-mon {
 				temperature = <100000>;
@@ -1675,6 +1722,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 13>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			wlan_cx_mon: wlan-cx-mon {
 				temperature = <100000>;
@@ -1708,6 +1756,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 14>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			dispaly_cx_mon: display-cx-mon {
 				temperature = <100000>;
@@ -1741,6 +1790,7 @@
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 15>;
 		thermal-governor = "step_wise";
+		wake-capable-sensor;
 		trips {
 			video_cx_mon: video-cx-mon {
 				temperature = <100000>;
@@ -1774,6 +1824,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150_adc_tm ADC_XO_THERM_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -1788,6 +1839,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150_adc_tm ADC_AMUX_THM2_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -1802,6 +1854,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150_adc_tm ADC_AMUX_THM4_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -1816,6 +1869,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150l_adc_tm ADC_AMUX_THM1_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -1830,6 +1884,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150l_adc_tm ADC_AMUX_THM2_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -1844,6 +1899,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150l_adc_tm ADC_GPIO1_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -1858,6 +1914,7 @@
 		polling-delay = <0>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6150l_adc_tm ADC_GPIO4_PU2>;
+		wake-capable-sensor;
 		trips {
 			active-config0 {
 				temperature = <125000>;
@@ -1872,6 +1929,7 @@
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&pm6150l_adc_tm ADC_GPIO4_PU2>;
+		wake-capable-sensor;
 		trips {
 			gold_trip: gold-trip {
 				temperature = <46000>;
diff --git a/arch/arm64/boot/dts/qcom/sm6150-usb.dtsi b/arch/arm64/boot/dts/qcom/sm6150-usb.dtsi
index 3d5e6be..29f8858 100644
--- a/arch/arm64/boot/dts/qcom/sm6150-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150-usb.dtsi
@@ -138,10 +138,12 @@
 		compatible = "qcom,qusb2phy";
 		reg = <0x88e2000 0x180>,
 			<0x01fcb250 0x4>,
-			<0x007801f8 0x4>;
+			<0x007801f8 0x4>,
+			<0x01fcb3e4 0x4>;
 		reg-names = "qusb_phy_base",
 			"tcsr_clamp_dig_n_1p8",
-			"tune2_efuse_addr";
+			"tune2_efuse_addr",
+			"tcsr_conn_box_spare_0";
 
 		vdd-supply = <&pm6150_l4>;
 		vdda18-supply = <&pm6150_l11>;
@@ -396,8 +398,10 @@
 	/* Secondary USB port related High Speed PHY */
 	qusb_phy1: qusb@88e3000 {
 		compatible = "qcom,qusb2phy";
-		reg = <0x88e3000 0x180>;
-		reg-names = "qusb_phy_base";
+		reg = <0x88e3000 0x180>,
+			<0x01fcb3e4 0x4>;
+		reg-names = "qusb_phy_base",
+			"tcsr_conn_box_spare_0";
 
 		vdd-supply = <&pm6150_l4>;
 		vdda18-supply = <&pm6150_l11>;
diff --git a/arch/arm64/boot/dts/qcom/sm6150.dtsi b/arch/arm64/boot/dts/qcom/sm6150.dtsi
index 89d7720..5c964fc6 100644
--- a/arch/arm64/boot/dts/qcom/sm6150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6150.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
@@ -640,10 +640,15 @@
 		};
 
 		cont_splash_memory: cont_splash_region@9c000000 {
-			reg = <0x0 0x9c000000 0x0 0x02400000>;
+			reg = <0x0 0x9c000000 0x0 0x02300000>;
 			label = "cont_splash_region";
 		};
 
+		dfps_data_memory: dfps_data_region@9e300000 {
+			reg = <0x0 0x9e300000 0x0 0x0100000>;
+			label = "dfps_data_region";
+		};
+
 		dump_mem: mem_dump_region {
 			compatible = "shared-dma-pool";
 			reusable;
@@ -2532,6 +2537,7 @@
 		qcom,smmu-fast-map;
 		qcom,use-ipa-pm;
 		qcom,bandwidth-vote-for-ipa;
+		qcom,ipa-endp-delay-wa;
 		qcom,msm-bus,name = "ipa";
 		qcom,msm-bus,num-cases = <5>;
 		qcom,msm-bus,num-paths = <4>;
@@ -2653,6 +2659,7 @@
 		reg = <0x0 0x200000>;
 		reg-names = "rmtfs";
 		qcom,client-id = <0x00000001>;
+		qcom,guard-memory;
 	};
 
 	llcc_pmu: llcc-pmu@90cc000 {
diff --git a/arch/arm64/boot/dts/qcom/sm8150-audio.dtsi b/arch/arm64/boot/dts/qcom/sm8150-audio.dtsi
index 61b45d2..32e1ec1 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-audio.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
@@ -124,6 +124,7 @@
 				<&dai_sec_tdm_rx_0>, <&dai_sec_tdm_tx_0>,
 				<&dai_tert_tdm_rx_0>, <&dai_tert_tdm_tx_0>,
 				<&dai_quat_tdm_rx_0>, <&dai_quat_tdm_tx_0>,
+				<&dai_quat_tdm_rx_1>,
 				<&dai_quin_tdm_rx_0>, <&dai_quin_tdm_tx_0>;
 		asoc-cpu-names = "msm-dai-q6-hdmi.8",  "msm-dai-q6-dp.24608",
 				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
@@ -148,6 +149,7 @@
 				"msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881",
 				"msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897",
 				"msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913",
+				"msm-dai-q6-tdm.36914",
 				"msm-dai-q6-tdm.36928", "msm-dai-q6-tdm.36929";
 		fsa4480-i2c-handle = <&fsa4480>;
 	};
@@ -169,3 +171,13 @@
 		elemental-addr = [ff ff ff fe 17 02];
 	};
 };
+
+&tdm_quat_rx {
+	qcom,msm-cpudai-tdm-group-num-ports = <2>;
+	qcom,msm-cpudai-tdm-group-port-id = <36912 36914>;
+	dai_quat_tdm_rx_1: qcom,msm-dai-q6-tdm-quat-rx-1 {
+		compatible = "qcom,msm-dai-q6-tdm";
+		qcom,msm-cpudai-tdm-dev-id = <36914>;
+		qcom,msm-cpudai-tdm-data-align = <0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8150-cdp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-cdp.dtsi
index 84c11b5..03b9e3a 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-cdp.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
@@ -290,6 +290,7 @@
 	compatible = "qcom,ufs-phy-qmp-v4";
 
 	vdda-phy-supply = <&pm8150_l5>;
+	vdda-phy-always-on;
 	vdda-pll-supply = <&pm8150l_l3>;
 	vdda-phy-max-microamp = <90200>;
 	vdda-pll-max-microamp = <19000>;
diff --git a/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi b/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi
index 8d7a04f..54748c8 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-coresight.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
@@ -1227,6 +1227,15 @@
 					<&tpda_spss_out_funnel_spss>;
 				};
 			};
+
+			port@2 {
+				reg = <1>;
+				funnel_spss_in_spss_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+					<&spss_etm0_out_funnel_spss>;
+				};
+			};
 		};
 	};
 
@@ -1284,6 +1293,19 @@
 		};
 	};
 
+	spss_etm0 {
+		compatible = "qcom,coresight-dummy";
+
+		coresight-name = "coresight-spss-etm0";
+		qcom,dummy-source;
+
+		port {
+			spss_etm0_out_funnel_spss: endpoint {
+				remote-endpoint = <&funnel_spss_in_spss_etm0>;
+			};
+		};
+	};
+
 	tpdm_qm: tpdm@69d0000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b968>;
diff --git a/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi b/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi
index 4bde423..b991576 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-gpu.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* 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
@@ -90,7 +90,7 @@
 
 		qcom,ubwc-mode = <3>;
 
-		qcom,snapshot-size = <1048576>; //bytes
+		qcom,snapshot-size = <1310720>; //bytes
 
 		qcom,gpu-qdss-stm = <0x161c0000 0x40000>; // base addr, size
 
diff --git a/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi
index d16c507..f0741f6 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-mhi.dtsi
@@ -17,6 +17,8 @@
 	mhi_0: qcom,mhi@0 {
 		reg = <0 0 0 0 0 >;
 
+		pci-ids = "17cb:0305", "17cb:0306";
+
 		/* controller specific configuration */
 		qcom,smmu-cfg = <0x3>;
 
@@ -548,6 +550,8 @@
 	mhi_1: qcom,mhi@0 {
 		reg = <0 0 0 0 0 >;
 
+		pci-ids = "17cb:0305", "17cb:0306";
+
 		/* controller specific configuration */
 		qcom,smmu-cfg = <0x3>;
 		qcom,msm-bus,name = "mhi";
diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi
index ae96172..a24186c 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dtsi
@@ -265,6 +265,7 @@
 	compatible = "qcom,ufs-phy-qmp-v4";
 
 	vdda-phy-supply = <&pm8150_l5>;
+	vdda-phy-always-on;
 	vdda-pll-supply = <&pm8150l_l3>;
 	vdda-phy-max-microamp = <90200>;
 	vdda-pll-max-microamp = <19000>;
@@ -624,12 +625,14 @@
 		      <&pm8150b_vadc ADC_USB_IN_I>,
 		      <&pm8150b_vadc ADC_SBUx>,
 		      <&pm8150b_vadc ADC_VPH_PWR>,
-		      <&pm8150b_vadc ADC_CHG_TEMP>;
+		      <&pm8150b_vadc ADC_CHG_TEMP>,
+		      <&pm8150b_vadc ADC_USB_IN_V_16>;
 	io-channel-names = "mid_voltage",
 			   "usb_in_current",
 			   "sbux_res",
 			   "vph_voltage",
-			   "chg_temp";
+			   "chg_temp",
+			   "usb_in_voltage";
 	qcom,battery-data = <&mtp_batterydata>;
 	qcom,step-charging-enable;
 	qcom,sw-jeita-enable;
@@ -644,6 +647,8 @@
 };
 
 &smb1390_charger {
+	/delete-property/ compatible;
+	compatible = "qcom,smb1390-charger-psy";
 	io-channels = <&pm8150b_vadc ADC_AMUX_THM2>;
 	io-channel-names = "cp_die_temp";
 	status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/sm8150-pcie.dtsi b/arch/arm64/boot/dts/qcom/sm8150-pcie.dtsi
index 115c6eb..7b7f34d 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-pcie.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-pcie.dtsi
@@ -239,6 +239,7 @@
 
 		pcie_rc0: pcie_rc0 {
 			reg = <0 0 0 0 0>;
+			pci-ids = "17cb:0108";
 		};
 	};
 
@@ -556,6 +557,7 @@
 
 		pcie_rc1: pcie_rc1 {
 			reg = <0 0 0 0 0>;
+			pci-ids = "17cb:0108";
 		};
 	};
 
@@ -798,4 +800,20 @@
 		qcom,pcie-edma;
 		status = "disabled";
 	};
+
+	mhi_device: mhi_dev@1c0b000 {
+		compatible = "qcom,msm-mhi-dev";
+		reg = <0x1c0b000 0x1000>;
+		reg-names = "mhi_mmio_base";
+		qcom,mhi-ep-msi = <0>;
+		qcom,mhi-version = <0x1000000>;
+		qcom,use-pcie-edma;
+		dmas = <&pcie1_edma 0 0>, <&pcie1_edma 1 0>;
+		dma-names = "tx", "rx";
+		interrupts = <0 440 0>;
+		interrupt-names = "mhi-device-inta";
+		qcom,mhi-ifc-id = <0x010817cb>;
+		qcom,mhi-interrupt;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sm8150-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sm8150-pinctrl.dtsi
index 853881c..d5bc0b2 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-pinctrl.dtsi
@@ -253,6 +253,20 @@
 		};
 
 		qupv3_se13_4uart_pins: qupv3_se13_4uart_pins {
+			qupv3_se13_pins_default: qupv3_se13_pins_default {
+				mux {
+					pins = "gpio43", "gpio44", "gpio45",
+								"gpio46";
+					function = "gpio";
+					};
+
+				config {
+					pins = "gpio43", "gpio44", "gpio45",
+								"gpio46";
+					drive-strength = <2>;
+					bias-disable;
+					};
+			};
 			qupv3_se13_ctsrx: qupv3_se13_ctsrx {
 				mux {
 					pins = "gpio43", "gpio46";
diff --git a/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi
index 87f66ea..f1c4666 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-pmic-overlay.dtsi
@@ -88,6 +88,11 @@
 	};
 };
 
+&pm8150b_fg {
+	nvmem-names = "fg_sdam";
+	nvmem = <&pm8150_sdam_2>;
+};
+
 &pm8150b_qnovo {
 	pinctrl-names = "q_state1", "q_state2";
 	pinctrl-0 = <&qnovo_fet_ctrl_state1>;
diff --git a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi
index 8d63970..cbc5757 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-qrd.dtsi
@@ -230,6 +230,7 @@
 	compatible = "qcom,ufs-phy-qmp-v4";
 
 	vdda-phy-supply = <&pm8150_l5>;
+	vdda-phy-always-on;
 	vdda-pll-supply = <&pm8150l_l3>;
 	vdda-phy-max-microamp = <90200>;
 	vdda-pll-max-microamp = <19000>;
@@ -592,16 +593,21 @@
 		      <&pm8150b_vadc ADC_USB_IN_I>,
 		      <&pm8150b_vadc ADC_SBUx>,
 		      <&pm8150b_vadc ADC_VPH_PWR>,
-		      <&pm8150b_vadc ADC_CHG_TEMP>;
+		      <&pm8150b_vadc ADC_CHG_TEMP>,
+		      <&pm8150b_vadc ADC_USB_IN_V_16>;
 	io-channel-names = "mid_voltage",
 			   "usb_in_current",
 			   "sbux_res",
 			   "vph_voltage",
-			   "chg_temp";
+			   "chg_temp",
+			   "usb_in_voltage";
 	qcom,battery-data = <&qrd_batterydata>;
 	qcom,sw-jeita-enable;
 	qcom,wd-bark-time-secs = <16>;
 	qcom,suspend-input-on-debug-batt;
+	qcom,thermal-mitigation = <4875000 4000000 3500000
+				3000000 2500000 2000000
+				1500000 1000000 500000>;
 };
 
 &smb1390 {
@@ -611,6 +617,8 @@
 };
 
 &smb1390_charger {
+	/delete-property/ compatible;
+	compatible = "qcom,smb1390-charger-psy";
 	io-channels = <&pm8150b_vadc ADC_AMUX_THM2>;
 	io-channel-names = "cp_die_temp";
 	status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/sm8150-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sm8150-qupv3.dtsi
index 4ef1873..7438104 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-qupv3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-qupv3.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
@@ -420,11 +420,12 @@
 		clocks = <&clock_gcc GCC_QUPV3_WRAP2_S3_CLK>,
 			<&clock_gcc GCC_QUPV3_WRAP_2_M_AHB_CLK>,
 			<&clock_gcc GCC_QUPV3_WRAP_2_S_AHB_CLK>;
-		pinctrl-names = "default", "sleep";
-		pinctrl-0 = <&qupv3_se13_ctsrx>, <&qupv3_se13_rts>,
-						<&qupv3_se13_tx>;
+		pinctrl-names = "default", "active", "sleep";
+		pinctrl-0 = <&qupv3_se13_pins_default>;
 		pinctrl-1 = <&qupv3_se13_ctsrx>, <&qupv3_se13_rts>,
 						<&qupv3_se13_tx>;
+		pinctrl-2 = <&qupv3_se13_ctsrx>, <&qupv3_se13_rts>,
+						<&qupv3_se13_tx>;
 		interrupts-extended = <&pdc GIC_SPI 585 0>,
 				<&tlmm 46 0>;
 		qcom,wrapper-core = <&qupv3_2>;
@@ -1073,6 +1074,7 @@
 		pinctrl-1 = <&qupv3_se22_spi_sleep>;
 		spi-max-frequency = <50000000>;
 		qcom,wrapper-core = <&qupv3_3>;
+		qcom,disable-dma;
 		status = "disabled";
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi
index eff9ec2..4d3fdfb 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi
@@ -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
@@ -394,7 +394,6 @@
 		qcom,mdss-default-ot-wr-limit = <32>;
 
 		qcom,mdss-sbuf-headroom = <20>;
-		qcom,mdss-rot-linewidth = <8192>;
 
 		cache-slice-names = "rotator";
 		cache-slices = <&llcc 4>;
diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-qrd.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-qrd.dtsi
index 6e57ff0..747515f 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m-qrd.dtsi
@@ -587,6 +587,8 @@
 };
 
 &smb1390_charger {
+	/delete-property/ compatible;
+	compatible = "qcom,smb1390-charger-psy";
 	io-channels = <&pm8150b_vadc ADC_AMUX_THM2>;
 	io-channel-names = "cp_die_temp";
 	status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi
index 93b4591..14f305b 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-sdx50m.dtsi
@@ -549,6 +549,23 @@
 			};
 		};
 	};
+
+	soc {
+		trips {
+			soc_trip1: soc-trip1 {
+				temperature = <20>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			soc_modem {
+				trip = <&soc_trip1>;
+				cooling-device =
+					<&modem1_proc 3 3>;
+			};
+		};
+	};
 };
 
 &reserved_memory {
diff --git a/arch/arm64/boot/dts/qcom/sm8150-sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sdxprairie.dtsi
index 8bee87b..d01cb9e 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-sdxprairie.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-sdxprairie.dtsi
@@ -113,6 +113,7 @@
 		qcom,register-collection-on-crash;
 		qcom,testbus-collection-on-crash;
 		qcom,non-tn-collection-on-crash;
+		qcom,secure-debug-check-action = <0>;
 	};
 
 	qcom,ipa_fws {
@@ -126,6 +127,12 @@
 		qcom,pil-force-shutdown;
 		memory-region = <&pil_ipa_fw_mem>;
 	};
+	ipa_mpm: qcom,ipa-mpm {
+		compatible = "qcom,ipa-mpm";
+		qcom,mhi-chdb-base = <0x40300300>;
+		qcom,mhi-erdb-base = <0x40300700>;
+		qcom,iova-mapping = <0x10000000 0x1FFFFFFF>;
+	 };
 };
 
 &reserved_memory {
diff --git a/arch/arm64/boot/dts/qcom/sm8150-v2-camera.dtsi b/arch/arm64/boot/dts/qcom/sm8150-v2-camera.dtsi
index e92fd1b..c0793f3 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-v2-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-v2-camera.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
@@ -235,10 +235,10 @@
 				};
 
 				iova-mem-region-shared {
-					/* Shared region is 100MB long */
+					/* Shared region is 150MB long */
 					iova-region-name = "shared";
 					iova-region-start = <0x7400000>;
-					iova-region-len = <0x6400000>;
+					iova-region-len = <0x9600000>;
 					iova-region-id = <0x1>;
 					status = "ok";
 				};
@@ -246,7 +246,7 @@
 				iova-mem-region-secondary-heap {
 					/* Secondary heap region is 1MB long */
 					iova-region-name = "secheap";
-					iova-region-start = <0xd800000>;
+					iova-region-start = <0x10A00000>;
 					iova-region-len = <0x100000>;
 					iova-region-id = <0x4>;
 					status = "ok";
@@ -255,8 +255,8 @@
 				iova-mem-region-io {
 					/* IO region is approximately 3.3 GB */
 					iova-region-name = "io";
-					iova-region-start = <0xda00000>;
-					iova-region-len = <0xd2500000>;
+					iova-region-start = <0x10C00000>;
+					iova-region-len = <0xCF300000>;
 					iova-region-id = <0x3>;
 					status = "ok";
 				};
@@ -264,7 +264,7 @@
 				iova-mem-qdss-region {
 					/* QDSS region is appropriate 1MB */
 					iova-region-name = "qdss";
-					iova-region-start = <0xd900000>;
+					iova-region-start = <0x10B00000>;
 					iova-region-len = <0x100000>;
 					iova-region-id = <0x5>;
 					qdss-phy-addr = <0x16790000>;
diff --git a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi
index a426f6e..ebcd765 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-v2.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* 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
@@ -642,7 +642,7 @@
 			qcom,gpu-freq = <427000000>;
 			qcom,bus-freq = <6>;
 			qcom,bus-min = <5>;
-			qcom,bus-max = <7>;
+			qcom,bus-max = <9>;
 		};
 
 		qcom,gpu-pwrlevel@3 {
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index 35df47b..a415d52e 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -3687,6 +3687,9 @@
 		mhi,max-channels = <30>;
 		mhi,timeout = <10000>;
 
+		#address-cells = <1>;
+		#size-cells = <0>;
+
 		mhi_chan@0 {
 			reg = <0>;
 			label = "LOOPBACK";
diff --git a/arch/arm64/boot/dts/qcom/trinket-bus.dtsi b/arch/arm64/boot/dts/qcom/trinket-bus.dtsi
index 915059d..2518475 100644
--- a/arch/arm64/boot/dts/qcom/trinket-bus.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-bus.dtsi
@@ -19,9 +19,13 @@
 		reg = <0x1880000 0x60200>,
 			<0x4480000 0x80000>,
 			<0x1900000 0x8200>,
+			<0x1880000 0x60200>,
+			<0x1880000 0x60200>,
+			<0x1880000 0x60200>,
 			<0x1880000 0x60200>;
 		reg-names = "sys_noc-base", "bimc-base", "config_noc-base",
-				"qup_virt-base";
+				"qup_virt-base", "fab-gpu_vert-base",
+				"mmnrt_virt-base", "mmrt_virt-base";
 
 		/*Buses*/
 
@@ -31,8 +35,7 @@
 			qcom,fab-dev;
 			qcom,base-name = "bimc-base";
 			qcom,bus-type = <2>;
-			qcom,bypass-qos-prg;
-			qcom,util-fact = <161>;
+			qcom,util-fact = <153>;
 			clock-names = "bus_clk", "bus_a_clk";
 			clocks = <&clock_rpmcc BIMC_MSMBUS_CLK>,
 				<&clock_rpmcc BIMC_MSMBUS_A_CLK>;
@@ -67,8 +70,7 @@
 			label = "fab-sys_noc";
 			qcom,fab-dev;
 			qcom,base-name = "sys_noc-base";
-			qcom,bypass-qos-prg;
-			qcom,bus-type = <1>;
+			qcom,bus-type = <3>;
 			qcom,base-offset = <0x15000>;
 			qcom,qos-off = <0x1000>;
 			clock-names = "bus_clk", "bus_a_clk";
@@ -76,6 +78,43 @@
 				<&clock_rpmcc SNOC_MSMBUS_A_CLK>;
 		};
 
+		fab_gpu_vert: fab-gpu_vert {
+			cell-id = <MSM_BUS_FAB_GPU_VIRT>;
+			label = "fab-gpu_vert";
+			qcom,vert-dev;
+			qcom,base-name = "fab-gpu_vert-base";
+			qcom,bypass-qos-prg;
+			qcom,bus-type = <3>;
+		};
+
+		fab_mmnrt_virt: fab-mmnrt_virt {
+			cell-id = <MSM_BUS_FAB_MMNRT_VIRT>;
+			label = "fab-mmnrt_virt";
+			qcom,fab-dev;
+			qcom,base-name = "mmnrt_virt-base";
+			qcom,bus-type = <3>;
+			qcom,base-offset = <0x15000>;
+			qcom,qos-off = <0x1000>;
+			qcom,util-fact = <142>;
+			clock-names = "bus_clk", "bus_a_clk";
+			clocks = <&clock_rpmcc CPP_MMNRT_MSMBUS_CLK>,
+				<&clock_rpmcc CPP_MMNRT_MSMBUS_A_CLK>;
+		};
+
+		fab_mmrt_virt: fab-mmrt_virt {
+			cell-id = <MSM_BUS_FAB_MMRT_VIRT>;
+			label = "fab-mmrt_virt";
+			qcom,fab-dev;
+			qcom,base-name = "mmrt_virt-base";
+			qcom,bus-type = <3>;
+			qcom,base-offset = <0x15000>;
+			qcom,qos-off = <0x1000>;
+			qcom,util-fact = <142>;
+			clock-names = "bus_clk", "bus_a_clk";
+			clocks = <&clock_rpmcc MDP_MMRT_MSMBUS_CLK>,
+				<&clock_rpmcc MDP_MMRT_MSMBUS_A_CLK>;
+		};
+
 		/*Masters*/
 
 		mas_apps_proc: mas-apps-proc {
@@ -200,8 +239,7 @@
 			qcom,qport = <22>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_anoc_snoc>;
-			qcom,prio1 = <1>;
-			qcom,prio0 = <1>;
+			qcom,prio = <2>;
 			clock-names = "node_clk", "node_a_clk";
 			clocks = <&clock_rpmcc CRYPTO_MSMBUS_SNOC_PERIPH_CLK>,
 				<&clock_rpmcc CRYPTO_MSMBUS_SNOC_PERIPH_A_CLK>;
@@ -272,13 +310,10 @@
 			qcom,agg-ports = <1>;
 			qcom,ap-owned;
 			qcom,qport = <15>;
-			qcom,qos-mode = "bypass";
+			qcom,qos-mode = "fixed";
+			qcom,prio = <3>;
 			qcom,connections = <&slv_snoc_bimc_nrt>;
-			qcom,util-fact = <153>;
-			clock-names = "node_clk", "node_a_clk";
-			clocks = <&clock_rpmcc CPP_MMNRT_MSMBUS_CLK>,
-				<&clock_rpmcc CPP_MMNRT_MSMBUS_A_CLK>;
-			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,bus-dev = <&fab_mmnrt_virt>;
 			qcom,mas-rpm-id = <ICBID_MASTER_CPP>;
 		};
 
@@ -289,13 +324,10 @@
 			qcom,agg-ports = <1>;
 			qcom,ap-owned;
 			qcom,qport = <4>;
-			qcom,qos-mode = "bypass";
+			qcom,qos-mode = "fixed";
+			qcom,prio = <1>;
 			qcom,connections = <&slv_snoc_bimc_nrt>;
-			qcom,util-fact = <153>;
-			clock-names = "node_clk", "node_a_clk";
-			clocks = <&clock_rpmcc JPEG_MMNRT_MSMBUS_CLK>,
-				<&clock_rpmcc JPEG_MMNRT_MSMBUS_A_CLK>;
-			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,bus-dev = <&fab_mmnrt_virt>;
 			qcom,mas-rpm-id = <ICBID_MASTER_JPEG>;
 		};
 
@@ -307,12 +339,9 @@
 			qcom,ap-owned;
 			qcom,qport = <5>;
 			qcom,qos-mode = "bypass";
-			qcom,util-fact = <153>;
-			clock-names = "node_clk", "node_a_clk";
-			clocks = <&clock_rpmcc MDP_MMRT_MSMBUS_CLK>,
-				<&clock_rpmcc MDP_MMRT_MSMBUS_A_CLK>;
+			qcom,forwarding;
 			qcom,connections = <&slv_snoc_bimc_rt>;
-			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,bus-dev = <&fab_mmrt_virt>;
 			qcom,mas-rpm-id = <ICBID_MASTER_MDP0>;
 		};
 
@@ -325,8 +354,7 @@
 			qcom,qport = <20>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_qxs_imem &slv_snoc_bimc>;
-			qcom,prio1 = <0>;
-			qcom,prio0 = <0>;
+			qcom,prio = <2>;
 			qcom,bus-dev = <&fab_sys_noc>;
 			qcom,mas-rpm-id = <ICBID_MASTER_PIMEM>;
 		};
@@ -339,12 +367,9 @@
 			qcom,ap-owned;
 			qcom,qport = <9>;
 			qcom,qos-mode = "bypass";
+			qcom,forwarding;
 			qcom,connections = <&slv_snoc_bimc_nrt>;
-			qcom,util-fact = <153>;
-			clock-names = "node_clk", "node_a_clk";
-			clocks = <&clock_rpmcc VENUS_MMNRT_MSMBUS_CLK>,
-				<&clock_rpmcc VENUS_MMNRT_MSMBUS_A_CLK>;
-			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,bus-dev = <&fab_mmnrt_virt>;
 			qcom,mas-rpm-id = <ICBID_MASTER_VIDEO_P0>;
 		};
 
@@ -356,12 +381,9 @@
 			qcom,ap-owned;
 			qcom,qport = <13>;
 			qcom,qos-mode = "bypass";
+			qcom,forwarding;
 			qcom,connections = <&slv_snoc_bimc_nrt>;
-			qcom,util-fact = <153>;
-			clock-names = "node_clk", "node_a_clk";
-			clocks = <&clock_rpmcc ARM9_MMNRT_MSMBUS_CLK>,
-				<&clock_rpmcc ARM9_MMNRT_MSMBUS_A_CLK>;
-			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,bus-dev = <&fab_mmnrt_virt>;
 			qcom,mas-rpm-id = <ICBID_MASTER_VIDEO_PROC>;
 
 		};
@@ -374,12 +396,9 @@
 			qcom,ap-owned;
 			qcom,qport = <10>;
 			qcom,qos-mode = "bypass";
+			qcom,forwarding;
 			qcom,connections = <&slv_snoc_bimc_rt>;
-			qcom,util-fact = <153>;
-			clock-names = "node_clk", "node_a_clk";
-			clocks = <&clock_rpmcc VFE_MMRT_MSMBUS_CLK>,
-				<&clock_rpmcc VFE_MMRT_MSMBUS_A_CLK>;
-			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,bus-dev = <&fab_mmrt_virt>;
 			qcom,mas-rpm-id = <ICBID_MASTER_VFE0>;
 		};
 
@@ -392,8 +411,7 @@
 			qcom,qport = <2>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_anoc_snoc>;
-			qcom,prio1 = <1>;
-			qcom,prio0 = <1>;
+			qcom,prio = <2>;
 			qcom,bus-dev = <&fab_sys_noc>;
 			qcom,mas-rpm-id = <ICBID_MASTER_QDSS_BAM>;
 		};
@@ -407,8 +425,7 @@
 			qcom,qport = <0>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_anoc_snoc>;
-			qcom,prio1 = <1>;
-			qcom,prio0 = <1>;
+			qcom,prio = <2>;
 			clock-names = "node_clk", "node_a_clk";
 			clocks = <&clock_rpmcc QUP0_MSMBUS_SNOC_PERIPH_CLK>,
 				<&clock_rpmcc QUP0_MSMBUS_SNOC_PERIPH_A_CLK>;
@@ -425,8 +442,7 @@
 			qcom,qport = <1>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_anoc_snoc>;
-			qcom,prio1 = <1>;
-			qcom,prio0 = <1>;
+			qcom,prio = <2>;
 			clock-names = "node_clk", "node_a_clk";
 			clocks = <&clock_rpmcc QUP1_MSMBUS_SNOC_PERIPH_CLK>,
 				<&clock_rpmcc QUP1_MSMBUS_SNOC_PERIPH_A_CLK>;
@@ -454,8 +470,7 @@
 			qcom,qport = <3>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_anoc_snoc>;
-			qcom,prio1 = <2>;
-			qcom,prio0 = <2>;
+			qcom,prio = <2>;
 			qcom,bus-dev = <&fab_sys_noc>;
 			qcom,mas-rpm-id = <ICBID_MASTER_IPA>;
 		};
@@ -483,8 +498,7 @@
 			qcom,qport = <12>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_anoc_snoc>;
-			qcom,prio1 = <1>;
-			qcom,prio0 = <1>;
+			qcom,prio = <2>;
 			qcom,bus-dev = <&fab_sys_noc>;
 			qcom,mas-rpm-id = <ICBID_MASTER_QDSS_ETR>;
 		};
@@ -498,8 +512,7 @@
 			qcom,qport = <17>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_anoc_snoc>;
-			qcom,prio1 = <1>;
-			qcom,prio0 = <1>;
+			qcom,prio = <2>;
 			clock-names = "node_clk", "node_a_clk";
 			clocks = <&clock_rpmcc SDC1_MSMBUS_SNOC_PERIPH_CLK>,
 				<&clock_rpmcc SDC1_MSMBUS_SNOC_PERIPH_A_CLK>;
@@ -516,8 +529,7 @@
 			qcom,qport = <23>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_anoc_snoc>;
-			qcom,prio1 = <1>;
-			qcom,prio0 = <1>;
+			qcom,prio = <2>;
 			clock-names = "node_clk", "node_a_clk";
 			clocks = <&clock_rpmcc SDC2_MSMBUS_SNOC_PERIPH_CLK>,
 				<&clock_rpmcc SDC2_MSMBUS_SNOC_PERIPH_A_CLK>;
@@ -534,8 +546,7 @@
 			qcom,qport = <25>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_anoc_snoc>;
-			qcom,prio1 = <2>;
-			qcom,prio0 = <2>;
+			qcom,prio = <2>;
 			clock-names = "node_clk", "node_a_clk";
 			clocks = <&clock_rpmcc RPM_SMD_SNOC_LPASS_CLK>,
 				<&clock_rpmcc RPM_SMD_SNOC_LPASS_A_CLK>;
@@ -552,25 +563,32 @@
 			qcom,qport = <24>;
 			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_anoc_snoc>;
-			qcom,prio1 = <2>;
-			qcom,prio0 = <2>;
+			qcom,prio = <2>;
 			qcom,bus-dev = <&fab_sys_noc>;
 			qcom,mas-rpm-id = <ICBID_MASTER_USB3_0>;
 		};
 
+		mas_qnm_gpu_qos: mas-qnm-gpu-qos {
+			cell-id = <MSM_BUS_MASTER_GRAPHICS_3D_PORT1>;
+			label = "mas-qnm-gpu-qos";
+			qcom,buswidth = <32>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,qport = <16>;
+			qcom,qos-mode = "fixed";
+			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,prio = <0>;
+			qcom,mas-rpm-id = <ICBID_MASTER_GFX3D>;
+		};
+
 		mas_qnm_gpu: mas-qnm-gpu {
 			cell-id = <MSM_BUS_MASTER_GRAPHICS_3D>;
 			label = "mas-qnm-gpu";
 			qcom,buswidth = <32>;
 			qcom,agg-ports = <1>;
 			qcom,ap-owned;
-			qcom,qport = <16>;
-			qcom,qos-mode = "fixed";
 			qcom,connections = <&slv_gpu_cdsp_bimc>;
-			qcom,prio1 = <0>;
-			qcom,prio0 = <0>;
-			qcom,util-fact = <161>;
-			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,bus-dev = <&fab_gpu_vert>;
 			qcom,mas-rpm-id = <ICBID_MASTER_GFX3D>;
 
 		};
@@ -991,7 +1009,7 @@
 			qcom,buswidth = <16>;
 			qcom,agg-ports = <1>;
 			qcom,ap-owned;
-			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,bus-dev = <&fab_mmnrt_virt>;
 			qcom,connections = <&mas_snoc_bimc_nrt>;
 			qcom,slv-rpm-id = <ICBID_SLAVE_SNOC_BIMC_NRT>;
 		};
@@ -1002,7 +1020,7 @@
 			qcom,buswidth = <16>;
 			qcom,agg-ports = <1>;
 			qcom,ap-owned;
-			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,bus-dev = <&fab_mmrt_virt>;
 			qcom,connections = <&mas_snoc_bimc_rt>;
 			qcom,slv-rpm-id = <ICBID_SLAVE_SNOC_BIMC_RT>;
 		};
@@ -1090,8 +1108,7 @@
 			label = "slv-gpu-cdsp-bimc";
 			qcom,buswidth = <32>;
 			qcom,agg-ports = <1>;
-			qcom,util-fact = <161>;
-			qcom,bus-dev = <&fab_sys_noc>;
+			qcom,bus-dev = <&fab_gpu_vert>;
 			qcom,connections = <&mas_gpu_cdsp_bimc>;
 			qcom,slv-rpm-id = <ICBID_SLAVE_GPU_CDSP_BIMC>;
 		};
diff --git a/arch/arm64/boot/dts/qcom/trinket-camera-sensor-idp.dtsi b/arch/arm64/boot/dts/qcom/trinket-camera-sensor-idp.dtsi
index 430397e..fa72354 100644
--- a/arch/arm64/boot/dts/qcom/trinket-camera-sensor-idp.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-camera-sensor-idp.dtsi
@@ -34,6 +34,18 @@
 		qcom,cam-vreg-op-mode = <0>;
 	};
 
+	actuator1: qcom,actuator@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <1>;
+		cam_vaf-supply = <&L5P>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000>;
+		qcom,cam-vreg-max-voltage = <2800000>;
+		qcom,cam-vreg-op-mode = <0>;
+	};
+
 	eeprom0: qcom,eeprom@0 {
 		cell-index = <0>;
 		reg = <0>;
@@ -72,7 +84,43 @@
 
 	eeprom1: qcom,eeprom@1 {
 		cell-index = <1>;
-		reg = <0x1>;
+		reg = <1>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&L12A>;
+		cam_vana-supply = <&L4P>;
+		cam_vdig-supply = <&L1P>;
+		cam_clk-supply = <&camss_top_gdsc>;
+		cam_vaf-supply = <&L5P>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+				"cam_clk", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <1800000 2800000 1200000 0 2800000>;
+		qcom,cam-vreg-max-voltage = <1800000 2800000 1200000 0 2800000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000 0 100000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				 &cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				 &cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 35 0>,
+			<&tlmm 46 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+					  "CAM_RESET1";
+		qcom,sensor-position = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_gcc GCC_CAMSS_MCLK1_CLK_SRC>,
+			<&clock_gcc GCC_CAMSS_MCLK1_CLK>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	eeprom2: qcom,eeprom@2 {
+		cell-index = <2>;
+		reg = <0x2>;
 		compatible = "qcom,eeprom";
 		cam_vio-supply = <&L12A>;
 		cam_vana-supply = <&L4P>;
@@ -156,15 +204,18 @@
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <1>;
 		qcom,mount-angle = <90>;
+		qcom,actuator-src = <&actuator1>;
+		qcom,eeprom-src = <&eeprom1>;
 		cam_vio-supply = <&L12A>;
 		cam_vana-supply = <&L4P>;
 		cam_vdig-supply = <&L1P>;
 		cam_clk-supply = <&camss_top_gdsc>;
+		cam_vaf-supply = <&L5P>;
 		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
-				"cam_clk";
-		qcom,cam-vreg-min-voltage = <1800000 2800000 1200000 0>;
-		qcom,cam-vreg-max-voltage = <1800000 2800000 1200000 0>;
-		qcom,cam-vreg-op-mode = <0 80000 105000 0>;
+				"cam_clk", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <1800000 2800000 1200000 0 2800000>;
+		qcom,cam-vreg-max-voltage = <1800000 2800000 1200000 0 2800000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000 0 100000>;
 		qcom,gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk1_active
@@ -195,7 +246,7 @@
 		qcom,csiphy-sd-index = <2>;
 		qcom,csid-sd-index = <2>;
 		qcom,mount-angle = <90>;
-		qcom,eeprom-src = <&eeprom1>;
+		qcom,eeprom-src = <&eeprom2>;
 		cam_vio-supply = <&L12A>;
 		cam_vana-supply = <&L4P>;
 		cam_vdig-supply = <&L1P>;
diff --git a/arch/arm64/boot/dts/qcom/trinket-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/trinket-camera-sensor-qrd.dtsi
new file mode 100644
index 0000000..430397e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/trinket-camera-sensor-qrd.dtsi
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ */
+&soc {
+	led_flash0: qcom,camera-flash@0 {
+		cell-index = <0>;
+		compatible = "qcom,camera-flash";
+		qcom,flash-source = <&pmi632_flash0 &pmi632_flash1>;
+		qcom,torch-source = <&pmi632_torch0 &pmi632_torch1>;
+		qcom,switch-source = <&pmi632_switch0 &pmi632_switch0>;
+		status = "ok";
+	};
+};
+
+&cci {
+	actuator0: qcom,actuator@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+		cam_vaf-supply = <&L5P>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000>;
+		qcom,cam-vreg-max-voltage = <2800000>;
+		qcom,cam-vreg-op-mode = <0>;
+	};
+
+	eeprom0: qcom,eeprom@0 {
+		cell-index = <0>;
+		reg = <0>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&L12A>;
+		cam_vana-supply = <&L3P>;
+		cam_vdig-supply = <&L2P>;
+		cam_clk-supply = <&camss_top_gdsc>;
+		cam_vaf-supply = <&L5P>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+				"cam_clk", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <1800000 2800000 1104000 0 2800000>;
+		qcom,cam-vreg-max-voltage = <1800000 2800000 1104000 0 2800000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000 0 100000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_active
+				&cam_sensor_rear_active>;
+		pinctrl-1 = <&cam_sensor_mclk0_suspend
+				&cam_sensor_rear_suspend>;
+		gpios = <&tlmm 34 0>,
+			<&tlmm 48 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+					"CAM_RESET0";
+		qcom,sensor-position = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_gcc GCC_CAMSS_MCLK0_CLK_SRC>,
+				<&clock_gcc GCC_CAMSS_MCLK0_CLK>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	eeprom1: qcom,eeprom@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&L12A>;
+		cam_vana-supply = <&L4P>;
+		cam_vdig-supply = <&L1P>;
+		cam_clk-supply = <&camss_top_gdsc>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+				"cam_clk";
+		qcom,cam-vreg-min-voltage = <1800000 2800000 1200000 0>;
+		qcom,cam-vreg-max-voltage = <1800000 2800000 1200000 0>;
+		qcom,cam-vreg-op-mode = <0 80000 105000 0>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_active
+			&cam_sensor_front_active>;
+		pinctrl-1 = <&cam_sensor_mclk2_suspend
+			&cam_sensor_front_suspend>;
+		gpios = <&tlmm 36 0>,
+		    <&tlmm 42 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+				"CAM_RESET";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_gcc GCC_CAMSS_MCLK2_CLK_SRC>,
+		    <&clock_gcc GCC_CAMSS_MCLK2_CLK>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	qcom,camera@0 {
+		cell-index = <0>;
+		compatible = "qcom,camera";
+		reg = <0x0>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <90>;
+		qcom,actuator-src = <&actuator0>;
+		qcom,eeprom-src = <&eeprom0>;
+		qcom,led-flash-src = <&led_flash0>;
+		cam_vio-supply = <&L12A>;
+		cam_vana-supply = <&L3P>;
+		cam_vdig-supply = <&L2P>;
+		cam_clk-supply = <&camss_top_gdsc>;
+		cam_vaf-supply = <&L5P>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+				"cam_clk", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <1800000 2800000 1104000 0 2800000>;
+		qcom,cam-vreg-max-voltage = <1800000 2800000 1104000 0 2800000>;
+		qcom,cam-vreg-op-mode = <0 80000 105000 0 100000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_active
+				&cam_sensor_rear_active>;
+		pinctrl-1 = <&cam_sensor_mclk0_suspend
+				&cam_sensor_rear_suspend>;
+		gpios = <&tlmm 34 0>,
+			<&tlmm 48 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+					"CAM_RESET0";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_gcc GCC_CAMSS_MCLK0_CLK_SRC>,
+				<&clock_gcc GCC_CAMSS_MCLK0_CLK>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	qcom,camera@1 {
+		cell-index = <1>;
+		compatible = "qcom,camera";
+		reg = <0x1>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <90>;
+		cam_vio-supply = <&L12A>;
+		cam_vana-supply = <&L4P>;
+		cam_vdig-supply = <&L1P>;
+		cam_clk-supply = <&camss_top_gdsc>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+				"cam_clk";
+		qcom,cam-vreg-min-voltage = <1800000 2800000 1200000 0>;
+		qcom,cam-vreg-max-voltage = <1800000 2800000 1200000 0>;
+		qcom,cam-vreg-op-mode = <0 80000 105000 0>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				 &cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				 &cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 35 0>,
+			<&tlmm 46 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+					  "CAM_RESET1";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_gcc GCC_CAMSS_MCLK1_CLK_SRC>,
+			<&clock_gcc GCC_CAMSS_MCLK1_CLK>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	qcom,camera@2 {
+		cell-index = <2>;
+		compatible = "qcom,camera";
+		reg = <0x02>;
+		qcom,csiphy-sd-index = <2>;
+		qcom,csid-sd-index = <2>;
+		qcom,mount-angle = <90>;
+		qcom,eeprom-src = <&eeprom1>;
+		cam_vio-supply = <&L12A>;
+		cam_vana-supply = <&L4P>;
+		cam_vdig-supply = <&L1P>;
+		cam_clk-supply = <&camss_top_gdsc>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+				"cam_clk";
+		qcom,cam-vreg-min-voltage = <1800000 2800000 1200000 0>;
+		qcom,cam-vreg-max-voltage = <1800000 2800000 1200000 0>;
+		qcom,cam-vreg-op-mode = <0 80000 105000 0>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_active
+				 &cam_sensor_front_active>;
+		pinctrl-1 = <&cam_sensor_mclk2_suspend
+				 &cam_sensor_front_suspend>;
+		gpios = <&tlmm 36 0>,
+			<&tlmm 42 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+					"CAM_RESET2";
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_gcc GCC_CAMSS_MCLK2_CLK_SRC>,
+			<&clock_gcc GCC_CAMSS_MCLK2_CLK>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+};
diff --git a/arch/arm64/boot/dts/qcom/trinket-camera.dtsi b/arch/arm64/boot/dts/qcom/trinket-camera.dtsi
index 692461b..8120a0a 100644
--- a/arch/arm64/boot/dts/qcom/trinket-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-camera.dtsi
@@ -254,6 +254,7 @@
 	qcom,cam_smmu {
 		compatible = "qcom,msm-cam-smmu";
 		status = "ok";
+		qcom,camera-secure-sid;
 
 		msm_cam_smmu_cb1 {
 			compatible = "qcom,msm-cam-smmu-cb";
@@ -271,12 +272,12 @@
 
 		msm_cam_smmu_cb4 {
 			compatible = "qcom,msm-cam-smmu-cb";
-			iommus = <&apps_smmu 0x820 0x0001>;
+			iommus = <&apps_smmu 0x820 0x0000>;
 			label = "jpeg_enc0";
 		};
 		msm_cam_smmu_cb5 {
 			compatible = "qcom,msm-cam-smmu-cb";
-			iommus = <&apps_smmu 0x821 0x0001>;
+			iommus = <&apps_smmu 0x821 0x0000>;
 			label = "jpeg_dma";
 		};
 
@@ -309,9 +310,25 @@
 			"cpp_core_clk", "camss_cpp_ahb_clk",
 			"camss_cpp_axi_clk", "micro_iface_clk",
 			"cpp_vbif_ahb_clk", "mmss_throttle_camss_nrt_axi_clk";
-		qcom,clock-rates = <0 0 256000000 256000000 0 0 0 0 0>;
-		qcom,min-clock-rate = <256000000>;
+		qcom,clock-rates = <0 0 240000000 240000000 0 0 0 0 0>;
+		qcom,min-clock-rate = <240000000>;
 		qcom,bus-master = <1>;
+		qcom,vbif-qos-setting = <0x550 0x33333333>,
+			<0x554 0x00333333>,
+			<0x558 0x33333333>,
+			<0x55c 0x00333333>,
+			<0x560 0x33333333>,
+			<0x564 0x00333333>,
+			<0x568 0x33333333>,
+			<0x56c 0x00333333>,
+			<0x570 0x33333333>,
+			<0x574 0x00333333>,
+			<0x578 0x33333333>,
+			<0x57c 0x00333333>,
+			<0x580 0x33333333>,
+			<0x584 0x00333333>,
+			<0x588 0x33333333>,
+			<0x58c 0x00333333>;
 		status = "ok";
 		qcom,msm-bus,name = "msm_camera_cpp";
 		qcom,msm-bus,num-cases = <2>;
@@ -323,8 +340,8 @@
 		qcom,cpp-cx-ipeak = <&cx_ipeak_lm 7>;
 		resets = <&clock_gcc GCC_CAMSS_MICRO_BCR>;
 		reset-names = "micro_iface_reset";
-		qcom,src-clock-rates = <120000000 256000000 384000000
-					480000000 533000000 576000000>;
+		qcom,src-clock-rates = <120000000 240000000 320000000
+					480000000 576000000>;
 		qcom,micro-reset;
 		qcom,cpp-fw-payload-info {
 			qcom,stripe-base = <790>;
@@ -477,7 +494,7 @@
 		ds-regs = <0x424 0x428 0x42c 0x430 0x434
 			0x438 0x43c 0x440 0x444 0x448 0x44c
 			0x450 0x454 0x458 0x45c 0x460 0x464>;
-		ds-settings = <0xcccc1111
+		ds-settings = <0xcccc0011
 			0xcccc0011
 			0xcccc0011
 			0xcccc0011
@@ -555,7 +572,7 @@
 		ds-regs = <0x424 0x428 0x42c 0x430 0x434
 			0x438 0x43c 0x440 0x444 0x448 0x44c
 			0x450 0x454 0x458 0x45c 0x460 0x464>;
-		ds-settings = <0xcccc1111
+		ds-settings = <0xcccc0011
 			0xcccc0011
 			0xcccc0011
 			0xcccc0011
@@ -648,7 +665,7 @@
 		clock-names = "mmss_camss_ahb_clk",
 			"mmss_camss_top_ahb_clk",
 			"core_src_clk",
-			"core_src",
+			"core_clk",
 			"mmss_camss_jpeg_ahb_clk",
 			"mmss_camss_jpeg_axi_clk";
 		clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>,
@@ -659,7 +676,14 @@
 			<&clock_gcc GCC_CAMSS_JPEG_AXI_CLK>;
 		qcom,clock-rates = <0 0 480000000 0 0 0>;
 		qcom,vbif-reg-settings = <0x4 0x1>;
-		qcom,vbif-qos-setting = <0x550 0x1111>;
+		qcom,vbif-qos-setting = <0x550 0x00001111>,
+			<0x558 0x00001111>,
+			<0x560 0x00001111>,
+			<0x568 0x00001111>,
+			<0x570 0x00001111>,
+			<0x578 0x00001111>,
+			<0x580 0x00001111>,
+			<0x588 0x00001111>;
 		qcom,prefetch-reg-settings = <0x30c 0x1111>,
 			<0x318 0x31>,
 			<0x324 0x31>,
@@ -697,7 +721,14 @@
 			<&clock_gcc GCC_CAMSS_JPEG_AXI_CLK>;
 		qcom,clock-rates = <0 0 480000000 0 0 0>;
 		qcom,vbif-reg-settings = <0x4 0x1>;
-		qcom,vbif-qos-setting = <0x550 0x1111>;
+		qcom,vbif-qos-setting = <0x550 0x00001111>,
+			<0x558 0x00001111>,
+			<0x560 0x00001111>,
+			<0x568 0x00001111>,
+			<0x570 0x00001111>,
+			<0x578 0x00001111>,
+			<0x580 0x00001111>,
+			<0x588 0x00001111>;
 		qcom,prefetch-reg-settings = <0x18c 0x11>,
 			<0x1a0 0x31>,
 			<0x1b0 0x31>;
diff --git a/arch/arm64/boot/dts/qcom/trinket-coresight.dtsi b/arch/arm64/boot/dts/qcom/trinket-coresight.dtsi
index b16d2c0..c23f23e 100644
--- a/arch/arm64/boot/dts/qcom/trinket-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-coresight.dtsi
@@ -162,6 +162,15 @@
 				};
 			};
 
+			port@2 {
+				reg = <1>;
+				funnel_merg_in_funnel_in1: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_in1_out_funnel_merg>;
+				};
+			};
+
 			port@3 {
 				reg = <2>;
 				funnel_merg_in_funnel_in2: endpoint {
@@ -216,6 +225,41 @@
 		};
 	};
 
+	funnel_in1: funnel@8042000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x8042000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-in1";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_in1_out_funnel_merg: endpoint {
+					remote-endpoint =
+						<&funnel_merg_in_funnel_in1>;
+				};
+			};
+
+			port@1 {
+				reg = <7>;
+				funnel_in1_in_tpda_mapss: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpda_mapss_out_funnel_in1>;
+				};
+			};
+		};
+	};
+
 	stm: stm@8002000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b962>;
@@ -328,6 +372,15 @@
 			};
 
 			port@2 {
+				reg = <2>;
+				funnel_apss1_in_tpda_actpm: endpoint {
+					slave-mode;
+					remote-endpoint =
+					    <&tpda_actpm_out_funnel_apss1>;
+				};
+			};
+
+			port@3 {
 				reg = <3>;
 				funnel_apss1_in_tpda_llm_silver: endpoint {
 					slave-mode;
@@ -336,7 +389,7 @@
 				};
 			};
 
-			port@3 {
+			port@4 {
 				reg = <4>;
 				funnel_apss1_in_tpda_apss: endpoint {
 					slave-mode;
@@ -347,6 +400,60 @@
 		};
 	};
 
+	tpda_mapss: tpda@8a04000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
+		reg = <0x8a04000 0x1000>;
+		reg-names = "tpda-base";
+
+		coresight-name = "coresight-tpda-mapss";
+
+		qcom,tpda-atid = <76>;
+		qcom,dsb-elem-size = <0 32>;
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				tpda_mapss_out_funnel_in1: endpoint {
+					remote-endpoint =
+					       <&funnel_in1_in_tpda_mapss>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				tpda_mapss_in_tpdm_mapss: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_mapss_out_tpda_mapss>;
+				};
+			};
+		};
+	};
+
+	tpdm_mapss: tpdm@8a01000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+		reg = <0x8a01000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-mapss";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		port {
+			tpdm_mapss_out_tpda_mapss: endpoint {
+				remote-endpoint = <&tpda_mapss_in_tpdm_mapss>;
+			};
+		};
+	};
+
 	tpda_apss: tpda@9862000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b969>;
@@ -401,6 +508,61 @@
 		};
 	};
 
+	tpda_actpm: tpda@9832000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
+		reg = <0x9832000 0x1000>;
+		reg-names = "tpda-base";
+
+		coresight-name = "coresight-tpda-actpm";
+
+		qcom,tpda-atid = <77>;
+		qcom,cmb-elem-size = <0 32>;
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				tpda_actpm_out_funnel_apss1: endpoint {
+					remote-endpoint =
+					<&funnel_apss1_in_tpda_actpm>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				tpda_actpm_in_tpdm_actpm: endpoint {
+					slave-mode;
+					remote-endpoint =
+					<&tpdm_actpm_out_tpda_actpm>;
+				};
+			};
+		};
+	};
+
+	tpdm_actpm: tpdm@9830000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+		reg = <0x9830000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-actpm";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		port {
+			tpdm_actpm_out_tpda_actpm: endpoint {
+				remote-endpoint =
+					<&tpda_actpm_in_tpdm_actpm>;
+			};
+		};
+	};
+
 	tpda_llm_silver: tpda@98c0000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b969>;
@@ -826,6 +988,15 @@
 			};
 
 			port@2 {
+				reg = <1>;
+				tpda_in_funnel_gpu: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_gpu_out_tpda>;
+				};
+			};
+
+			port@3 {
 				reg = <3>;
 				tpda_in_funnel_monaq: endpoint {
 					slave-mode;
@@ -834,7 +1005,7 @@
 				};
 			};
 
-			port@3 {
+			port@4 {
 				reg = <4>;
 				tpda_in_funnel_lpass_1: endpoint {
 					slave-mode;
@@ -843,7 +1014,7 @@
 				};
 			};
 
-			port@4 {
+			port@5 {
 				reg = <5>;
 				tpda_in_funnel_turing: endpoint {
 					slave-mode;
@@ -852,7 +1023,7 @@
 				};
 			};
 
-			port@5 {
+			port@6 {
 				reg = <7>;
 				tpda_in_tpdm_vsense: endpoint {
 					slave-mode;
@@ -861,7 +1032,7 @@
 				};
 			};
 
-			port@6 {
+			port@7 {
 				reg = <8>;
 				tpda_in_tpdm_dcc: endpoint {
 					slave-mode;
@@ -870,7 +1041,7 @@
 				};
 			};
 
-			port@7 {
+			port@8 {
 				reg = <10>;
 				tpda_in_tpdm_prng: endpoint {
 					slave-mode;
@@ -879,7 +1050,7 @@
 				};
 			};
 
-			port@8 {
+			port@9 {
 				reg = <12>;
 				tpda_in_tpdm_qm: endpoint {
 					slave-mode;
@@ -888,7 +1059,7 @@
 				};
 			};
 
-			port@9 {
+			port@10 {
 				reg = <13>;
 				tpda_in_tpdm_west: endpoint {
 					slave-mode;
@@ -897,7 +1068,7 @@
 				};
 			};
 
-			port@10 {
+			port@11 {
 				reg = <14>;
 				tpda_in_tpdm_pimem: endpoint {
 					slave-mode;
@@ -909,6 +1080,74 @@
 		};
 	};
 
+	funnel_gpu: funnel@8944000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x8944000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-gpu";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>,
+			<&clock_gpucc GPU_CC_CX_APB_CLK>;
+		clock-names = "apb_pclk", "gpu_apb_clk";
+		qcom,proxy-clks = "gpu_apb_clk";
+
+		vddcx-supply = <&gpu_cx_gdsc>;
+		vdd-supply = <&gpu_gx_gdsc>;
+		regulator-names = "vddcx", "vdd";
+		qcom,proxy-regs  = "vddcx", "vdd";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_gpu_out_tpda: endpoint {
+					remote-endpoint =
+					  <&tpda_in_funnel_gpu>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				funnel_gpu_in_tpdm_gpu: endpoint {
+					slave-mode;
+					remote-endpoint =
+					  <&tpdm_gpu_out_funnel_gpu>;
+				};
+			};
+		};
+	};
+
+	tpdm_gpu: tpdm@8940000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+		reg = <0x8940000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-gpu";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>,
+			<&clock_gpucc GPU_CC_CX_APB_CLK>;
+		clock-names = "apb_pclk", "gpu_apb_clk";
+
+		qcom,tpdm-clks = "gpu_apb_clk";
+
+		vddcx-supply = <&gpu_cx_gdsc>;
+		vdd-supply = <&gpu_gx_gdsc>;
+		regulator-names = "vddcx", "vdd";
+		qcom,tpdm-regs  = "vddcx", "vdd";
+
+		port {
+			tpdm_gpu_out_funnel_gpu: endpoint {
+				remote-endpoint = <&funnel_gpu_in_tpdm_gpu>;
+			};
+		};
+	};
+
 	tpdm_vsense: tpdm@8840000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b968>;
@@ -1023,7 +1262,7 @@
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b908>;
 
-		reg = <0x89c1000 0x1>,
+		reg = <0x89c5000 0x1>,
 			<0x89c3000 0x1000>;
 		reg-names = "funnel-base-dummy", "funnel-base-real";
 
@@ -1335,7 +1574,7 @@
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b908>;
 
-		reg = <0x8867010 0x10>,
+		reg = <0x8868010 0x10>,
 			<0x8861000 0x1000>;
 		reg-names = "funnel-base-dummy", "funnel-base-real";
 
@@ -1407,7 +1646,7 @@
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b908>;
 
-		reg = <0x08b50020 0x1>,
+		reg = <0x8982000 0x1>,
 			<0x8981000 0x1000>;
 		reg-names = "funnel-base-dummy", "funnel-base-real";
 
@@ -1857,7 +2096,7 @@
 		tgu-conditions = <4>;
 		tgu-regs = <8>;
 		tgu-timer-counters = <8>;
-
+		interrupts = <0 53 1>, <0 54 1>, <0 55 1>, <0 56 1>;
 		coresight-name = "coresight-tgu-apss";
 
 		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
@@ -1935,4 +2174,136 @@
 		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
 		clock-names = "apb_pclk";
 	};
+
+	cti_arm9: cti@8b50000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x8b50000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-arm9_cti";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_cortex_m3: cti@8b30000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x8b30000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-cortex_m3";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_dlmt_cti0: cti@89c1000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x89c1000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-dlmt_cti0";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_gpu_isdb_cti: cti@8941000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x8941000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-gpu_isdb_cti";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_lpass_q6_cti: cti@8987000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x8987000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-lpass_q6_cti";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_mapss_cti: cti@8a02000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x8a02000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-mapss_cti";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_mss_q6_cti: cti@883b000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x883b000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-mss_q6_cti";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_turing_q6_cti: cti@8867000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x8867000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-turing_q6_cti";
+
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_wcss_cti0: cti@cadc000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0xcadc000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-wcss_cti0";
+		status = "disabled";
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_wcss_cti1: cti@cadd000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0xcadd000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-wcss_cti1";
+		status = "disabled";
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_wcss_cti2: cti@cade000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0xcade000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-wcss_cti2";
+		status = "disabled";
+		clocks = <&clock_rpmcc RPM_SMD_QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/trinket-gpu.dtsi b/arch/arm64/boot/dts/qcom/trinket-gpu.dtsi
index 8ac0dd9..590557a 100644
--- a/arch/arm64/boot/dts/qcom/trinket-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-gpu.dtsi
@@ -82,11 +82,13 @@
 			<&clock_gpucc GPU_CC_AHB_CLK>,
 			<&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
 			<&clock_gcc GCC_SYS_NOC_COMPUTE_SF_AXI_CLK>,
-			<&clock_gpucc GPU_CC_CX_GMU_CLK>;
+			<&clock_gpucc GPU_CC_CX_GMU_CLK>,
+			<&clock_gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>;
 
 		clock-names = "core_clk", "rbbmtimer_clk", "mem_clk",
-				"iface_clock", "mem_iface_clk",
-				"alt_mem_iface_clk", "gmu_clk";
+				"iface_clk", "mem_iface_clk",
+				"alt_mem_iface_clk", "gmu_clk",
+				"smmu_vote";
 
 		/* Bus Scale Settings */
 		qcom,gpubw-dev = <&gpubw>;
@@ -127,6 +129,10 @@
 		qcom,ca-target-pwrlevel = <5>;
 
 		qcom,gpu-speed-bin = <0x6004 0x1fe00000 21>;
+		qcom,gpu-gaming-bin = <0x6018 0x80 7>;
+
+		/* CX iPeak limit support */
+		qcom,gpu-cx-ipeak = <&cx_ipeak_lm 5>;
 
 		/* GPU Mempools */
 		qcom,gpu-mempools {
@@ -429,10 +435,11 @@
 
 		clocks = <&clock_gcc GCC_BIMC_GPU_AXI_CLK>,
 			<&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
-			<&clock_gcc GCC_SYS_NOC_COMPUTE_SF_AXI_CLK>;
+			<&clock_gcc GCC_SYS_NOC_COMPUTE_SF_AXI_CLK>,
+			<&clock_gpucc GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK>;
 
 		clock-names = "mem_clk", "mem_iface_clk",
-				"alt_mem_iface_clk";
+				"alt_mem_iface_clk", "smmu_vote";
 
 		qcom,retention;
 		qcom,hyp_secure_alloc;
diff --git a/arch/arm64/boot/dts/qcom/trinket-idp.dtsi b/arch/arm64/boot/dts/qcom/trinket-idp.dtsi
index be98998..eeaf1c0 100644
--- a/arch/arm64/boot/dts/qcom/trinket-idp.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-idp.dtsi
@@ -68,11 +68,14 @@
 			};
 		};
 	};
+
+	quiet-therm-step {
+		status = "disabled";
+	};
 };
 
 &qupv3_se1_i2c {
 	status = "ok";
-	qcom,clk-freq-out = <1000000>;
 	nq@28 {
 		compatible = "qcom,nq-nci";
 		reg = <0x28>;
@@ -134,6 +137,7 @@
 	qcom,qg-iterm-ma = <100>;
 	qcom,hold-soc-while-full;
 	qcom,linearize-soc;
+	qcom,qg-use-s7-ocv;
 };
 
 &pmi632_charger {
@@ -151,6 +155,7 @@
 	qcom,hw-die-temp-mitigation;
 	qcom,hw-connector-mitigation;
 	qcom,connector-internal-pull-kohm = <100>;
+	qcom,float-option = <1>;
 	qcom,thermal-mitigation = <3000000 2500000
 			2000000 1500000 1000000 500000>;
 };
@@ -305,8 +310,37 @@
 	qcom,platform-bklight-en-gpio = <&pmi632_gpios 6 0>;
 };
 
+&dsi_sim_vid {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+	qcom,platform-reset-gpio = <&tlmm 90 0>;
+};
+
+&dsi_hx83112a_truly_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+	pwms = <&pm6125_pwm 0 0>;
+	qcom,bl-pmic-pwm-period-usecs = <100>;
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,platform-reset-gpio = <&tlmm 90 0>;
+	qcom,platform-bklight-en-gpio = <&pmi632_gpios 6 0>;
+};
+
+&dsi_nt36672_truly_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+	pwms = <&pm6125_pwm 0 0>;
+	qcom,bl-pmic-pwm-period-usecs = <100>;
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,platform-reset-gpio = <&tlmm 90 0>;
+	qcom,platform-bklight-en-gpio = <&pmi632_gpios 6 0>;
+};
+
 &qupv3_se2_i2c {
 	status = "okay";
+	qcom,i2c-touch-active="synaptics,tcm-i2c";
 
 	synaptics_tcm@20 {
 		compatible = "synaptics,tcm-i2c";
@@ -328,4 +362,21 @@
 		synaptics,ubl-i2c-addr = <0x20>;
 		synaptics,y-flip;
 	};
+
+	himax_ts@48 {
+		compatible = "himax,hxcommon";
+		reg = <0x48>;
+		interrupt-parent = <&tlmm>;
+		interrupts = <88 0x2008>;
+		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>;
+		himax,panel-coords = <0 1080 0 2160>;
+		himax,display-coords = <0 1080 0 2160>;
+		himax,irq-gpio = <&tlmm 88 0x00>;
+		himax,rst-gpio = <&tlmm 87 0x00>;
+		report_type = <1>;
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/trinket-ion.dtsi b/arch/arm64/boot/dts/qcom/trinket-ion.dtsi
index aa8a2f2..3aec5ff 100644
--- a/arch/arm64/boot/dts/qcom/trinket-ion.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-ion.dtsi
@@ -52,5 +52,11 @@
 				token = <0x20000000>;
 			};
 		};
+
+		qcom,ion-heap@22 { /* ADSP HEAP */
+			reg = <22>;
+			memory-region = <&sdsp_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/trinket-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/trinket-pinctrl.dtsi
index 44952a8..1fbf7f1 100644
--- a/arch/arm64/boot/dts/qcom/trinket-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-pinctrl.dtsi
@@ -1658,12 +1658,12 @@
 		cam_sensor_rear2_active: cam_sensor_rear2_active {
 			/* RESET */
 			mux {
-				pins = "gpio45";
+				pins = "gpio46";
 				function = "gpio";
 			};
 
 			config {
-				pins = "gpio45";
+				pins = "gpio46";
 				bias-disable; /* No PULL */
 				drive-strength = <2>; /* 2 MA */
 			};
@@ -1672,12 +1672,12 @@
 		cam_sensor_rear2_suspend: cam_sensor_rear2_suspend {
 			/* RESET */
 			mux {
-				pins = "gpio45";
+				pins = "gpio46";
 				function = "gpio";
 			};
 
 			config {
-				pins = "gpio45";
+				pins = "gpio46";
 				bias-pull-down; /* PULL DOWN */
 				drive-strength = <2>; /* 2 MA */
 				output-low;
@@ -1739,6 +1739,47 @@
 				drive-strength = <2>; /* 2 MA */
 			};
 		};
+
+		fpc_reset_int: fpc_reset_int {
+			fpc_reset_low: reset_low {
+				mux {
+					pins = "gpio93";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio93";
+					drive-strength = <2>;
+					bias-disable;
+					output-low;
+				};
+			};
+
+			fpc_reset_high: reset_high {
+				mux {
+					pins = "gpio93";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio93";
+					drive-strength = <2>;
+					bias-disable;
+					output-high;
+				};
+			};
+
+			fpc_int_low: int_low {
+				mux {
+					pins = "gpio92";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio92";
+					drive-strength = <2>;
+					bias-pull-down;
+					input-enable;
+				};
+			};
+		};
 	};
 };
 
diff --git a/arch/arm64/boot/dts/qcom/trinket-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/trinket-qrd-overlay.dts
index 8eca056..f60d871 100644
--- a/arch/arm64/boot/dts/qcom/trinket-qrd-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/trinket-qrd-overlay.dts
@@ -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
@@ -13,6 +13,7 @@
 /dts-v1/;
 /plugin/;
 
+#include <dt-bindings/clock/qcom,gcc-trinket.h>
 #include "trinket-qrd.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/trinket-qrd.dtsi b/arch/arm64/boot/dts/qcom/trinket-qrd.dtsi
index fcc1425..1dafdd1 100644
--- a/arch/arm64/boot/dts/qcom/trinket-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-qrd.dtsi
@@ -18,6 +18,9 @@
 #include "trinket-audio-overlay.dtsi"
 #include <dt-bindings/clock/qcom,gcc-trinket.h>
 
+#include <dt-bindings/clock/qcom,gcc-trinket.h>
+#include "trinket-camera-sensor-qrd.dtsi"
+
 &qupv3_se1_i2c {
 	status = "ok";
 	#include "smb1355.dtsi"
@@ -29,6 +32,24 @@
 		#include "qg-batterydata-ascent-3450mah.dtsi"
 		#include "qg-batterydata-mlp356477-2800mah.dtsi"
 	};
+
+	fingerprint: fpc1020 {
+		compatible = "fpc,fpc1020";
+		interrupt-parent = <&tlmm>;
+		interrupts = <92 0>;
+		fpc,gpio_rst = <&tlmm 93 0>;
+		fpc,gpio_irq = <&tlmm 92 0>;
+		vcc_spi-supply = <&pm6125_l9>;
+		vdd_io-supply  = <&pm6125_l9>;
+		vdd_ana-supply = <&pm6125_l9>;
+		fpc,enable-on-boot;
+		pinctrl-names = "fpc1020_reset_reset",
+				"fpc1020_reset_active",
+				"fpc1020_irq_active";
+		pinctrl-0 = <&fpc_reset_low>;
+		pinctrl-1 = <&fpc_reset_high>;
+		pinctrl-2 = <&fpc_int_low>;
+	};
 };
 
 &pmi632_qg {
@@ -36,6 +57,7 @@
 	qcom,qg-iterm-ma = <100>;
 	qcom,hold-soc-while-full;
 	qcom,linearize-soc;
+	qcom,qg-use-s7-ocv;
 };
 
 &pmi632_charger {
@@ -52,6 +74,7 @@
 	qcom,hw-die-temp-mitigation;
 	qcom,hw-connector-mitigation;
 	qcom,connector-internal-pull-kohm = <100>;
+	qcom,float-option = <1>;
 	qcom,thermal-mitigation = <3000000 2500000
 			2000000 1500000 1000000 500000>;
 };
@@ -83,7 +106,6 @@
 
 &qupv3_se1_i2c {
 	status = "ok";
-	qcom,clk-freq-out = <1000000>;
 	nq@28 {
 		compatible = "qcom,nq-nci";
 		reg = <0x28>;
@@ -298,7 +320,7 @@
 	qcom,platform-reset-gpio = <&tlmm 90 0>;
 };
 
-&dsi_td4330_truly_cmd_display {
+&dsi_td4330_truly_vid_display {
 	qcom,dsi-display-active;
 };
 
@@ -330,7 +352,13 @@
 		"IN3_AUX", "AUX_OUT",
 		"TX SWR_ADC0", "ADC1_OUTPUT",
 		"TX SWR_ADC2", "ADC2_OUTPUT",
-		"TX SWR_ADC3", "ADC3_OUTPUT",
+		"WSA SRC0_INP", "SRC0",
+		"WSA_TX DEC0_INP", "TX DEC0 MUX",
+		"WSA_TX DEC1_INP", "TX DEC1 MUX",
+		"RX_TX DEC0_INP", "TX DEC0 MUX",
+		"RX_TX DEC1_INP", "TX DEC1 MUX",
+		"RX_TX DEC2_INP", "TX DEC2 MUX",
+		"RX_TX DEC3_INP", "TX DEC3 MUX",
 		"SpkrLeft IN", "WSA_SPK1 OUT",
 		"WSA_SPK1 OUT", "VA_MCLK";
 		qcom,wsa-max-devs = <1>;
@@ -345,3 +373,17 @@
 		qcom,msm_audio_ssr_devs = <&audio_apr>, <&q6core>,
 				<&bolero>;
 };
+
+&qusb_phy0 {
+	qcom,qusb-phy-init-seq = <0xc8 0x80
+				0x93 0x84
+				0x83 0x88
+				0xc7 0x8c
+				0x30 0x08
+				0x79 0x0c
+				0x21 0x10
+				0x14 0x9c
+				0x80 0x04
+				0x9f 0x1c
+				0x00 0x18>;
+};
diff --git a/arch/arm64/boot/dts/qcom/trinket-regulator.dtsi b/arch/arm64/boot/dts/qcom/trinket-regulator.dtsi
index 707ce39..15c3eaa 100644
--- a/arch/arm64/boot/dts/qcom/trinket-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-regulator.dtsi
@@ -159,8 +159,8 @@
 
 	rpm-regulator-ldoa4 {
 		status = "okay";
-		pm6125_l4-parent-supply = <&pm6125_l7>;
 		L4A: pm6125_l4: regulator-l4 {
+			parent-supply = <&pm6125_l7>;
 			regulator-min-microvolt = <872000>;
 			regulator-max-microvolt = <976000>;
 			qcom,init-voltage = <872000>;
@@ -271,8 +271,8 @@
 
 	rpm-regulator-ldoa15 {
 		status = "okay";
-		pm6125_l15-parent-supply = <&pm6125_l10>;
 		L15A: pm6125_l15: regulator-l15 {
+			parent-supply = <&pm6125_l10>;
 			regulator-min-microvolt = <3104000>;
 			regulator-max-microvolt = <3232000>;
 			qcom,init-voltage = <3104000>;
@@ -353,9 +353,9 @@
 	rpm-regulator-ldoa23 {
 		status = "okay";
 		L23A: pm6125_l23: regulator-l23 {
-			regulator-min-microvolt = <3200000>;
+			regulator-min-microvolt = <3000000>;
 			regulator-max-microvolt = <3400000>;
-			qcom,init-voltage = <3200000>;
+			qcom,init-voltage = <3000000>;
 			status = "okay";
 		};
 	};
diff --git a/arch/arm64/boot/dts/qcom/trinket-rumi.dtsi b/arch/arm64/boot/dts/qcom/trinket-rumi.dtsi
index 74e81c2..4916523 100644
--- a/arch/arm64/boot/dts/qcom/trinket-rumi.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-rumi.dtsi
@@ -98,7 +98,7 @@
 	/delete-node/ camera-lowf;
 	/delete-node/ video-lowf;
 	/delete-node/ cpu-1-0-lowf;
-	/delete-node/ cpuss-2-lowf;
+	/delete-node/ cpuss-0-lowf;
 	/delete-node/ mdm-core-lowf;
 	/delete-node/ display-lowf;
 	/delete-node/ gpu-lowf;
diff --git a/arch/arm64/boot/dts/qcom/trinket-sde-display.dtsi b/arch/arm64/boot/dts/qcom/trinket-sde-display.dtsi
index 5e7b8d5..2fdaf05 100644
--- a/arch/arm64/boot/dts/qcom/trinket-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-sde-display.dtsi
@@ -12,6 +12,9 @@
 
 #include "dsi-panel-td4330-truly-singlemipi-fhd-cmd.dtsi"
 #include "dsi-panel-td4330-truly-singlemipi-fhd-video.dtsi"
+#include "dsi-panel-sim-video.dtsi"
+#include "dsi-panel-hx83112a-truly-singlemipi-fhd-video.dtsi"
+#include "dsi-panel-nt36672-truly-fhd-video.dtsi"
 #include <dt-bindings/clock/mdss-14nm-pll-clk.h>
 
 &soc {
@@ -94,7 +97,9 @@
 
 		qcom,dsi-ctrl-num = <0>;
 		qcom,dsi-phy-num = <0>;
-		qcom,dsi-select-clocks = "mux_byte_clk0", "mux_pixel_clk0";
+		qcom,dsi-select-clocks = "mux_byte_clk0", "mux_pixel_clk0",
+			"src_byte_clk0", "src_pixel_clk0",
+			"shadow_byte_clk0", "shadow_pixel_clk0";
 
 		qcom,dsi-panel = <&dsi_td4330_truly_video>;
 	};
@@ -110,6 +115,39 @@
 		qcom,dsi-panel = <&dsi_td4330_truly_cmd>;
 	};
 
+	dsi_sim_vid_display: qcom,dsi-display@2 {
+		label = "dsi_sim_vid_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl-num = <0>;
+		qcom,dsi-phy-num = <0>;
+		qcom,dsi-select-clocks = "mux_byte_clk0", "mux_pixel_clk0";
+
+		qcom,dsi-panel = <&dsi_sim_vid>;
+	};
+
+	dsi_hx83112a_truly_vid_display: qcom,dsi-display@3 {
+		label = "dsi_hx83112a_truly_vid_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl-num = <0>;
+		qcom,dsi-phy-num = <0>;
+		qcom,dsi-select-clocks = "mux_byte_clk0", "mux_pixel_clk0";
+
+		qcom,dsi-panel = <&dsi_hx83112a_truly_video>;
+	};
+
+	dsi_nt36672_truly_vid_display: qcom,dsi-display@4 {
+		label = "dsi_nt36672_truly_vid_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl-num = <0>;
+		qcom,dsi-phy-num = <0>;
+		qcom,dsi-select-clocks = "mux_byte_clk0", "mux_pixel_clk0";
+
+		qcom,dsi-panel = <&dsi_nt36672_truly_video>;
+	};
+
 	sde_dsi: qcom,dsi-display {
 		compatible = "qcom,dsi-display";
 
@@ -117,8 +155,14 @@
 		qcom,dsi-phy = <&mdss_dsi_phy0>;
 
 		clocks = <&mdss_dsi0_pll BYTE0_MUX_CLK>,
-			 <&mdss_dsi0_pll PIX0_MUX_CLK>;
-		clock-names = "mux_byte_clk0", "mux_pixel_clk0";
+			 <&mdss_dsi0_pll PIX0_MUX_CLK>,
+			 <&mdss_dsi0_pll BYTE0_SRC_CLK>,
+			 <&mdss_dsi0_pll PIX0_SRC_CLK>,
+			 <&mdss_dsi0_pll SHADOW_BYTE0_SRC_CLK>,
+			 <&mdss_dsi0_pll SHADOW_PIX0_SRC_CLK>;
+		clock-names = "mux_byte_clk0", "mux_pixel_clk0",
+			"src_byte_clk0", "src_pixel_clk0",
+			"shadow_byte_clk0", "shadow_pixel_clk0";
 		pinctrl-names = "panel_active", "panel_suspend";
 		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
 		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
@@ -131,7 +175,10 @@
 
 		qcom,dsi-display-list =
 			<&dsi_td4330_truly_vid_display
-			&dsi_td4330_truly_cmd_display>;
+			&dsi_td4330_truly_cmd_display
+			&dsi_sim_vid_display
+			&dsi_hx83112a_truly_vid_display
+			&dsi_nt36672_truly_vid_display>;
 	};
 
 	sde_wb: qcom,wb-display@0 {
@@ -157,6 +204,9 @@
 	qcom,mdss-dsi-panel-status-value = <0x1c>;
 	qcom,mdss-dsi-panel-on-check-value = <0x1c>;
 	qcom,mdss-dsi-panel-status-read-length = <1>;
+	qcom,dsi-dyn-clk-enable;
+	qcom,dsi-dyn-clk-list =
+		<1048269600 1030798440 1035166232 1039534024 1043901816>;
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings =
@@ -169,14 +219,14 @@
 			qcom,display-topology = <1 0 1>;
 			qcom,default-topology-index = <0>;
 			qcom,partial-update-enabled = "single_roi";
-			qcom,panel-roi-alignment = <16 16 8 2 16 16>;
+			qcom,panel-roi-alignment = <40 40 40 40 40 40>;
 		};
 	};
 };
 
 &dsi_td4330_truly_video {
 	qcom,mdss-dsi-t-clk-post = <0x0e>;
-	qcom,mdss-dsi-t-clk-pre = <0x36>;
+	qcom,mdss-dsi-t-clk-pre = <0x35>;
 	qcom,dsi-supported-dfps-list = <60 55 48>;
 	qcom,mdss-dsi-pan-enable-dynamic-fps;
 	qcom,mdss-dsi-pan-fps-update =
@@ -188,14 +238,89 @@
 	qcom,mdss-dsi-panel-status-value = <0x1c>;
 	qcom,mdss-dsi-panel-on-check-value = <0x1c>;
 	qcom,mdss-dsi-panel-status-read-length = <1>;
+	qcom,dsi-dyn-clk-enable;
+	qcom,dsi-dyn-clk-list =
+		<1005903360 989138304 993329568 997520832 1001712096>;
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings =
-				[26 20 09 0B 06 02 04 a0
-				26 20 09 0B 06 02 04 a0
-				26 20 09 0B 06 02 04 a0
-				26 20 09 0B 06 02 04 a0
-				26 1F 09 0B 06 02 04 a0];
+				[25 20 09 0A 06 03 04 a0
+				25 20 09 0A 06 03 04 a0
+				25 20 09 0A 06 03 04 a0
+				25 20 09 0A 06 03 04 a0
+				25 1F 08 0A 06 03 04 a0];
+
+			qcom,display-topology = <1 0 1>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_sim_vid {
+	qcom,mdss-dsi-display-timings {
+		qcom,mdss-dsi-t-clk-post = <0x0e>;
+		qcom,mdss-dsi-t-clk-pre = <0x31>;
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings =
+				[24 1f 08 09 05 02 04 a0
+				24 1f 08 09 05 02 04 a0
+				24 1f 08 09 05 02 04 a0
+				24 1f 08 09 05 02 04 a0
+				24 1c 08 09 05 02 04 a0];
+
+			qcom,display-topology = <1 0 1>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_hx83112a_truly_video {
+	qcom,mdss-dsi-t-clk-post = <0x0e>;
+	qcom,mdss-dsi-t-clk-pre = <0x31>;
+	qcom,dsi-supported-dfps-list = <60 55 53 43>;
+	qcom,mdss-dsi-pan-enable-dynamic-fps;
+	qcom,mdss-dsi-pan-fps-update =
+		"dfps_immediate_porch_mode_vfp";
+	qcom,esd-check-enabled;
+	qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+	qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+	qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+	qcom,mdss-dsi-panel-status-value = <0x9d 0x9d 0x9d 0x9d>;
+	qcom,mdss-dsi-panel-on-check-value = <0x9d 0x9d 0x9d 0x9d>;
+	qcom,mdss-dsi-panel-status-read-length = <4>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings =
+				[24 1f 08 09 05 02 04 a0
+				24 1f 08 09 05 02 04 a0
+				24 1f 08 09 05 02 04 a0
+				24 1f 08 09 05 02 04 a0
+				24 1c 08 09 05 02 04 a0];
+
+			qcom,display-topology = <1 0 1>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_nt36672_truly_video {
+	qcom,mdss-dsi-t-clk-post = <0x0D>;
+	qcom,mdss-dsi-t-clk-pre = <0x30>;
+	qcom,esd-check-enabled;
+	qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+	qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+	qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+	qcom,mdss-dsi-panel-status-value = <0x9c>;
+	qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+	qcom,mdss-dsi-panel-status-read-length = <1>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings =
+				[24 1F 08 09 05 02 04 a0
+				24 1F 08 09 05 02 04 a0
+				24 1F 08 09 05 02 04 a0
+				24 1F 08 09 05 02 04 a0
+				24 1B 08 09 05 02 04 a0];
 
 			qcom,display-topology = <1 0 1>;
 			qcom,default-topology-index = <0>;
diff --git a/arch/arm64/boot/dts/qcom/trinket-sde-pll.dtsi b/arch/arm64/boot/dts/qcom/trinket-sde-pll.dtsi
index cffbb24..052a163 100644
--- a/arch/arm64/boot/dts/qcom/trinket-sde-pll.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-sde-pll.dtsi
@@ -17,11 +17,14 @@
 		cell-index = <0>;
 		#clock-cells = <1>;
 		reg = <0x5e94400 0x588>,
-		      <0x5f03000 0x8>;
-		reg-names = "pll_base", "gdsc_base";
+		      <0x5f03000 0x8>,
+		      <0x5e94200 0x100>;
+		reg-names = "pll_base", "gdsc_base",
+			"dynamic_pll_base";
 		clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>;
 		clock-names = "iface_clk";
 		clock-rate = <0>;
+		memory-region = <&dfps_data_memory>;
 		gdsc-supply = <&mdss_core_gdsc>;
 		qcom,dsi-pll-ssc-en;
 		qcom,dsi-pll-ssc-mode = "down-spread";
diff --git a/arch/arm64/boot/dts/qcom/trinket-sde.dtsi b/arch/arm64/boot/dts/qcom/trinket-sde.dtsi
index f12b46b..ae1261e 100644
--- a/arch/arm64/boot/dts/qcom/trinket-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-sde.dtsi
@@ -37,6 +37,7 @@
 				"lut_clk", "rot_clk";
 		clock-rate = <0 0 0 0 0 256000000 19200000 192000000>;
 		clock-max-rate = <0 0 0 0 0 307000000 19200000 307000000>;
+		qcom,dss-cx-ipeak = <&cx_ipeak_lm 1>;
 
 		sde-vdd-supply = <&mdss_core_gdsc>;
 
@@ -51,6 +52,8 @@
 
 		#power-domain-cells = <0>;
 
+		#list-cells = <1>;
+
 		/* hw blocks */
 		qcom,sde-off = <0x1000>;
 		qcom,sde-len = <0x45c>;
@@ -182,6 +185,8 @@
 		qcom,sde-reg-dma-trigger-off = <0x119c>;
 
 		qcom,sde-secure-sid-mask = <0x0000401>;
+		qcom,sde-num-mnoc-ports = <1>;
+		qcom,sde-axi-bus-width = <16>;
 
 		qcom,sde-sspp-vig-blocks {
 			qcom,sde-vig-csc-off = <0x1a00>;
@@ -283,7 +288,12 @@
 
 		power-domains = <&mdss_mdp>;
 
+		/*Offline rotator RT setting */
+		qcom,mdss-rot-parent = <&mdss_mdp 0>;
+		qcom,mdss-rot-xin-id = <10 11>;
+
 		/* Offline rotator QoS setting */
+		qcom,mdss-rot-vbif-qos-setting = <3 3 4 4 5 5 6 6>;
 		qcom,mdss-rot-cdp-setting = <1 1>;
 		qcom,mdss-rot-qos-lut = <0x0 0x0 0x0 0x0>;
 		qcom,mdss-rot-danger-lut = <0x0 0x0>;
@@ -368,8 +378,10 @@
 		label = "dsi-phy-0";
 		cell-index = <0>;
 		reg = <0x5e94400 0x588>,
-			<0x5e01400 0x100>;
-		reg-names = "dsi_phy", "phy_clamp_base";
+			<0x5e01400 0x100>,
+			<0x5e94200 0x100>;
+		reg-names = "dsi_phy", "phy_clamp_base",
+			"dyn_refresh_base";
 		vdda-0p9-supply = <&VDD_MX_LEVEL>;
 		qcom,platform-strength-ctrl = [ff 06
 						ff 06
@@ -390,9 +402,11 @@
 				reg = <0>;
 				qcom,supply-name = "vdda-0p9";
 				qcom,supply-min-voltage =
-					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
-				qcom,supply-max-voltage =
 					<RPM_SMD_REGULATOR_LEVEL_NOM>;
+				qcom,supply-max-voltage =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+				qcom,supply-off-min-voltage =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
 				qcom,supply-enable-load = <0>;
 				qcom,supply-disable-load = <0>;
 			};
diff --git a/arch/arm64/boot/dts/qcom/trinket-tasha-codec.dtsi b/arch/arm64/boot/dts/qcom/trinket-tasha-codec.dtsi
index d8aaf77..0276333 100644
--- a/arch/arm64/boot/dts/qcom/trinket-tasha-codec.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-tasha-codec.dtsi
@@ -120,8 +120,8 @@
 	asoc-codec = <&stub_codec>;
 	asoc-codec-names = "msm-stub-codec.1";
 	qcom,wsa-max-devs = <2>;
-	qcom,wsa-devs = <&wsa881x_70211>, <&wsa881x_70212>,
-		<&wsa881x_70213>, <&wsa881x_70214>;
+	qcom,wsa-devs = <&wsa881x_70212>, <&wsa881x_70211>,
+		<&wsa881x_70214>, <&wsa881x_70213>;
 	qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
 		"SpkrLeft", "SpkrRight";
 	qcom,msm_audio_ssr_devs = <&audio_apr>, <&wcd9335>,
diff --git a/arch/arm64/boot/dts/qcom/trinket-thermal.dtsi b/arch/arm64/boot/dts/qcom/trinket-thermal.dtsi
index b3d75f3..d820295 100644
--- a/arch/arm64/boot/dts/qcom/trinket-thermal.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket-thermal.dtsi
@@ -16,12 +16,23 @@
 &clock_cpucc {
 	#address-cells = <1>;
 	#size-cells = <1>;
-	lmh_dcvs0: qcom,limits-dcvs@0xf550800 {
+	lmh_dcvs0: qcom,limits-dcvs@f521000 {
 		compatible = "qcom,msm-hw-limits";
 		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
 		qcom,affinity = <0>;
 		reg = <0xf550800 0x1000>,
 			<0xf521000 0x1000>;
+		qcom,plat-mitigation-disable;
+		#thermal-sensor-cells = <0>;
+	};
+
+	lmh_dcvs1: qcom,limits-dcvs@f523000 {
+		compatible = "qcom,msm-hw-limits";
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		qcom,affinity = <1>;
+		reg = <0xf550800 0x1000>,
+			<0xf523000 0x1000>;
+		qcom,plat-mitigation-disable;
 		#thermal-sensor-cells = <0>;
 	};
 };
@@ -88,13 +99,6 @@
 	};
 };
 
-&rpm_bus {
-	rpm_smd_cdev: rpm-smd-cdev {
-		compatible = "qcom,rpm-smd-cooling-device";
-		#cooling-cells = <2>;
-	};
-};
-
 &thermal_zones {
 	rf-pa0-therm-adc {
 		polling-delay-passive = <0>;
@@ -171,6 +175,13 @@
 		polling-delay = <5000>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6125_adc_tm_iio ADC_GPIO1_PU2>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
 	};
 
 	emmc-ufs-therm-adc {
@@ -178,6 +189,13 @@
 		polling-delay = <5000>;
 		thermal-governor = "user_space";
 		thermal-sensors = <&pm6125_adc_tm_iio ADC_GPIO3_PU2>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
 	};
 
 	aoss0-usr {
@@ -566,6 +584,11 @@
 				hysteresis = <0>;
 				type = "passive";
 			};
+			gpu_cx_mon: gpu-cx-mon {
+				temperature = <100000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
 		};
 		cooling-maps {
 			gpu_cdev {
@@ -573,6 +596,23 @@
 				cooling-device = <&msm_gpu THERMAL_NO_LIMIT
 							THERMAL_NO_LIMIT>;
 			};
+			gpu-cx-cdev0 {
+				trip = <&gpu_cx_mon>;
+				cooling-device = <&msm_gpu THERMAL_MAX_LIMIT
+							THERMAL_MAX_LIMIT>;
+			};
+			gpu-cx-cdev1 {
+				trip = <&gpu_cx_mon>;
+				cooling-device = <&modem_proc 3 3>;
+			};
+			gpu-cx-cdev2 {
+				trip = <&gpu_cx_mon>;
+				cooling-device = <&modem_pa 3 3>;
+			};
+			gpu-cx-cdev3 {
+				trip = <&gpu_cx_mon>;
+				cooling-device = <&msm_cdsp_rm 4 4>;
+			};
 		};
 	};
 
@@ -589,11 +629,11 @@
 		};
 	};
 
-	cpuss-0-step {
+	cpuss-1-step {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
-		thermal-sensors = <&tsens0 6>;
+		thermal-sensors = <&tsens0 7>;
 		trips {
 			cpu5_7_config: cpu-5-7-config {
 				temperature = <110000>;
@@ -617,11 +657,11 @@
 		};
 	};
 
-	cpuss-1-step {
+	cpuss-2-step {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
-		thermal-sensors = <&tsens0 7>;
+		thermal-sensors = <&tsens0 8>;
 		trips {
 			cpu4_6_config: cpu-4-6-config {
 				temperature = <110000>;
@@ -645,11 +685,11 @@
 		};
 	};
 
-	cpuss-2-step {
+	cpuss-0-step {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
-		thermal-sensors = <&tsens0 8>;
+		thermal-sensors = <&tsens0 6>;
 		trips {
 			silv_cpus_config: silv-cpus-config {
 				temperature = <110000>;
@@ -850,27 +890,6 @@
 		};
 	};
 
-	aoss0-lowc {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_cap";
-		thermal-sensors = <&tsens0 0>;
-		tracks-low;
-		trips {
-			aoss0_lowc: aoss0-lowc {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			rpm_smd_cdev {
-				trip = <&aoss0_lowc>;
-				cooling-device = <&rpm_smd_cdev 2 2>;
-			};
-		};
-	};
-
 	cdsp-lowf {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
@@ -948,27 +967,6 @@
 		};
 	};
 
-	cdsp-lowc {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_cap";
-		thermal-sensors = <&tsens0 1>;
-		tracks-low;
-		trips {
-			cdsp_lowc: cdsp-lowc {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			rpm_smd_cdev {
-				trip = <&cdsp_lowc>;
-				cooling-device = <&rpm_smd_cdev 2 2>;
-			};
-		};
-	};
-
 	wlan-lowf {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
@@ -1046,27 +1044,6 @@
 		};
 	};
 
-	wlan-lowc {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_cap";
-		thermal-sensors = <&tsens0 2>;
-		tracks-low;
-		trips {
-			wlan_lowc: wlan-lowc {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			rpm_smd_cdev {
-				trip = <&wlan_lowc>;
-				cooling-device = <&rpm_smd_cdev 2 2>;
-			};
-		};
-	};
-
 	camera-lowf {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
@@ -1144,27 +1121,6 @@
 		};
 	};
 
-	camera-lowc {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_cap";
-		thermal-sensors = <&tsens0 3>;
-		tracks-low;
-		trips {
-			camera_lowc: camera-lowc {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			rpm_smd_cdev {
-				trip = <&camera_lowc>;
-				cooling-device = <&rpm_smd_cdev 2 2>;
-			};
-		};
-	};
-
 	video-lowf {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
@@ -1242,27 +1198,6 @@
 		};
 	};
 
-	video-lowc {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_cap";
-		thermal-sensors = <&tsens0 4>;
-		tracks-low;
-		trips {
-			video_lowc: video-lowc {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			rpm_smd_cdev {
-				trip = <&video_lowc>;
-				cooling-device = <&rpm_smd_cdev 2 2>;
-			};
-		};
-	};
-
 	cpu-1-0-lowf {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
@@ -1340,32 +1275,11 @@
 		};
 	};
 
-	cpu-1-0-lowc {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_cap";
-		thermal-sensors = <&tsens0 9>;
-		tracks-low;
-		trips {
-			cpu_1_0_lowc: cpu-1-0-lowc {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			rpm_smd_cdev {
-				trip = <&cpu_1_0_lowc>;
-				cooling-device = <&rpm_smd_cdev 2 2>;
-			};
-		};
-	};
-
-	cpuss-2-lowf {
+	cpuss-0-lowf {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
-		thermal-sensors = <&tsens0 8>;
+		thermal-sensors = <&tsens0 6>;
 		tracks-low;
 		trips {
 			cpu0_lowf_trip: cpu0-lowf-trip {
@@ -1438,27 +1352,6 @@
 		};
 	};
 
-	cpuss-2-lowc {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_cap";
-		thermal-sensors = <&tsens0 8>;
-		tracks-low;
-		trips {
-			cpuss_2_lowc: cpuss-2-lowc {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			rpm_smd_cdev {
-				trip = <&cpuss_2_lowc>;
-				cooling-device = <&rpm_smd_cdev 2 2>;
-			};
-		};
-	};
-
 	mdm-core-lowf {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
@@ -1536,27 +1429,6 @@
 		};
 	};
 
-	mdm-core-lowc {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_cap";
-		thermal-sensors = <&tsens0 13>;
-		tracks-low;
-		trips {
-			mdm_core_lowc: mdm-core-lowc {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			rpm_smd_cdev {
-				trip = <&mdm_core_lowc>;
-				cooling-device = <&rpm_smd_cdev 2 2>;
-			};
-		};
-	};
-
 	display-lowf {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
@@ -1634,27 +1506,6 @@
 		};
 	};
 
-	display-lowc {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_cap";
-		thermal-sensors = <&tsens0 14>;
-		tracks-low;
-		trips {
-			display_lowc: display-lowc {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			rpm_smd_cdev {
-				trip = <&display_lowc>;
-				cooling-device = <&rpm_smd_cdev 2 2>;
-			};
-		};
-	};
-
 	gpu-lowf {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
@@ -1732,27 +1583,6 @@
 		};
 	};
 
-	gpu-lowc {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_cap";
-		thermal-sensors = <&tsens0 15>;
-		tracks-low;
-		trips {
-			gpu_lowc: gpu-lowc {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			rpm_smd_cdev {
-				trip = <&gpu_lowc>;
-				cooling-device = <&rpm_smd_cdev 2 2>;
-			};
-		};
-	};
-
 	cdsp-step {
 		polling-delay-passive = <10>;
 		polling-delay = <0>;
@@ -1769,8 +1599,8 @@
 				hysteresis = <0>;
 				type = "passive";
 			};
-			cdsp_trip2: cdsp-trip2 {
-				temperature = <105000>;
+			cdsp_cx_mon: cdsp-cx-mon {
+				temperature = <100000>;
 				hysteresis = <5000>;
 				type = "passive";
 			};
@@ -1785,10 +1615,348 @@
 				cooling-device = <&msm_cdsp_rm
 						THERMAL_NO_LIMIT 4>;
 			};
-			cdsp-cdev1 {
-				trip = <&cdsp_trip2>;
+			cdsp-cx-cdev0 {
+				trip = <&cdsp_cx_mon>;
+				cooling-device = <&msm_gpu THERMAL_MAX_LIMIT
+							THERMAL_MAX_LIMIT>;
+			};
+			cdsp-cx-cdev1 {
+				trip = <&cdsp_cx_mon>;
+				cooling-device = <&modem_proc 3 3>;
+			};
+			cdsp-cx-cdev2 {
+				trip = <&cdsp_cx_mon>;
+				cooling-device = <&modem_pa 3 3>;
+			};
+			cdsp-cx-cdev3 {
+				trip = <&cdsp_cx_mon>;
 				cooling-device = <&msm_cdsp_rm 4 4>;
 			};
 		};
 	};
+
+	wlan-step {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 2>;
+		thermal-governor = "step_wise";
+		trips {
+			wlan_cx_mon: wlan-cx-mon {
+				temperature = <100000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			wlan-cx-cdev0 {
+				trip = <&wlan_cx_mon>;
+				cooling-device = <&msm_gpu THERMAL_MAX_LIMIT
+							THERMAL_MAX_LIMIT>;
+			};
+			wlan-cx-cdev1 {
+				trip = <&wlan_cx_mon>;
+				cooling-device = <&modem_proc 3 3>;
+			};
+			wlan-cx-cdev2 {
+				trip = <&wlan_cx_mon>;
+				cooling-device = <&modem_pa 3 3>;
+			};
+			wlan-cx-cdev3 {
+				trip = <&wlan_cx_mon>;
+				cooling-device = <&msm_cdsp_rm 4 4>;
+			};
+		};
+	};
+
+	camera-step {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 3>;
+		thermal-governor = "step_wise";
+		trips {
+			camera_cx_mon: camera-cx-mon {
+				temperature = <100000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			camera-cx-cdev0 {
+				trip = <&camera_cx_mon>;
+				cooling-device = <&msm_gpu THERMAL_MAX_LIMIT
+							THERMAL_MAX_LIMIT>;
+			};
+			camera-cx-cdev1 {
+				trip = <&camera_cx_mon>;
+				cooling-device = <&modem_proc 3 3>;
+			};
+			camera-cx-cdev2 {
+				trip = <&camera_cx_mon>;
+				cooling-device = <&modem_pa 3 3>;
+			};
+			camera-cx-cdev3 {
+				trip = <&camera_cx_mon>;
+				cooling-device = <&msm_cdsp_rm 4 4>;
+			};
+		};
+	};
+
+	video-step {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 4>;
+		thermal-governor = "step_wise";
+		trips {
+			video_cx_mon: video-cx-mon {
+				temperature = <100000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			video-cx-cdev0 {
+				trip = <&video_cx_mon>;
+				cooling-device = <&msm_gpu THERMAL_MAX_LIMIT
+							THERMAL_MAX_LIMIT>;
+			};
+			video-cx-cdev1 {
+				trip = <&video_cx_mon>;
+				cooling-device = <&modem_proc 3 3>;
+			};
+			video-cx-cdev2 {
+				trip = <&video_cx_mon>;
+				cooling-device = <&modem_pa 3 3>;
+			};
+			video-cx-cdev3 {
+				trip = <&video_cx_mon>;
+				cooling-device = <&msm_cdsp_rm 4 4>;
+			};
+		};
+	};
+
+	mdm-core-step {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 13>;
+		thermal-governor = "step_wise";
+		trips {
+			mdm_core_cx_mon: mdm-core-cx-mon {
+				temperature = <100000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			mdm-cx-cdev0 {
+				trip = <&mdm_core_cx_mon>;
+				cooling-device = <&msm_gpu THERMAL_MAX_LIMIT
+							THERMAL_MAX_LIMIT>;
+			};
+			mdm-cx-cdev1 {
+				trip = <&mdm_core_cx_mon>;
+				cooling-device = <&modem_proc 3 3>;
+			};
+			mdm-cx-cdev2 {
+				trip = <&mdm_core_cx_mon>;
+				cooling-device = <&modem_pa 3 3>;
+			};
+			mdm-cx-cdev3 {
+				trip = <&mdm_core_cx_mon>;
+				cooling-device = <&msm_cdsp_rm 4 4>;
+			};
+		};
+	};
+
+	display-step {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 14>;
+		thermal-governor = "step_wise";
+		trips {
+			dispaly_cx_mon: display-cx-mon {
+				temperature = <100000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			display-cx-cdev0 {
+				trip = <&dispaly_cx_mon>;
+				cooling-device = <&msm_gpu THERMAL_MAX_LIMIT
+							THERMAL_MAX_LIMIT>;
+			};
+			display-cx-cdev1 {
+				trip = <&dispaly_cx_mon>;
+				cooling-device = <&modem_proc 3 3>;
+			};
+			display-cx-cdev2 {
+				trip = <&dispaly_cx_mon>;
+				cooling-device = <&modem_pa 3 3>;
+			};
+			display-cx-cdev3 {
+				trip = <&dispaly_cx_mon>;
+				cooling-device = <&msm_cdsp_rm 4 4>;
+			};
+		};
+	};
+
+	quiet-therm-step {
+		polling-delay-passive = <2000>;
+		polling-delay = <0>;
+		thermal-governor = "step_wise";
+		thermal-sensors = <&pm6125_adc_tm ADC_AMUX_THM2_PU2>;
+		trips {
+			gold_trip: gold-trip {
+				temperature = <46000>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+			modem_trip0: modem-trip0 {
+				temperature = <46000>;
+				hysteresis = <4000>;
+				type = "passive";
+			};
+			modem_trip1: modem-trip1 {
+				temperature = <48000>;
+				hysteresis = <2000>;
+				type = "passive";
+			};
+			skin_gpu_trip: skin-gpu-trip {
+				temperature = <48000>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+			modem_trip2: modem-trip2 {
+				temperature = <50000>;
+				hysteresis = <2000>;
+				type = "passive";
+			};
+			batt_trip0: batt-trip0 {
+				temperature = <50000>;
+				hysteresis = <4000>;
+				type = "passive";
+			};
+			silver_trip: silver-trip {
+				temperature = <52000>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+			modem_trip3_batt_trip1: modem-trip3 {
+				temperature = <52000>;
+				hysteresis = <2000>;
+				type = "passive";
+			};
+			cx_emer_trip: cx-emer-trip {
+				temperature = <52000>;
+				hysteresis = <4000>;
+				type = "passive";
+			};
+			batt_trip2: batt-trip2 {
+				temperature = <54000>;
+				hysteresis = <2000>;
+				type = "passive";
+			};
+			batt_trip3: batt-trip3 {
+				temperature = <56000>;
+				hysteresis = <2000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			skin_cpu4 {
+				trip = <&gold_trip>;
+				cooling-device =
+					/* throttle from fmax to 1401600KHz */
+					<&CPU4 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-5)>;
+			};
+			skin_cpu5 {
+				trip = <&gold_trip>;
+				cooling-device = <&CPU5 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-5)>;
+			};
+			skin_cpu6 {
+				trip = <&gold_trip>;
+				cooling-device = <&CPU6 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-5)>;
+			};
+			skin_cpu7 {
+				trip = <&gold_trip>;
+				cooling-device = <&CPU7 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-5)>;
+			};
+			skin_cpu0 {
+				trip = <&silver_trip>;
+				/* throttle from fmax to 1420800KHz */
+				cooling-device = <&CPU0 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-6)>;
+			};
+			skin_cpu1 {
+				trip = <&silver_trip>;
+				cooling-device = <&CPU1 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-6)>;
+			};
+			skin_cpu2 {
+				trip = <&silver_trip>;
+				cooling-device = <&CPU2 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-6)>;
+			};
+			skin_cpu3 {
+				trip = <&silver_trip>;
+				cooling-device = <&CPU3 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-6)>;
+			};
+			skin_gpu {
+				trip = <&skin_gpu_trip>;
+				cooling-device = <&msm_gpu THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-3)>;
+			};
+			modem_lvl1 {
+				trip = <&modem_trip1>;
+				cooling-device = <&modem_pa 1 1>;
+			};
+			modem_lvl2 {
+				trip = <&modem_trip2>;
+				cooling-device = <&modem_pa 2 2>;
+			};
+			modem_lvl3 {
+				trip = <&modem_trip3_batt_trip1>;
+				cooling-device = <&modem_pa 3 3>;
+			};
+			modem_proc_lvl1 {
+				trip = <&modem_trip0>;
+				cooling-device = <&modem_proc 1 1>;
+			};
+			modem_proc_lvl3 {
+				trip = <&modem_trip3_batt_trip1>;
+				cooling-device = <&modem_proc 3 3>;
+			};
+			battery_lvl0 {
+				trip = <&batt_trip0>;
+				cooling-device = <&pmi632_charger 1 1>;
+			};
+			battery_lvl1 {
+				trip = <&modem_trip3_batt_trip1>;
+				cooling-device = <&pmi632_charger 2 2>;
+			};
+			battery_lvl2 {
+				trip = <&batt_trip2>;
+				cooling-device = <&pmi632_charger 4 4>;
+			};
+			battery_lvl3 {
+				trip = <&batt_trip3>;
+				cooling-device = <&pmi632_charger 5 5>;
+			};
+			cx_skin_gpu {
+				trip = <&cx_emer_trip>;
+				cooling-device = <&msm_gpu THERMAL_MAX_LIMIT
+							THERMAL_MAX_LIMIT>;
+			};
+			cx-skin-cdsp {
+				trip = <&cx_emer_trip>;
+				cooling-device = <&msm_cdsp_rm 4 4>;
+			};
+		};
+	};
+
 };
diff --git a/arch/arm64/boot/dts/qcom/trinket.dtsi b/arch/arm64/boot/dts/qcom/trinket.dtsi
index 96f3000..542df77 100644
--- a/arch/arm64/boot/dts/qcom/trinket.dtsi
+++ b/arch/arm64/boot/dts/qcom/trinket.dtsi
@@ -35,6 +35,13 @@
 	qcom,pmic-name = "pm6125 + pmi632";
 	interrupt-parent = <&wakegic>;
 
+	mem-offline {
+		compatible = "qcom,mem-offline";
+		offline-sizes = <0x1 0x40000000 0x0 0x40000000>,
+				<0x1 0xc0000000 0x0 0x80000000>;
+		granule = <512>;
+	};
+
 	aliases {
 		serial0 = &qupv3_se4_2uart;
 		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
@@ -56,11 +63,14 @@
 			enable-method = "psci";
 			capacity-dmips-mhz = <1024>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
+			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
 			next-level-cache = <&L2_0>;
 			qcom,lmh-dcvs = <&lmh_dcvs0>;
 			#cooling-cells = <2>;
 			L2_0: l2-cache {
 			      compatible = "arm,arch-cache";
+			      cache-size = <0x80000>;
 			      cache-level = <2>;
 			};
 			L1_I_0: l1-icache {
@@ -85,6 +95,8 @@
 			enable-method = "psci";
 			capacity-dmips-mhz = <1024>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
+			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
 			next-level-cache = <&L2_0>;
 			qcom,lmh-dcvs = <&lmh_dcvs0>;
 			#cooling-cells = <2>;
@@ -111,6 +123,8 @@
 			enable-method = "psci";
 			capacity-dmips-mhz = <1024>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
+			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
 			next-level-cache = <&L2_0>;
 			qcom,lmh-dcvs = <&lmh_dcvs0>;
 			#cooling-cells = <2>;
@@ -137,6 +151,8 @@
 			enable-method = "psci";
 			capacity-dmips-mhz = <1024>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
+			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
 			next-level-cache = <&L2_0>;
 			qcom,lmh-dcvs = <&lmh_dcvs0>;
 			#cooling-cells = <2>;
@@ -163,11 +179,14 @@
 			enable-method = "psci";
 			capacity-dmips-mhz = <1638>;
 			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
+			d-cache-size = <0x10000>;
+			i-cache-size = <0x10000>;
 			next-level-cache = <&L2_1>;
-			qcom,lmh-dcvs = <&lmh_dcvs0>;
+			qcom,lmh-dcvs = <&lmh_dcvs1>;
 			#cooling-cells = <2>;
 			L2_1: l2-cache {
 			      compatible = "arm,arch-cache";
+			      cache-size = <0x100000>;
 			      cache-level = <2>;
 			};
 
@@ -193,8 +212,10 @@
 			enable-method = "psci";
 			capacity-dmips-mhz = <1638>;
 			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
+			d-cache-size = <0x10000>;
+			i-cache-size = <0x10000>;
 			next-level-cache = <&L2_1>;
-			qcom,lmh-dcvs = <&lmh_dcvs0>;
+			qcom,lmh-dcvs = <&lmh_dcvs1>;
 			#cooling-cells = <2>;
 
 			L1_I_101: l1-icache {
@@ -219,8 +240,10 @@
 			enable-method = "psci";
 			capacity-dmips-mhz = <1638>;
 			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
+			d-cache-size = <0x10000>;
+			i-cache-size = <0x10000>;
 			next-level-cache = <&L2_1>;
-			qcom,lmh-dcvs = <&lmh_dcvs0>;
+			qcom,lmh-dcvs = <&lmh_dcvs1>;
 			#cooling-cells = <2>;
 
 			L1_I_102: l1-icache {
@@ -245,8 +268,10 @@
 			enable-method = "psci";
 			capacity-dmips-mhz = <1638>;
 			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
+			d-cache-size = <0x10000>;
+			i-cache-size = <0x10000>;
 			next-level-cache = <&L2_1>;
-			qcom,lmh-dcvs = <&lmh_dcvs0>;
+			qcom,lmh-dcvs = <&lmh_dcvs1>;
 			#cooling-cells = <2>;
 
 			L1_I_103: l1-icache {
@@ -495,7 +520,7 @@
 		cdsp_sec_mem: cdsp_sec_regions@5f800000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0 0x5f800000 0 0x800000>;
+			reg = <0 0x5f800000 0 0x1e00000>;
 		};
 
 		qseecom_mem: qseecom_region@5e400000 {
@@ -528,12 +553,35 @@
 			size = <0 0x800000>;
 		};
 
+		sdsp_mem: sdsp_region {
+			compatible = "shared-dma-pool";
+			alloc-ranges = <0 0x00000000 0 0xffffffff>;
+			reusable;
+			alignment = <0 0x400000>;
+			size = <0 0x400000>;
+		};
+
 		dump_mem: mem_dump_region {
 			compatible = "shared-dma-pool";
 			reusable;
 			size = <0 0x400000>;
 		};
 
+		cont_splash_memory: cont_splash_region@5c000000 {
+			reg = <0x0 0x5c000000 0x0 0x00f00000>;
+			label = "cont_splash_region";
+		};
+
+		dfps_data_memory: dfps_data_region@5cf00000 {
+			reg = <0x0 0x5cf00000 0x0 0x0100000>;
+			label = "dfps_data_region";
+		};
+
+		disp_rdump_memory: disp_rdump_region@5c000000 {
+			reg = <0x0 0x5c000000 0x0 0x01000000>;
+			label = "disp_rdump_region";
+		};
+
 		/* global autoconfigured region for contiguous allocations */
 		linux,cma {
 			compatible = "shared-dma-pool";
@@ -811,6 +859,8 @@
 		reg = <0x5f00000 0x20000>;
 		reg-names = "cc_base";
 		vdd_cx-supply = <&VDD_CX_LEVEL>;
+		clock-names = "cfg_ahb_clk";
+		clocks = <&clock_gcc GCC_DISP_AHB_CLK>;
 		#clock-cells = <1>;
 	};
 
@@ -829,6 +879,19 @@
 		reg = <0x0447d200 0x100>;
 	};
 
+	cpucc_debug: syscon@f11101c {
+		compatible = "syscon";
+		reg = <0xf11101c 0x4>;
+	};
+
+	clock_cpucc: qcom,cpucc@f521000 {
+		compatible = "qcom,clk-cpu-osm-trinket";
+		reg = <0xf521000 0x1400>,
+			<0xf523000 0x1400>;
+		reg-names = "osm_pwrcl_base", "osm_perfcl_base";
+		#clock-cells = <1>;
+	};
+
 	clock_debugcc: qcom,cc-debug {
 		compatible = "qcom,debugcc-trinket";
 		qcom,gcc = <&clock_gcc>;
@@ -836,53 +899,12 @@
 		qcom,dispcc = <&clock_dispcc>;
 		qcom,gpucc = <&clock_gpucc>;
 		qcom,mccc = <&mccc_debug>;
+		qcom,cpucc = <&cpucc_debug>;
 		clock-names = "cxo";
 		clocks = <&clock_rpmcc RPM_SMD_XO_CLK_SRC>;
 		#clock-cells = <1>;
 	};
 
-	clock_cpucc: qcom,cpucc {
-		compatible = "qcom,dummycc";
-		clock-output-names = "cpucc_clocks";
-		#clock-cells = <1>;
-	};
-
-	icnss: qcom,icnss@C800000 {
-		compatible = "qcom,icnss";
-		reg = <0xC800000 0x800000>,
-		      <0xa0000000 0x10000000>,
-		      <0xb0000000 0x10000>;
-		reg-names = "membase", "smmu_iova_base", "smmu_iova_ipa";
-		iommus = <&apps_smmu 0x80 0x1>;
-		interrupts = <0 358 0 /* CE0 */ >,
-			     <0 359 0 /* CE1 */ >,
-			     <0 360 0 /* CE2 */ >,
-			     <0 361 0 /* CE3 */ >,
-			     <0 362 0 /* CE4 */ >,
-			     <0 363 0 /* CE5 */ >,
-			     <0 364 0 /* CE6 */ >,
-			     <0 365 0 /* CE7 */ >,
-			     <0 366 0 /* CE8 */ >,
-			     <0 367 0 /* CE9 */ >,
-			     <0 368 0 /* CE10 */ >,
-			     <0 369 0 /* CE11 */ >;
-		qcom,smmu-s1-bypass;
-		qcom,wlan-msa-memory = <0x100000>;
-		qcom,wlan-msa-fixed-region = <&wlan_msa_mem>;
-		vdd-cx-mx-supply = <&L8A>;
-		vdd-1.8-xo-supply = <&L16A>;
-		vdd-1.3-rfa-supply = <&L17A>;
-		vdd-3.3-ch0-supply = <&L23A>;
-		qcom,vdd-cx-mx-config = <640000 640000>;
-		qcom,smp2p_map_wlan_1_in {
-			interrupts-extended = <&smp2p_wlan_1_in 0 0>,
-					      <&smp2p_wlan_1_in 1 0>;
-			interrupt-names = "qcom,smp2p-force-fatal-error",
-					  "qcom,smp2p-early-crash-ind";
-		};
-
-	};
-
 	arm64-cpu-erp {
 		compatible = "arm,arm64-cpu-erp";
 		interrupts = <0 43 4>,
@@ -1158,6 +1180,7 @@
 		qcom,ssctl-instance-id = <0x12>;
 		qcom,pas-id = <4>;
 		qcom,smem-id = <421>;
+		qcom,minidump-id = <3>;
 		qcom,complete-ramdump;
 
 		/* Inputs from mss */
@@ -1870,6 +1893,17 @@
 			#interrupt-cells = <2>;
 		};
 
+		smp2p_rdbg2_out: qcom,smp2p-rdbg2-out {
+			qcom,entry-name = "rdbg";
+			#qcom,smem-state-cells = <1>;
+		};
+
+		smp2p_rdbg2_in: qcom,smp2p-rdbg2-in {
+			qcom,entry-name = "rdbg";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
 		sleepstate_smp2p_out: sleepstate-out {
 			qcom,entry-name = "sleepstate";
 			#qcom,smem-state-cells = <1>;
@@ -1900,6 +1934,18 @@
 			interrupt-controller;
 			#interrupt-cells = <2>;
 		};
+
+		smp2p_rdbg5_out: qcom,smp2p-rdbg5-out {
+			qcom,entry-name = "rdbg";
+			#qcom,smem-state-cells = <1>;
+		};
+
+		smp2p_rdbg5_in: qcom,smp2p-rdbg5-in {
+			qcom,entry-name = "rdbg";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
 	};
 
 	qcom_seecom: qseecom@46d00000 {
@@ -2066,7 +2112,7 @@
 		qca,bt-vdd-xtal-supply = <&pm6125_l16>;
 
 		qca,bt-vdd-io-voltage-level = <1700000 1900000>; /* IO */
-		qca,bt-vdd-core-voltage-level = <1245000 1350000>; /* RFA */
+		qca,bt-vdd-core-voltage-level = <1304000 1304000>; /* RFA */
 		qca,bt-vdd-pa-voltage-level =  <3200000 3400000>;  /*chain0 */
 		qca,bt-vdd-xtal-voltage-level = <1700000 1900000>; /* XO */
 
@@ -2164,6 +2210,46 @@
 
 		qcom,devfreq,freq-table = <50000000 200000000>;
 
+		qcom,msm-bus,name = "sdhc1";
+		qcom,msm-bus,num-cases = <9>;
+		qcom,msm-bus,num-paths = <2>;
+		qcom,msm-bus,vectors-KBps =
+			/* No vote */
+			<78 512 0 0>, <1 606 0 0>,
+			/* 400 KB/s*/
+			<78 512 1046 3200>,
+			<1 606 1600 1600>,
+			/* 20 MB/s */
+			<78 512 52286 160000>,
+			<1 606 80000 80000>,
+			/* 25 MB/s */
+			<78 512 65360 200000>,
+			<1 606 100000 100000>,
+			/* 50 MB/s */
+			<78 512 130718 400000>,
+			<1 606 133320 133320>,
+			/* 100 MB/s */
+			<78 512 130718 400000>,
+			<1 606 150000 150000>,
+			/* 200 MB/s */
+			<78 512 261438 800000>,
+			<1 606 300000 300000>,
+			/* 400 MB/s */
+			<78 512 261438 800000>,
+			<1 606 300000 300000>,
+			/* Max. bandwidth */
+			<78 512 1338562 4096000>,
+			<1 606 1338562 4096000>;
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+			100750000 200000000 400000000 4294967295>;
+
+		/* PM QoS */
+		qcom,pm-qos-irq-type = "affine_irq";
+		qcom,pm-qos-irq-latency = <40 40>;
+		qcom,pm-qos-cpu-groups = <0x0f 0xf0>;
+		qcom,pm-qos-cmdq-latency-us = <40 40>, <40 40>;
+		qcom,pm-qos-legacy-latency-us = <40 40>, <40 40>;
+
 		qcom,scaling-lower-bus-speed-mode = "DDR52";
 
 		clocks = <&clock_gcc GCC_SDCC1_AHB_CLK>,
@@ -2174,7 +2260,7 @@
 		qcom,ice-clk-rates = <300000000 75000000>;
 
 		/* DLL HSR settings. Refer go/hsr - <Target> DLL settings */
-		qcom,dll-hsr-list = <0x000F642C 0x0 0x0 0x00010800 0x80040868>;
+		qcom,dll-hsr-list = <0x000f642c 0x0 0x0 0x00010800 0x80040873>;
 
 		qcom,nonremovable;
 		status = "disabled";
@@ -2199,12 +2285,48 @@
 
 		qcom,devfreq,freq-table = <50000000 202000000>;
 
+		qcom,msm-bus,name = "sdhc2";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <2>;
+		qcom,msm-bus,vectors-KBps =
+			/* No vote */
+			<81 512 0 0>, <1 608 0 0>,
+			/* 400 KB/s*/
+			<81 512 1046 3200>,
+			<1 608 1600 1600>,
+			/* 20 MB/s */
+			<81 512 52286 160000>,
+			<1 608 80000 80000>,
+			/* 25 MB/s */
+			<81 512 65360 200000>,
+			<1 608 100000 100000>,
+			/* 50 MB/s */
+			<81 512 130718 400000>,
+			<1 608 133320 133320>,
+			/* 100 MB/s */
+			<81 512 261438 400000>,
+			<1 608 150000 150000>,
+			/* 200 MB/s */
+			<81 512 261438 800000>,
+			<1 608 300000 300000>,
+			/* Max. bandwidth */
+			<81 512 1338562 4096000>,
+			<1 608 1338562 4096000>;
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+			100750000 200000000 4294967295>;
+
+		/* PM QoS */
+		qcom,pm-qos-irq-type = "affine_irq";
+		qcom,pm-qos-irq-latency = <40 40>;
+		qcom,pm-qos-cpu-groups = <0x0f 0xf0>;
+		qcom,pm-qos-legacy-latency-us = <40 40>, <40 40>;
+
 		clocks = <&clock_gcc GCC_SDCC2_AHB_CLK>,
 			<&clock_gcc GCC_SDCC2_APPS_CLK>;
 		clock-names = "iface_clk", "core_clk";
 
 		/* DLL HSR settings. Refer go/hsr - <Target> DLL settings */
-		qcom,dll-hsr-list = <0x0007642C 0x0 0x0 0x00010800 0x80040868>;
+		qcom,dll-hsr-list = <0x0007642c 0x0 0x0 0x00010800 0x80040873>;
 
 		status = "disabled";
 	};
@@ -2235,6 +2357,7 @@
 		qcom,modem-cfg-emb-pipe-flt;
 		qcom,ipa-wdi2;
 		qcom,ipa-wdi2_over_gsi;
+		qcom,ipa-endp-delay-wa;
 		qcom,ipa-fltrt-not-hashable;
 		qcom,use-64-bit-dma-mask;
 		qcom,arm-smmu;
@@ -2355,31 +2478,31 @@
 
 	ddr_bw_opp_table: ddr-bw-opp-table {
 		compatible = "operating-points-v2";
-		BW_OPP_ENTRY( 200, 4); /*  762 MB/s */
-		BW_OPP_ENTRY( 300, 4); /* 1144 MB/s */
-		BW_OPP_ENTRY( 451, 4); /* 1721 MB/s */
-		BW_OPP_ENTRY( 547, 4); /* 2086 MB/s */
-		BW_OPP_ENTRY( 681, 4); /* 2597 MB/s */
-		BW_OPP_ENTRY( 768, 4); /* 2929 MB/s */
-		BW_OPP_ENTRY(1017, 4); /* 3879 MB/s */
-		BW_OPP_ENTRY(1353, 4); /* 5161 MB/s */
-		BW_OPP_ENTRY(1555, 4); /* 5931 MB/s */
-		BW_OPP_ENTRY(1804, 4); /* 6881 MB/s */
+		BW_OPP_ENTRY( 200, 8); /* 1525 MB/s */
+		BW_OPP_ENTRY( 300, 8); /* 2288 MB/s */
+		BW_OPP_ENTRY( 451, 8); /* 3440 MB/s */
+		BW_OPP_ENTRY( 547, 8); /* 4173 MB/s */
+		BW_OPP_ENTRY( 681, 8); /* 5195 MB/s */
+		BW_OPP_ENTRY( 768, 8); /* 5859 MB/s */
+		BW_OPP_ENTRY(1017, 8); /* 7759 MB/s */
+		BW_OPP_ENTRY(1353, 8); /*10322 MB/s */
+		BW_OPP_ENTRY(1555, 8); /*11863 MB/s */
+		BW_OPP_ENTRY(1804, 8); /*13763 MB/s */
 	};
 
 	suspendable_ddr_bw_opp_table: suspendable-ddr-bw-opp-table {
 		compatible = "operating-points-v2";
-		BW_OPP_ENTRY(   0, 4); /*    0 MB/s */
-		BW_OPP_ENTRY( 200, 4); /*  762 MB/s */
-		BW_OPP_ENTRY( 300, 4); /* 1144 MB/s */
-		BW_OPP_ENTRY( 451, 4); /* 1721 MB/s */
-		BW_OPP_ENTRY( 547, 4); /* 2086 MB/s */
-		BW_OPP_ENTRY( 681, 4); /* 2597 MB/s */
-		BW_OPP_ENTRY( 768, 4); /* 2929 MB/s */
-		BW_OPP_ENTRY(1017, 4); /* 3879 MB/s */
-		BW_OPP_ENTRY(1353, 4); /* 5161 MB/s */
-		BW_OPP_ENTRY(1555, 4); /* 5931 MB/s */
-		BW_OPP_ENTRY(1804, 4); /* 6881 MB/s */
+		BW_OPP_ENTRY(   0, 8); /*    0 MB/s */
+		BW_OPP_ENTRY( 200, 8); /* 1525 MB/s */
+		BW_OPP_ENTRY( 300, 8); /* 2288 MB/s */
+		BW_OPP_ENTRY( 451, 8); /* 3440 MB/s */
+		BW_OPP_ENTRY( 547, 8); /* 4173 MB/s */
+		BW_OPP_ENTRY( 681, 8); /* 5195 MB/s */
+		BW_OPP_ENTRY( 768, 8); /* 5859 MB/s */
+		BW_OPP_ENTRY(1017, 8); /* 7759 MB/s */
+		BW_OPP_ENTRY(1353, 8); /*10322 MB/s */
+		BW_OPP_ENTRY(1555, 8); /*11863 MB/s */
+		BW_OPP_ENTRY(1804, 8); /*13763 MB/s */
 	};
 
 	cpu_cpu_ddr_bw: qcom,cpu-cpu-ddr-bw {
@@ -2395,7 +2518,7 @@
 		compatible = "qcom,bimc-bwmon4";
 		reg = <0x01b8e200 0x100>, <0x01b8e100 0x100>;
 		reg-names = "base", "global_base";
-		interrupts = <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>;
 		qcom,mport = <0>;
 		qcom,hw-timer-hz = <19200000>;
 		qcom,target-dev = <&cpu_cpu_ddr_bw>;
@@ -2418,10 +2541,10 @@
 		qcom,cachemiss-ev = <0x17>;
 		qcom,stall-cycle-ev = <0xE7>;
 		qcom,core-dev-table =
-			<  864000 MHZ_TO_MBPS( 300, 4) >,
-			< 1305600 MHZ_TO_MBPS( 547, 4) >,
-			< 1420000 MHZ_TO_MBPS( 768, 4) >,
-			< 1804800 MHZ_TO_MBPS(1017, 4) >;
+			<  864000 MHZ_TO_MBPS( 300, 8) >,
+			< 1305600 MHZ_TO_MBPS( 547, 8) >,
+			< 1420000 MHZ_TO_MBPS( 768, 8) >,
+			< 1804800 MHZ_TO_MBPS(1017, 8) >;
 	};
 
 	cpu4_cpu_ddr_lat: qcom,cpu4-cpu-ddr-lat {
@@ -2440,10 +2563,10 @@
 		qcom,cachemiss-ev = <0x17>;
 		qcom,stall-cycle-ev = <0x24>;
 		qcom,core-dev-table =
-			<  902400 MHZ_TO_MBPS( 451, 4) >,
-			< 1401600 MHZ_TO_MBPS(1017, 4) >,
-			< 1804800 MHZ_TO_MBPS(1555, 4) >,
-			< 2016000 MHZ_TO_MBPS(1804, 4) >;
+			<  902400 MHZ_TO_MBPS( 451, 8) >,
+			< 1401600 MHZ_TO_MBPS(1017, 8) >,
+			< 1804800 MHZ_TO_MBPS(1555, 8) >,
+			< 2016000 MHZ_TO_MBPS(1804, 8) >;
 	};
 
 	cpu0_cpu_ddr_latfloor: qcom,cpu0-cpu-ddr-latfloor {
@@ -2460,10 +2583,10 @@
 		qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>;
 		qcom,target-dev = <&cpu0_cpu_ddr_latfloor>;
 		qcom,core-dev-table =
-			<  614400 MHZ_TO_MBPS( 300, 4) >,
-			< 1017600 MHZ_TO_MBPS( 451, 4) >,
-			< 1420000 MHZ_TO_MBPS( 547, 4) >,
-			< 1804800 MHZ_TO_MBPS( 768, 4) >;
+			<  614400 MHZ_TO_MBPS( 300, 8) >,
+			< 1017600 MHZ_TO_MBPS( 451, 8) >,
+			< 1420000 MHZ_TO_MBPS( 547, 8) >,
+			< 1804800 MHZ_TO_MBPS( 768, 8) >;
 	};
 
 	cpu4_cpu_ddr_latfloor: qcom,cpu4-cpu-ddr-latfloor {
@@ -2480,11 +2603,24 @@
 		qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>;
 		qcom,target-dev = <&cpu4_cpu_ddr_latfloor>;
 		qcom,core-dev-table =
-			<  902400 MHZ_TO_MBPS( 300, 4) >,
-			< 1056000 MHZ_TO_MBPS( 547, 4) >,
-			< 1401680 MHZ_TO_MBPS( 768, 4) >,
-			< 1804800 MHZ_TO_MBPS(1017, 4) >,
-			< 2016000 MHZ_TO_MBPS(1804, 4) >;
+			<  902400 MHZ_TO_MBPS( 300, 8) >,
+			< 1056000 MHZ_TO_MBPS( 547, 8) >,
+			< 1401680 MHZ_TO_MBPS( 768, 8) >,
+			< 1804800 MHZ_TO_MBPS(1017, 8) >,
+			< 2016000 MHZ_TO_MBPS(1804, 8) >;
+	};
+
+	demux {
+		compatible = "qcom,demux";
+	};
+
+	qfprom: qfprom@1b46018 {
+		compatible = "qcom,qfprom";
+		reg = <0x1b46018 0x4>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		read-only;
+		ranges;
 	};
 };
 
@@ -2507,6 +2643,7 @@
 #include "trinket-bus.dtsi"
 #include "trinket-sde-pll.dtsi"
 #include "trinket-sde.dtsi"
+#include "msm-rdbg.dtsi"
 
 &pm6125_vadc {
 	pinctrl-names = "default";
@@ -2667,6 +2804,7 @@
 
 &pmi632_adc_tm {
 	io-channels = <&pmi632_vadc ADC_GPIO1_PU2>,
+			<&pmi632_vadc ADC_VBAT_SNS>,
 			<&pmi632_vadc ADC_GPIO2_PU2>;
 
 	/* Channel nodes */
@@ -2676,6 +2814,13 @@
 		qcom,hw-settle-time = <200>;
 	};
 
+	vbat_sns {
+		reg = <ADC_VBAT_SNS>;
+		qcom,kernel-client;
+		qcom,scale-type = <0>;
+		qcom,prescaling = <3>;
+	};
+
 	skin_therm {
 		reg = <ADC_GPIO2_PU2>;
 		qcom,ratiometric;
@@ -2770,6 +2915,47 @@
 #include "trinket-audio.dtsi"
 #include "trinket-thermal.dtsi"
 
+&soc {
+	icnss: qcom,icnss@C800000 {
+		compatible = "qcom,icnss";
+		reg = <0xC800000 0x800000>,
+		      <0xa0000000 0x10000000>,
+		      <0xb0000000 0x10000>;
+		reg-names = "membase", "smmu_iova_base", "smmu_iova_ipa";
+		iommus = <&apps_smmu 0x80 0x1>;
+		interrupts = <0 358 0 /* CE0 */ >,
+			     <0 359 0 /* CE1 */ >,
+			     <0 360 0 /* CE2 */ >,
+			     <0 361 0 /* CE3 */ >,
+			     <0 362 0 /* CE4 */ >,
+			     <0 363 0 /* CE5 */ >,
+			     <0 364 0 /* CE6 */ >,
+			     <0 365 0 /* CE7 */ >,
+			     <0 366 0 /* CE8 */ >,
+			     <0 367 0 /* CE9 */ >,
+			     <0 368 0 /* CE10 */ >,
+			     <0 369 0 /* CE11 */ >;
+		qcom,smmu-s1-bypass;
+		qcom,wlan-msa-memory = <0x100000>;
+		qcom,wlan-msa-fixed-region = <&wlan_msa_mem>;
+		vdd-cx-mx-supply = <&L8A>;
+		vdd-1.8-xo-supply = <&L16A>;
+		vdd-1.3-rfa-supply = <&L17A>;
+		vdd-3.3-ch0-supply = <&L23A>;
+		qcom,vdd-cx-mx-config = <640000 640000>;
+		qcom,vdd-3.3-ch0-config = <3000000 3312000>;
+		qcom,icnss-adc_tm = <&pmi632_adc_tm>;
+		io-channels = <&pmi632_vadc ADC_VBAT_SNS>;
+		io-channel-names = "icnss";
+		qcom,smp2p_map_wlan_1_in {
+		interrupts-extended = <&smp2p_wlan_1_in 0 0>,
+					      <&smp2p_wlan_1_in 1 0>;
+			interrupt-names = "qcom,smp2p-force-fatal-error",
+					  "qcom,smp2p-early-crash-ind";
+		};
+	};
+};
+
 &qupv3_se1_i2c {
 	status="ok";
 	#include "pm8008.dtsi"
@@ -2791,6 +2977,18 @@
 	};
 };
 
+&pm8008_gpios {
+	gpio1_active {
+		pm8008_gpio1_active: pm8008_gpio1_active {
+			pins = "gpio1";
+			function = "normal";
+			power-source = <1>;
+			bias-disable;
+			input-enable;
+		};
+	};
+};
+
 &pm8008_chip {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pm8008_active>;
@@ -2800,6 +2998,12 @@
 	vdd_l1_l2-supply = <&S6A>;
 };
 
+&pm8008_9 {
+	/* GPIO1 pinctrl config */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pm8008_gpio1_active>;
+};
+
 &L1P {
 	regulator-min-microvolt = <1200000>;
 	regulator-max-microvolt = <1200000>;
diff --git a/arch/arm64/configs/vendor/atoll-perf_defconfig b/arch/arm64/configs/vendor/atoll-perf_defconfig
new file mode 100644
index 0000000..6ec690a
--- /dev/null
+++ b/arch/arm64/configs/vendor/atoll-perf_defconfig
@@ -0,0 +1,700 @@
+CONFIG_LOCALVERSION="-perf"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_SCHED_WALT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_BLK_CGROUP=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_BPF=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB_FREELIST_RANDOM=y
+CONFIG_SLAB_FREELIST_HARDENED=y
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_ATOLL=y
+CONFIG_ARCH_SDMMAGPIE=y
+CONFIG_PCI=y
+CONFIG_PCI_MSM=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT=y
+CONFIG_HZ_100=y
+CONFIG_CMA=y
+CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_SECCOMP=y
+# CONFIG_UNMAP_KERNEL_AT_EL0 is not set
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_SWP_EMULATION=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+# CONFIG_ARM64_VHE is not set
+CONFIG_RANDOMIZE_BASE=y
+# CONFIG_EFI is not set
+CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
+CONFIG_KRYO_PMU_WORKAROUND=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_SOCKET_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_SOCKET_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_IP_SCTP=y
+CONFIG_L2TP=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_QRTR=y
+CONFIG_QRTR_SMD=y
+CONFIG_SOCKEV_NLMCAST=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_CERTIFICATION_ONUS=y
+CONFIG_CFG80211_REG_CELLULAR_HINTS=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_RFKILL=y
+CONFIG_NFC_NQ=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_REGMAP_WCD_IRQ=y
+CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
+CONFIG_DMA_CMA=y
+CONFIG_ZRAM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_HDCP_QSEECOM=y
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_QPNP_MISC=y
+CONFIG_FPR_FPC=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_DEFAULT_KEY=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_SKY2=y
+CONFIG_RMNET=y
+CONFIG_SMSC911X=y
+CONFIG_AT803X_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
+CONFIG_WIL6210=m
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_GENL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ST=y
+CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y
+CONFIG_TOUCHSCREEN_HIMAX_I2C=y
+CONFIG_TOUCHSCREEN_HIMAX_INCELL=y
+CONFIG_TOUCHSCREEN_HIMAX_IC_HX83112=y
+CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+CONFIG_SERIAL_MSM_GENI=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+# CONFIG_DEVPORT is not set
+CONFIG_DIAG_CHAR=y
+CONFIG_MSM_FASTCVPD=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_QCOM_GENI=y
+CONFIG_SPI=y
+CONFIG_SPI_QCOM_GENI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SPMI=y
+CONFIG_SPMI_SIMULATOR=y
+CONFIG_PM8150_PMIC_SIMULATOR=y
+CONFIG_PM8150B_PMIC_SIMULATOR=y
+CONFIG_PM8150L_PMIC_SIMULATOR=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PINCTRL_SX150X=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_PINCTRL_SDMMAGPIE=y
+CONFIG_PINCTRL_ATOLL=y
+CONFIG_PINCTRL_SLPI=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_XGENE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_QPNP_QG=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
+CONFIG_QPNP_SMB5=y
+CONFIG_SMB1390_CHARGE_PUMP_PSY=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_QCOM_SPMI_TEMP_ALARM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_QTI_VIRTUAL_SENSOR=y
+CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
+CONFIG_QTI_BCL_PMIC5=y
+CONFIG_QTI_BCL_SOC_DRIVER=y
+CONFIG_QTI_ADC_TM=y
+CONFIG_QTI_CX_IPEAK_COOLING_DEVICE=y
+CONFIG_MFD_I2C_PMIC=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_QPNP_AMOLED=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_REFGEN=y
+CONFIG_REGULATOR_RPMH=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_FIXED_MINOR_RANGES=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_SPECTRA_CAMERA=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_MSM_NPU=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
+CONFIG_DVB_MPQ_SW=y
+CONFIG_DRM=y
+CONFIG_DRM_MSM_REGISTER_LOGGING=y
+CONFIG_DRM_SDE_EVTLOG_DEBUG=y
+CONFIG_DRM_SDE_RSC=y
+CONFIG_DRM_ANALOGIX_ANX7625=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_BACKLIGHT_QCOM_SPMI_WLED=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_AUDIO_QMI=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_PLANTRONICS=y
+CONFIG_HID_QVR=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760_HOST_ROLE=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_QCOM_EMU_PHY=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_MSM_HSUSB_PHY=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=900
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
+CONFIG_USB_CONFIGFS_F_GSI=y
+CONFIG_USB_CONFIGFS_F_QDSS=y
+CONFIG_USB_PD_POLICY=y
+CONFIG_QPNP_USB_PDPHY=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=m
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_QTI_TRI_LED=y
+CONFIG_LEDS_QPNP_VIBRATOR_LDO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_EDAC=y
+CONFIG_EDAC_KRYO_ARM64=y
+CONFIG_EDAC_KRYO_ARM64_PANIC_ON_UE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_GPI_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_DEFER_FREE_NO_SCHED_IDLE=y
+CONFIG_QCOM_GENI_SE=y
+CONFIG_QPNP_REVID=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_USB_BAM=y
+CONFIG_IPA3=y
+CONFIG_IPA_WDI_UNIFIED_API=y
+CONFIG_RMNET_IPA3=y
+CONFIG_RNDIS_IPA=y
+CONFIG_IPA_UT=y
+CONFIG_MSM_11AD=m
+CONFIG_QCOM_MDSS_PLL=y
+CONFIG_SPMI_PMIC_CLKDIV=y
+CONFIG_MSM_CLK_AOP_QMP=y
+CONFIG_MSM_GCC_SM8150=y
+CONFIG_MSM_NPUCC_SM8150=y
+CONFIG_MSM_VIDEOCC_SM8150=y
+CONFIG_MSM_CAMCC_SM8150=y
+CONFIG_CLOCK_CPU_OSM=y
+CONFIG_MSM_DISPCC_SM8150=y
+CONFIG_MSM_DEBUGCC_SM8150=y
+CONFIG_MSM_CLK_RPMH=y
+CONFIG_MSM_GPUCC_SM8150=y
+CONFIG_MSM_GCC_SM6150=y
+CONFIG_MSM_GPUCC_SM6150=y
+CONFIG_MSM_VIDEOCC_SM6150=y
+CONFIG_MSM_DEBUGCC_SM6150=y
+CONFIG_MSM_CAMCC_SM6150=y
+CONFIG_MSM_DISPCC_SM6150=y
+CONFIG_MSM_SCC_SM6150=y
+CONFIG_MSM_CAMCC_SDMMAGPIE=y
+CONFIG_MSM_DISPCC_SDMMAGPIE=y
+CONFIG_MSM_GCC_SDMMAGPIE=y
+CONFIG_MSM_VIDEOCC_SDMMAGPIE=y
+CONFIG_MSM_NPUCC_SDMMAGPIE=y
+CONFIG_MSM_GPUCC_SDMMAGPIE=y
+CONFIG_MSM_DEBUGCC_SDMMAGPIE=y
+CONFIG_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_QCOM=y
+CONFIG_QCOM_APCS_IPC=y
+CONFIG_MSM_QMP=y
+CONFIG_IOMMU_IO_PGTABLE_FAST=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
+CONFIG_RPMSG_CHAR=y
+CONFIG_RPMSG_QCOM_GLINK_SMEM=y
+CONFIG_RPMSG_QCOM_GLINK_SPI=y
+CONFIG_QCOM_CPUSS_DUMP=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_QCOM_LLCC=y
+CONFIG_QCOM_SM6150_LLCC=y
+CONFIG_QCOM_SDMMAGPIE_LLCC=y
+CONFIG_QCOM_ATOLL_LLCC=y
+CONFIG_QCOM_LLCC_PERFMON=m
+CONFIG_QCOM_QMI_HELPERS=y
+CONFIG_QCOM_SMEM=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QCOM_SMP2P=y
+CONFIG_QPNP_PBS=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_SYSMON_QMI_COMM=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y
+CONFIG_SSR_SYSMON_NOTIF_TIMEOUT=20000
+CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000
+CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_QCOM_DCC_V2=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_ICNSS=y
+CONFIG_ICNSS_QMI=y
+CONFIG_QCOM_EUD=y
+CONFIG_QCOM_MINIDUMP=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_BUS_CONFIG_RPMH=y
+CONFIG_QCOM_COMMAND_DB=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_QTI_RPMH_API=y
+CONFIG_QSEE_IPC_IRQ=y
+CONFIG_QCOM_GLINK=y
+CONFIG_QCOM_GLINK_PKT=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_MSM_CDSP_LOADER=y
+CONFIG_QCOM_SMCINVOKE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_PM=y
+CONFIG_QCOM_FSA4480_I2C=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_QMP_DEBUGFS_CLIENT=y
+CONFIG_QCOM_SMP2P_SLEEPSTATE=y
+CONFIG_QCOM_CDSP_RM=y
+CONFIG_QCOM_CX_IPEAK=y
+CONFIG_DEVFREQ_GOV_PASSIVE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_ARM_MEMLAT_MON=y
+CONFIG_QCOMCCI_HWMON=y
+CONFIG_QCOM_M4M_HWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y
+CONFIG_DEVFREQ_GOV_MEMLAT=y
+CONFIG_DEVFREQ_SIMPLE_DEV=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_DEVFREQ_GOV_CDSPL3=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_QCOM_SPMI_ADC5=y
+CONFIG_PWM=y
+CONFIG_PWM_QTI_LPG=y
+CONFIG_QCOM_KGSL=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_ARM_DSU_PMU=y
+CONFIG_QCOM_LLCC_PMU=y
+CONFIG_RAS=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_NVMEM_SPMI_SDAM=y
+CONFIG_SENSORS_SSC=y
+CONFIG_ESOC=y
+CONFIG_ESOC_DEV=y
+CONFIG_ESOC_CLIENT=y
+CONFIG_ESOC_MDM_4x=y
+CONFIG_ESOC_MDM_DRV=y
+CONFIG_ESOC_MDM_DBG_ENG=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_PAGE_OWNER=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_IPC_LOGGING=y
+CONFIG_DEBUG_ALIGN_RODATA=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_CORESIGHT_DUMMY=y
+CONFIG_CORESIGHT_REMOTE_ETM=y
+CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_EVENT=y
+CONFIG_PFK=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_FORTIFY_SOURCE=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
+CONFIG_STACK_HASH_ORDER_SHIFT=12
diff --git a/arch/arm64/configs/vendor/atoll_defconfig b/arch/arm64/configs/vendor/atoll_defconfig
new file mode 100644
index 0000000..134c7d1
--- /dev/null
+++ b/arch/arm64/configs/vendor/atoll_defconfig
@@ -0,0 +1,794 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_SCHED_WALT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_BLK_CGROUP=y
+CONFIG_DEBUG_BLK_CGROUP=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_BPF=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB_FREELIST_RANDOM=y
+CONFIG_SLAB_FREELIST_HARDENED=y
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_ATOLL=y
+CONFIG_PCI=y
+CONFIG_PCI_MSM=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT=y
+CONFIG_HZ_100=y
+CONFIG_CLEANCACHE=y
+CONFIG_CMA=y
+CONFIG_CMA_DEBUGFS=y
+CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_SECCOMP=y
+# CONFIG_UNMAP_KERNEL_AT_EL0 is not set
+CONFIG_PRINT_VMEMLAYOUT=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_SWP_EMULATION=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+# CONFIG_ARM64_VHE is not set
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
+CONFIG_KRYO_PMU_WORKAROUND=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_DEBUG=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_SOCKET_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_SOCKET_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_IP_SCTP=y
+CONFIG_L2TP=y
+CONFIG_L2TP_DEBUGFS=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_DNS_RESOLVER=y
+CONFIG_QRTR=y
+CONFIG_QRTR_SMD=y
+CONFIG_SOCKEV_NLMCAST=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_CERTIFICATION_ONUS=y
+CONFIG_CFG80211_REG_CELLULAR_HINTS=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
+CONFIG_RFKILL=y
+CONFIG_NFC_NQ=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_REGMAP_WCD_IRQ=y
+CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
+CONFIG_DMA_CMA=y
+CONFIG_ZRAM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_HDCP_QSEECOM=y
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_QPNP_MISC=y
+CONFIG_FPR_FPC=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_DEFAULT_KEY=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_RMNET=y
+CONFIG_AT803X_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
+CONFIG_WIL6210=m
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_GENL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ST=y
+CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y
+CONFIG_TOUCHSCREEN_HIMAX_I2C=y
+CONFIG_TOUCHSCREEN_HIMAX_INCELL=y
+CONFIG_TOUCHSCREEN_HIMAX_IC_HX83112=y
+CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_REFLASH=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_RECOVERY=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+CONFIG_SERIAL_MSM_GENI=y
+CONFIG_SERIAL_MSM_GENI_CONSOLE=y
+CONFIG_SERIAL_DEV_BUS=y
+CONFIG_TTY_PRINTK=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+# CONFIG_DEVPORT is not set
+CONFIG_DIAG_CHAR=y
+CONFIG_MSM_FASTCVPD=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_QCOM_GENI=y
+CONFIG_SPI=y
+CONFIG_SPI_QCOM_GENI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SPMI=y
+CONFIG_SPMI_SIMULATOR=y
+CONFIG_PM8150_PMIC_SIMULATOR=y
+CONFIG_PM8150B_PMIC_SIMULATOR=y
+CONFIG_PM8150L_PMIC_SIMULATOR=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PINCTRL_SX150X=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_PINCTRL_SDMMAGPIE=y
+CONFIG_PINCTRL_ATOLL=y
+CONFIG_PINCTRL_SLPI=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_XGENE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_QPNP_QG=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
+CONFIG_QPNP_SMB5=y
+CONFIG_SMB1390_CHARGE_PUMP_PSY=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_QCOM_SPMI_TEMP_ALARM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_QTI_VIRTUAL_SENSOR=y
+CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
+CONFIG_QTI_BCL_PMIC5=y
+CONFIG_QTI_BCL_SOC_DRIVER=y
+CONFIG_QTI_ADC_TM=y
+CONFIG_QTI_CX_IPEAK_COOLING_DEVICE=y
+CONFIG_MFD_I2C_PMIC=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_QPNP_AMOLED=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_REFGEN=y
+CONFIG_REGULATOR_RPMH=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_FIXED_MINOR_RANGES=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_SPECTRA_CAMERA=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_MSM_NPU=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
+CONFIG_DVB_MPQ_SW=y
+CONFIG_DRM=y
+CONFIG_DRM_MSM_REGISTER_LOGGING=y
+CONFIG_DRM_SDE_EVTLOG_DEBUG=y
+CONFIG_DRM_SDE_RSC=y
+CONFIG_DRM_ANALOGIX_ANX7625=y
+CONFIG_FB_VIRTUAL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_QCOM_SPMI_WLED=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_AUDIO_QMI=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_PLANTRONICS=y
+CONFIG_HID_QVR=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760_HOST_ROLE=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_QCOM_EMU_PHY=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_MSM_HSUSB_PHY=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=900
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
+CONFIG_USB_CONFIGFS_F_GSI=y
+CONFIG_USB_CONFIGFS_F_QDSS=y
+CONFIG_USB_PD_POLICY=y
+CONFIG_QPNP_USB_PDPHY=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=m
+CONFIG_MMC_RING_BUFFER=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_QTI_TRI_LED=y
+CONFIG_LEDS_QPNP_VIBRATOR_LDO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_EDAC=y
+CONFIG_EDAC_KRYO_ARM64=y
+CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE=y
+CONFIG_EDAC_KRYO_ARM64_PANIC_ON_UE=y
+CONFIG_EDAC_QCOM_LLCC=y
+CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE=y
+CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_GPI_DMA=y
+CONFIG_QCOM_GPI_DMA_DEBUG=y
+CONFIG_DEBUG_DMA_BUF_REF=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_DEFER_FREE_NO_SCHED_IDLE=y
+CONFIG_QCOM_GENI_SE=y
+CONFIG_QPNP_REVID=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_USB_BAM=y
+CONFIG_IPA3=y
+CONFIG_IPA_WDI_UNIFIED_API=y
+CONFIG_RMNET_IPA3=y
+CONFIG_RNDIS_IPA=y
+CONFIG_IPA_UT=y
+CONFIG_MSM_11AD=m
+CONFIG_QCOM_MDSS_PLL=y
+CONFIG_SPMI_PMIC_CLKDIV=y
+CONFIG_MSM_CLK_AOP_QMP=y
+CONFIG_MSM_GCC_SM8150=y
+CONFIG_MSM_NPUCC_SM8150=y
+CONFIG_MSM_VIDEOCC_SM8150=y
+CONFIG_MSM_CAMCC_SM8150=y
+CONFIG_CLOCK_CPU_OSM=y
+CONFIG_MSM_DISPCC_SM8150=y
+CONFIG_MSM_DEBUGCC_SM8150=y
+CONFIG_MSM_CLK_RPMH=y
+CONFIG_MSM_GPUCC_SM8150=y
+CONFIG_MSM_GCC_SM6150=y
+CONFIG_MSM_GPUCC_SM6150=y
+CONFIG_MSM_VIDEOCC_SM6150=y
+CONFIG_MSM_DEBUGCC_SM6150=y
+CONFIG_MSM_CAMCC_SM6150=y
+CONFIG_MSM_DISPCC_SM6150=y
+CONFIG_MSM_SCC_SM6150=y
+CONFIG_MSM_CAMCC_SDMMAGPIE=y
+CONFIG_MSM_DISPCC_SDMMAGPIE=y
+CONFIG_MSM_GCC_SDMMAGPIE=y
+CONFIG_MSM_VIDEOCC_SDMMAGPIE=y
+CONFIG_MSM_NPUCC_SDMMAGPIE=y
+CONFIG_MSM_GPUCC_SDMMAGPIE=y
+CONFIG_MSM_DEBUGCC_SDMMAGPIE=y
+CONFIG_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_QCOM=y
+CONFIG_QCOM_APCS_IPC=y
+CONFIG_MSM_QMP=y
+CONFIG_IOMMU_IO_PGTABLE_FAST=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
+CONFIG_RPMSG_CHAR=y
+CONFIG_RPMSG_QCOM_GLINK_SMEM=y
+CONFIG_RPMSG_QCOM_GLINK_SPI=y
+CONFIG_QCOM_CPUSS_DUMP=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_QCOM_LLCC=y
+CONFIG_QCOM_SM6150_LLCC=y
+CONFIG_QCOM_SDMMAGPIE_LLCC=y
+CONFIG_QCOM_ATOLL_LLCC=y
+CONFIG_QCOM_LLCC_PERFMON=m
+CONFIG_QCOM_QMI_HELPERS=y
+CONFIG_QCOM_SMEM=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QCOM_WDOG_IPI_ENABLE=y
+CONFIG_QCOM_SMP2P=y
+CONFIG_QPNP_PBS=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_SYSMON_QMI_COMM=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y
+CONFIG_SSR_SYSMON_NOTIF_TIMEOUT=20000
+CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000
+CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_CORE_HANG_DETECT=y
+CONFIG_QCOM_DCC_V2=y
+CONFIG_MSM_GLADIATOR_HANG_DETECT=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_ICNSS=y
+CONFIG_ICNSS_DEBUG=y
+CONFIG_ICNSS_QMI=y
+CONFIG_QCOM_EUD=y
+CONFIG_QCOM_MINIDUMP=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_BUS_CONFIG_RPMH=y
+CONFIG_QCOM_COMMAND_DB=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_QTI_RPMH_API=y
+CONFIG_QSEE_IPC_IRQ=y
+CONFIG_QCOM_GLINK=y
+CONFIG_QCOM_GLINK_PKT=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_MSM_CDSP_LOADER=y
+CONFIG_QCOM_SMCINVOKE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_PM=y
+CONFIG_QCOM_FSA4480_I2C=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_QMP_DEBUGFS_CLIENT=y
+CONFIG_QCOM_SMP2P_SLEEPSTATE=y
+CONFIG_QCOM_CDSP_RM=y
+CONFIG_QCOM_CX_IPEAK=y
+CONFIG_DEVFREQ_GOV_PASSIVE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_ARM_MEMLAT_MON=y
+CONFIG_QCOMCCI_HWMON=y
+CONFIG_QCOM_M4M_HWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y
+CONFIG_DEVFREQ_GOV_MEMLAT=y
+CONFIG_DEVFREQ_SIMPLE_DEV=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_DEVFREQ_GOV_CDSPL3=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_QCOM_SPMI_ADC5=y
+CONFIG_PWM=y
+CONFIG_PWM_QTI_LPG=y
+CONFIG_QCOM_KGSL=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_QTI_PDC_SDMMAGPIE=y
+CONFIG_PHY_XGENE=y
+CONFIG_ARM_DSU_PMU=y
+CONFIG_QCOM_LLCC_PMU=y
+CONFIG_RAS=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_NVMEM_SPMI_SDAM=y
+CONFIG_SENSORS_SSC=y
+CONFIG_ESOC=y
+CONFIG_ESOC_DEV=y
+CONFIG_ESOC_CLIENT=y
+CONFIG_ESOC_DEBUG=y
+CONFIG_ESOC_MDM_4x=y
+CONFIG_ESOC_MDM_DRV=y
+CONFIG_ESOC_MDM_DBG_ENG=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_EFIVAR_FS=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_MODULE_LOAD_INFO=y
+CONFIG_DEBUG_INFO=y
+CONFIG_PAGE_OWNER=y
+CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SLUB_DEBUG_PANIC_ON=y
+CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
+CONFIG_PAGE_POISONING=y
+CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_WORK=y
+CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
+CONFIG_SLUB_DEBUG_ON=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_PANIC_ON_SCHED_BUG=y
+CONFIG_PANIC_ON_RT_THROTTLING=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_STACK_END_CHECK=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_LOCK_TORTURE_TEST=m
+CONFIG_DEBUG_SG=y
+CONFIG_DEBUG_NOTIFIERS=y
+CONFIG_DEBUG_CREDENTIALS=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAIL_MMC_REQUEST=y
+CONFIG_UFS_FAULT_INJECTION=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_IPC_LOGGING=y
+CONFIG_QCOM_RTB=y
+CONFIG_QCOM_RTB_SEPARATE_CPUS=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_PREEMPTIRQ_EVENTS=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LKDTM=m
+CONFIG_ATOMIC64_SELFTEST=m
+CONFIG_TEST_USER_COPY=m
+CONFIG_MEMTEST=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
+CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_ARM64_STRICT_BREAK_BEFORE_MAKE=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_SOURCE_ETM4X=y
+CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_CORESIGHT_DUMMY=y
+CONFIG_CORESIGHT_REMOTE_ETM=y
+CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_TGU=y
+CONFIG_CORESIGHT_EVENT=y
+CONFIG_PFK=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_HARDENED_USERCOPY_PAGESPAN=y
+CONFIG_FORTIFY_SOURCE=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
+CONFIG_XZ_DEC=y
diff --git a/arch/arm64/configs/vendor/qcs405-perf_defconfig b/arch/arm64/configs/vendor/qcs405-perf_defconfig
index 26d80b3..cae1a48 100644
--- a/arch/arm64/configs/vendor/qcs405-perf_defconfig
+++ b/arch/arm64/configs/vendor/qcs405-perf_defconfig
@@ -26,6 +26,7 @@
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_EMBEDDED=y
+CONFIG_SLAB_FREELIST_HARDENED=y
 CONFIG_PROFILING=y
 CONFIG_CC_STACKPROTECTOR_STRONG=y
 CONFIG_MODULES=y
@@ -49,6 +50,7 @@
 CONFIG_CP15_BARRIER_EMULATION=y
 CONFIG_SETEND_EMULATION=y
 CONFIG_ARM64_SW_TTBR0_PAN=y
+CONFIG_RANDOMIZE_BASE=y
 CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
@@ -275,8 +277,6 @@
 CONFIG_INPUT_GPIO=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVMEM is not set
-CONFIG_SERIAL_MSM=y
-CONFIG_SERIAL_RX_CONSOLE_ONLY=y
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM_LEGACY=y
@@ -491,6 +491,12 @@
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_UBIFS_FS=y
 CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+# CONFIG_SQUASHFS_ZLIB is not set
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
@@ -505,6 +511,7 @@
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_SCHEDSTATS=y
 CONFIG_IPC_LOGGING=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_CORESIGHT=y
 CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
 CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y
@@ -520,11 +527,14 @@
 CONFIG_SECURITY_NETWORK=y
 CONFIG_LSM_MMAP_MIN_ADDR=4096
 CONFIG_HARDENED_USERCOPY=y
+CONFIG_HARDENED_USERCOPY_PAGESPAN=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_CRYPTO_CTR=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
 CONFIG_CRYPTO_DEV_QCOM_ICE=y
 CONFIG_STACK_HASH_ORDER_SHIFT=12
diff --git a/arch/arm64/configs/vendor/qcs405_defconfig b/arch/arm64/configs/vendor/qcs405_defconfig
index ad9485a..e1bf94de 100644
--- a/arch/arm64/configs/vendor/qcs405_defconfig
+++ b/arch/arm64/configs/vendor/qcs405_defconfig
@@ -27,6 +27,7 @@
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_EMBEDDED=y
+CONFIG_SLAB_FREELIST_HARDENED=y
 CONFIG_PROFILING=y
 CONFIG_CC_STACKPROTECTOR_STRONG=y
 CONFIG_MODULES=y
@@ -52,6 +53,7 @@
 CONFIG_CP15_BARRIER_EMULATION=y
 CONFIG_SETEND_EMULATION=y
 CONFIG_ARM64_SW_TTBR0_PAN=y
+CONFIG_RANDOMIZE_BASE=y
 CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
@@ -506,6 +508,12 @@
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_UBIFS_FS=y
 CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+# CONFIG_SQUASHFS_ZLIB is not set
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
@@ -539,7 +547,6 @@
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
-CONFIG_DEBUG_LIST=y
 CONFIG_FAULT_INJECTION=y
 CONFIG_FAIL_PAGE_ALLOC=y
 CONFIG_UFS_FAULT_INJECTION=y
@@ -550,6 +557,7 @@
 CONFIG_QCOM_RTB_SEPARATE_CPUS=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_LKDTM=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_CORESIGHT=y
 CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
 CONFIG_CORESIGHT_SOURCE_ETM4X=y
@@ -568,10 +576,13 @@
 CONFIG_SECURITY_NETWORK=y
 CONFIG_LSM_MMAP_MIN_ADDR=4096
 CONFIG_HARDENED_USERCOPY=y
+CONFIG_HARDENED_USERCOPY_PAGESPAN=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_CRYPTO_CTR=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
 CONFIG_CRYPTO_DEV_QCOM_ICE=y
diff --git a/arch/arm64/configs/vendor/qti-quin-gvm-perf_defconfig b/arch/arm64/configs/vendor/qti-quin-gvm-perf_defconfig
index 6e579f6..681a9e9 100644
--- a/arch/arm64/configs/vendor/qti-quin-gvm-perf_defconfig
+++ b/arch/arm64/configs/vendor/qti-quin-gvm-perf_defconfig
@@ -216,6 +216,7 @@
 CONFIG_NET_ACT_SKBEDIT=y
 CONFIG_SOCKEV_NLMCAST=y
 CONFIG_CAN=y
+CONFIG_QTI_CAN=y
 CONFIG_BT=y
 CONFIG_CFG80211=y
 CONFIG_CFG80211_CERTIFICATION_ONUS=y
@@ -250,7 +251,6 @@
 CONFIG_DUMMY=y
 CONFIG_TUN=y
 CONFIG_VIRTIO_NET=y
-CONFIG_PHYLIB=y
 CONFIG_MICREL_PHY=y
 CONFIG_PPP=y
 CONFIG_PPP_BSDCOMP=y
@@ -264,6 +264,7 @@
 CONFIG_PPPOPNS=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
@@ -277,6 +278,7 @@
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_MSM_GENI=y
 CONFIG_SERIAL_DEV_BUS=y
 CONFIG_TTY_PRINTK=y
 CONFIG_HW_RANDOM=y
@@ -289,6 +291,8 @@
 CONFIG_SPMI=y
 CONFIG_PINCTRL_SX150X=y
 CONFIG_PINCTRL_SM8150=y
+CONFIG_PINCTRL_SM6150=y
+CONFIG_PINCTRL_SLPI=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
@@ -327,12 +331,18 @@
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
 CONFIG_USB_ISP1760=y
 CONFIG_USB_ISP1760_HOST_ROLE=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
 CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_QCOM_EMU_PHY=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_HSUSB_PHY=y
 CONFIG_DUAL_ROLE_USB_INTF=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_VBUS_DRAW=900
@@ -354,6 +364,7 @@
 CONFIG_USB_CONFIGFS_F_GSI=y
 CONFIG_USB_CONFIGFS_F_QDSS=y
 CONFIG_USB_PD_POLICY=y
+CONFIG_QPNP_USB_PDPHY=y
 CONFIG_RTC_CLASS=y
 CONFIG_DMADEVICES=y
 CONFIG_UIO=y
@@ -363,7 +374,11 @@
 CONFIG_ASHMEM=y
 CONFIG_ION=y
 CONFIG_QCOM_GENI_SE=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_USB_BAM=y
 CONFIG_COMMON_CLK_QCOM=y
+CONFIG_QCOM_CLK_VIRT=y
 CONFIG_HWSPINLOCK=y
 CONFIG_MAILBOX=y
 CONFIG_IOMMU_IO_PGTABLE_FAST=y
@@ -373,6 +388,8 @@
 CONFIG_IOMMU_DEBUG_TRACKING=y
 CONFIG_IOMMU_TESTS=y
 CONFIG_QCOM_SMEM=y
+CONFIG_MSM_HAB=y
+CONFIG_EXTCON_USB_GPIO=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_EXT4_FS=y
diff --git a/arch/arm64/configs/vendor/qti-quin-gvm_defconfig b/arch/arm64/configs/vendor/qti-quin-gvm_defconfig
index bbad084..72670da 100644
--- a/arch/arm64/configs/vendor/qti-quin-gvm_defconfig
+++ b/arch/arm64/configs/vendor/qti-quin-gvm_defconfig
@@ -226,6 +226,7 @@
 CONFIG_DNS_RESOLVER=y
 CONFIG_SOCKEV_NLMCAST=y
 CONFIG_CAN=y
+CONFIG_QTI_CAN=y
 CONFIG_BT=y
 CONFIG_CFG80211=y
 CONFIG_CFG80211_CERTIFICATION_ONUS=y
@@ -261,7 +262,6 @@
 CONFIG_DUMMY=y
 CONFIG_TUN=y
 CONFIG_VIRTIO_NET=y
-CONFIG_PHYLIB=y
 CONFIG_MICREL_PHY=y
 CONFIG_PPP=y
 CONFIG_PPP_BSDCOMP=y
@@ -275,6 +275,7 @@
 CONFIG_PPPOPNS=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
@@ -288,6 +289,8 @@
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_MSM_GENI=y
+CONFIG_SERIAL_MSM_GENI_CONSOLE=y
 CONFIG_SERIAL_DEV_BUS=y
 CONFIG_TTY_PRINTK=y
 CONFIG_HW_RANDOM=y
@@ -300,6 +303,8 @@
 CONFIG_SPMI=y
 CONFIG_PINCTRL_SX150X=y
 CONFIG_PINCTRL_SM8150=y
+CONFIG_PINCTRL_SM6150=y
+CONFIG_PINCTRL_SLPI=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
@@ -339,12 +344,18 @@
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
 CONFIG_USB_ISP1760=y
 CONFIG_USB_ISP1760_HOST_ROLE=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
 CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_QCOM_EMU_PHY=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_HSUSB_PHY=y
 CONFIG_DUAL_ROLE_USB_INTF=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_VBUS_DRAW=900
@@ -366,6 +377,7 @@
 CONFIG_USB_CONFIGFS_F_GSI=y
 CONFIG_USB_CONFIGFS_F_QDSS=y
 CONFIG_USB_PD_POLICY=y
+CONFIG_QPNP_USB_PDPHY=y
 CONFIG_RTC_CLASS=y
 CONFIG_DMADEVICES=y
 CONFIG_UIO=y
@@ -375,7 +387,11 @@
 CONFIG_ASHMEM=y
 CONFIG_ION=y
 CONFIG_QCOM_GENI_SE=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_USB_BAM=y
 CONFIG_COMMON_CLK_QCOM=y
+CONFIG_QCOM_CLK_VIRT=y
 CONFIG_HWSPINLOCK=y
 CONFIG_MAILBOX=y
 CONFIG_IOMMU_IO_PGTABLE_FAST=y
@@ -385,6 +401,8 @@
 CONFIG_IOMMU_DEBUG_TRACKING=y
 CONFIG_IOMMU_TESTS=y
 CONFIG_QCOM_SMEM=y
+CONFIG_MSM_HAB=y
+CONFIG_EXTCON_USB_GPIO=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_EXT4_FS=y
@@ -432,6 +450,7 @@
 CONFIG_FAIL_PAGE_ALLOC=y
 CONFIG_FAULT_INJECTION_DEBUG_FS=y
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_IPC_LOGGING=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_LKDTM=m
 CONFIG_ATOMIC64_SELFTEST=m
diff --git a/arch/arm64/configs/vendor/sa8155-perf_defconfig b/arch/arm64/configs/vendor/sa8155-perf_defconfig
index 46360bf..68bfa8c 100644
--- a/arch/arm64/configs/vendor/sa8155-perf_defconfig
+++ b/arch/arm64/configs/vendor/sa8155-perf_defconfig
@@ -106,6 +106,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
@@ -286,6 +287,7 @@
 CONFIG_PPP_MPPE=y
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=y
+CONFIG_PPTP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPPOLAC=y
 CONFIG_PPPOPNS=y
@@ -298,6 +300,7 @@
 CONFIG_CNSS2=y
 CONFIG_CNSS2_DEBUG=y
 CONFIG_CNSS2_QMI=y
+CONFIG_CNSS_ASYNC=y
 CONFIG_CNSS_GENL=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
@@ -572,6 +575,7 @@
 CONFIG_EXTCON_USB_GPIO=y
 CONFIG_IIO=y
 CONFIG_QCOM_SPMI_ADC5=y
+CONFIG_IIO_ST_ASM330LHH=y
 CONFIG_PWM=y
 CONFIG_PWM_QTI_LPG=y
 CONFIG_QCOM_KGSL=y
diff --git a/arch/arm64/configs/vendor/sa8155_defconfig b/arch/arm64/configs/vendor/sa8155_defconfig
index fdd12f6..eb825a2 100644
--- a/arch/arm64/configs/vendor/sa8155_defconfig
+++ b/arch/arm64/configs/vendor/sa8155_defconfig
@@ -113,6 +113,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
@@ -297,6 +298,7 @@
 CONFIG_PPP_MPPE=y
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=y
+CONFIG_PPTP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPPOLAC=y
 CONFIG_PPPOPNS=y
@@ -309,6 +311,7 @@
 CONFIG_CNSS2=y
 CONFIG_CNSS2_DEBUG=y
 CONFIG_CNSS2_QMI=y
+CONFIG_CNSS_ASYNC=y
 CONFIG_CNSS_GENL=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
@@ -509,6 +512,7 @@
 CONFIG_USB_BAM=y
 CONFIG_MSM_MHI_DEV=y
 CONFIG_IPA3=y
+CONFIG_IPA_DEBUG=y
 CONFIG_IPA_WDI_UNIFIED_API=y
 CONFIG_RMNET_IPA3=y
 CONFIG_RNDIS_IPA=y
@@ -599,6 +603,7 @@
 CONFIG_EXTCON_USB_GPIO=y
 CONFIG_IIO=y
 CONFIG_QCOM_SPMI_ADC5=y
+CONFIG_IIO_ST_ASM330LHH=y
 CONFIG_PWM=y
 CONFIG_PWM_QTI_LPG=y
 CONFIG_QCOM_KGSL=y
diff --git a/arch/arm64/configs/vendor/sdmsteppe-auto-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-auto-perf_defconfig
index b7dae79..dc7b4d1 100644
--- a/arch/arm64/configs/vendor/sdmsteppe-auto-perf_defconfig
+++ b/arch/arm64/configs/vendor/sdmsteppe-auto-perf_defconfig
@@ -59,7 +59,6 @@
 CONFIG_ARCH_SDMMAGPIE=y
 CONFIG_PCI=y
 CONFIG_PCI_MSM=y
-CONFIG_PCI_MSM_MSI=y
 CONFIG_SCHED_MC=y
 CONFIG_NR_CPUS=8
 CONFIG_PREEMPT=y
@@ -442,6 +441,7 @@
 CONFIG_USB_ISP1760_HOST_ROLE=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_LINK_LAYER_TEST=y
+CONFIG_USB_QCOM_DIAG_BRIDGE=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_QCOM_EMU_PHY=y
 CONFIG_USB_MSM_SSPHY_QMP=y
diff --git a/arch/arm64/configs/vendor/sdmsteppe-auto_defconfig b/arch/arm64/configs/vendor/sdmsteppe-auto_defconfig
index f1e8fd5..fc53bac 100644
--- a/arch/arm64/configs/vendor/sdmsteppe-auto_defconfig
+++ b/arch/arm64/configs/vendor/sdmsteppe-auto_defconfig
@@ -62,7 +62,6 @@
 CONFIG_ARCH_SDMMAGPIE=y
 CONFIG_PCI=y
 CONFIG_PCI_MSM=y
-CONFIG_PCI_MSM_MSI=y
 CONFIG_SCHED_MC=y
 CONFIG_NR_CPUS=8
 CONFIG_PREEMPT=y
@@ -458,6 +457,7 @@
 CONFIG_USB_ISP1760_HOST_ROLE=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_LINK_LAYER_TEST=y
+CONFIG_USB_QCOM_DIAG_BRIDGE=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_QCOM_EMU_PHY=y
 CONFIG_USB_MSM_SSPHY_QMP=y
@@ -530,6 +530,7 @@
 CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_USB_BAM=y
 CONFIG_IPA3=y
+CONFIG_IPA_DEBUG=y
 CONFIG_IPA_WDI_UNIFIED_API=y
 CONFIG_RMNET_IPA3=y
 CONFIG_RNDIS_IPA=y
diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig
index 71a1095..8374520 100644
--- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig
+++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig
@@ -105,6 +105,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
 CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
@@ -291,6 +292,7 @@
 CONFIG_PPP_MPPE=y
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=y
+CONFIG_PPTP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPPOLAC=y
 CONFIG_PPPOPNS=y
diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig
index 70afcb5..5985c0a 100644
--- a/arch/arm64/configs/vendor/sdmsteppe_defconfig
+++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig
@@ -111,6 +111,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
 CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
@@ -300,6 +301,7 @@
 CONFIG_PPP_MPPE=y
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=y
+CONFIG_PPTP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPPOLAC=y
 CONFIG_PPPOPNS=y
@@ -537,6 +539,7 @@
 CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_USB_BAM=y
 CONFIG_IPA3=y
+CONFIG_IPA_DEBUG=y
 CONFIG_IPA_WDI_UNIFIED_API=y
 CONFIG_RMNET_IPA3=y
 CONFIG_RNDIS_IPA=y
diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig
index cc6525a..a81f40f 100644
--- a/arch/arm64/configs/vendor/sm8150-perf_defconfig
+++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig
@@ -113,6 +113,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
 CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
@@ -302,6 +303,7 @@
 CONFIG_PPP_MPPE=y
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=y
+CONFIG_PPTP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPPOLAC=y
 CONFIG_PPPOPNS=y
@@ -359,7 +361,7 @@
 CONFIG_SMB1355_SLAVE_CHARGER=y
 CONFIG_QPNP_SMB5=y
 CONFIG_QPNP_QNOVO5=y
-CONFIG_SMB1390_CHARGE_PUMP=y
+CONFIG_SMB1390_CHARGE_PUMP_PSY=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_WRITABLE_TRIPS=y
 CONFIG_THERMAL_GOV_USER_SPACE=y
diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig
index 17b7c6c..2104ea4 100644
--- a/arch/arm64/configs/vendor/sm8150_defconfig
+++ b/arch/arm64/configs/vendor/sm8150_defconfig
@@ -120,6 +120,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
 CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
@@ -313,6 +314,7 @@
 CONFIG_PPP_MPPE=y
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=y
+CONFIG_PPTP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPPOLAC=y
 CONFIG_PPPOPNS=y
@@ -374,7 +376,7 @@
 CONFIG_SMB1355_SLAVE_CHARGER=y
 CONFIG_QPNP_SMB5=y
 CONFIG_QPNP_QNOVO5=y
-CONFIG_SMB1390_CHARGE_PUMP=y
+CONFIG_SMB1390_CHARGE_PUMP_PSY=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_WRITABLE_TRIPS=y
 CONFIG_THERMAL_GOV_USER_SPACE=y
@@ -530,10 +532,11 @@
 CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_USB_BAM=y
 CONFIG_IPA3=y
+CONFIG_IPA_DEBUG=y
 CONFIG_IPA_WDI_UNIFIED_API=y
 CONFIG_RMNET_IPA3=y
 CONFIG_RNDIS_IPA=y
-CONFIG_IPA3_MHI_PROXY=y
+CONFIG_IPA3_MHI_PRIME_MANAGER=y
 CONFIG_IPA_UT=y
 CONFIG_MSM_11AD=m
 CONFIG_SEEMP_CORE=y
diff --git a/arch/arm64/configs/vendor/trinket-perf_defconfig b/arch/arm64/configs/vendor/trinket-perf_defconfig
index 266282b..c206b77 100644
--- a/arch/arm64/configs/vendor/trinket-perf_defconfig
+++ b/arch/arm64/configs/vendor/trinket-perf_defconfig
@@ -1,3 +1,4 @@
+CONFIG_HOTPLUG_SIZE_BITS=29
 CONFIG_LOCALVERSION="-perf"
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_FHANDLE is not set
@@ -63,6 +64,10 @@
 CONFIG_NR_CPUS=8
 CONFIG_PREEMPT=y
 CONFIG_HZ_100=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y
+CONFIG_MEMORY_HOTPLUG_MOVABLE_NODE=y
+CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_CMA=y
 CONFIG_ZSMALLOC=y
 CONFIG_BALANCE_ANON_FILE_RECLAIM=y
@@ -105,6 +110,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
 CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
@@ -250,6 +256,7 @@
 CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
 CONFIG_DMA_CMA=y
 CONFIG_ZRAM=y
+CONFIG_ZRAM_DEDUP=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
@@ -258,6 +265,7 @@
 CONFIG_UID_SYS_STATS=y
 CONFIG_MEMORY_STATE_TIME=y
 CONFIG_QPNP_MISC=y
+CONFIG_FPR_FPC=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
@@ -287,6 +295,7 @@
 CONFIG_PPP_MPPE=y
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=y
+CONFIG_PPTP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPPOLAC=y
 CONFIG_PPPOPNS=y
@@ -296,6 +305,7 @@
 CONFIG_WIL6210=m
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_GENL=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
@@ -324,8 +334,10 @@
 CONFIG_SERIAL_MSM_GENI=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM_LEGACY=y
+# CONFIG_DEVPORT is not set
 CONFIG_DIAG_CHAR=y
 CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QCOM_GENI=y
 CONFIG_SPI=y
@@ -361,7 +373,6 @@
 CONFIG_QTI_BCL_SOC_DRIVER=y
 CONFIG_QTI_ADC_TM=y
 CONFIG_QTI_CX_IPEAK_COOLING_DEVICE=y
-CONFIG_QTI_RPM_SMD_COOLING_DEVICE=y
 CONFIG_MFD_I2C_PMIC=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -373,6 +384,7 @@
 CONFIG_REGULATOR_STUB=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_VIDEO_ADV_DEBUG=y
@@ -411,6 +423,9 @@
 CONFIG_MSM_VIDC_GOVERNORS=y
 CONFIG_MSM_SDE_ROTATOR=y
 CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
+CONFIG_DVB_MPQ_SW=y
 CONFIG_DRM=y
 CONFIG_DRM_MSM_REGISTER_LOGGING=y
 CONFIG_DRM_SDE_EVTLOG_DEBUG=y
@@ -538,6 +553,8 @@
 CONFIG_RPMSG_QCOM_GLINK_SMEM=y
 CONFIG_RPMSG_QCOM_GLINK_SPI=y
 CONFIG_MSM_RPM_SMD=y
+CONFIG_QCOM_MEM_OFFLINE=y
+CONFIG_OVERRIDE_MEMORY_LIMIT=y
 CONFIG_QCOM_CPUSS_DUMP=y
 CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_QCOM_QMI_HELPERS=y
@@ -583,6 +600,7 @@
 CONFIG_QMP_DEBUGFS_CLIENT=y
 CONFIG_QCOM_SMP2P_SLEEPSTATE=y
 CONFIG_QCOM_CDSP_RM=y
+CONFIG_QCOM_CX_IPEAK=y
 CONFIG_DEVFREQ_GOV_PASSIVE=y
 CONFIG_QCOM_BIMC_BWMON=y
 CONFIG_ARM_MEMLAT_MON=y
@@ -604,6 +622,7 @@
 CONFIG_RAS=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_QCOM_QFPROM=y
 CONFIG_NVMEM_SPMI_SDAM=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
diff --git a/arch/arm64/configs/vendor/trinket_defconfig b/arch/arm64/configs/vendor/trinket_defconfig
index b1855d5..4edd93b 100644
--- a/arch/arm64/configs/vendor/trinket_defconfig
+++ b/arch/arm64/configs/vendor/trinket_defconfig
@@ -1,3 +1,4 @@
+CONFIG_HOTPLUG_SIZE_BITS=29
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_FHANDLE is not set
 CONFIG_AUDIT=y
@@ -66,6 +67,10 @@
 CONFIG_NR_CPUS=8
 CONFIG_PREEMPT=y
 CONFIG_HZ_100=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y
+CONFIG_MEMORY_HOTPLUG_MOVABLE_NODE=y
+CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_CLEANCACHE=y
 CONFIG_CMA=y
 CONFIG_CMA_DEBUGFS=y
@@ -112,6 +117,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
 CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
@@ -259,6 +265,7 @@
 CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
 CONFIG_DMA_CMA=y
 CONFIG_ZRAM=y
+CONFIG_ZRAM_DEDUP=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
@@ -267,6 +274,7 @@
 CONFIG_UID_SYS_STATS=y
 CONFIG_MEMORY_STATE_TIME=y
 CONFIG_QPNP_MISC=y
+CONFIG_FPR_FPC=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
@@ -298,6 +306,7 @@
 CONFIG_PPP_MPPE=y
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=y
+CONFIG_PPTP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPPOLAC=y
 CONFIG_PPPOPNS=y
@@ -307,6 +316,7 @@
 CONFIG_WIL6210=m
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_GENL=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
@@ -339,8 +349,10 @@
 CONFIG_TTY_PRINTK=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM_LEGACY=y
+# CONFIG_DEVPORT is not set
 CONFIG_DIAG_CHAR=y
 CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QCOM_GENI=y
 CONFIG_SPI=y
@@ -376,7 +388,6 @@
 CONFIG_QTI_BCL_SOC_DRIVER=y
 CONFIG_QTI_ADC_TM=y
 CONFIG_QTI_CX_IPEAK_COOLING_DEVICE=y
-CONFIG_QTI_RPM_SMD_COOLING_DEVICE=y
 CONFIG_MFD_I2C_PMIC=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -388,6 +399,7 @@
 CONFIG_REGULATOR_STUB=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_VIDEO_ADV_DEBUG=y
@@ -426,6 +438,9 @@
 CONFIG_MSM_VIDC_GOVERNORS=y
 CONFIG_MSM_SDE_ROTATOR=y
 CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
+CONFIG_DVB_MPQ_SW=y
 CONFIG_DRM=y
 CONFIG_DRM_MSM_REGISTER_LOGGING=y
 CONFIG_DRM_SDE_EVTLOG_DEBUG=y
@@ -530,6 +545,7 @@
 CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_USB_BAM=y
 CONFIG_IPA3=y
+CONFIG_IPA_DEBUG=y
 CONFIG_IPA_WDI_UNIFIED_API=y
 CONFIG_RMNET_IPA3=y
 CONFIG_RNDIS_IPA=y
@@ -561,6 +577,8 @@
 CONFIG_RPMSG_QCOM_GLINK_SMEM=y
 CONFIG_RPMSG_QCOM_GLINK_SPI=y
 CONFIG_MSM_RPM_SMD=y
+CONFIG_QCOM_MEM_OFFLINE=y
+CONFIG_OVERRIDE_MEMORY_LIMIT=y
 CONFIG_QCOM_CPUSS_DUMP=y
 CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_QCOM_QMI_HELPERS=y
@@ -612,6 +630,7 @@
 CONFIG_QMP_DEBUGFS_CLIENT=y
 CONFIG_QCOM_SMP2P_SLEEPSTATE=y
 CONFIG_QCOM_CDSP_RM=y
+CONFIG_QCOM_CX_IPEAK=y
 CONFIG_DEVFREQ_GOV_PASSIVE=y
 CONFIG_QCOM_BIMC_BWMON=y
 CONFIG_ARM_MEMLAT_MON=y
@@ -634,6 +653,7 @@
 CONFIG_RAS=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_QCOM_QFPROM=y
 CONFIG_NVMEM_SPMI_SDAM=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
@@ -716,6 +736,7 @@
 CONFIG_TEST_USER_COPY=m
 CONFIG_MEMTEST=y
 CONFIG_BUG_ON_DATA_CORRUPTION=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
 CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_ARM64_STRICT_BREAK_BEFORE_MAKE=y
 CONFIG_CORESIGHT=y
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index fe2a97a..317e974 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -385,27 +385,33 @@ alternative_endif
  * 	size:		size of the region
  * 	Corrupts:	kaddr, size, tmp1, tmp2
  */
+	.macro __dcache_op_workaround_clean_cache, op, kaddr
+alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE
+	dc	\op, \kaddr
+alternative_else
+	dc	civac, \kaddr
+alternative_endif
+	.endm
+
 	.macro dcache_by_line_op op, domain, kaddr, size, tmp1, tmp2
 	dcache_line_size \tmp1, \tmp2
 	add	\size, \kaddr, \size
 	sub	\tmp2, \tmp1, #1
 	bic	\kaddr, \kaddr, \tmp2
 9998:
-	.if	(\op == cvau || \op == cvac)
-alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE
-	dc	\op, \kaddr
-alternative_else
-	dc	civac, \kaddr
-alternative_endif
-	.elseif	(\op == cvap)
-alternative_if ARM64_HAS_DCPOP
-	sys 3, c7, c12, 1, \kaddr	// dc cvap
-alternative_else
-	dc	cvac, \kaddr
-alternative_endif
+	.ifc	\op, cvau
+	__dcache_op_workaround_clean_cache \op, \kaddr
+	.else
+	.ifc	\op, cvac
+	__dcache_op_workaround_clean_cache \op, \kaddr
+	.else
+	.ifc	\op, cvap
+	sys	3, c7, c12, 1, \kaddr	// dc cvap
 	.else
 	dc	\op, \kaddr
 	.endif
+	.endif
+	.endif
 	add	\kaddr, \kaddr, \tmp1
 	cmp	\kaddr, \size
 	b.lo	9998b
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index d87b9eb..e2675f9d 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -138,7 +138,23 @@ static inline u64 __raw_readq_no_log(const volatile void __iomem *addr)
 #define __raw_readq(a)		__raw_read_logged((a), q, u64)
 
 /* IO barriers */
-#define __iormb()		rmb()
+#define __iormb(v)							\
+({									\
+	unsigned long tmp;						\
+									\
+	rmb();								\
+									\
+	/*								\
+	 * Create a dummy control dependency from the IO read to any	\
+	 * later instructions. This ensures that a subsequent call to	\
+	 * udelay() will be ordered due to the ISB in get_cycles().	\
+	 */								\
+	asm volatile("eor	%0, %1, %1\n"				\
+		     "cbnz	%0, ."					\
+		     : "=r" (tmp) : "r" ((unsigned long)(v))		\
+		     : "memory");					\
+})
+
 #define __iowmb()		wmb()
 
 #define mmiowb()		do { } while (0)
@@ -179,10 +195,10 @@ static inline u64 __raw_readq_no_log(const volatile void __iomem *addr)
  * following Normal memory access. Writes are ordered relative to any prior
  * Normal memory access.
  */
-#define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(); __v; })
-#define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })
-#define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(); __v; })
-#define readq(c)		({ u64 __v = readq_relaxed(c); __iormb(); __v; })
+#define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(__v); __v; })
+#define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(__v); __v; })
+#define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(__v); __v; })
+#define readq(c)		({ u64 __v = readq_relaxed(c); __iormb(__v); __v; })
 
 #define writeb(v,c)		({ __iowmb(); writeb_relaxed((v),(c)); })
 #define writew(v,c)		({ __iowmb(); writew_relaxed((v),(c)); })
@@ -190,13 +206,13 @@ static inline u64 __raw_readq_no_log(const volatile void __iomem *addr)
 #define writeq(v,c)		({ __iowmb(); writeq_relaxed((v),(c)); })
 
 #define readb_no_log(c) \
-		({ u8  __v = readb_relaxed_no_log(c); __iormb(); __v; })
+		({ u8  __v = readb_relaxed_no_log(c); __iormb(__v); __v; })
 #define readw_no_log(c) \
-		({ u16 __v = readw_relaxed_no_log(c); __iormb(); __v; })
+		({ u16 __v = readw_relaxed_no_log(c); __iormb(__v); __v; })
 #define readl_no_log(c) \
-		({ u32 __v = readl_relaxed_no_log(c); __iormb(); __v; })
+		({ u32 __v = readl_relaxed_no_log(c); __iormb(__v); __v; })
 #define readq_no_log(c) \
-		({ u64 __v = readq_relaxed_no_log(c); __iormb(); __v; })
+		({ u64 __v = readq_relaxed_no_log(c); __iormb(__v); __v; })
 
 #define writeb_no_log(v, c) \
 		({ __iowmb(); writeb_relaxed_no_log((v), (c)); })
@@ -251,9 +267,9 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 /*
  * io{read,write}{16,32,64}be() macros
  */
-#define ioread16be(p)		({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
-#define ioread32be(p)		({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
-#define ioread64be(p)		({ __u64 __v = be64_to_cpu((__force __be64)__raw_readq(p)); __iormb(); __v; })
+#define ioread16be(p)		({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(__v); __v; })
+#define ioread32be(p)		({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(__v); __v; })
+#define ioread64be(p)		({ __u64 __v = be64_to_cpu((__force __be64)__raw_readq(p)); __iormb(__v); __v; })
 
 #define iowrite16be(v,p)	({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); })
 #define iowrite32be(v,p)	({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); })
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 73cc430..1d6d980 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -23,6 +23,8 @@
 #include <asm/types.h>
 
 /* Hyp Configuration Register (HCR) bits */
+#define HCR_API		(UL(1) << 41)
+#define HCR_APK		(UL(1) << 40)
 #define HCR_E2H		(UL(1) << 34)
 #define HCR_ID		(UL(1) << 33)
 #define HCR_CD		(UL(1) << 32)
@@ -82,6 +84,7 @@
 			 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
 #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
 #define HCR_INT_OVERRIDE   (HCR_FMO | HCR_IMO)
+#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK)
 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
 
 /* TCR_EL2 Registers bits */
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index 38aad4f..b16b5e0 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -46,7 +46,6 @@ static inline void contextidr_thread_switch(struct task_struct *next)
 	write_sysreg(pid, contextidr_el1);
 	isb();
 
-	uncached_logk(LOGK_CTXID, (void *)(u64)pid);
 
 }
 
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index a0c6e5b..7617215 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -514,7 +514,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.matches = is_kryo_midr,
 	},
 #endif
-#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
+#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
 	{
 		.desc = "Qualcomm Technologies Falkor erratum 1009",
 		.capability = ARM64_WORKAROUND_REPEAT_TLBI,
@@ -522,6 +522,8 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 			   MIDR_CPU_VAR_REV(0, 0),
 			   MIDR_CPU_VAR_REV(0, 0)),
 	},
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_1286807
 	{
 	/* Cortex-A76 r0p0 to r3p0 */
 		.desc = "ARM erratum 1286807",
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index e1be42e..5a10e3a 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -79,7 +79,6 @@
 	.macro mcount_get_lr reg
 	ldr	\reg, [x29]
 	ldr	\reg, [\reg, #8]
-	mcount_adjust_addr	\reg, \reg
 	.endm
 
 	.macro mcount_get_lr_addr reg
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 261f3f8..ec39327 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -414,10 +414,9 @@
 #endif
 
 	/* Hyp configuration. */
-	mov	x0, #HCR_RW			// 64-bit EL1
+	mov_q	x0, HCR_HOST_NVHE_FLAGS
 	cbz	x2, set_hcr
-	orr	x0, x0, #HCR_TGE		// Enable Host Extensions
-	orr	x0, x0, #HCR_E2H
+	mov_q	x0, HCR_HOST_VHE_FLAGS
 set_hcr:
 	msr	hcr_el2, x0
 	isb
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index a028cc9..bb444c6 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -299,8 +299,10 @@ int swsusp_arch_suspend(void)
 		dcache_clean_range(__idmap_text_start, __idmap_text_end);
 
 		/* Clean kvm setup code to PoC? */
-		if (el2_reset_needed())
+		if (el2_reset_needed()) {
 			dcache_clean_range(__hyp_idmap_text_start, __hyp_idmap_text_end);
+			dcache_clean_range(__hyp_text_start, __hyp_text_end);
+		}
 
 		/* make the crash dump kernel image protected again */
 		crash_post_resume();
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index e1261fb..17f325b 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -28,6 +28,8 @@
 #include <asm/virt.h>
 
 	.text
+	.pushsection	.hyp.text, "ax"
+
 	.align 11
 
 ENTRY(__hyp_stub_vectors)
diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
index c7fcb23..40f9f0b 100644
--- a/arch/arm64/kernel/image.h
+++ b/arch/arm64/kernel/image.h
@@ -76,16 +76,6 @@
 __efistub_stext_offset = stext - _text;
 
 /*
- * Prevent the symbol aliases below from being emitted into the kallsyms
- * table, by forcing them to be absolute symbols (which are conveniently
- * ignored by scripts/kallsyms) rather than section relative symbols.
- * The distinction is only relevant for partial linking, and only for symbols
- * that are defined within a section declaration (which is not the case for
- * the definitions below) so the resulting values will be identical.
- */
-#define KALLSYMS_HIDE(sym)	ABSOLUTE(sym)
-
-/*
  * The EFI stub has its own symbol namespace prefixed by __efistub_, to
  * isolate it from the kernel proper. The following symbols are legally
  * accessed by the stub, so provide some aliases to make them accessible.
@@ -94,27 +84,27 @@ __efistub_stext_offset = stext - _text;
  * linked at. The routines below are all implemented in assembler in a
  * position independent manner
  */
-__efistub_memcmp		= KALLSYMS_HIDE(__pi_memcmp);
-__efistub_memchr		= KALLSYMS_HIDE(__pi_memchr);
-__efistub_memcpy		= KALLSYMS_HIDE(__pi_memcpy);
-__efistub_memmove		= KALLSYMS_HIDE(__pi_memmove);
-__efistub_memset		= KALLSYMS_HIDE(__pi_memset);
-__efistub_strlen		= KALLSYMS_HIDE(__pi_strlen);
-__efistub_strnlen		= KALLSYMS_HIDE(__pi_strnlen);
-__efistub_strcmp		= KALLSYMS_HIDE(__pi_strcmp);
-__efistub_strncmp		= KALLSYMS_HIDE(__pi_strncmp);
-__efistub___flush_dcache_area	= KALLSYMS_HIDE(__pi___flush_dcache_area);
+__efistub_memcmp		= __pi_memcmp;
+__efistub_memchr		= __pi_memchr;
+__efistub_memcpy		= __pi_memcpy;
+__efistub_memmove		= __pi_memmove;
+__efistub_memset		= __pi_memset;
+__efistub_strlen		= __pi_strlen;
+__efistub_strnlen		= __pi_strnlen;
+__efistub_strcmp		= __pi_strcmp;
+__efistub_strncmp		= __pi_strncmp;
+__efistub___flush_dcache_area	= __pi___flush_dcache_area;
 
 #ifdef CONFIG_KASAN
-__efistub___memcpy		= KALLSYMS_HIDE(__pi_memcpy);
-__efistub___memmove		= KALLSYMS_HIDE(__pi_memmove);
-__efistub___memset		= KALLSYMS_HIDE(__pi_memset);
+__efistub___memcpy		= __pi_memcpy;
+__efistub___memmove		= __pi_memmove;
+__efistub___memset		= __pi_memset;
 #endif
 
-__efistub__text			= KALLSYMS_HIDE(_text);
-__efistub__end			= KALLSYMS_HIDE(_end);
-__efistub__edata		= KALLSYMS_HIDE(_edata);
-__efistub_screen_info		= KALLSYMS_HIDE(screen_info);
+__efistub__text			= _text;
+__efistub__end			= _end;
+__efistub__edata		= _edata;
+__efistub_screen_info		= screen_info;
 
 #endif
 
diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c
index 47080c4..ae72782 100644
--- a/arch/arm64/kernel/kaslr.c
+++ b/arch/arm64/kernel/kaslr.c
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 
+#include <asm/cacheflush.h>
 #include <asm/fixmap.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/memory.h>
@@ -43,7 +44,7 @@ static __init u64 get_kaslr_seed(void *fdt)
 	return ret;
 }
 
-static __init const u8 *get_cmdline(void *fdt)
+static __init const u8 *kaslr_get_cmdline(void *fdt)
 {
 	static __initconst const u8 default_cmdline[] = CONFIG_CMDLINE;
 
@@ -87,6 +88,7 @@ u64 __init kaslr_early_init(u64 dt_phys)
 	 * we end up running with module randomization disabled.
 	 */
 	module_alloc_base = (u64)_etext - MODULES_VSIZE;
+	__flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
 
 	/*
 	 * Try to map the FDT early. If this fails, we simply bail,
@@ -109,7 +111,7 @@ u64 __init kaslr_early_init(u64 dt_phys)
 	 * Check if 'nokaslr' appears on the command line, and
 	 * return 0 if that is the case.
 	 */
-	cmdline = get_cmdline(fdt);
+	cmdline = kaslr_get_cmdline(fdt);
 	str = strstr(cmdline, "nokaslr");
 	if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
 		return 0;
@@ -180,5 +182,8 @@ u64 __init kaslr_early_init(u64 dt_phys)
 	module_alloc_base += (module_range * (seed & ((1 << 21) - 1))) >> 21;
 	module_alloc_base &= PAGE_MASK;
 
+	__flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
+	__flush_dcache_area(&memstart_offset_seed, sizeof(memstart_offset_seed));
+
 	return offset;
 }
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 3e7958f..e0a80e2 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -1302,6 +1302,7 @@ static struct platform_driver armv8_pmu_driver = {
 	.driver		= {
 		.name	= ARMV8_PMU_PDEV_NAME,
 		.of_match_table = armv8_pmu_of_device_ids,
+		.suppress_bind_attrs = true,
 	},
 	.probe		= armv8_pmu_device_probe,
 };
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 8bdfb7a..fc981a8 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -105,7 +105,8 @@
 		*(.discard)
 		*(.discard.*)
 		*(.interp .dynamic)
-		*(.dynsym .dynstr .hash)
+		*(.dynsym .dynstr .hash .gnu.hash)
+		*(.eh_frame)
 	}
 
 	. = KIMAGE_VADDR + TEXT_OFFSET;
@@ -182,12 +183,12 @@
 
 	PERCPU_SECTION(L1_CACHE_BYTES)
 
-	.rela : ALIGN(8) {
+	.rela.dyn : ALIGN(8) {
 		*(.rela .rela*)
 	}
 
-	__rela_offset	= ABSOLUTE(ADDR(.rela) - KIMAGE_VADDR);
-	__rela_size	= SIZEOF(.rela);
+	__rela_offset	= ABSOLUTE(ADDR(.rela.dyn) - KIMAGE_VADDR);
+	__rela_size	= SIZEOF(.rela.dyn);
 
 	. = ALIGN(SEGMENT_ALIGN);
 	__initdata_end = .;
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index b2f1992..4484599 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -127,7 +127,7 @@ static void __hyp_text __deactivate_traps_nvhe(void)
 	mdcr_el2 |= MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT;
 
 	write_sysreg(mdcr_el2, mdcr_el2);
-	write_sysreg(HCR_RW, hcr_el2);
+	write_sysreg(HCR_HOST_NVHE_FLAGS, hcr_el2);
 	write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
 }
 
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index ee57688..99defce 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -254,6 +254,9 @@
  *	- size    - size in question
  */
 ENTRY(__clean_dcache_area_pop)
+	alternative_if_not ARM64_HAS_DCPOP
+	b	__clean_dcache_area_poc
+	alternative_else_nop_endif
 	dcache_by_line_op cvap, sy, x0, x1, x2, x3
 	ret
 ENDPIPROC(__clean_dcache_area_pop)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 23e3d3e..8d4470f 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -800,6 +800,7 @@
 	select SYS_SUPPORTS_HIGHMEM
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select ZONE_DMA32 if 64BIT
+	select SWIOTLB if ARCH_DMA_ADDR_T_64BIT && PCI
 
 config SIBYTE_LITTLESUR
 	bool "Sibyte BCM91250C2-LittleSur"
@@ -822,6 +823,7 @@
 	select SYS_HAS_CPU_SB1
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SWIOTLB if ARCH_DMA_ADDR_T_64BIT && PCI
 
 config SIBYTE_BIGSUR
 	bool "Sibyte BCM91480B-BigSur"
@@ -835,6 +837,7 @@
 	select SYS_SUPPORTS_HIGHMEM
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select ZONE_DMA32 if 64BIT
+	select SWIOTLB if ARCH_DMA_ADDR_T_64BIT && PCI
 
 config SNI_RM
 	bool "SNI RM200/300/400"
@@ -3153,6 +3156,7 @@
 config MIPS32_N32
 	bool "Kernel support for n32 binaries"
 	depends on 64BIT
+	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
 	select COMPAT
 	select MIPS32_COMPAT
 	select SYSVIPC_COMPAT if SYSVIPC
diff --git a/arch/mips/boot/dts/img/boston.dts b/arch/mips/boot/dts/img/boston.dts
index f7aad80..bebb0fa 100644
--- a/arch/mips/boot/dts/img/boston.dts
+++ b/arch/mips/boot/dts/img/boston.dts
@@ -141,6 +141,12 @@
 				#size-cells = <2>;
 				#interrupt-cells = <1>;
 
+				eg20t_phub@2,0,0 {
+					compatible = "pci8086,8801";
+					reg = <0x00020000 0 0 0 0>;
+					intel,eg20t-prefetch = <0>;
+				};
+
 				eg20t_mac@2,0,1 {
 					compatible = "pci8086,8802";
 					reg = <0x00020100 0 0 0 0>;
diff --git a/arch/mips/configs/ath79_defconfig b/arch/mips/configs/ath79_defconfig
index 25ed914..8a22978 100644
--- a/arch/mips/configs/ath79_defconfig
+++ b/arch/mips/configs/ath79_defconfig
@@ -72,6 +72,7 @@
 # CONFIG_SERIAL_8250_PCI is not set
 CONFIG_SERIAL_8250_NR_UARTS=1
 CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_AR933X=y
 CONFIG_SERIAL_AR933X_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index c05dcf5..273ef58 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -369,8 +369,8 @@ enum mm_32a_minor_op {
 	mm_ext_op = 0x02c,
 	mm_pool32axf_op = 0x03c,
 	mm_srl32_op = 0x040,
+	mm_srlv32_op = 0x050,
 	mm_sra_op = 0x080,
-	mm_srlv32_op = 0x090,
 	mm_rotr_op = 0x0c0,
 	mm_lwxs_op = 0x118,
 	mm_addu32_op = 0x150,
diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c
index d626a9a..e3c3d94 100644
--- a/arch/mips/jazz/jazzdma.c
+++ b/arch/mips/jazz/jazzdma.c
@@ -72,14 +72,15 @@ static int __init vdma_init(void)
 						    get_order(VDMA_PGTBL_SIZE));
 	BUG_ON(!pgtbl);
 	dma_cache_wback_inv((unsigned long)pgtbl, VDMA_PGTBL_SIZE);
-	pgtbl = (VDMA_PGTBL_ENTRY *)KSEG1ADDR(pgtbl);
+	pgtbl = (VDMA_PGTBL_ENTRY *)CKSEG1ADDR((unsigned long)pgtbl);
 
 	/*
 	 * Clear the R4030 translation table
 	 */
 	vdma_pgtbl_init();
 
-	r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE, CPHYSADDR(pgtbl));
+	r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,
+			  CPHYSADDR((unsigned long)pgtbl));
 	r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM, VDMA_PGTBL_SIZE);
 	r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
 
diff --git a/arch/mips/kernel/cmpxchg.c b/arch/mips/kernel/cmpxchg.c
index 0b9535b..6b2a4a9 100644
--- a/arch/mips/kernel/cmpxchg.c
+++ b/arch/mips/kernel/cmpxchg.c
@@ -54,10 +54,9 @@ unsigned long __xchg_small(volatile void *ptr, unsigned long val, unsigned int s
 unsigned long __cmpxchg_small(volatile void *ptr, unsigned long old,
 			      unsigned long new, unsigned int size)
 {
-	u32 mask, old32, new32, load32;
+	u32 mask, old32, new32, load32, load;
 	volatile u32 *ptr32;
 	unsigned int shift;
-	u8 load;
 
 	/* Check that ptr is naturally aligned */
 	WARN_ON((unsigned long)ptr & (size - 1));
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 8f5bd04..7f3f136 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -457,5 +457,5 @@ void mips_cm_error_report(void)
 	}
 
 	/* reprime cause register */
-	write_gcr_error_cause(0);
+	write_gcr_error_cause(cm_error);
 }
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index f0bc331..c4ef1c3 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -224,9 +224,11 @@ static struct irq_chip ltq_eiu_type = {
 	.irq_set_type = ltq_eiu_settype,
 };
 
-static void ltq_hw_irqdispatch(int module)
+static void ltq_hw_irq_handler(struct irq_desc *desc)
 {
+	int module = irq_desc_get_irq(desc) - 2;
 	u32 irq;
+	int hwirq;
 
 	irq = ltq_icu_r32(module, LTQ_ICU_IM0_IOSR);
 	if (irq == 0)
@@ -237,7 +239,8 @@ static void ltq_hw_irqdispatch(int module)
 	 * other bits might be bogus
 	 */
 	irq = __fls(irq);
-	do_IRQ((int)irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module));
+	hwirq = irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module);
+	generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq));
 
 	/* if this is a EBU irq, we need to ack it or get a deadlock */
 	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
@@ -245,49 +248,6 @@ static void ltq_hw_irqdispatch(int module)
 			LTQ_EBU_PCC_ISTAT);
 }
 
-#define DEFINE_HWx_IRQDISPATCH(x)					\
-	static void ltq_hw ## x ## _irqdispatch(void)			\
-	{								\
-		ltq_hw_irqdispatch(x);					\
-	}
-DEFINE_HWx_IRQDISPATCH(0)
-DEFINE_HWx_IRQDISPATCH(1)
-DEFINE_HWx_IRQDISPATCH(2)
-DEFINE_HWx_IRQDISPATCH(3)
-DEFINE_HWx_IRQDISPATCH(4)
-
-#if MIPS_CPU_TIMER_IRQ == 7
-static void ltq_hw5_irqdispatch(void)
-{
-	do_IRQ(MIPS_CPU_TIMER_IRQ);
-}
-#else
-DEFINE_HWx_IRQDISPATCH(5)
-#endif
-
-static void ltq_hw_irq_handler(struct irq_desc *desc)
-{
-	ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2);
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-	int irq;
-
-	if (!pending) {
-		spurious_interrupt();
-		return;
-	}
-
-	pending >>= CAUSEB_IP;
-	while (pending) {
-		irq = fls(pending) - 1;
-		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
-		pending &= ~BIT(irq);
-	}
-}
-
 static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
 {
 	struct irq_chip *chip = &ltq_irq_type;
@@ -343,28 +303,10 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
 	for (i = 0; i < MAX_IM; i++)
 		irq_set_chained_handler(i + 2, ltq_hw_irq_handler);
 
-	if (cpu_has_vint) {
-		pr_info("Setting up vectored interrupts\n");
-		set_vi_handler(2, ltq_hw0_irqdispatch);
-		set_vi_handler(3, ltq_hw1_irqdispatch);
-		set_vi_handler(4, ltq_hw2_irqdispatch);
-		set_vi_handler(5, ltq_hw3_irqdispatch);
-		set_vi_handler(6, ltq_hw4_irqdispatch);
-		set_vi_handler(7, ltq_hw5_irqdispatch);
-	}
-
 	ltq_domain = irq_domain_add_linear(node,
 		(MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE,
 		&irq_domain_ops, 0);
 
-#ifndef CONFIG_MIPS_MT_SMP
-	set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
-		IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
-#else
-	set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
-		IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
-#endif
-
 	/* tell oprofile which irq to use */
 	ltq_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
 
diff --git a/arch/mips/net/ebpf_jit.c b/arch/mips/net/ebpf_jit.c
index 962b025..8004bfc 100644
--- a/arch/mips/net/ebpf_jit.c
+++ b/arch/mips/net/ebpf_jit.c
@@ -348,12 +348,15 @@ static int build_int_epilogue(struct jit_ctx *ctx, int dest_reg)
 	const struct bpf_prog *prog = ctx->skf;
 	int stack_adjust = ctx->stack_size;
 	int store_offset = stack_adjust - 8;
+	enum reg_val_type td;
 	int r0 = MIPS_R_V0;
 
-	if (dest_reg == MIPS_R_RA &&
-	    get_reg_val_type(ctx, prog->len, BPF_REG_0) == REG_32BIT_ZERO_EX)
+	if (dest_reg == MIPS_R_RA) {
 		/* Don't let zero extended value escape. */
-		emit_instr(ctx, sll, r0, r0, 0);
+		td = get_reg_val_type(ctx, prog->len, BPF_REG_0);
+		if (td == REG_64BIT || td == REG_32BIT_ZERO_EX)
+			emit_instr(ctx, sll, r0, r0, 0);
+	}
 
 	if (ctx->flags & EBPF_SAVE_RA) {
 		emit_instr(ctx, ld, MIPS_R_RA, store_offset, MIPS_R_SP);
@@ -1968,7 +1971,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
 
 	/* Update the icache */
 	flush_icache_range((unsigned long)ctx.target,
-			   (unsigned long)(ctx.target + ctx.idx * sizeof(u32)));
+			   (unsigned long)&ctx.target[ctx.idx]);
 
 	if (bpf_jit_enable > 1)
 		/* Dump JIT code */
diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c
index 2a5bb84..288b58b 100644
--- a/arch/mips/pci/msi-octeon.c
+++ b/arch/mips/pci/msi-octeon.c
@@ -369,7 +369,9 @@ int __init octeon_msi_initialize(void)
 	int irq;
 	struct irq_chip *msi;
 
-	if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
+	if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_INVALID) {
+		return 0;
+	} else if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
 		msi_rcv_reg[0] = CVMX_PEXP_NPEI_MSI_RCV0;
 		msi_rcv_reg[1] = CVMX_PEXP_NPEI_MSI_RCV1;
 		msi_rcv_reg[2] = CVMX_PEXP_NPEI_MSI_RCV2;
diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c
index 3e92a06..4adb8f1f 100644
--- a/arch/mips/pci/pci-octeon.c
+++ b/arch/mips/pci/pci-octeon.c
@@ -572,6 +572,11 @@ static int __init octeon_pci_setup(void)
 	if (octeon_has_feature(OCTEON_FEATURE_PCIE))
 		return 0;
 
+	if (!octeon_is_pci_host()) {
+		pr_notice("Not in host mode, PCI Controller not initialized\n");
+		return 0;
+	}
+
 	/* Point pcibios_map_irq() to the PCI version of it */
 	octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq;
 
@@ -583,11 +588,6 @@ static int __init octeon_pci_setup(void)
 	else
 		octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG;
 
-	if (!octeon_is_pci_host()) {
-		pr_notice("Not in host mode, PCI Controller not initialized\n");
-		return 0;
-	}
-
 	/* PCI I/O and PCI MEM values */
 	set_io_port_base(OCTEON_PCI_IOSPACE_BASE);
 	ioport_resource.start = 0;
diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
index f26736b..fae36f0 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -39,6 +39,7 @@
 
 	config SOC_MT7620
 		bool "MT7620/8"
+		select CPU_MIPSR2_IRQ_VI
 		select HW_HAS_PCI
 
 	config SOC_MT7621
diff --git a/arch/mips/sibyte/common/Makefile b/arch/mips/sibyte/common/Makefile
index b3d6bf2..3ef3fb65 100644
--- a/arch/mips/sibyte/common/Makefile
+++ b/arch/mips/sibyte/common/Makefile
@@ -1,4 +1,5 @@
 obj-y := cfe.o
+obj-$(CONFIG_SWIOTLB)			+= dma.o
 obj-$(CONFIG_SIBYTE_BUS_WATCHER)	+= bus_watcher.o
 obj-$(CONFIG_SIBYTE_CFE_CONSOLE)	+= cfe_console.o
 obj-$(CONFIG_SIBYTE_TBPROF)		+= sb_tbprof.o
diff --git a/arch/mips/sibyte/common/dma.c b/arch/mips/sibyte/common/dma.c
new file mode 100644
index 0000000..eb47a94
--- /dev/null
+++ b/arch/mips/sibyte/common/dma.c
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *	DMA support for Broadcom SiByte platforms.
+ *
+ *	Copyright (c) 2018  Maciej W. Rozycki
+ */
+
+#include <linux/swiotlb.h>
+#include <asm/bootinfo.h>
+
+void __init plat_swiotlb_setup(void)
+{
+	swiotlb_init(1);
+}
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
index ce196046..d1a6069 100644
--- a/arch/mips/vdso/Makefile
+++ b/arch/mips/vdso/Makefile
@@ -121,7 +121,7 @@
 	$(call cmd,force_checksrc)
 	$(call if_changed_rule,cc_o_c)
 
-$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32
+$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=32
 $(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
 	$(call if_changed_dep,cpp_lds_S)
 
@@ -161,7 +161,7 @@
 	$(call cmd,force_checksrc)
 	$(call if_changed_rule,cc_o_c)
 
-$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32
+$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=n32
 $(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
 	$(call if_changed_dep,cpp_lds_S)
 
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 1a2be6e..eca5b2a 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -312,15 +312,29 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
 long do_syscall_trace_enter(struct pt_regs *regs)
 {
-	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
-	    tracehook_report_syscall_entry(regs)) {
+	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+		int rc = tracehook_report_syscall_entry(regs);
+
 		/*
-		 * Tracing decided this syscall should not happen or the
-		 * debugger stored an invalid system call number. Skip
-		 * the system call and the system call restart handling.
+		 * As tracesys_next does not set %r28 to -ENOSYS
+		 * when %r20 is set to -1, initialize it here.
 		 */
-		regs->gr[20] = -1UL;
-		goto out;
+		regs->gr[28] = -ENOSYS;
+
+		if (rc) {
+			/*
+			 * A nonzero return code from
+			 * tracehook_report_syscall_entry() tells us
+			 * to prevent the syscall execution.  Skip
+			 * the syscall call and the syscall restart handling.
+			 *
+			 * Note that the tracer may also just change
+			 * regs->gr[20] to an invalid syscall number,
+			 * that is handled by tracesys_next.
+			 */
+			regs->gr[20] = -1UL;
+			return -1;
+		}
 	}
 
 	/* Do the secure computing check after ptrace. */
@@ -344,7 +358,6 @@ long do_syscall_trace_enter(struct pt_regs *regs)
 			regs->gr[24] & 0xffffffff,
 			regs->gr[23] & 0xffffffff);
 
-out:
 	/*
 	 * Sign extend the syscall number to 64bit since it may have been
 	 * modified by a compat ptrace call
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 1381693..7452e50 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -236,7 +236,12 @@
 
 # Work around a gcc code-gen bug with -fno-omit-frame-pointer.
 ifeq ($(CONFIG_FUNCTION_TRACER),y)
-KBUILD_CFLAGS		+= -mno-sched-epilog
+# Work around gcc code-gen bugs with -pg / -fno-omit-frame-pointer in gcc <= 4.8
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=44199
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52828
+ifneq ($(cc-name),clang)
+KBUILD_CFLAGS		+= $(call cc-ifversion, -lt, 0409, -mno-sched-epilog)
+endif
 endif
 
 cpu-as-$(CONFIG_4xx)		+= -Wa,-m405
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index b479926..e2a5a93 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -49,6 +49,11 @@
 
 BOOTAFLAGS	:= -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
 
+ifeq ($(cc-name),clang)
+BOOTCFLAGS += $(CLANG_FLAGS)
+BOOTAFLAGS += $(CLANG_FLAGS)
+endif
+
 ifdef CONFIG_DEBUG_INFO
 BOOTCFLAGS	+= -g
 endif
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index 32dfe6d..9b9d174 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -15,7 +15,7 @@
 RELA = 7
 RELACOUNT = 0x6ffffff9
 
-	.text
+	.data
 	/* A procedure descriptor used when booting this as a COFF file.
 	 * When making COFF, this comes first in the link and we're
 	 * linked at 0x500000.
@@ -23,6 +23,8 @@
 	.globl	_zimage_start_opd
 _zimage_start_opd:
 	.long	0x500000, 0, 0, 0
+	.text
+	b	_zimage_start
 
 #ifdef __powerpc64__
 .balign 8
diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
index 334459a..9086324 100644
--- a/arch/powerpc/include/asm/epapr_hcalls.h
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -508,7 +508,7 @@ static unsigned long epapr_hypercall(unsigned long *in,
 
 static inline long epapr_hypercall0_1(unsigned int nr, unsigned long *r2)
 {
-	unsigned long in[8];
+	unsigned long in[8] = {0};
 	unsigned long out[8];
 	unsigned long r;
 
@@ -520,7 +520,7 @@ static inline long epapr_hypercall0_1(unsigned int nr, unsigned long *r2)
 
 static inline long epapr_hypercall0(unsigned int nr)
 {
-	unsigned long in[8];
+	unsigned long in[8] = {0};
 	unsigned long out[8];
 
 	return epapr_hypercall(in, out, nr);
@@ -528,7 +528,7 @@ static inline long epapr_hypercall0(unsigned int nr)
 
 static inline long epapr_hypercall1(unsigned int nr, unsigned long p1)
 {
-	unsigned long in[8];
+	unsigned long in[8] = {0};
 	unsigned long out[8];
 
 	in[0] = p1;
@@ -538,7 +538,7 @@ static inline long epapr_hypercall1(unsigned int nr, unsigned long p1)
 static inline long epapr_hypercall2(unsigned int nr, unsigned long p1,
 				    unsigned long p2)
 {
-	unsigned long in[8];
+	unsigned long in[8] = {0};
 	unsigned long out[8];
 
 	in[0] = p1;
@@ -549,7 +549,7 @@ static inline long epapr_hypercall2(unsigned int nr, unsigned long p1,
 static inline long epapr_hypercall3(unsigned int nr, unsigned long p1,
 				    unsigned long p2, unsigned long p3)
 {
-	unsigned long in[8];
+	unsigned long in[8] = {0};
 	unsigned long out[8];
 
 	in[0] = p1;
@@ -562,7 +562,7 @@ static inline long epapr_hypercall4(unsigned int nr, unsigned long p1,
 				    unsigned long p2, unsigned long p3,
 				    unsigned long p4)
 {
-	unsigned long in[8];
+	unsigned long in[8] = {0};
 	unsigned long out[8];
 
 	in[0] = p1;
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h
index 1e7a335..15bc07a 100644
--- a/arch/powerpc/include/asm/fadump.h
+++ b/arch/powerpc/include/asm/fadump.h
@@ -200,7 +200,7 @@ struct fad_crash_memory_ranges {
 	unsigned long long	size;
 };
 
-extern int is_fadump_boot_memory_area(u64 addr, ulong size);
+extern int is_fadump_memory_area(u64 addr, ulong size);
 extern int early_init_dt_scan_fw_dump(unsigned long node,
 		const char *uname, int depth, void *data);
 extern int fadump_reserve_mem(void);
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index 565cead..cf26e62 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -54,7 +54,7 @@
 #endif
 
 #define access_ok(type, addr, size)		\
-	(__chk_user_ptr(addr),			\
+	(__chk_user_ptr(addr), (void)(type),		\
 	 __access_ok((__force unsigned long)(addr), (size), get_fs()))
 
 /*
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 1479c61..a1089c9 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -5,6 +5,9 @@
 
 CFLAGS_ptrace.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
+# Disable clang warning for using setjmp without setjmp.h header
+CFLAGS_crash.o		+= $(call cc-disable-warning, builtin-requires-header)
+
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
 ifeq ($(CONFIG_PPC64),y)
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 5a64703..62d7ef6 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -117,13 +117,19 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
 
 /*
  * If fadump is registered, check if the memory provided
- * falls within boot memory area.
+ * falls within boot memory area and reserved memory area.
  */
-int is_fadump_boot_memory_area(u64 addr, ulong size)
+int is_fadump_memory_area(u64 addr, ulong size)
 {
+	u64 d_start = fw_dump.reserve_dump_area_start;
+	u64 d_end = d_start + fw_dump.reserve_dump_area_size;
+
 	if (!fw_dump.dump_registered)
 		return 0;
 
+	if (((addr + size) > d_start) && (addr <= d_end))
+		return 1;
+
 	return (addr + size) > RMA_START && addr <= fw_dump.boot_memory_size;
 }
 
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 92fb1c8..636ea85 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -866,7 +866,23 @@ static long restore_tm_user_regs(struct pt_regs *regs,
 	/* If TM bits are set to the reserved value, it's an invalid context */
 	if (MSR_TM_RESV(msr_hi))
 		return 1;
-	/* Pull in the MSR TM bits from the user context */
+
+	/*
+	 * Disabling preemption, since it is unsafe to be preempted
+	 * with MSR[TS] set without recheckpointing.
+	 */
+	preempt_disable();
+
+	/*
+	 * CAUTION:
+	 * After regs->MSR[TS] being updated, make sure that get_user(),
+	 * put_user() or similar functions are *not* called. These
+	 * functions can generate page faults which will cause the process
+	 * to be de-scheduled with MSR[TS] set but without calling
+	 * tm_recheckpoint(). This can cause a bug.
+	 *
+	 * Pull in the MSR TM bits from the user context
+	 */
 	regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr_hi & MSR_TS_MASK);
 	/* Now, recheckpoint.  This loads up all of the checkpointed (older)
 	 * registers, including FP and V[S]Rs.  After recheckpointing, the
@@ -891,6 +907,8 @@ static long restore_tm_user_regs(struct pt_regs *regs,
 	}
 #endif
 
+	preempt_enable();
+
 	return 0;
 }
 #endif
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index b2c0029..979b946 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -452,20 +452,6 @@ static long restore_tm_sigcontexts(struct task_struct *tsk,
 	if (MSR_TM_RESV(msr))
 		return -EINVAL;
 
-	/* pull in MSR TS bits from user context */
-	regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK);
-
-	/*
-	 * Ensure that TM is enabled in regs->msr before we leave the signal
-	 * handler. It could be the case that (a) user disabled the TM bit
-	 * through the manipulation of the MSR bits in uc_mcontext or (b) the
-	 * TM bit was disabled because a sufficient number of context switches
-	 * happened whilst in the signal handler and load_tm overflowed,
-	 * disabling the TM bit. In either case we can end up with an illegal
-	 * TM state leading to a TM Bad Thing when we return to userspace.
-	 */
-	regs->msr |= MSR_TM;
-
 	/* pull in MSR LE from user context */
 	regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
 
@@ -557,6 +543,34 @@ static long restore_tm_sigcontexts(struct task_struct *tsk,
 	tm_enable();
 	/* Make sure the transaction is marked as failed */
 	tsk->thread.tm_texasr |= TEXASR_FS;
+
+	/*
+	 * Disabling preemption, since it is unsafe to be preempted
+	 * with MSR[TS] set without recheckpointing.
+	 */
+	preempt_disable();
+
+	/* pull in MSR TS bits from user context */
+	regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK);
+
+	/*
+	 * Ensure that TM is enabled in regs->msr before we leave the signal
+	 * handler. It could be the case that (a) user disabled the TM bit
+	 * through the manipulation of the MSR bits in uc_mcontext or (b) the
+	 * TM bit was disabled because a sufficient number of context switches
+	 * happened whilst in the signal handler and load_tm overflowed,
+	 * disabling the TM bit. In either case we can end up with an illegal
+	 * TM state leading to a TM Bad Thing when we return to userspace.
+	 *
+	 * CAUTION:
+	 * After regs->MSR[TS] being updated, make sure that get_user(),
+	 * put_user() or similar functions are *not* called. These
+	 * functions can generate page faults which will cause the process
+	 * to be de-scheduled with MSR[TS] set but without calling
+	 * tm_recheckpoint(). This can cause a bug.
+	 */
+	regs->msr |= MSR_TM;
+
 	/* This loads the checkpointed FP/VEC state, if used */
 	tm_recheckpoint(&tsk->thread, msr);
 
@@ -570,6 +584,8 @@ static long restore_tm_sigcontexts(struct task_struct *tsk,
 		regs->msr |= MSR_VEC;
 	}
 
+	preempt_enable();
+
 	return err;
 }
 #endif
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index ecb4536..a35995a 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -540,8 +540,11 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 #ifdef CONFIG_PPC_BOOK3S_64
 	case KVM_CAP_SPAPR_TCE:
 	case KVM_CAP_SPAPR_TCE_64:
-		/* fallthrough */
+		r = 1;
+		break;
 	case KVM_CAP_SPAPR_TCE_VFIO:
+		r = !!cpu_has_feature(CPU_FTR_HVMODE);
+		break;
 	case KVM_CAP_PPC_RTAS:
 	case KVM_CAP_PPC_FIXUP_HCALL:
 	case KVM_CAP_PPC_ENABLE_HCALL:
diff --git a/arch/powerpc/mm/dump_linuxpagetables.c b/arch/powerpc/mm/dump_linuxpagetables.c
index 31c1c61..0bbaf73 100644
--- a/arch/powerpc/mm/dump_linuxpagetables.c
+++ b/arch/powerpc/mm/dump_linuxpagetables.c
@@ -19,6 +19,7 @@
 #include <linux/hugetlb.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/highmem.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <asm/fixmap.h>
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 6e1e390..52863de 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -215,7 +215,9 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault)
 static bool bad_kernel_fault(bool is_exec, unsigned long error_code,
 			     unsigned long address)
 {
-	if (is_exec && (error_code & (DSISR_NOEXEC_OR_G | DSISR_KEYFAULT))) {
+	/* NX faults set DSISR_PROTFAULT on the 8xx, DSISR_NOEXEC_OR_G on others */
+	if (is_exec && (error_code & (DSISR_NOEXEC_OR_G | DSISR_KEYFAULT |
+				      DSISR_PROTFAULT))) {
 		printk_ratelimited(KERN_CRIT "kernel tried to execute"
 				   " exec-protected page (%lx) -"
 				   "exploit attempt? (uid: %d)\n",
diff --git a/arch/powerpc/perf/isa207-common.c b/arch/powerpc/perf/isa207-common.c
index 2efee3f..cf9c35a 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -228,8 +228,13 @@ void isa207_get_mem_weight(u64 *weight)
 	u64 mmcra = mfspr(SPRN_MMCRA);
 	u64 exp = MMCRA_THR_CTR_EXP(mmcra);
 	u64 mantissa = MMCRA_THR_CTR_MANT(mmcra);
+	u64 sier = mfspr(SPRN_SIER);
+	u64 val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
 
-	*weight = mantissa << (2 * exp);
+	if (val == 0 || val == 7)
+		*weight = 0;
+	else
+		*weight = mantissa << (2 * exp);
 }
 
 int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index e9149d0..f4e6565 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -284,6 +284,8 @@ int dlpar_detach_node(struct device_node *dn)
 	if (rc)
 		return rc;
 
+	of_node_put(dn);
+
 	return 0;
 }
 
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 1d48ab4..93e09f1 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -441,8 +441,11 @@ static bool lmb_is_removable(struct of_drconf_cell *lmb)
 	phys_addr = lmb->base_addr;
 
 #ifdef CONFIG_FA_DUMP
-	/* Don't hot-remove memory that falls in fadump boot memory area */
-	if (is_fadump_boot_memory_area(phys_addr, block_sz))
+	/*
+	 * Don't hot-remove memory that falls in fadump boot memory area
+	 * and memory that is reserved for capturing old kernel memory.
+	 */
+	if (is_fadump_memory_area(phys_addr, block_sz))
 		return false;
 #endif
 
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index 1bc3abb..549e99e 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -1,7 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for xmon
 
-subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+# Disable clang warning for using setjmp without setjmp.h header
+subdir-ccflags-y := $(call cc-disable-warning, builtin-requires-header)
+
+subdir-ccflags-$(CONFIG_PPC_WERROR) += -Werror
 
 GCOV_PROFILE := n
 UBSAN_SANITIZE := n
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index a5938fa..f752f77 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -78,6 +78,9 @@ static int xmon_gate;
 #define xmon_owner 0
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_PPC_PSERIES
+static int set_indicator_token = RTAS_UNKNOWN_SERVICE;
+#endif
 static unsigned long in_xmon __read_mostly = 0;
 static int xmon_on = IS_ENABLED(CONFIG_XMON_DEFAULT);
 
@@ -357,7 +360,6 @@ static inline void disable_surveillance(void)
 #ifdef CONFIG_PPC_PSERIES
 	/* Since this can't be a module, args should end up below 4GB. */
 	static struct rtas_args args;
-	int token;
 
 	/*
 	 * At this point we have got all the cpus we can into
@@ -366,11 +368,11 @@ static inline void disable_surveillance(void)
 	 * If we did try to take rtas.lock there would be a
 	 * real possibility of deadlock.
 	 */
-	token = rtas_token("set-indicator");
-	if (token == RTAS_UNKNOWN_SERVICE)
+	if (set_indicator_token == RTAS_UNKNOWN_SERVICE)
 		return;
 
-	rtas_call_unlocked(&args, token, 3, 1, NULL, SURVEILLANCE_TOKEN, 0, 0);
+	rtas_call_unlocked(&args, set_indicator_token, 3, 1, NULL,
+			   SURVEILLANCE_TOKEN, 0, 0);
 
 #endif /* CONFIG_PPC_PSERIES */
 }
@@ -3472,6 +3474,14 @@ static void xmon_init(int enable)
 		__debugger_iabr_match = xmon_iabr_match;
 		__debugger_break_match = xmon_break_match;
 		__debugger_fault_handler = xmon_fault_handler;
+
+#ifdef CONFIG_PPC_PSERIES
+		/*
+		 * Get the token here to avoid trying to get a lock
+		 * during the crash, causing a deadlock.
+		 */
+		set_indicator_token = rtas_token("set-indicator");
+#endif
 	} else {
 		__debugger = NULL;
 		__debugger_ipi = NULL;
diff --git a/arch/s390/include/uapi/asm/zcrypt.h b/arch/s390/include/uapi/asm/zcrypt.h
index 137ef47..b9fb420 100644
--- a/arch/s390/include/uapi/asm/zcrypt.h
+++ b/arch/s390/include/uapi/asm/zcrypt.h
@@ -161,8 +161,8 @@ struct ica_xcRB {
  * @cprb_len:		CPRB header length [0x0020]
  * @cprb_ver_id:	CPRB version id.   [0x04]
  * @pad_000:		Alignment pad bytes
- * @flags:		Admin cmd [0x80] or functional cmd [0x00]
- * @func_id:		Function id / subtype [0x5434]
+ * @flags:		Admin bit [0x80], Special bit [0x20]
+ * @func_id:		Function id / subtype [0x5434] "T4"
  * @source_id:		Source id [originator id]
  * @target_id:		Target id [usage/ctrl domain id]
  * @ret_code:		Return code
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index a321983..4ba5ad4 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -226,10 +226,10 @@ static noinline __init void detect_machine_type(void)
 	if (stsi(vmms, 3, 2, 2) || !vmms->count)
 		return;
 
-	/* Running under KVM? If not we assume z/VM */
+	/* Detect known hypervisors */
 	if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_KVM;
-	else
+	else if (!memcmp(vmms->vm[0].cpi, "\xa9\x61\xe5\xd4", 4))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_VM;
 }
 
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 98c1f79..3cb71fc 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -884,6 +884,8 @@ void __init setup_arch(char **cmdline_p)
 		pr_info("Linux is running under KVM in 64-bit mode\n");
 	else if (MACHINE_IS_LPAR)
 		pr_info("Linux is running natively in 64-bit mode\n");
+	else
+		pr_info("Linux is running as a guest in 64-bit mode\n");
 
 	/* Have one command line that is parsed and saved in /proc/cmdline */
 	/* boot_command_line has been already set up in early.c */
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index ae5df417..27258db 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -387,9 +387,13 @@ void smp_call_online_cpu(void (*func)(void *), void *data)
  */
 void smp_call_ipl_cpu(void (*func)(void *), void *data)
 {
+	struct lowcore *lc = pcpu_devices->lowcore;
+
+	if (pcpu_devices[0].address == stap())
+		lc = &S390_lowcore;
+
 	pcpu_delegate(&pcpu_devices[0], func, data,
-		      pcpu_devices->lowcore->panic_stack -
-		      PANIC_FRAME_OFFSET + PAGE_SIZE);
+		      lc->panic_stack - PANIC_FRAME_OFFSET + PAGE_SIZE);
 }
 
 int smp_find_processor_id(u16 address)
@@ -1168,7 +1172,11 @@ static ssize_t __ref rescan_store(struct device *dev,
 {
 	int rc;
 
+	rc = lock_device_hotplug_sysfs();
+	if (rc)
+		return rc;
 	rc = smp_rescan_cpus();
+	unlock_device_hotplug();
 	return rc ? rc : count;
 }
 static DEVICE_ATTR(rescan, 0200, NULL, rescan_store);
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
index 7485398..9c04562 100644
--- a/arch/um/include/asm/pgtable.h
+++ b/arch/um/include/asm/pgtable.h
@@ -197,12 +197,17 @@ static inline pte_t pte_mkold(pte_t pte)
 
 static inline pte_t pte_wrprotect(pte_t pte)
 { 
-	pte_clear_bits(pte, _PAGE_RW);
+	if (likely(pte_get_bits(pte, _PAGE_RW)))
+		pte_clear_bits(pte, _PAGE_RW);
+	else
+		return pte;
 	return(pte_mknewprot(pte)); 
 }
 
 static inline pte_t pte_mkread(pte_t pte)
 { 
+	if (unlikely(pte_get_bits(pte, _PAGE_USER)))
+		return pte;
 	pte_set_bits(pte, _PAGE_USER);
 	return(pte_mknewprot(pte)); 
 }
@@ -221,6 +226,8 @@ static inline pte_t pte_mkyoung(pte_t pte)
 
 static inline pte_t pte_mkwrite(pte_t pte)	
 {
+	if (unlikely(pte_get_bits(pte,  _PAGE_RW)))
+		return pte;
 	pte_set_bits(pte, _PAGE_RW);
 	return(pte_mknewprot(pte)); 
 }
diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 1911310..a77fd3c 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -112,7 +112,7 @@ static int vvar_fault(const struct vm_special_mapping *sm,
 				    __pa_symbol(&__vvar_page) >> PAGE_SHIFT);
 	} else if (sym_offset == image->sym_pvclock_page) {
 		struct pvclock_vsyscall_time_info *pvti =
-			pvclock_pvti_cpu0_va();
+			pvclock_get_pvti_cpu0_va();
 		if (pvti && vclock_was_used(VCLOCK_PVCLOCK)) {
 			ret = vm_insert_pfn(
 				vma,
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 7d12b0d..e14a395 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -2250,6 +2250,19 @@ void perf_check_microcode(void)
 		x86_pmu.check_microcode();
 }
 
+static int x86_pmu_check_period(struct perf_event *event, u64 value)
+{
+	if (x86_pmu.check_period && x86_pmu.check_period(event, value))
+		return -EINVAL;
+
+	if (value && x86_pmu.limit_period) {
+		if (x86_pmu.limit_period(event, value) > value)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 static struct pmu pmu = {
 	.pmu_enable		= x86_pmu_enable,
 	.pmu_disable		= x86_pmu_disable,
@@ -2274,6 +2287,7 @@ static struct pmu pmu = {
 	.event_idx		= x86_pmu_event_idx,
 	.sched_task		= x86_pmu_sched_task,
 	.task_ctx_size          = sizeof(struct x86_perf_task_context),
+	.check_period		= x86_pmu_check_period,
 };
 
 void arch_perf_update_userpage(struct perf_event *event,
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 7bb8015..9f556c9 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -3420,6 +3420,11 @@ static void free_excl_cntrs(int cpu)
 
 static void intel_pmu_cpu_dying(int cpu)
 {
+	fini_debug_store_on_cpu(cpu);
+}
+
+static void intel_pmu_cpu_dead(int cpu)
+{
 	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
 	struct intel_shared_regs *pc;
 
@@ -3431,8 +3436,6 @@ static void intel_pmu_cpu_dying(int cpu)
 	}
 
 	free_excl_cntrs(cpu);
-
-	fini_debug_store_on_cpu(cpu);
 }
 
 static void intel_pmu_sched_task(struct perf_event_context *ctx,
@@ -3442,6 +3445,11 @@ static void intel_pmu_sched_task(struct perf_event_context *ctx,
 	intel_pmu_lbr_sched_task(ctx, sched_in);
 }
 
+static int intel_pmu_check_period(struct perf_event *event, u64 value)
+{
+	return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0;
+}
+
 PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
 
 PMU_FORMAT_ATTR(ldlat, "config1:0-15");
@@ -3521,6 +3529,9 @@ static __initconst const struct x86_pmu core_pmu = {
 	.cpu_prepare		= intel_pmu_cpu_prepare,
 	.cpu_starting		= intel_pmu_cpu_starting,
 	.cpu_dying		= intel_pmu_cpu_dying,
+	.cpu_dead		= intel_pmu_cpu_dead,
+
+	.check_period		= intel_pmu_check_period,
 };
 
 static struct attribute *intel_pmu_attrs[];
@@ -3560,8 +3571,12 @@ static __initconst const struct x86_pmu intel_pmu = {
 	.cpu_prepare		= intel_pmu_cpu_prepare,
 	.cpu_starting		= intel_pmu_cpu_starting,
 	.cpu_dying		= intel_pmu_cpu_dying,
+	.cpu_dead		= intel_pmu_cpu_dead,
+
 	.guest_get_msrs		= intel_guest_get_msrs,
 	.sched_task		= intel_pmu_sched_task,
+
+	.check_period		= intel_pmu_check_period,
 };
 
 static __init void intel_clovertown_quirk(void)
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index a68aba8..6b66285 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -1221,6 +1221,8 @@ static struct pci_driver snbep_uncore_pci_driver = {
 	.id_table	= snbep_uncore_pci_ids,
 };
 
+#define NODE_ID_MASK	0x7
+
 /*
  * build pci bus to socket mapping
  */
@@ -1242,7 +1244,7 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
 		err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
 		if (err)
 			break;
-		nodeid = config;
+		nodeid = config & NODE_ID_MASK;
 		/* get the Node ID mapping */
 		err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
 		if (err)
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index 3c51fcaf..fbbc103 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -639,6 +639,11 @@ struct x86_pmu {
 	 * Intel host/guest support (KVM)
 	 */
 	struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
+
+	/*
+	 * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
+	 */
+	int (*check_period) (struct perf_event *event, u64 period);
 };
 
 struct x86_perf_task_context {
@@ -848,7 +853,7 @@ static inline int amd_pmu_init(void)
 
 #ifdef CONFIG_CPU_SUP_INTEL
 
-static inline bool intel_pmu_has_bts(struct perf_event *event)
+static inline bool intel_pmu_has_bts_period(struct perf_event *event, u64 period)
 {
 	struct hw_perf_event *hwc = &event->hw;
 	unsigned int hw_event, bts_event;
@@ -859,7 +864,14 @@ static inline bool intel_pmu_has_bts(struct perf_event *event)
 	hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
 	bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
 
-	return hw_event == bts_event && hwc->sample_period == 1;
+	return hw_event == bts_event && period == 1;
+}
+
+static inline bool intel_pmu_has_bts(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	return intel_pmu_has_bts_period(event, hwc->sample_period);
 }
 
 int intel_pmu_save_and_restart(struct perf_event *event);
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 8e02b30..3ebd777 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -51,7 +51,7 @@ static unsigned long get_dr(int n)
 /*
  * fill in the user structure for a core dump..
  */
-static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
+static void fill_dump(struct pt_regs *regs, struct user32 *dump)
 {
 	u32 fs, gs;
 	memset(dump, 0, sizeof(*dump));
@@ -157,10 +157,12 @@ static int aout_core_dump(struct coredump_params *cprm)
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 	has_dumped = 1;
+
+	fill_dump(cprm->regs, &dump);
+
 	strncpy(dump.u_comm, current->comm, sizeof(current->comm));
 	dump.u_ar0 = offsetof(struct user32, regs);
 	dump.signal = cprm->siginfo->si_signo;
-	dump_thread32(cprm->regs, &dump);
 
 	/*
 	 * If the size of the dump file exceeds the rlimit, then see
diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h
index 69dcdf1..fa2c93c 100644
--- a/arch/x86/include/asm/fpu/internal.h
+++ b/arch/x86/include/asm/fpu/internal.h
@@ -106,6 +106,9 @@ extern void fpstate_sanitize_xstate(struct fpu *fpu);
 #define user_insn(insn, output, input...)				\
 ({									\
 	int err;							\
+									\
+	might_fault();							\
+									\
 	asm volatile(ASM_STAC "\n"					\
 		     "1:" #insn "\n\t"					\
 		     "2: " ASM_CLAC "\n"				\
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 523308d..72fac86 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -539,7 +539,20 @@ struct kvm_vcpu_arch {
 	struct kvm_mmu_memory_cache mmu_page_cache;
 	struct kvm_mmu_memory_cache mmu_page_header_cache;
 
+	/*
+	 * QEMU userspace and the guest each have their own FPU state.
+	 * In vcpu_run, we switch between the user and guest FPU contexts.
+	 * While running a VCPU, the VCPU thread will have the guest FPU
+	 * context.
+	 *
+	 * Note that while the PKRU state lives inside the fpu registers,
+	 * it is switched out separately at VMENTER and VMEXIT time. The
+	 * "guest_fpu" state here contains the guest FPU context, with the
+	 * host PRKU bits.
+	 */
+	struct fpu user_fpu;
 	struct fpu guest_fpu;
+
 	u64 xcr0;
 	u64 guest_supported_xcr0;
 	u32 guest_xstate_size;
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index ed97ef3..7ebcbd1 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -182,6 +182,10 @@ static inline void switch_ldt(struct mm_struct *prev, struct mm_struct *next)
 
 void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk);
 
+/*
+ * Init a new mm.  Used on mm copies, like at fork()
+ * and on mm's that are brand-new, like at execve().
+ */
 static inline int init_new_context(struct task_struct *tsk,
 				   struct mm_struct *mm)
 {
@@ -232,8 +236,22 @@ do {						\
 } while (0)
 #endif
 
+static inline void arch_dup_pkeys(struct mm_struct *oldmm,
+				  struct mm_struct *mm)
+{
+#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+	if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
+		return;
+
+	/* Duplicate the oldmm pkey state in mm: */
+	mm->context.pkey_allocation_map = oldmm->context.pkey_allocation_map;
+	mm->context.execute_only_pkey   = oldmm->context.execute_only_pkey;
+#endif
+}
+
 static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
 {
+	arch_dup_pkeys(oldmm, mm);
 	paravirt_arch_dup_mmap(oldmm, mm);
 	return ldt_dup_context(oldmm, mm);
 }
diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h
index 7764617..bf6d269 100644
--- a/arch/x86/include/asm/pgtable_64_types.h
+++ b/arch/x86/include/asm/pgtable_64_types.h
@@ -94,6 +94,11 @@ typedef struct { pteval_t pte; } pte_t;
 # define __VMEMMAP_BASE		_AC(0xffffea0000000000, UL)
 #endif
 
+#define GUARD_HOLE_PGD_ENTRY	-256UL
+#define GUARD_HOLE_SIZE		(16UL << PGDIR_SHIFT)
+#define GUARD_HOLE_BASE_ADDR	(GUARD_HOLE_PGD_ENTRY << PGDIR_SHIFT)
+#define GUARD_HOLE_END_ADDR	(GUARD_HOLE_BASE_ADDR + GUARD_HOLE_SIZE)
+
 #define LDT_PGD_ENTRY		-240UL
 #define LDT_BASE_ADDR		(LDT_PGD_ENTRY << PGDIR_SHIFT)
 
diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h
index 3e4ed8f..a7471dc 100644
--- a/arch/x86/include/asm/pvclock.h
+++ b/arch/x86/include/asm/pvclock.h
@@ -5,15 +5,6 @@
 #include <linux/clocksource.h>
 #include <asm/pvclock-abi.h>
 
-#ifdef CONFIG_KVM_GUEST
-extern struct pvclock_vsyscall_time_info *pvclock_pvti_cpu0_va(void);
-#else
-static inline struct pvclock_vsyscall_time_info *pvclock_pvti_cpu0_va(void)
-{
-	return NULL;
-}
-#endif
-
 /* some helper functions for xen and kvm pv clock sources */
 u64 pvclock_clocksource_read(struct pvclock_vcpu_time_info *src);
 u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src);
@@ -102,4 +93,14 @@ struct pvclock_vsyscall_time_info {
 
 #define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
 
+#ifdef CONFIG_PARAVIRT_CLOCK
+void pvclock_set_pvti_cpu0_va(struct pvclock_vsyscall_time_info *pvti);
+struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void);
+#else
+static inline struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void)
+{
+	return NULL;
+}
+#endif
+
 #endif /* _ASM_X86_PVCLOCK_H */
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
index 3de6933..afbc872 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -104,9 +104,9 @@ extern int panic_on_unrecovered_nmi;
 
 void math_emulate(struct math_emu_info *);
 #ifndef CONFIG_X86_32
-asmlinkage void smp_thermal_interrupt(void);
-asmlinkage void smp_threshold_interrupt(void);
-asmlinkage void smp_deferred_error_interrupt(void);
+asmlinkage void smp_thermal_interrupt(struct pt_regs *regs);
+asmlinkage void smp_threshold_interrupt(struct pt_regs *regs);
+asmlinkage void smp_deferred_error_interrupt(struct pt_regs *regs);
 #endif
 
 extern void ist_enter(struct pt_regs *regs);
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index aae77eb..4111edb 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -293,8 +293,7 @@ do {									\
 		__put_user_asm(x, ptr, retval, "l", "k", "ir", errret);	\
 		break;							\
 	case 8:								\
-		__put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval,	\
-				   errret);				\
+		__put_user_asm_u64(x, ptr, retval, errret);		\
 		break;							\
 	default:							\
 		__put_user_bad();					\
@@ -440,8 +439,10 @@ do {									\
 #define __put_user_nocheck(x, ptr, size)			\
 ({								\
 	int __pu_err;						\
+	__typeof__(*(ptr)) __pu_val;				\
+	__pu_val = x;						\
 	__uaccess_begin();					\
-	__put_user_size((x), (ptr), (size), __pu_err, -EFAULT);	\
+	__put_user_size(__pu_val, (ptr), (size), __pu_err, -EFAULT);\
 	__uaccess_end();					\
 	__builtin_expect(__pu_err, 0);				\
 })
diff --git a/arch/x86/include/asm/uv/bios.h b/arch/x86/include/asm/uv/bios.h
index e652a7c..3f697a9 100644
--- a/arch/x86/include/asm/uv/bios.h
+++ b/arch/x86/include/asm/uv/bios.h
@@ -48,7 +48,8 @@ enum {
 	BIOS_STATUS_SUCCESS		=  0,
 	BIOS_STATUS_UNIMPLEMENTED	= -ENOSYS,
 	BIOS_STATUS_EINVAL		= -EINVAL,
-	BIOS_STATUS_UNAVAIL		= -EBUSY
+	BIOS_STATUS_UNAVAIL		= -EBUSY,
+	BIOS_STATUS_ABORT		= -EINTR,
 };
 
 /* Address map parameters */
@@ -167,4 +168,9 @@ extern long system_serial_number;
 
 extern struct kobject *sgi_uv_kobj;	/* /sys/firmware/sgi_uv */
 
+/*
+ * EFI runtime lock; cf. firmware/efi/runtime-wrappers.c for details
+ */
+extern struct semaphore __efi_uv_runtime_lock;
+
 #endif /* _ASM_X86_UV_BIOS_H */
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 98b24d6..ec7aedb 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -68,7 +68,7 @@ void __init check_bugs(void)
 	 * identify_boot_cpu() initialized SMT support information, let the
 	 * core code know.
 	 */
-	cpu_smt_check_topology_early();
+	cpu_smt_check_topology();
 
 	if (!IS_ENABLED(CONFIG_SMP)) {
 		pr_info("CPU: ");
@@ -212,7 +212,7 @@ static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
 static enum spectre_v2_user_mitigation spectre_v2_user __ro_after_init =
 	SPECTRE_V2_USER_NONE;
 
-#ifdef RETPOLINE
+#ifdef CONFIG_RETPOLINE
 static bool spectre_v2_bad_module;
 
 bool retpoline_module_ok(bool has_retpoline)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 98e4e4d..54874e2b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -773,6 +773,7 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
 			quirk_no_way_out(i, m, regs);
 
 		if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) {
+			m->bank = i;
 			mce_read_aux(m, i);
 			*msg = tmp;
 			return 1;
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index beec0dae..4fa97a4 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -23,6 +23,7 @@
 #include <linux/string.h>
 
 #include <asm/amd_nb.h>
+#include <asm/traps.h>
 #include <asm/apic.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
@@ -99,7 +100,7 @@ static u32 smca_bank_addrs[MAX_NR_BANKS][NR_BLOCKS] __ro_after_init =
 	[0 ... MAX_NR_BANKS - 1] = { [0 ... NR_BLOCKS - 1] = -1 }
 };
 
-const char *smca_get_name(enum smca_bank_types t)
+static const char *smca_get_name(enum smca_bank_types t)
 {
 	if (t >= N_SMCA_BANK_TYPES)
 		return NULL;
@@ -823,7 +824,7 @@ static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc)
 	mce_log(&m);
 }
 
-asmlinkage __visible void __irq_entry smp_deferred_error_interrupt(void)
+asmlinkage __visible void __irq_entry smp_deferred_error_interrupt(struct pt_regs *regs)
 {
 	entering_irq();
 	trace_deferred_error_apic_entry(DEFERRED_ERROR_VECTOR);
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 2da67b7..ee229ce 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -25,6 +25,7 @@
 #include <linux/cpu.h>
 
 #include <asm/processor.h>
+#include <asm/traps.h>
 #include <asm/apic.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
@@ -390,7 +391,7 @@ static void unexpected_thermal_interrupt(void)
 
 static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt;
 
-asmlinkage __visible void __irq_entry smp_thermal_interrupt(struct pt_regs *r)
+asmlinkage __visible void __irq_entry smp_thermal_interrupt(struct pt_regs *regs)
 {
 	entering_irq();
 	trace_thermal_apic_entry(THERMAL_APIC_VECTOR);
diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c
index 2b584b3..c21e0a1 100644
--- a/arch/x86/kernel/cpu/mcheck/threshold.c
+++ b/arch/x86/kernel/cpu/mcheck/threshold.c
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 
 #include <asm/irq_vectors.h>
+#include <asm/traps.h>
 #include <asm/apic.h>
 #include <asm/mce.h>
 #include <asm/trace/irq_vectors.h>
@@ -18,7 +19,7 @@ static void default_threshold_interrupt(void)
 
 void (*mce_threshold_vector)(void) = default_threshold_interrupt;
 
-asmlinkage __visible void __irq_entry smp_threshold_interrupt(void)
+asmlinkage __visible void __irq_entry smp_threshold_interrupt(struct pt_regs *regs)
 {
 	entering_irq();
 	trace_threshold_apic_entry(THRESHOLD_APIC_VECTOR);
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 48703d4..08806d6 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -47,12 +47,6 @@ early_param("no-kvmclock", parse_no_kvmclock);
 static struct pvclock_vsyscall_time_info *hv_clock;
 static struct pvclock_wall_clock wall_clock;
 
-struct pvclock_vsyscall_time_info *pvclock_pvti_cpu0_va(void)
-{
-	return hv_clock;
-}
-EXPORT_SYMBOL_GPL(pvclock_pvti_cpu0_va);
-
 /*
  * The wallclock is the time of day when we booted. Since then, some time may
  * have elapsed since the hypervisor wrote the data. So we try to account for
@@ -335,6 +329,7 @@ int __init kvm_setup_vsyscall_timeinfo(void)
 		return 1;
 	}
 
+	pvclock_set_pvti_cpu0_va(hv_clock);
 	put_cpu();
 
 	kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK;
diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c
index 5c3f6d6..761f6af 100644
--- a/arch/x86/kernel/pvclock.c
+++ b/arch/x86/kernel/pvclock.c
@@ -25,8 +25,10 @@
 
 #include <asm/fixmap.h>
 #include <asm/pvclock.h>
+#include <asm/vgtod.h>
 
 static u8 valid_flags __read_mostly = 0;
+static struct pvclock_vsyscall_time_info *pvti_cpu0_va __read_mostly;
 
 void pvclock_set_flags(u8 flags)
 {
@@ -144,3 +146,15 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock,
 
 	set_normalized_timespec(ts, now.tv_sec, now.tv_nsec);
 }
+
+void pvclock_set_pvti_cpu0_va(struct pvclock_vsyscall_time_info *pvti)
+{
+	WARN_ON(vclock_was_used(VCLOCK_PVCLOCK));
+	pvti_cpu0_va = pvti;
+}
+
+struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void)
+{
+	return pvti_cpu0_va;
+}
+EXPORT_SYMBOL_GPL(pvclock_get_pvti_cpu0_va);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 4dc79d1..c387047 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2929,6 +2929,14 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
 	kvm_mmu_reset_context(&svm->vcpu);
 	kvm_mmu_load(&svm->vcpu);
 
+	/*
+	 * Drop what we picked up for L2 via svm_complete_interrupts() so it
+	 * doesn't end up in L1.
+	 */
+	svm->vcpu.arch.nmi_injected = false;
+	kvm_clear_exception_queue(&svm->vcpu);
+	kvm_clear_interrupt_queue(&svm->vcpu);
+
 	return 0;
 }
 
@@ -4006,25 +4014,14 @@ static int avic_incomplete_ipi_interception(struct vcpu_svm *svm)
 		kvm_lapic_reg_write(apic, APIC_ICR, icrl);
 		break;
 	case AVIC_IPI_FAILURE_TARGET_NOT_RUNNING: {
-		int i;
-		struct kvm_vcpu *vcpu;
-		struct kvm *kvm = svm->vcpu.kvm;
 		struct kvm_lapic *apic = svm->vcpu.arch.apic;
 
 		/*
-		 * At this point, we expect that the AVIC HW has already
-		 * set the appropriate IRR bits on the valid target
-		 * vcpus. So, we just need to kick the appropriate vcpu.
+		 * Update ICR high and low, then emulate sending IPI,
+		 * which is handled when writing APIC_ICR.
 		 */
-		kvm_for_each_vcpu(i, vcpu, kvm) {
-			bool m = kvm_apic_match_dest(vcpu, apic,
-						     icrl & KVM_APIC_SHORT_MASK,
-						     GET_APIC_DEST_FIELD(icrh),
-						     icrl & KVM_APIC_DEST_MASK);
-
-			if (m && !avic_vcpu_is_running(vcpu))
-				kvm_vcpu_wake_up(vcpu);
-		}
+		kvm_lapic_reg_write(apic, APIC_ICR2, icrh);
+		kvm_lapic_reg_write(apic, APIC_ICR, icrl);
 		break;
 	}
 	case AVIC_IPI_FAILURE_INVALID_TARGET:
@@ -5319,6 +5316,13 @@ static bool svm_cpu_has_accelerated_tpr(void)
 
 static bool svm_has_emulated_msr(int index)
 {
+	switch (index) {
+	case MSR_IA32_MCG_EXT_CTL:
+		return false;
+	default:
+		break;
+	}
+
 	return true;
 }
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 16bb8e3..8e5a977 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/sched.h>
+#include <linux/sched/smt.h>
 #include <linux/moduleparam.h>
 #include <linux/mod_devicetable.h>
 #include <linux/trace_events.h>
@@ -2229,7 +2230,8 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
 	if (!entry_only)
 		j = find_msr(&m->host, msr);
 
-	if (i == NR_AUTOLOAD_MSRS || j == NR_AUTOLOAD_MSRS) {
+	if ((i < 0 && m->guest.nr == NR_AUTOLOAD_MSRS) ||
+		(j < 0 &&  m->host.nr == NR_AUTOLOAD_MSRS)) {
 		printk_once(KERN_WARNING "Not enough msr switch entries. "
 				"Can't add msr %x\n", msr);
 		return;
@@ -7708,6 +7710,7 @@ static void free_nested(struct vcpu_vmx *vmx)
 	if (!vmx->nested.vmxon)
 		return;
 
+	hrtimer_cancel(&vmx->nested.preemption_timer);
 	vmx->nested.vmxon = false;
 	free_vpid(vmx->nested.vpid02);
 	vmx->nested.posted_intr_nv = -1;
@@ -10119,7 +10122,7 @@ static int vmx_vm_init(struct kvm *kvm)
 			 * Warn upon starting the first VM in a potentially
 			 * insecure environment.
 			 */
-			if (cpu_smt_control == CPU_SMT_ENABLED)
+			if (sched_smt_active())
 				pr_warn_once(L1TF_MSG_SMT);
 			if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER)
 				pr_warn_once(L1TF_MSG_L1D);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ac431fa..b0e7621 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3020,7 +3020,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 	pagefault_enable();
 	kvm_x86_ops->vcpu_put(vcpu);
-	kvm_put_guest_fpu(vcpu);
 	vcpu->arch.last_host_tsc = rdtsc();
 	/*
 	 * If userspace has set any breakpoints or watchpoints, dr6 is restored
@@ -4612,6 +4611,13 @@ int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
 {
 	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
 
+	/*
+	 * FIXME: this should call handle_emulation_failure if X86EMUL_IO_NEEDED
+	 * is returned, but our callers are not ready for that and they blindly
+	 * call kvm_inject_page_fault.  Ensure that they at least do not leak
+	 * uninitialized kernel stack memory into cr2 and error code.
+	 */
+	memset(exception, 0, sizeof(*exception));
 	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
 					  exception);
 }
@@ -5377,13 +5383,10 @@ static void emulator_halt(struct x86_emulate_ctxt *ctxt)
 
 static void emulator_get_fpu(struct x86_emulate_ctxt *ctxt)
 {
-	preempt_disable();
-	kvm_load_guest_fpu(emul_to_vcpu(ctxt));
 }
 
 static void emulator_put_fpu(struct x86_emulate_ctxt *ctxt)
 {
-	preempt_enable();
 }
 
 static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
@@ -5927,8 +5930,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
 		toggle_interruptibility(vcpu, ctxt->interruptibility);
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
 		kvm_rip_write(vcpu, ctxt->eip);
-		if (r == EMULATE_DONE &&
-		    (ctxt->tf || (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)))
+		if (r == EMULATE_DONE && ctxt->tf)
 			kvm_vcpu_do_singlestep(vcpu, &r);
 		if (!ctxt->have_exception ||
 		    exception_type(ctxt->exception.vector) == EXCPT_TRAP)
@@ -7083,7 +7085,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 	preempt_disable();
 
 	kvm_x86_ops->prepare_guest_switch(vcpu);
-	kvm_load_guest_fpu(vcpu);
 
 	/*
 	 * Disable IRQs before setting IN_GUEST_MODE.  Posted interrupt
@@ -7865,32 +7866,25 @@ static void fx_init(struct kvm_vcpu *vcpu)
 	vcpu->arch.cr0 |= X86_CR0_ET;
 }
 
+/* Swap (qemu) user FPU context for the guest FPU context. */
 void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
 {
-	if (vcpu->guest_fpu_loaded)
-		return;
-
-	/*
-	 * Restore all possible states in the guest,
-	 * and assume host would use all available bits.
-	 * Guest xcr0 would be loaded later.
-	 */
-	vcpu->guest_fpu_loaded = 1;
-	__kernel_fpu_begin();
+	preempt_disable();
+	copy_fpregs_to_fpstate(&vcpu->arch.user_fpu);
 	/* PKRU is separately restored in kvm_x86_ops->run.  */
 	__copy_kernel_to_fpregs(&vcpu->arch.guest_fpu.state,
 				~XFEATURE_MASK_PKRU);
+	preempt_enable();
 	trace_kvm_fpu(1);
 }
 
+/* When vcpu_run ends, restore user space FPU context. */
 void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
 {
-	if (!vcpu->guest_fpu_loaded)
-		return;
-
-	vcpu->guest_fpu_loaded = 0;
+	preempt_disable();
 	copy_fpregs_to_fpstate(&vcpu->arch.guest_fpu);
-	__kernel_fpu_end();
+	copy_kernel_to_fpregs(&vcpu->arch.user_fpu.state);
+	preempt_enable();
 	++vcpu->stat.fpu_reload;
 	trace_kvm_fpu(0);
 }
diff --git a/arch/x86/lib/kaslr.c b/arch/x86/lib/kaslr.c
index 79778ab..a536651 100644
--- a/arch/x86/lib/kaslr.c
+++ b/arch/x86/lib/kaslr.c
@@ -36,8 +36,8 @@ static inline u16 i8254(void)
 	u16 status, timer;
 
 	do {
-		outb(I8254_PORT_CONTROL,
-		     I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
+		outb(I8254_CMD_READBACK | I8254_SELECT_COUNTER0,
+		     I8254_PORT_CONTROL);
 		status = inb(I8254_PORT_COUNTER0);
 		timer  = inb(I8254_PORT_COUNTER0);
 		timer |= inb(I8254_PORT_COUNTER0) << 8;
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index 2a4849e..6bca45d 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -51,10 +51,10 @@ struct addr_marker {
 enum address_markers_idx {
 	USER_SPACE_NR = 0,
 	KERNEL_SPACE_NR,
-	LOW_KERNEL_NR,
-#if defined(CONFIG_MODIFY_LDT_SYSCALL) && defined(CONFIG_X86_5LEVEL)
+#ifdef CONFIG_MODIFY_LDT_SYSCALL
 	LDT_NR,
 #endif
+	LOW_KERNEL_NR,
 	VMALLOC_START_NR,
 	VMEMMAP_START_NR,
 #ifdef CONFIG_KASAN
@@ -62,9 +62,6 @@ enum address_markers_idx {
 	KASAN_SHADOW_END_NR,
 #endif
 	CPU_ENTRY_AREA_NR,
-#if defined(CONFIG_MODIFY_LDT_SYSCALL) && !defined(CONFIG_X86_5LEVEL)
-	LDT_NR,
-#endif
 #ifdef CONFIG_X86_ESPFIX64
 	ESPFIX_START_NR,
 #endif
@@ -465,11 +462,11 @@ static inline bool is_hypervisor_range(int idx)
 {
 #ifdef CONFIG_X86_64
 	/*
-	 * ffff800000000000 - ffff87ffffffffff is reserved for
-	 * the hypervisor.
+	 * A hole in the beginning of kernel address space reserved
+	 * for a hypervisor.
 	 */
-	return	(idx >= pgd_index(__PAGE_OFFSET) - 16) &&
-		(idx <  pgd_index(__PAGE_OFFSET));
+	return	(idx >= pgd_index(GUARD_HOLE_BASE_ADDR)) &&
+		(idx <  pgd_index(GUARD_HOLE_END_ADDR));
 #else
 	return false;
 #endif
diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
index 526536c..ca1e8e6 100644
--- a/arch/x86/pci/broadcom_bus.c
+++ b/arch/x86/pci/broadcom_bus.c
@@ -50,8 +50,8 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
 	word1 = read_pci_config_16(bus, slot, func, 0xc0);
 	word2 = read_pci_config_16(bus, slot, func, 0xc2);
 	if (word1 != word2) {
-		res.start = (word1 << 16) | 0x0000;
-		res.end   = (word2 << 16) | 0xffff;
+		res.start = ((resource_size_t) word1 << 16) | 0x0000;
+		res.end   = ((resource_size_t) word2 << 16) | 0xffff;
 		res.flags = IORESOURCE_MEM;
 		update_res(info, res.start, res.end, res.flags, 0);
 	}
diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c
index 4a6a5a2..eb33432 100644
--- a/arch/x86/platform/uv/bios_uv.c
+++ b/arch/x86/platform/uv/bios_uv.c
@@ -29,7 +29,8 @@
 
 struct uv_systab *uv_systab;
 
-s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
+static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
+			u64 a4, u64 a5)
 {
 	struct uv_systab *tab = uv_systab;
 	s64 ret;
@@ -51,6 +52,19 @@ s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
 
 	return ret;
 }
+
+s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
+{
+	s64 ret;
+
+	if (down_interruptible(&__efi_uv_runtime_lock))
+		return BIOS_STATUS_ABORT;
+
+	ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
+	up(&__efi_uv_runtime_lock);
+
+	return ret;
+}
 EXPORT_SYMBOL_GPL(uv_bios_call);
 
 s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
@@ -59,10 +73,15 @@ s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
 	unsigned long bios_flags;
 	s64 ret;
 
+	if (down_interruptible(&__efi_uv_runtime_lock))
+		return BIOS_STATUS_ABORT;
+
 	local_irq_save(bios_flags);
-	ret = uv_bios_call(which, a1, a2, a3, a4, a5);
+	ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
 	local_irq_restore(bios_flags);
 
+	up(&__efi_uv_runtime_lock);
+
 	return ret;
 }
 
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index fd173e64..481d792 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -900,10 +900,7 @@ static u64 xen_read_msr_safe(unsigned int msr, int *err)
 	val = native_read_msr_safe(msr, err);
 	switch (msr) {
 	case MSR_IA32_APICBASE:
-#ifdef CONFIG_X86_X2APIC
-		if (!(cpuid_ecx(1) & (1 << (X86_FEATURE_X2APIC & 31))))
-#endif
-			val &= ~X2APIC_ENABLE;
+		val &= ~X2APIC_ENABLE;
 		break;
 	}
 	return val;
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
index b33fa12..7631e61 100644
--- a/arch/x86/xen/mmu_pv.c
+++ b/arch/x86/xen/mmu_pv.c
@@ -614,19 +614,20 @@ static int __xen_pgd_walk(struct mm_struct *mm, pgd_t *pgd,
 			  unsigned long limit)
 {
 	int i, nr, flush = 0;
-	unsigned hole_low, hole_high;
+	unsigned hole_low = 0, hole_high = 0;
 
 	/* The limit is the last byte to be touched */
 	limit--;
 	BUG_ON(limit >= FIXADDR_TOP);
 
+#ifdef CONFIG_X86_64
 	/*
 	 * 64-bit has a great big hole in the middle of the address
-	 * space, which contains the Xen mappings.  On 32-bit these
-	 * will end up making a zero-sized hole and so is a no-op.
+	 * space, which contains the Xen mappings.
 	 */
-	hole_low = pgd_index(USER_LIMIT);
-	hole_high = pgd_index(PAGE_OFFSET);
+	hole_low = pgd_index(GUARD_HOLE_BASE_ADDR);
+	hole_high = pgd_index(GUARD_HOLE_END_ADDR);
+#endif
 
 	nr = pgd_index(limit) + 1;
 	for (i = 0; i < nr; i++) {
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index 3e3a58e..1d83152 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -22,6 +22,8 @@ static DEFINE_PER_CPU(u64, spec_ctrl);
 
 void xen_arch_pre_suspend(void)
 {
+	xen_save_time_memory_area();
+
 	if (xen_pv_domain())
 		xen_pv_pre_suspend();
 }
@@ -32,6 +34,8 @@ void xen_arch_post_suspend(int cancelled)
 		xen_pv_post_suspend(cancelled);
 	else
 		xen_hvm_post_suspend(cancelled);
+
+	xen_restore_time_memory_area();
 }
 
 static void xen_vcpu_notify_restore(void *data)
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 80c2a4b..0370633 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -31,6 +31,8 @@
 /* Xen may fire a timer up to this many ns early */
 #define TIMER_SLOP	100000
 
+static u64 xen_sched_clock_offset __read_mostly;
+
 /* Get the TSC speed from Xen */
 static unsigned long xen_tsc_khz(void)
 {
@@ -57,6 +59,11 @@ static u64 xen_clocksource_get_cycles(struct clocksource *cs)
 	return xen_clocksource_read();
 }
 
+static u64 xen_sched_clock(void)
+{
+	return xen_clocksource_read() - xen_sched_clock_offset;
+}
+
 static void xen_read_wallclock(struct timespec *ts)
 {
 	struct shared_info *s = HYPERVISOR_shared_info;
@@ -354,8 +361,6 @@ void xen_timer_resume(void)
 {
 	int cpu;
 
-	pvclock_resume();
-
 	if (xen_clockevent != &xen_vcpuop_clockevent)
 		return;
 
@@ -367,12 +372,107 @@ void xen_timer_resume(void)
 }
 
 static const struct pv_time_ops xen_time_ops __initconst = {
-	.sched_clock = xen_clocksource_read,
+	.sched_clock = xen_sched_clock,
 	.steal_clock = xen_steal_clock,
 };
 
+static struct pvclock_vsyscall_time_info *xen_clock __read_mostly;
+static u64 xen_clock_value_saved;
+
+void xen_save_time_memory_area(void)
+{
+	struct vcpu_register_time_memory_area t;
+	int ret;
+
+	xen_clock_value_saved = xen_clocksource_read() - xen_sched_clock_offset;
+
+	if (!xen_clock)
+		return;
+
+	t.addr.v = NULL;
+
+	ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, 0, &t);
+	if (ret != 0)
+		pr_notice("Cannot save secondary vcpu_time_info (err %d)",
+			  ret);
+	else
+		clear_page(xen_clock);
+}
+
+void xen_restore_time_memory_area(void)
+{
+	struct vcpu_register_time_memory_area t;
+	int ret;
+
+	if (!xen_clock)
+		goto out;
+
+	t.addr.v = &xen_clock->pvti;
+
+	ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, 0, &t);
+
+	/*
+	 * We don't disable VCLOCK_PVCLOCK entirely if it fails to register the
+	 * secondary time info with Xen or if we migrated to a host without the
+	 * necessary flags. On both of these cases what happens is either
+	 * process seeing a zeroed out pvti or seeing no PVCLOCK_TSC_STABLE_BIT
+	 * bit set. Userspace checks the latter and if 0, it discards the data
+	 * in pvti and fallbacks to a system call for a reliable timestamp.
+	 */
+	if (ret != 0)
+		pr_notice("Cannot restore secondary vcpu_time_info (err %d)",
+			  ret);
+
+out:
+	/* Need pvclock_resume() before using xen_clocksource_read(). */
+	pvclock_resume();
+	xen_sched_clock_offset = xen_clocksource_read() - xen_clock_value_saved;
+}
+
+static void xen_setup_vsyscall_time_info(void)
+{
+	struct vcpu_register_time_memory_area t;
+	struct pvclock_vsyscall_time_info *ti;
+	int ret;
+
+	ti = (struct pvclock_vsyscall_time_info *)get_zeroed_page(GFP_KERNEL);
+	if (!ti)
+		return;
+
+	t.addr.v = &ti->pvti;
+
+	ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, 0, &t);
+	if (ret) {
+		pr_notice("xen: VCLOCK_PVCLOCK not supported (err %d)\n", ret);
+		free_page((unsigned long)ti);
+		return;
+	}
+
+	/*
+	 * If primary time info had this bit set, secondary should too since
+	 * it's the same data on both just different memory regions. But we
+	 * still check it in case hypervisor is buggy.
+	 */
+	if (!(ti->pvti.flags & PVCLOCK_TSC_STABLE_BIT)) {
+		t.addr.v = NULL;
+		ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area,
+					 0, &t);
+		if (!ret)
+			free_page((unsigned long)ti);
+
+		pr_notice("xen: VCLOCK_PVCLOCK not supported (tsc unstable)\n");
+		return;
+	}
+
+	xen_clock = ti;
+	pvclock_set_pvti_cpu0_va(xen_clock);
+
+	xen_clocksource.archdata.vclock_mode = VCLOCK_PVCLOCK;
+}
+
 static void __init xen_time_init(void)
 {
+	struct pvclock_vcpu_time_info *pvti;
 	int cpu = smp_processor_id();
 	struct timespec tp;
 
@@ -396,6 +496,16 @@ static void __init xen_time_init(void)
 
 	setup_force_cpu_cap(X86_FEATURE_TSC);
 
+	/*
+	 * We check ahead on the primary time info if this
+	 * bit is supported hence speeding up Xen clocksource.
+	 */
+	pvti = &__this_cpu_read(xen_vcpu)->time;
+	if (pvti->flags & PVCLOCK_TSC_STABLE_BIT) {
+		pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
+		xen_setup_vsyscall_time_info();
+	}
+
 	xen_setup_runstate_info(cpu);
 	xen_setup_timer(cpu);
 	xen_setup_cpu_clockevents();
@@ -408,6 +518,7 @@ static void __init xen_time_init(void)
 
 void __ref xen_init_time_ops(void)
 {
+	xen_sched_clock_offset = xen_clocksource_read();
 	pv_time_ops = xen_time_ops;
 
 	x86_init.timers.timer_init = xen_time_init;
@@ -450,6 +561,7 @@ void __init xen_hvm_init_time_ops(void)
 		return;
 	}
 
+	xen_sched_clock_offset = xen_clocksource_read();
 	pv_time_ops = xen_time_ops;
 	x86_init.timers.setup_percpu_clockev = xen_time_init;
 	x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents;
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index f377e18..75011b8 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -70,6 +70,8 @@ void xen_setup_runstate_info(int cpu);
 void xen_teardown_timer(int cpu);
 u64 xen_clocksource_read(void);
 void xen_setup_cpu_clockevents(void);
+void xen_save_time_memory_area(void);
+void xen_restore_time_memory_area(void);
 void __init xen_init_time_ops(void);
 void __init xen_hvm_init_time_ops(void);
 
diff --git a/block/blk-flush.c b/block/blk-flush.c
index 4938bec..6603352 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -402,7 +402,7 @@ static void mq_flush_data_end_io(struct request *rq, blk_status_t error)
 	blk_flush_complete_seq(rq, fq, REQ_FSEQ_DATA, error);
 	spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
 
-	blk_mq_run_hw_queue(hctx, true);
+	blk_mq_sched_restart(hctx);
 }
 
 /**
diff --git a/block/genhd.c b/block/genhd.c
index 449ef56..7568c16 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -672,7 +672,8 @@ void device_add_disk(struct device *parent, struct gendisk *disk)
 
 	/* Register BDI before referencing it from bdev */
 	bdi = disk->queue->backing_dev_info;
-	bdi_register_owner(bdi, disk_to_dev(disk));
+	retval = bdi_register_owner(bdi, disk_to_dev(disk));
+	WARN_ON(retval);
 
 	blk_register_region(disk_devt(disk), disk->minors, NULL,
 			    exact_match, exact_lock, disk);
@@ -685,9 +686,11 @@ void device_add_disk(struct device *parent, struct gendisk *disk)
 	 */
 	WARN_ON_ONCE(!blk_get_queue(disk->queue));
 
-	retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
-				   "bdi");
-	WARN_ON(retval);
+	if (!retval) {
+		retval = sysfs_create_link(&disk_to_dev(disk)->kobj,
+				&bdi->dev->kobj, "bdi");
+		WARN_ON(retval);
+	}
 
 	disk_add_events(disk);
 	blk_integrity_add(disk);
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 8239f27..1c0ba2e 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -930,7 +930,8 @@
 	  8 for decryption), this implementation only uses just two S-boxes of
 	  256 bytes each, and attempts to eliminate data dependent latencies by
 	  prefetching the entire table into the cache at the start of each
-	  block.
+	  block. Interrupts are also disabled to avoid races where cachelines
+	  are evicted when the CPU is interrupted to do something else.
 
 config CRYPTO_AES_586
 	tristate "AES cipher algorithms (i586)"
diff --git a/crypto/aes_ti.c b/crypto/aes_ti.c
index 03023b2..1ff9785b 100644
--- a/crypto/aes_ti.c
+++ b/crypto/aes_ti.c
@@ -269,6 +269,7 @@ static void aesti_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 	const u32 *rkp = ctx->key_enc + 4;
 	int rounds = 6 + ctx->key_length / 4;
 	u32 st0[4], st1[4];
+	unsigned long flags;
 	int round;
 
 	st0[0] = ctx->key_enc[0] ^ get_unaligned_le32(in);
@@ -276,6 +277,12 @@ static void aesti_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 	st0[2] = ctx->key_enc[2] ^ get_unaligned_le32(in + 8);
 	st0[3] = ctx->key_enc[3] ^ get_unaligned_le32(in + 12);
 
+	/*
+	 * Temporarily disable interrupts to avoid races where cachelines are
+	 * evicted when the CPU is interrupted to do something else.
+	 */
+	local_irq_save(flags);
+
 	st0[0] ^= __aesti_sbox[ 0] ^ __aesti_sbox[128];
 	st0[1] ^= __aesti_sbox[32] ^ __aesti_sbox[160];
 	st0[2] ^= __aesti_sbox[64] ^ __aesti_sbox[192];
@@ -300,6 +307,8 @@ static void aesti_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 	put_unaligned_le32(subshift(st1, 1) ^ rkp[5], out + 4);
 	put_unaligned_le32(subshift(st1, 2) ^ rkp[6], out + 8);
 	put_unaligned_le32(subshift(st1, 3) ^ rkp[7], out + 12);
+
+	local_irq_restore(flags);
 }
 
 static void aesti_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
@@ -308,6 +317,7 @@ static void aesti_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 	const u32 *rkp = ctx->key_dec + 4;
 	int rounds = 6 + ctx->key_length / 4;
 	u32 st0[4], st1[4];
+	unsigned long flags;
 	int round;
 
 	st0[0] = ctx->key_dec[0] ^ get_unaligned_le32(in);
@@ -315,6 +325,12 @@ static void aesti_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 	st0[2] = ctx->key_dec[2] ^ get_unaligned_le32(in + 8);
 	st0[3] = ctx->key_dec[3] ^ get_unaligned_le32(in + 12);
 
+	/*
+	 * Temporarily disable interrupts to avoid races where cachelines are
+	 * evicted when the CPU is interrupted to do something else.
+	 */
+	local_irq_save(flags);
+
 	st0[0] ^= __aesti_inv_sbox[ 0] ^ __aesti_inv_sbox[128];
 	st0[1] ^= __aesti_inv_sbox[32] ^ __aesti_inv_sbox[160];
 	st0[2] ^= __aesti_inv_sbox[64] ^ __aesti_inv_sbox[192];
@@ -339,6 +355,8 @@ static void aesti_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 	put_unaligned_le32(inv_subshift(st1, 1) ^ rkp[5], out + 4);
 	put_unaligned_le32(inv_subshift(st1, 2) ^ rkp[6], out + 8);
 	put_unaligned_le32(inv_subshift(st1, 3) ^ rkp[7], out + 12);
+
+	local_irq_restore(flags);
 }
 
 static struct crypto_alg aes_alg = {
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 42dfdd1..f816a728 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -122,8 +122,10 @@ static void alg_do_release(const struct af_alg_type *type, void *private)
 
 int af_alg_release(struct socket *sock)
 {
-	if (sock->sk)
+	if (sock->sk) {
 		sock_put(sock->sk);
+		sock->sk = NULL;
+	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(af_alg_release);
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 0db344d..053287d 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -58,14 +58,22 @@ int crypto_authenc_extractkeys(struct crypto_authenc_keys *keys, const u8 *key,
 		return -EINVAL;
 	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
 		return -EINVAL;
-	if (RTA_PAYLOAD(rta) < sizeof(*param))
+
+	/*
+	 * RTA_OK() didn't align the rtattr's payload when validating that it
+	 * fits in the buffer.  Yet, the keys should start on the next 4-byte
+	 * aligned boundary.  To avoid confusion, require that the rtattr
+	 * payload be exactly the param struct, which has a 4-byte aligned size.
+	 */
+	if (RTA_PAYLOAD(rta) != sizeof(*param))
 		return -EINVAL;
+	BUILD_BUG_ON(sizeof(*param) % RTA_ALIGNTO);
 
 	param = RTA_DATA(rta);
 	keys->enckeylen = be32_to_cpu(param->enckeylen);
 
-	key += RTA_ALIGN(rta->rta_len);
-	keylen -= RTA_ALIGN(rta->rta_len);
+	key += rta->rta_len;
+	keylen -= rta->rta_len;
 
 	if (keylen < keys->enckeylen)
 		return -EINVAL;
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index 6de852c..4ba4470 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -279,7 +279,7 @@ static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
 	struct aead_request *req = areq->data;
 
 	err = err ?: crypto_authenc_esn_decrypt_tail(req, 0);
-	aead_request_complete(req, err);
+	authenc_esn_request_complete(req, err);
 }
 
 static int crypto_authenc_esn_decrypt(struct aead_request *req)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index f14695e..5889f64 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -675,6 +675,8 @@ static void __ghes_panic(struct ghes *ghes)
 {
 	__ghes_print_estatus(KERN_EMERG, ghes->generic, ghes->estatus);
 
+	ghes_clear_estatus(ghes);
+
 	/* reboot to log the error! */
 	if (!panic_timeout)
 		panic_timeout = ghes_panic_timeout;
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 8260b90..4a6c5e7 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -208,6 +208,32 @@ static int xlat_status(struct nvdimm *nvdimm, void *buf, unsigned int cmd,
 	return xlat_nvdimm_status(buf, cmd, status);
 }
 
+static int cmd_to_func(struct nfit_mem *nfit_mem, unsigned int cmd,
+		struct nd_cmd_pkg *call_pkg)
+{
+	if (call_pkg) {
+		int i;
+
+		if (nfit_mem->family != call_pkg->nd_family)
+			return -ENOTTY;
+
+		for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
+			if (call_pkg->nd_reserved2[i])
+				return -EINVAL;
+		return call_pkg->nd_command;
+	}
+
+	/* Linux ND commands == NVDIMM_FAMILY_INTEL function numbers */
+	if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
+		return cmd;
+
+	/*
+	 * Force function number validation to fail since 0 is never
+	 * published as a valid function in dsm_mask.
+	 */
+	return 0;
+}
+
 int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 		unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
 {
@@ -220,21 +246,11 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 	unsigned long cmd_mask, dsm_mask;
 	u32 offset, fw_status = 0;
 	acpi_handle handle;
-	unsigned int func;
 	const guid_t *guid;
-	int rc, i;
+	int func, rc, i;
 
 	if (cmd_rc)
 		*cmd_rc = -EINVAL;
-	func = cmd;
-	if (cmd == ND_CMD_CALL) {
-		call_pkg = buf;
-		func = call_pkg->nd_command;
-
-		for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
-			if (call_pkg->nd_reserved2[i])
-				return -EINVAL;
-	}
 
 	if (nvdimm) {
 		struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
@@ -242,9 +258,12 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 
 		if (!adev)
 			return -ENOTTY;
-		if (call_pkg && nfit_mem->family != call_pkg->nd_family)
-			return -ENOTTY;
 
+		if (cmd == ND_CMD_CALL)
+			call_pkg = buf;
+		func = cmd_to_func(nfit_mem, cmd, call_pkg);
+		if (func < 0)
+			return func;
 		dimm_name = nvdimm_name(nvdimm);
 		cmd_name = nvdimm_cmd_name(cmd);
 		cmd_mask = nvdimm_cmd_mask(nvdimm);
@@ -255,6 +274,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 	} else {
 		struct acpi_device *adev = to_acpi_dev(acpi_desc);
 
+		func = cmd;
 		cmd_name = nvdimm_bus_cmd_name(cmd);
 		cmd_mask = nd_desc->cmd_mask;
 		dsm_mask = cmd_mask;
@@ -269,7 +289,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 	if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
 		return -ENOTTY;
 
-	if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask))
+	/*
+	 * Check for a valid command.  For ND_CMD_CALL, we also have to
+	 * make sure that the DSM function is supported.
+	 */
+	if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask))
+		return -ENOTTY;
+	else if (!test_bit(cmd, &cmd_mask))
 		return -ENOTTY;
 
 	in_obj.type = ACPI_TYPE_PACKAGE;
@@ -1503,6 +1529,13 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
 		return 0;
 	}
 
+	/*
+	 * Function 0 is the command interrogation function, don't
+	 * export it to potential userspace use, and enable it to be
+	 * used as an error value in acpi_nfit_ctl().
+	 */
+	dsm_mask &= ~1UL;
+
 	guid = to_nfit_uuid(nfit_mem->family);
 	for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
 		if (acpi_check_dsm(adev_dimm->handle, guid, 1, 1ULL << i))
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 8fb74d9..a7907b5 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -147,9 +147,9 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
 		{
 			struct acpi_srat_mem_affinity *p =
 			    (struct acpi_srat_mem_affinity *)header;
-			pr_debug("SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n",
-				 (unsigned long)p->base_address,
-				 (unsigned long)p->length,
+			pr_debug("SRAT Memory (0x%llx length 0x%llx) in proximity domain %d %s%s%s\n",
+				 (unsigned long long)p->base_address,
+				 (unsigned long long)p->length,
 				 p->proximity_domain,
 				 (p->flags & ACPI_SRAT_MEM_ENABLED) ?
 				 "enabled" : "disabled",
diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c
index 6c99d3f..8735ac9 100644
--- a/drivers/acpi/pmic/intel_pmic_xpower.c
+++ b/drivers/acpi/pmic/intel_pmic_xpower.c
@@ -27,8 +27,11 @@
 #define GPI1_LDO_ON		(3 << 0)
 #define GPI1_LDO_OFF		(4 << 0)
 
-#define AXP288_ADC_TS_PIN_GPADC	0xf2
-#define AXP288_ADC_TS_PIN_ON	0xf3
+#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK		GENMASK(1, 0)
+#define AXP288_ADC_TS_CURRENT_OFF			(0 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING		(1 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND		(2 << 0)
+#define AXP288_ADC_TS_CURRENT_ON			(3 << 0)
 
 static struct pmic_table power_table[] = {
 	{
@@ -211,22 +214,44 @@ static int intel_xpower_pmic_update_power(struct regmap *regmap, int reg,
  */
 static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg)
 {
+	int ret, adc_ts_pin_ctrl;
 	u8 buf[2];
-	int ret;
 
-	ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL,
-			   AXP288_ADC_TS_PIN_GPADC);
+	/*
+	 * The current-source used for the battery temp-sensor (TS) is shared
+	 * with the GPADC. For proper fuel-gauge and charger operation the TS
+	 * current-source needs to be permanently on. But to read the GPADC we
+	 * need to temporary switch the TS current-source to ondemand, so that
+	 * the GPADC can use it, otherwise we will always read an all 0 value.
+	 *
+	 * Note that the switching from on to on-ondemand is not necessary
+	 * when the TS current-source is off (this happens on devices which
+	 * do not use the TS-pin).
+	 */
+	ret = regmap_read(regmap, AXP288_ADC_TS_PIN_CTRL, &adc_ts_pin_ctrl);
 	if (ret)
 		return ret;
 
-	/* After switching to the GPADC pin give things some time to settle */
-	usleep_range(6000, 10000);
+	if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) {
+		ret = regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL,
+					 AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+					 AXP288_ADC_TS_CURRENT_ON_ONDEMAND);
+		if (ret)
+			return ret;
+
+		/* Wait a bit after switching the current-source */
+		usleep_range(6000, 10000);
+	}
 
 	ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2);
 	if (ret == 0)
 		ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f);
 
-	regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON);
+	if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) {
+		regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL,
+				   AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+				   AXP288_ADC_TS_CURRENT_ON);
+	}
 
 	return ret;
 }
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 1b475bc..665e93c 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -131,6 +131,23 @@ void acpi_power_resources_list_free(struct list_head *list)
 	}
 }
 
+static bool acpi_power_resource_is_dup(union acpi_object *package,
+				       unsigned int start, unsigned int i)
+{
+	acpi_handle rhandle, dup;
+	unsigned int j;
+
+	/* The caller is expected to check the package element types */
+	rhandle = package->package.elements[i].reference.handle;
+	for (j = start; j < i; j++) {
+		dup = package->package.elements[j].reference.handle;
+		if (dup == rhandle)
+			return true;
+	}
+
+	return false;
+}
+
 int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
 				 struct list_head *list)
 {
@@ -150,6 +167,11 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
 			err = -ENODEV;
 			break;
 		}
+
+		/* Some ACPI tables contain duplicate power resource references */
+		if (acpi_power_resource_is_dup(package, start, i))
+			continue;
+
 		err = acpi_add_power_resource(rhandle);
 		if (err)
 			break;
diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c
index 324b35bf..f567fa5 100644
--- a/drivers/acpi/spcr.c
+++ b/drivers/acpi/spcr.c
@@ -148,6 +148,13 @@ int __init parse_spcr(bool earlycon)
 	}
 
 	switch (table->baud_rate) {
+	case 0:
+		/*
+		 * SPCR 1.04 defines 0 as a preconfigured state of UART.
+		 * Assume firmware or bootloader configures console correctly.
+		 */
+		baud_rate = 0;
+		break;
 	case 3:
 		baud_rate = 9600;
 		break;
@@ -196,6 +203,10 @@ int __init parse_spcr(bool earlycon)
 		 * UART so don't attempt to change to the baud rate state
 		 * in the table because driver cannot calculate the dividers
 		 */
+		baud_rate = 0;
+	}
+
+	if (!baud_rate) {
 		snprintf(opts, sizeof(opts), "%s,%s,0x%llx", uart, iotype,
 			 table->serial_port.address);
 	} else {
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index cde7dcc..018c624 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -355,6 +355,7 @@ struct binder_error {
  * @min_priority:         minimum scheduling priority
  *                        (invariant after initialized)
  * @inherit_rt:           inherit RT scheduling policy from caller
+ * @txn_security_ctx:     require sender's security context
  *                        (invariant after initialized)
  * @async_todo:           list of async work items
  *                        (protected by @proc->inner_lock)
@@ -394,6 +395,7 @@ struct binder_node {
 		u8 sched_policy:2;
 		u8 inherit_rt:1;
 		u8 accept_fds:1;
+		u8 txn_security_ctx:1;
 		u8 min_priority;
 	};
 	bool has_async_transaction;
@@ -651,6 +653,7 @@ struct binder_transaction {
 	struct binder_priority	saved_priority;
 	bool    set_priority_called;
 	kuid_t	sender_euid;
+	binder_uintptr_t security_ctx;
 	/**
 	 * @lock:  protects @from, @to_proc, and @to_thread
 	 *
@@ -1360,6 +1363,7 @@ static struct binder_node *binder_init_node_ilocked(
 	node->min_priority = to_kernel_prio(node->sched_policy, priority);
 	node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
 	node->inherit_rt = !!(flags & FLAT_BINDER_FLAG_INHERIT_RT);
+	node->txn_security_ctx = !!(flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX);
 	spin_lock_init(&node->lock);
 	INIT_LIST_HEAD(&node->work.entry);
 	INIT_LIST_HEAD(&node->async_todo);
@@ -2897,6 +2901,8 @@ static void binder_transaction(struct binder_proc *proc,
 	binder_size_t last_fixup_min_off = 0;
 	struct binder_context *context = proc->context;
 	int t_debug_id = atomic_inc_return(&binder_last_id);
+	char *secctx = NULL;
+	u32 secctx_sz = 0;
 
 	e = binder_transaction_log_add(&binder_transaction_log);
 	e->debug_id = t_debug_id;
@@ -3120,6 +3126,20 @@ static void binder_transaction(struct binder_proc *proc,
 		t->priority = target_proc->default_priority;
 	}
 
+	if (target_node && target_node->txn_security_ctx) {
+		u32 secid;
+
+		security_task_getsecid(proc->tsk, &secid);
+		ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
+		if (ret) {
+			return_error = BR_FAILED_REPLY;
+			return_error_param = ret;
+			return_error_line = __LINE__;
+			goto err_get_secctx_failed;
+		}
+		extra_buffers_size += ALIGN(secctx_sz, sizeof(u64));
+	}
+
 	trace_binder_transaction(reply, t, target_node);
 
 	t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
@@ -3136,6 +3156,19 @@ static void binder_transaction(struct binder_proc *proc,
 		t->buffer = NULL;
 		goto err_binder_alloc_buf_failed;
 	}
+	if (secctx) {
+		size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
+				    ALIGN(tr->offsets_size, sizeof(void *)) +
+				    ALIGN(extra_buffers_size, sizeof(void *)) -
+				    ALIGN(secctx_sz, sizeof(u64));
+		char *kptr = t->buffer->data + buf_offset;
+
+		t->security_ctx = (uintptr_t)kptr +
+		    binder_alloc_get_user_buffer_offset(&target_proc->alloc);
+		memcpy(kptr, secctx, secctx_sz);
+		security_release_secctx(secctx, secctx_sz);
+		secctx = NULL;
+	}
 	t->buffer->debug_id = t->debug_id;
 	t->buffer->transaction = t;
 	t->buffer->target_node = target_node;
@@ -3406,6 +3439,9 @@ static void binder_transaction(struct binder_proc *proc,
 	t->buffer->transaction = NULL;
 	binder_alloc_free_buf(&target_proc->alloc, t->buffer);
 err_binder_alloc_buf_failed:
+	if (secctx)
+		security_release_secctx(secctx, secctx_sz);
+err_get_secctx_failed:
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
@@ -4052,11 +4088,13 @@ static int binder_thread_read(struct binder_proc *proc,
 
 	while (1) {
 		uint32_t cmd;
-		struct binder_transaction_data tr;
+		struct binder_transaction_data_secctx tr;
+		struct binder_transaction_data *trd = &tr.transaction_data;
 		struct binder_work *w = NULL;
 		struct list_head *list = NULL;
 		struct binder_transaction *t = NULL;
 		struct binder_thread *t_from;
+		size_t trsize = sizeof(*trd);
 
 		binder_inner_proc_lock(proc);
 		if (!binder_worklist_empty_ilocked(&thread->todo))
@@ -4252,41 +4290,47 @@ static int binder_thread_read(struct binder_proc *proc,
 			struct binder_node *target_node = t->buffer->target_node;
 			struct binder_priority node_prio;
 
-			tr.target.ptr = target_node->ptr;
-			tr.cookie =  target_node->cookie;
+			trd->target.ptr = target_node->ptr;
+			trd->cookie =  target_node->cookie;
 			node_prio.sched_policy = target_node->sched_policy;
 			node_prio.prio = target_node->min_priority;
 			binder_transaction_priority(current, t, node_prio,
 						    target_node->inherit_rt);
 			cmd = BR_TRANSACTION;
 		} else {
-			tr.target.ptr = 0;
-			tr.cookie = 0;
+			trd->target.ptr = 0;
+			trd->cookie = 0;
 			cmd = BR_REPLY;
 		}
-		tr.code = t->code;
-		tr.flags = t->flags;
-		tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);
+		trd->code = t->code;
+		trd->flags = t->flags;
+		trd->sender_euid = from_kuid(current_user_ns(), t->sender_euid);
 
 		t_from = binder_get_txn_from(t);
 		if (t_from) {
 			struct task_struct *sender = t_from->proc->tsk;
 
-			tr.sender_pid = task_tgid_nr_ns(sender,
-							task_active_pid_ns(current));
+			trd->sender_pid =
+				task_tgid_nr_ns(sender,
+						task_active_pid_ns(current));
 		} else {
-			tr.sender_pid = 0;
+			trd->sender_pid = 0;
 		}
 
-		tr.data_size = t->buffer->data_size;
-		tr.offsets_size = t->buffer->offsets_size;
-		tr.data.ptr.buffer = (binder_uintptr_t)
+		trd->data_size = t->buffer->data_size;
+		trd->offsets_size = t->buffer->offsets_size;
+		trd->data.ptr.buffer = (binder_uintptr_t)
 			((uintptr_t)t->buffer->data +
 			binder_alloc_get_user_buffer_offset(&proc->alloc));
-		tr.data.ptr.offsets = tr.data.ptr.buffer +
+		trd->data.ptr.offsets = trd->data.ptr.buffer +
 					ALIGN(t->buffer->data_size,
 					    sizeof(void *));
 
+		tr.secctx = t->security_ctx;
+		if (t->security_ctx) {
+			cmd = BR_TRANSACTION_SEC_CTX;
+			trsize = sizeof(tr);
+		}
 		if (put_user(cmd, (uint32_t __user *)ptr)) {
 			if (t_from)
 				binder_thread_dec_tmpref(t_from);
@@ -4297,7 +4341,7 @@ static int binder_thread_read(struct binder_proc *proc,
 			return -EFAULT;
 		}
 		ptr += sizeof(uint32_t);
-		if (copy_to_user(ptr, &tr, sizeof(tr))) {
+		if (copy_to_user(ptr, &tr, trsize)) {
 			if (t_from)
 				binder_thread_dec_tmpref(t_from);
 
@@ -4306,7 +4350,7 @@ static int binder_thread_read(struct binder_proc *proc,
 
 			return -EFAULT;
 		}
-		ptr += sizeof(tr);
+		ptr += trsize;
 
 		trace_binder_transaction_received(t);
 		binder_stat_br(proc, thread, cmd);
@@ -4314,16 +4358,18 @@ static int binder_thread_read(struct binder_proc *proc,
 			     "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",
 			     proc->pid, thread->pid,
 			     (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
-			     "BR_REPLY",
+				(cmd == BR_TRANSACTION_SEC_CTX) ?
+				     "BR_TRANSACTION_SEC_CTX" : "BR_REPLY",
 			     t->debug_id, t_from ? t_from->proc->pid : 0,
 			     t_from ? t_from->pid : 0, cmd,
 			     t->buffer->data_size, t->buffer->offsets_size,
-			     (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);
+			     (u64)trd->data.ptr.buffer,
+			     (u64)trd->data.ptr.offsets);
 
 		if (t_from)
 			binder_thread_dec_tmpref(t_from);
 		t->buffer->allow_user_free = 1;
-		if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
+		if (cmd != BR_REPLY && !(t->flags & TF_ONE_WAY)) {
 			binder_inner_proc_lock(thread->proc);
 			t->to_parent = thread->transaction_stack;
 			t->to_thread = thread;
@@ -4668,7 +4714,8 @@ static int binder_ioctl_write_read(struct file *filp,
 	return ret;
 }
 
-static int binder_ioctl_set_ctx_mgr(struct file *filp)
+static int binder_ioctl_set_ctx_mgr(struct file *filp,
+				    struct flat_binder_object *fbo)
 {
 	int ret = 0;
 	struct binder_proc *proc = filp->private_data;
@@ -4697,7 +4744,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp)
 	} else {
 		context->binder_context_mgr_uid = curr_euid;
 	}
-	new_node = binder_new_node(proc, NULL);
+	new_node = binder_new_node(proc, fbo);
 	if (!new_node) {
 		ret = -ENOMEM;
 		goto out;
@@ -4715,6 +4762,42 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp)
 	return ret;
 }
 
+static int binder_ioctl_get_node_info_for_ref(struct binder_proc *proc,
+		struct binder_node_info_for_ref *info)
+{
+	struct binder_node *node;
+	struct binder_context *context = proc->context;
+	__u32 handle = info->handle;
+
+	if (info->strong_count || info->weak_count || info->reserved1 ||
+	    info->reserved2 || info->reserved3) {
+		binder_user_error("%d BINDER_GET_NODE_INFO_FOR_REF: only handle may be non-zero.",
+				  proc->pid);
+		return -EINVAL;
+	}
+
+	/* This ioctl may only be used by the context manager */
+	mutex_lock(&context->context_mgr_node_lock);
+	if (!context->binder_context_mgr_node ||
+		context->binder_context_mgr_node->proc != proc) {
+		mutex_unlock(&context->context_mgr_node_lock);
+		return -EPERM;
+	}
+	mutex_unlock(&context->context_mgr_node_lock);
+
+	node = binder_get_node_from_ref(proc, handle, true, NULL);
+	if (!node)
+		return -EINVAL;
+
+	info->strong_count = node->local_strong_refs +
+		node->internal_strong_refs;
+	info->weak_count = node->local_weak_refs;
+
+	binder_put_node(node);
+
+	return 0;
+}
+
 static int binder_ioctl_get_node_debug_info(struct binder_proc *proc,
 				struct binder_node_debug_info *info)
 {
@@ -4784,8 +4867,20 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		binder_inner_proc_unlock(proc);
 		break;
 	}
+	case BINDER_SET_CONTEXT_MGR_EXT: {
+		struct flat_binder_object fbo;
+
+		if (copy_from_user(&fbo, ubuf, sizeof(fbo))) {
+			ret = -EINVAL;
+			goto err;
+		}
+		ret = binder_ioctl_set_ctx_mgr(filp, &fbo);
+		if (ret)
+			goto err;
+		break;
+	}
 	case BINDER_SET_CONTEXT_MGR:
-		ret = binder_ioctl_set_ctx_mgr(filp);
+		ret = binder_ioctl_set_ctx_mgr(filp, NULL);
 		if (ret)
 			goto err;
 		break;
@@ -4809,6 +4904,25 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		}
 		break;
 	}
+	case BINDER_GET_NODE_INFO_FOR_REF: {
+		struct binder_node_info_for_ref info;
+
+		if (copy_from_user(&info, ubuf, sizeof(info))) {
+			ret = -EFAULT;
+			goto err;
+		}
+
+		ret = binder_ioctl_get_node_info_for_ref(proc, &info);
+		if (ret < 0)
+			goto err;
+
+		if (copy_to_user(ubuf, &info, sizeof(info))) {
+			ret = -EFAULT;
+			goto err;
+		}
+
+		break;
+	}
 	case BINDER_GET_NODE_DEBUG_INFO: {
 		struct binder_node_debug_info info;
 
diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c
index 537d118..3e82a4a 100644
--- a/drivers/ata/sata_rcar.c
+++ b/drivers/ata/sata_rcar.c
@@ -880,7 +880,9 @@ static int sata_rcar_probe(struct platform_device *pdev)
 	int ret = 0;
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0)
+	if (irq < 0)
+		return irq;
+	if (!irq)
 		return -EINVAL;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(struct sata_rcar_priv),
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index e58538c..7ba2436 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -717,7 +717,7 @@ static int he_init_cs_block_rcm(struct he_dev *he_dev)
 			instead of '/ 512', use '>> 9' to prevent a call
 			to divdu3 on x86 platforms
 		*/
-		rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9;
+		rate_cps = (unsigned long long) (1UL << exp) * (man + 512) >> 9;
 
 		if (rate_cps < 10)
 			rate_cps = 10;	/* 2.2.1 minimum payload rate is 10 cps */
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 22a64fd3..3464c49 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -33,6 +33,9 @@ static struct kset *system_kset;
 
 #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr)
 
+#define DRIVER_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \
+	struct driver_attribute driver_attr_##_name =		\
+		__ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)
 
 static int __must_check bus_rescan_devices_helper(struct device *dev,
 						void *data);
@@ -197,7 +200,7 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf,
 	bus_put(bus);
 	return err;
 }
-static DRIVER_ATTR_WO(unbind);
+static DRIVER_ATTR_IGNORE_LOCKDEP(unbind, S_IWUSR, NULL, unbind_store);
 
 /*
  * Manually attach a device to a driver.
@@ -233,7 +236,7 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
 	bus_put(bus);
 	return err;
 }
-static DRIVER_ATTR_WO(bind);
+static DRIVER_ATTR_IGNORE_LOCKDEP(bind, S_IWUSR, NULL, bind_store);
 
 static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
 {
@@ -613,8 +616,10 @@ static void remove_probe_files(struct bus_type *bus)
 static ssize_t uevent_store(struct device_driver *drv, const char *buf,
 			    size_t count)
 {
-	kobject_synth_uevent(&drv->p->kobj, buf, count);
-	return count;
+	int rc;
+
+	rc = kobject_synth_uevent(&drv->p->kobj, buf, count);
+	return rc ? rc : count;
 }
 static DRIVER_ATTR_WO(uevent);
 
@@ -830,8 +835,10 @@ static void klist_devices_put(struct klist_node *n)
 static ssize_t bus_uevent_store(struct bus_type *bus,
 				const char *buf, size_t count)
 {
-	kobject_synth_uevent(&bus->p->subsys.kobj, buf, count);
-	return count;
+	int rc;
+
+	rc = kobject_synth_uevent(&bus->p->subsys.kobj, buf, count);
+	return rc ? rc : count;
 }
 static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
 
diff --git a/drivers/base/core.c b/drivers/base/core.c
index d7b30c3..d46e84d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -996,8 +996,14 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
 static ssize_t uevent_store(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	if (kobject_synth_uevent(&dev->kobj, buf, count))
+	int rc;
+
+	rc = kobject_synth_uevent(&dev->kobj, buf, count);
+
+	if (rc) {
 		dev_err(dev, "uevent: failed to send synthetic uevent\n");
+		return rc;
+	}
 
 	return count;
 }
@@ -1576,6 +1582,8 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
 		return;
 
 	mutex_lock(&gdp_mutex);
+	if (!kobject_has_children(glue_dir))
+		kobject_del(glue_dir);
 	kobject_put(glue_dir);
 	mutex_unlock(&gdp_mutex);
 }
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a027ef5..c5fdacf 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -834,9 +834,6 @@ static void __device_release_driver(struct device *dev, struct device *parent)
 
 	drv = dev->driver;
 	if (drv) {
-		if (driver_allows_async_probing(drv))
-			async_synchronize_full();
-
 		while (device_links_busy(dev)) {
 			device_unlock(dev);
 			if (parent)
@@ -941,6 +938,9 @@ void driver_detach(struct device_driver *drv)
 	struct device_private *dev_prv;
 	struct device *dev;
 
+	if (driver_allows_async_probing(drv))
+		async_synchronize_full();
+
 	for (;;) {
 		spin_lock(&drv->p->klist_devices.k_lock);
 		if (list_empty(&drv->p->klist_devices.k_list)) {
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index d486277..d5e7e8c 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -192,12 +192,12 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
 	if (IS_ERR(opp_table))
 		return 0;
 
-	count = opp_table->regulator_count;
-
 	/* Regulator may not be required for the device */
-	if (!count)
+	if (!opp_table->regulators)
 		goto put_opp_table;
 
+	count = opp_table->regulator_count;
+
 	uV = kmalloc_array(count, sizeof(*uV), GFP_KERNEL);
 	if (!uV)
 		goto put_opp_table;
@@ -921,6 +921,9 @@ static bool _opp_supported_by_regulators(struct dev_pm_opp *opp,
 	struct regulator *reg;
 	int i;
 
+	if (!opp_table->regulators)
+		return true;
+
 	for (i = 0; i < opp_table->regulator_count; i++) {
 		reg = opp_table->regulators[i];
 
@@ -1226,7 +1229,7 @@ static int _allocate_set_opp_data(struct opp_table *opp_table)
 	struct dev_pm_set_opp_data *data;
 	int len, count = opp_table->regulator_count;
 
-	if (WARN_ON(!count))
+	if (WARN_ON(!opp_table->regulators))
 		return -EINVAL;
 
 	/* space for set_opp_data */
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index a12f77e..ad13ec6 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -668,14 +668,15 @@ drbd_set_role(struct drbd_device *const device, enum drbd_role new_role, int for
 		if (rv == SS_TWO_PRIMARIES) {
 			/* Maybe the peer is detected as dead very soon...
 			   retry at most once more in this case. */
-			int timeo;
-			rcu_read_lock();
-			nc = rcu_dereference(connection->net_conf);
-			timeo = nc ? (nc->ping_timeo + 1) * HZ / 10 : 1;
-			rcu_read_unlock();
-			schedule_timeout_interruptible(timeo);
-			if (try < max_tries)
+			if (try < max_tries) {
+				int timeo;
 				try = max_tries - 1;
+				rcu_read_lock();
+				nc = rcu_dereference(connection->net_conf);
+				timeo = nc ? (nc->ping_timeo + 1) * HZ / 10 : 1;
+				rcu_read_unlock();
+				schedule_timeout_interruptible(timeo);
+			}
 			continue;
 		}
 		if (rv < SS_SUCCESS) {
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 796eaf3..1aad373 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -3361,7 +3361,7 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_peer_device *peer_device,
 	enum drbd_conns rv = C_MASK;
 	enum drbd_disk_state mydisk;
 	struct net_conf *nc;
-	int hg, rule_nr, rr_conflict, tentative;
+	int hg, rule_nr, rr_conflict, tentative, always_asbp;
 
 	mydisk = device->state.disk;
 	if (mydisk == D_NEGOTIATING)
@@ -3412,8 +3412,12 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_peer_device *peer_device,
 
 	rcu_read_lock();
 	nc = rcu_dereference(peer_device->connection->net_conf);
+	always_asbp = nc->always_asbp;
+	rr_conflict = nc->rr_conflict;
+	tentative = nc->tentative;
+	rcu_read_unlock();
 
-	if (hg == 100 || (hg == -100 && nc->always_asbp)) {
+	if (hg == 100 || (hg == -100 && always_asbp)) {
 		int pcount = (device->state.role == R_PRIMARY)
 			   + (peer_role == R_PRIMARY);
 		int forced = (hg == -100);
@@ -3452,9 +3456,6 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_peer_device *peer_device,
 			     "Sync from %s node\n",
 			     (hg < 0) ? "peer" : "this");
 	}
-	rr_conflict = nc->rr_conflict;
-	tentative = nc->tentative;
-	rcu_read_unlock();
 
 	if (hg == -100) {
 		/* FIXME this log message is not correct if we end up here
@@ -4138,7 +4139,7 @@ static int receive_uuids(struct drbd_connection *connection, struct packet_info
 	kfree(device->p_uuid);
 	device->p_uuid = p_uuid;
 
-	if (device->state.conn < C_CONNECTED &&
+	if ((device->state.conn < C_CONNECTED || device->state.pdsk == D_DISKLESS) &&
 	    device->state.disk < D_INCONSISTENT &&
 	    device->state.role == R_PRIMARY &&
 	    (device->ed_uuid & ~((u64)1)) != (p_uuid[UI_CURRENT] & ~((u64)1))) {
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 6d61633a..24a3fb3 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -82,6 +82,7 @@
 
 static DEFINE_IDR(loop_index_idr);
 static DEFINE_MUTEX(loop_index_mutex);
+static DEFINE_MUTEX(loop_ctl_mutex);
 
 static int max_part;
 static int part_shift;
@@ -1018,7 +1019,7 @@ static int loop_clr_fd(struct loop_device *lo)
 	 */
 	if (atomic_read(&lo->lo_refcnt) > 1) {
 		lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
-		mutex_unlock(&lo->lo_ctl_mutex);
+		mutex_unlock(&loop_ctl_mutex);
 		return 0;
 	}
 
@@ -1070,12 +1071,12 @@ static int loop_clr_fd(struct loop_device *lo)
 	if (!part_shift)
 		lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
 	loop_unprepare_queue(lo);
-	mutex_unlock(&lo->lo_ctl_mutex);
+	mutex_unlock(&loop_ctl_mutex);
 	/*
-	 * Need not hold lo_ctl_mutex to fput backing file.
-	 * Calling fput holding lo_ctl_mutex triggers a circular
+	 * Need not hold loop_ctl_mutex to fput backing file.
+	 * Calling fput holding loop_ctl_mutex triggers a circular
 	 * lock dependency possibility warning as fput can take
-	 * bd_mutex which is usually taken before lo_ctl_mutex.
+	 * bd_mutex which is usually taken before loop_ctl_mutex.
 	 */
 	fput(filp);
 	return 0;
@@ -1097,6 +1098,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 	if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE)
 		return -EINVAL;
 
+	if (lo->lo_offset != info->lo_offset ||
+	    lo->lo_sizelimit != info->lo_sizelimit) {
+		sync_blockdev(lo->lo_device);
+		kill_bdev(lo->lo_device);
+	}
+
 	/* I/O need to be drained during transfer transition */
 	blk_mq_freeze_queue(lo->lo_queue);
 
@@ -1125,6 +1132,14 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 
 	if (lo->lo_offset != info->lo_offset ||
 	    lo->lo_sizelimit != info->lo_sizelimit) {
+		/* kill_bdev should have truncated all the pages */
+		if (lo->lo_device->bd_inode->i_mapping->nrpages) {
+			err = -EAGAIN;
+			pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
+				__func__, lo->lo_number, lo->lo_file_name,
+				lo->lo_device->bd_inode->i_mapping->nrpages);
+			goto exit;
+		}
 		if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) {
 			err = -EFBIG;
 			goto exit;
@@ -1175,12 +1190,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 static int
 loop_get_status(struct loop_device *lo, struct loop_info64 *info)
 {
-	struct file *file;
+	struct path path;
 	struct kstat stat;
 	int ret;
 
 	if (lo->lo_state != Lo_bound) {
-		mutex_unlock(&lo->lo_ctl_mutex);
+		mutex_unlock(&loop_ctl_mutex);
 		return -ENXIO;
 	}
 
@@ -1199,17 +1214,17 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info)
 		       lo->lo_encrypt_key_size);
 	}
 
-	/* Drop lo_ctl_mutex while we call into the filesystem. */
-	file = get_file(lo->lo_backing_file);
-	mutex_unlock(&lo->lo_ctl_mutex);
-	ret = vfs_getattr(&file->f_path, &stat, STATX_INO,
-			  AT_STATX_SYNC_AS_STAT);
+	/* Drop loop_ctl_mutex while we call into the filesystem. */
+	path = lo->lo_backing_file->f_path;
+	path_get(&path);
+	mutex_unlock(&loop_ctl_mutex);
+	ret = vfs_getattr(&path, &stat, STATX_INO, AT_STATX_SYNC_AS_STAT);
 	if (!ret) {
 		info->lo_device = huge_encode_dev(stat.dev);
 		info->lo_inode = stat.ino;
 		info->lo_rdevice = huge_encode_dev(stat.rdev);
 	}
-	fput(file);
+	path_put(&path);
 	return ret;
 }
 
@@ -1294,7 +1309,7 @@ loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) {
 	int err;
 
 	if (!arg) {
-		mutex_unlock(&lo->lo_ctl_mutex);
+		mutex_unlock(&loop_ctl_mutex);
 		return -EINVAL;
 	}
 	err = loop_get_status(lo, &info64);
@@ -1312,7 +1327,7 @@ loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) {
 	int err;
 
 	if (!arg) {
-		mutex_unlock(&lo->lo_ctl_mutex);
+		mutex_unlock(&loop_ctl_mutex);
 		return -EINVAL;
 	}
 	err = loop_get_status(lo, &info64);
@@ -1346,22 +1361,39 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg)
 
 static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
 {
+	int err = 0;
+
 	if (lo->lo_state != Lo_bound)
 		return -ENXIO;
 
 	if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg))
 		return -EINVAL;
 
+	if (lo->lo_queue->limits.logical_block_size != arg) {
+		sync_blockdev(lo->lo_device);
+		kill_bdev(lo->lo_device);
+	}
+
 	blk_mq_freeze_queue(lo->lo_queue);
 
+	/* kill_bdev should have truncated all the pages */
+	if (lo->lo_queue->limits.logical_block_size != arg &&
+			lo->lo_device->bd_inode->i_mapping->nrpages) {
+		err = -EAGAIN;
+		pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
+			__func__, lo->lo_number, lo->lo_file_name,
+			lo->lo_device->bd_inode->i_mapping->nrpages);
+		goto out_unfreeze;
+	}
+
 	blk_queue_logical_block_size(lo->lo_queue, arg);
 	blk_queue_physical_block_size(lo->lo_queue, arg);
 	blk_queue_io_min(lo->lo_queue, arg);
 	loop_update_dio(lo);
-
+out_unfreeze:
 	blk_mq_unfreeze_queue(lo->lo_queue);
 
-	return 0;
+	return err;
 }
 
 static int lo_ioctl(struct block_device *bdev, fmode_t mode,
@@ -1370,7 +1402,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
 	struct loop_device *lo = bdev->bd_disk->private_data;
 	int err;
 
-	mutex_lock_nested(&lo->lo_ctl_mutex, 1);
+	mutex_lock_nested(&loop_ctl_mutex, 1);
 	switch (cmd) {
 	case LOOP_SET_FD:
 		err = loop_set_fd(lo, mode, bdev, arg);
@@ -1379,7 +1411,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
 		err = loop_change_fd(lo, bdev, arg);
 		break;
 	case LOOP_CLR_FD:
-		/* loop_clr_fd would have unlocked lo_ctl_mutex on success */
+		/* loop_clr_fd would have unlocked loop_ctl_mutex on success */
 		err = loop_clr_fd(lo);
 		if (!err)
 			goto out_unlocked;
@@ -1392,7 +1424,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
 		break;
 	case LOOP_GET_STATUS:
 		err = loop_get_status_old(lo, (struct loop_info __user *) arg);
-		/* loop_get_status() unlocks lo_ctl_mutex */
+		/* loop_get_status() unlocks loop_ctl_mutex */
 		goto out_unlocked;
 	case LOOP_SET_STATUS64:
 		err = -EPERM;
@@ -1402,7 +1434,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
 		break;
 	case LOOP_GET_STATUS64:
 		err = loop_get_status64(lo, (struct loop_info64 __user *) arg);
-		/* loop_get_status() unlocks lo_ctl_mutex */
+		/* loop_get_status() unlocks loop_ctl_mutex */
 		goto out_unlocked;
 	case LOOP_SET_CAPACITY:
 		err = -EPERM;
@@ -1422,7 +1454,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
 	default:
 		err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
 	}
-	mutex_unlock(&lo->lo_ctl_mutex);
+	mutex_unlock(&loop_ctl_mutex);
 
 out_unlocked:
 	return err;
@@ -1539,7 +1571,7 @@ loop_get_status_compat(struct loop_device *lo,
 	int err;
 
 	if (!arg) {
-		mutex_unlock(&lo->lo_ctl_mutex);
+		mutex_unlock(&loop_ctl_mutex);
 		return -EINVAL;
 	}
 	err = loop_get_status(lo, &info64);
@@ -1556,16 +1588,16 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode,
 
 	switch(cmd) {
 	case LOOP_SET_STATUS:
-		mutex_lock(&lo->lo_ctl_mutex);
+		mutex_lock(&loop_ctl_mutex);
 		err = loop_set_status_compat(
 			lo, (const struct compat_loop_info __user *) arg);
-		mutex_unlock(&lo->lo_ctl_mutex);
+		mutex_unlock(&loop_ctl_mutex);
 		break;
 	case LOOP_GET_STATUS:
-		mutex_lock(&lo->lo_ctl_mutex);
+		mutex_lock(&loop_ctl_mutex);
 		err = loop_get_status_compat(
 			lo, (struct compat_loop_info __user *) arg);
-		/* loop_get_status() unlocks lo_ctl_mutex */
+		/* loop_get_status() unlocks loop_ctl_mutex */
 		break;
 	case LOOP_SET_CAPACITY:
 	case LOOP_CLR_FD:
@@ -1609,7 +1641,7 @@ static void __lo_release(struct loop_device *lo)
 	if (atomic_dec_return(&lo->lo_refcnt))
 		return;
 
-	mutex_lock(&lo->lo_ctl_mutex);
+	mutex_lock(&loop_ctl_mutex);
 	if (lo->lo_flags & LO_FLAGS_AUTOCLEAR) {
 		/*
 		 * In autoclear mode, stop the loop thread
@@ -1627,7 +1659,7 @@ static void __lo_release(struct loop_device *lo)
 		blk_mq_unfreeze_queue(lo->lo_queue);
 	}
 
-	mutex_unlock(&lo->lo_ctl_mutex);
+	mutex_unlock(&loop_ctl_mutex);
 }
 
 static void lo_release(struct gendisk *disk, fmode_t mode)
@@ -1673,10 +1705,10 @@ static int unregister_transfer_cb(int id, void *ptr, void *data)
 	struct loop_device *lo = ptr;
 	struct loop_func_table *xfer = data;
 
-	mutex_lock(&lo->lo_ctl_mutex);
+	mutex_lock(&loop_ctl_mutex);
 	if (lo->lo_encryption == xfer)
 		loop_release_xfer(lo);
-	mutex_unlock(&lo->lo_ctl_mutex);
+	mutex_unlock(&loop_ctl_mutex);
 	return 0;
 }
 
@@ -1849,7 +1881,6 @@ static int loop_add(struct loop_device **l, int i)
 	if (!part_shift)
 		disk->flags |= GENHD_FL_NO_PART_SCAN;
 	disk->flags |= GENHD_FL_EXT_DEVT;
-	mutex_init(&lo->lo_ctl_mutex);
 	atomic_set(&lo->lo_refcnt, 0);
 	lo->lo_number		= i;
 	spin_lock_init(&lo->lo_lock);
@@ -1962,19 +1993,19 @@ static long loop_control_ioctl(struct file *file, unsigned int cmd,
 		ret = loop_lookup(&lo, parm);
 		if (ret < 0)
 			break;
-		mutex_lock(&lo->lo_ctl_mutex);
+		mutex_lock(&loop_ctl_mutex);
 		if (lo->lo_state != Lo_unbound) {
 			ret = -EBUSY;
-			mutex_unlock(&lo->lo_ctl_mutex);
+			mutex_unlock(&loop_ctl_mutex);
 			break;
 		}
 		if (atomic_read(&lo->lo_refcnt) > 0) {
 			ret = -EBUSY;
-			mutex_unlock(&lo->lo_ctl_mutex);
+			mutex_unlock(&loop_ctl_mutex);
 			break;
 		}
 		lo->lo_disk->private_data = NULL;
-		mutex_unlock(&lo->lo_ctl_mutex);
+		mutex_unlock(&loop_ctl_mutex);
 		idr_remove(&loop_index_idr, lo->lo_number);
 		loop_remove(lo);
 		break;
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index dfc54ce..b225175 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -54,7 +54,6 @@ struct loop_device {
 
 	spinlock_t		lo_lock;
 	int			lo_state;
-	struct mutex		lo_ctl_mutex;
 	struct kthread_worker	worker;
 	struct task_struct	*worker_task;
 	bool			use_dio;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index fe1414d..d32cd94 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -275,9 +275,10 @@ static void nbd_size_update(struct nbd_device *nbd)
 	blk_queue_physical_block_size(nbd->disk->queue, config->blksize);
 	set_capacity(nbd->disk, config->bytesize >> 9);
 	if (bdev) {
-		if (bdev->bd_disk)
+		if (bdev->bd_disk) {
 			bd_set_size(bdev, config->bytesize);
-		else
+			set_blocksize(bdev, config->blksize);
+		} else
 			bdev->bd_invalidated = 1;
 		bdput(bdev);
 	}
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 9057dad..f2b1994 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -6308,7 +6308,6 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
 	struct list_head *tmp;
 	int dev_id;
 	char opt_buf[6];
-	bool already = false;
 	bool force = false;
 	int ret;
 
@@ -6341,13 +6340,13 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
 		spin_lock_irq(&rbd_dev->lock);
 		if (rbd_dev->open_count && !force)
 			ret = -EBUSY;
-		else
-			already = test_and_set_bit(RBD_DEV_FLAG_REMOVING,
-							&rbd_dev->flags);
+		else if (test_and_set_bit(RBD_DEV_FLAG_REMOVING,
+					  &rbd_dev->flags))
+			ret = -EINPROGRESS;
 		spin_unlock_irq(&rbd_dev->lock);
 	}
 	spin_unlock(&rbd_dev_list_lock);
-	if (ret < 0 || already)
+	if (ret)
 		return ret;
 
 	if (force) {
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index ad97494..ed4d627 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -41,6 +41,8 @@ MODULE_VERSION(DRV_MODULE_VERSION);
 #define WAITING_FOR_GEN_CMD	0x04
 #define WAITING_FOR_ANY		-1
 
+#define	VDC_MAX_RETRIES	10
+
 static struct workqueue_struct *sunvdc_wq;
 
 struct vdc_req_entry {
@@ -427,6 +429,7 @@ static int __vdc_tx_trigger(struct vdc_port *port)
 		.end_idx		= dr->prod,
 	};
 	int err, delay;
+	int retries = 0;
 
 	hdr.seq = dr->snd_nxt;
 	delay = 1;
@@ -439,6 +442,8 @@ static int __vdc_tx_trigger(struct vdc_port *port)
 		udelay(delay);
 		if ((delay <<= 1) > 128)
 			delay = 128;
+		if (retries++ > VDC_MAX_RETRIES)
+			break;
 	} while (err == -EAGAIN);
 
 	if (err == -ENOTCONN)
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 0d7527c..2f7acdb 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -1027,7 +1027,11 @@ static void floppy_release(struct gendisk *disk, fmode_t mode)
 	struct swim3 __iomem *sw = fs->swim3;
 
 	mutex_lock(&swim3_mutex);
-	if (fs->ref_count > 0 && --fs->ref_count == 0) {
+	if (fs->ref_count > 0)
+		--fs->ref_count;
+	else if (fs->ref_count == -1)
+		fs->ref_count = 0;
+	if (fs->ref_count == 0) {
 		swim3_action(fs, MOTOR_OFF);
 		out_8(&sw->control_bic, 0xff);
 		swim3_select(fs, RELAX);
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 46979d5..57cb8ce 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -359,8 +359,10 @@ static ssize_t backing_dev_store(struct device *dev,
 
 	bdev = bdgrab(I_BDEV(inode));
 	err = blkdev_get(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL, zram);
-	if (err < 0)
+	if (err < 0) {
+		bdev = NULL;
 		goto out;
+	}
 
 	nr_pages = i_size_read(inode) >> PAGE_SHIFT;
 	bitmap_sz = BITS_TO_LONGS(nr_pages) * sizeof(long);
diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c
index d391fae..1fb1ae2 100644
--- a/drivers/bluetooth/bluetooth-power.c
+++ b/drivers/bluetooth/bluetooth-power.c
@@ -32,7 +32,10 @@
 #include <net/cnss.h>
 #endif
 
+#ifdef CONFIG_BTFM_SLIM
 #include "btfm_slim.h"
+#endif
+
 #include <linux/fs.h>
 
 #define BT_PWR_DBG(fmt, arg...)  pr_debug("%s: " fmt "\n", __func__, ## arg)
@@ -43,6 +46,7 @@
 static const struct of_device_id bt_power_match_table[] = {
 	{	.compatible = "qca,ar3002" },
 	{	.compatible = "qca,qca6174" },
+	{	.compatible = "qca,qca6390" },
 	{	.compatible = "qca,wcn3990" },
 	{}
 };
@@ -674,6 +678,7 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	int chipset_version = 0;
 
 	switch (cmd) {
+#ifdef CONFIG_BTFM_SLIM
 	case BT_CMD_SLIM_TEST:
 		if (!bt_power_pdata->slim_dev) {
 			BT_PWR_ERR("slim_dev is null\n");
@@ -683,6 +688,7 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 			bt_power_pdata->slim_dev->platform_data
 		);
 		break;
+#endif
 	case BT_CMD_PWR_CTRL:
 		pwr_cntrl = (int)arg;
 		BT_PWR_ERR("BT_CMD_PWR_CTRL pwr_cntrl:%d", pwr_cntrl);
@@ -736,20 +742,20 @@ static int __init bluetooth_power_init(void)
 
 	bt_major = register_chrdev(0, "bt", &bt_dev_fops);
 	if (bt_major < 0) {
-		BTFMSLIM_ERR("failed to allocate char dev\n");
+		BT_PWR_ERR("failed to allocate char dev\n");
 		goto chrdev_unreg;
 	}
 
 	bt_class = class_create(THIS_MODULE, "bt-dev");
 	if (IS_ERR(bt_class)) {
-		BTFMSLIM_ERR("coudn't create class");
+		BT_PWR_ERR("coudn't create class");
 		goto chrdev_unreg;
 	}
 
 
 	if (device_create(bt_class, NULL, MKDEV(bt_major, 0),
 		NULL, "btpower") == NULL) {
-		BTFMSLIM_ERR("failed to allocate char dev\n");
+		BT_PWR_ERR("failed to allocate char dev\n");
 		goto chrdev_unreg;
 	}
 	return 0;
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index ae3a753..72cd96a 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -889,6 +889,7 @@ static void __exit exit_gdrom(void)
 	platform_device_unregister(pd);
 	platform_driver_unregister(&gdrom_driver);
 	kfree(gd.toc);
+	kfree(gd.cd_info);
 }
 
 module_init(init_gdrom);
diff --git a/drivers/char/diag/Kconfig b/drivers/char/diag/Kconfig
index d54afaa..73296be 100644
--- a/drivers/char/diag/Kconfig
+++ b/drivers/char/diag/Kconfig
@@ -25,13 +25,13 @@
 	  Diag traffic from the USB endpoint.
 
 config DIAGFWD_BRIDGE_CODE
-	bool "Enable QSC/9K DIAG traffic over SMUX/HSIC"
+	bool "Enable remote DIAG traffic over MHI/HSIC"
 	depends on DIAG_CHAR
 	depends on USB_QCOM_DIAG_BRIDGE || MHI_BUS
 	default y
 	help
-	  SMUX/HSIC Transport Layer for DIAG Router. When the MHI/SMUX endpoints
+	  MHI/HSIC Transport Layer for DIAG Router. When the MHI/HSIC endpoints
 	  become available, this bridge driver enables DIAG traffic over MHI
-	  and SMUX.
+	  and HSIC.
 
 endmenu
diff --git a/drivers/char/diag/Makefile b/drivers/char/diag/Makefile
index 0b017c5..3334cb5 100644
--- a/drivers/char/diag/Makefile
+++ b/drivers/char/diag/Makefile
@@ -1,6 +1,5 @@
 obj-$(CONFIG_DIAG_CHAR) := diagchar.o
 obj-$(CONFIG_DIAGFWD_BRIDGE_CODE) += diagfwd_bridge.o
 obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE) += diagfwd_hsic.o
-obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE) += diagfwd_smux.o
 obj-$(CONFIG_MHI_BUS) += diagfwd_mhi.o
 diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagfwd_peripheral.o diagfwd_socket.o diagfwd_rpmsg.o diag_mux.o diag_memorydevice.o diag_usb.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index df68ffc..753678c 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1538,6 +1538,7 @@ void diag_dci_notify_client(int peripheral_mask, int data, int proc)
 					DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
 						"diag: dci client with pid = %d Exited..\n",
 						entry->tgid);
+					put_pid(pid_struct);
 					mutex_unlock(&driver->dci_mutex);
 					return;
 				}
@@ -1552,9 +1553,12 @@ void diag_dci_notify_client(int peripheral_mask, int data, int proc)
 					if (stat)
 						pr_err("diag: Err sending dci signal to client, signal data: 0x%x, stat: %d\n",
 							info.si_int, stat);
-				} else
+				} else {
 					pr_err("diag: client data is corrupted, signal data: 0x%x, stat: %d\n",
 						info.si_int, stat);
+				}
+				put_task_struct(dci_task);
+				put_pid(pid_struct);
 			}
 		}
 	}
@@ -2310,11 +2314,18 @@ struct diag_dci_client_tbl *dci_lookup_client_entry_pid(int tgid)
 			DIAG_LOG(DIAG_DEBUG_DCI,
 				"diag: valid task doesn't exist for pid = %d\n",
 				entry->tgid);
+			put_pid(pid_struct);
 			continue;
 		}
-		if (task_s == entry->client)
-			if (entry->client->tgid == tgid)
+		if (task_s == entry->client) {
+			if (entry->client->tgid == tgid) {
+				put_task_struct(task_s);
+				put_pid(pid_struct);
 				return entry;
+			}
+		}
+		put_task_struct(task_s);
+		put_pid(pid_struct);
 	}
 	return NULL;
 }
@@ -2937,6 +2948,7 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry)
 
 	mutex_lock(&driver->dci_mutex);
 
+	get_task_struct(current);
 	new_entry->client = current;
 	new_entry->tgid = current->tgid;
 	new_entry->client_info.notification_list =
@@ -3091,6 +3103,9 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry)
 		return DIAG_DCI_NO_REG;
 	driver->num_dci_client--;
 	driver->dci_client_id[entry->client_info.client_id - 1] = 0;
+
+	put_task_struct(entry->client);
+	entry->client = NULL;
 	/*
 	 * 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_debugfs.c b/drivers/char/diag/diag_debugfs.c
index d8214ae..db82d3d 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -23,7 +23,6 @@
 #endif
 #ifdef CONFIG_USB_QCOM_DIAG_BRIDGE
 #include "diagfwd_hsic.h"
-#include "diagfwd_smux.h"
 #endif
 #ifdef CONFIG_MHI_BUS
 #include "diagfwd_mhi.h"
diff --git a/drivers/char/diag/diag_ipc_logging.h b/drivers/char/diag/diag_ipc_logging.h
index 8b511d3..39c20da 100644
--- a/drivers/char/diag/diag_ipc_logging.h
+++ b/drivers/char/diag/diag_ipc_logging.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017 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
@@ -24,6 +24,7 @@
 #define DIAG_DEBUG_MASKS	0x0010
 #define DIAG_DEBUG_POWER	0x0020
 #define DIAG_DEBUG_BRIDGE	0x0040
+#define DIAG_DEBUG_CMD_INFO	0x0080
 
 #ifdef CONFIG_IPC_LOGGING
 extern uint16_t diag_debug_mask;
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index c58158b..5d44614 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -59,15 +59,6 @@ struct diag_md_info diag_md[NUM_DIAG_MD_DEV] = {
 		.md_info_inited = 0,
 		.tbl = NULL,
 		.ops = NULL,
-	},
-	{
-		.id = DIAG_MD_SMUX,
-		.ctx = 0,
-		.mempool = POOL_TYPE_QSC_MUX,
-		.num_tbl_entries = 0,
-		.md_info_inited = 0,
-		.tbl = NULL,
-		.ops = NULL,
 	}
 #endif
 };
diff --git a/drivers/char/diag/diag_memorydevice.h b/drivers/char/diag/diag_memorydevice.h
index 516209c..f252d1b 100644
--- a/drivers/char/diag/diag_memorydevice.h
+++ b/drivers/char/diag/diag_memorydevice.h
@@ -18,8 +18,7 @@
 #define DIAG_MD_BRIDGE_BASE	DIAG_MD_LOCAL_LAST
 #define DIAG_MD_MDM		(DIAG_MD_BRIDGE_BASE)
 #define DIAG_MD_MDM2		(DIAG_MD_BRIDGE_BASE + 1)
-#define DIAG_MD_SMUX		(DIAG_MD_BRIDGE_BASE + 2)
-#define DIAG_MD_BRIDGE_LAST	(DIAG_MD_BRIDGE_BASE + 3)
+#define DIAG_MD_BRIDGE_LAST	(DIAG_MD_BRIDGE_BASE + 2)
 
 #ifndef CONFIG_DIAGFWD_BRIDGE_CODE
 #define NUM_DIAG_MD_DEV		DIAG_MD_LOCAL_LAST
diff --git a/drivers/char/diag/diag_mux.c b/drivers/char/diag/diag_mux.c
index c31998c..f6a9f6e 100644
--- a/drivers/char/diag/diag_mux.c
+++ b/drivers/char/diag/diag_mux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-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
@@ -135,9 +135,10 @@ int diag_mux_queue_read(int proc)
 int diag_mux_write(int proc, unsigned char *buf, int len, int ctx)
 {
 	struct diag_logger_t *logger = NULL;
-	int peripheral;
+	int peripheral = -EINVAL, type = -EINVAL, log_sink;
+	unsigned char *offset = NULL;
 
-	if (proc < 0 || proc >= NUM_MUX_PROC)
+	if (proc < 0 || proc >= NUM_MUX_PROC || !buf)
 		return -EINVAL;
 	if (!diag_mux)
 		return -EIO;
@@ -145,16 +146,38 @@ int diag_mux_write(int proc, unsigned char *buf, int len, int ctx)
 	peripheral = diag_md_get_peripheral(ctx);
 	if (peripheral < 0) {
 		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
-			"diag:%s:%d invalid peripheral = %d\n",
-			__func__, __LINE__, peripheral);
+			"diag: invalid peripheral = %d\n", peripheral);
 		return -EINVAL;
 	}
 
-	if (MD_PERIPHERAL_MASK(peripheral) & diag_mux->mux_mask)
+	if (MD_PERIPHERAL_MASK(peripheral) & diag_mux->mux_mask) {
 		logger = diag_mux->md_ptr;
-	else
+		log_sink = DIAG_MEMORY_DEVICE_MODE;
+	} else {
 		logger = diag_mux->usb_ptr;
+		log_sink = DIAG_USB_MODE;
+	}
 
+	if (!proc) {
+		type = GET_BUF_TYPE(ctx);
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+			"diag: Packet from PD: %d, type: %d, len: %d to be written to %s\n",
+			peripheral, type, len,
+			(log_sink ? "MD_device" : "USB"));
+
+		if (type == TYPE_CMD) {
+			if (driver->p_hdlc_disabled[peripheral])
+				offset = buf + 4;
+			else
+				offset = buf;
+
+			DIAG_LOG(DIAG_DEBUG_CMD_INFO,
+				"diag: cmd rsp (%02x %02x %02x %02x) from PD: %d to be written to %s\n",
+				*(offset), *(offset+1), *(offset+2),
+				*(offset+3), peripheral,
+				(log_sink ? "MD_device" : "USB"));
+		}
+	}
 	if (logger && logger->log_ops && logger->log_ops->write)
 		return logger->log_ops->write(proc, buf, len, ctx);
 	return 0;
diff --git a/drivers/char/diag/diag_mux.h b/drivers/char/diag/diag_mux.h
index 2c10f85..9a45cff 100644
--- a/drivers/char/diag/diag_mux.h
+++ b/drivers/char/diag/diag_mux.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-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
@@ -39,8 +39,7 @@ struct diag_mux_ops {
 #define DIAG_MUX_BRIDGE_BASE	DIAG_MUX_LOCAL_LAST
 #define DIAG_MUX_MDM		(DIAG_MUX_BRIDGE_BASE)
 #define DIAG_MUX_MDM2		(DIAG_MUX_BRIDGE_BASE + 1)
-#define DIAG_MUX_SMUX		(DIAG_MUX_BRIDGE_BASE + 2)
-#define DIAG_MUX_BRIDGE_LAST	(DIAG_MUX_BRIDGE_BASE + 3)
+#define DIAG_MUX_BRIDGE_LAST	(DIAG_MUX_BRIDGE_BASE + 2)
 
 #ifndef CONFIG_DIAGFWD_BRIDGE_CODE
 #define NUM_MUX_PROC		DIAG_MUX_LOCAL_LAST
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index f4cf492..8ee8705 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -22,6 +22,7 @@
 #include <linux/sched.h>
 #include <linux/ratelimit.h>
 #include <linux/timer.h>
+#include <linux/sched/task.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <linux/usb/usbdiag.h>
 #endif
@@ -41,6 +42,7 @@
 #include "diag_ipc_logging.h"
 #include "diagfwd_peripheral.h"
 #include "diagfwd_mhi.h"
+#include "diagfwd_hsic.h"
 
 #include <linux/coresight-stm.h>
 #include <linux/kernel.h>
@@ -1126,24 +1128,6 @@ static int diag_process_userspace_remote(int proc, void *buf, int len)
 	return diagfwd_bridge_write(bridge_index, buf, len);
 }
 #else
-int diag_remote_init(void)
-{
-	return 0;
-}
-
-void diag_remote_exit(void)
-{
-}
-
-int diagfwd_bridge_init(void)
-{
-	return 0;
-}
-
-void diagfwd_bridge_exit(void)
-{
-}
-
 uint16_t diag_get_remote_device_mask(void)
 {
 	return 0;
@@ -3674,20 +3658,32 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
 				DIAG_LOG(DIAG_DEBUG_DCI,
 				"diag: valid task doesn't exist for pid = %d\n",
 				entry->tgid);
+				put_pid(pid_struct);
 				continue;
 			}
-			if (task_s == entry->client)
-				if (entry->client->tgid != current->tgid)
+			if (task_s == entry->client) {
+				if (entry->client->tgid != current->tgid) {
+					put_task_struct(task_s);
+					put_pid(pid_struct);
 					continue;
-			if (!entry->in_service)
+				}
+			}
+			if (!entry->in_service) {
+				put_task_struct(task_s);
+				put_pid(pid_struct);
 				continue;
+			}
 			if (copy_to_user(buf + ret, &data_type, sizeof(int))) {
+				put_task_struct(task_s);
+				put_pid(pid_struct);
 				mutex_unlock(&driver->dci_mutex);
 				goto end;
 			}
 			ret += sizeof(int);
 			if (copy_to_user(buf + ret, &entry->client_info.token,
 				sizeof(int))) {
+				put_task_struct(task_s);
+				put_pid(pid_struct);
 				mutex_unlock(&driver->dci_mutex);
 				goto end;
 			}
@@ -3699,9 +3695,13 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
 			atomic_dec(&driver->data_ready_notif[index]);
 			mutex_unlock(&driver->diagchar_mutex);
 			if (exit_stat == 1) {
+				put_task_struct(task_s);
+				put_pid(pid_struct);
 				mutex_unlock(&driver->dci_mutex);
 				goto end;
 			}
+			put_task_struct(task_s);
+			put_pid(pid_struct);
 		}
 		mutex_unlock(&driver->dci_mutex);
 		goto end;
@@ -4216,9 +4216,8 @@ static int __init diagchar_init(void)
 	INIT_LIST_HEAD(&driver->diag_id_list);
 	diag_add_diag_id_to_list(DIAG_ID_APPS, "APPS", APPS_DATA, APPS_DATA);
 	pr_debug("diagchar initialized now");
-	#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-	diag_register_with_mhi();
-	#endif
+	if (IS_ENABLED(CONFIG_DIAGFWD_BRIDGE_CODE))
+		diag_register_with_bridge();
 	return 0;
 
 fail:
@@ -4227,12 +4226,10 @@ static int __init diagchar_init(void)
 	diagchar_cleanup();
 	diag_mux_exit();
 	diagfwd_peripheral_exit();
-	diagfwd_bridge_exit();
 	diagfwd_exit();
 	diagfwd_cntl_exit();
 	diag_dci_exit();
 	diag_masks_exit();
-	diag_remote_exit();
 	return ret;
 
 }
@@ -4248,7 +4245,8 @@ static void diagchar_exit(void)
 	diag_dci_exit();
 	diag_masks_exit();
 	diag_md_session_exit();
-	diag_remote_exit();
+	if (IS_ENABLED(CONFIG_DIAGFWD_BRIDGE_CODE))
+		diag_unregister_bridge();
 	diag_debugfs_cleanup();
 	diagchar_cleanup();
 	pr_info("done diagchar exit\n");
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index c4be169..91a9ab6 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1006,8 +1006,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
 	entry.cmd_code_lo = (uint16_t)(*(uint16_t *)temp);
 	temp += sizeof(uint16_t);
 
-	pr_debug("diag: In %s, received cmd %02x %02x %02x\n",
-		 __func__, entry.cmd_code, entry.subsys_id, entry.cmd_code_hi);
+	DIAG_LOG(DIAG_DEBUG_CMD_INFO, "diag: received cmd %02x %02x %02x\n",
+		 entry.cmd_code, entry.subsys_id, entry.cmd_code_hi);
 
 	if (*buf == DIAG_CMD_LOG_ON_DMND && driver->log_on_demand_support &&
 	    driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask) {
diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c
index fe41845..7803ee1 100644
--- a/drivers/char/diag/diagfwd_bridge.c
+++ b/drivers/char/diag/diagfwd_bridge.c
@@ -18,25 +18,13 @@
 #include <linux/workqueue.h>
 #include <linux/ratelimit.h>
 #include <linux/platform_device.h>
-#ifdef USB_QCOM_DIAG_BRIDGE
-#include <linux/smux.h>
-#endif
 #include "diag_mux.h"
 #include "diagfwd_bridge.h"
-#ifdef USB_QCOM_DIAG_BRIDGE
 #include "diagfwd_hsic.h"
-#include "diagfwd_smux.h"
-#endif
 #include "diagfwd_mhi.h"
 #include "diag_dci.h"
 #include "diag_ipc_logging.h"
 
-#ifdef CONFIG_MHI_BUS
-#define diag_mdm_init		diag_mhi_init
-#else
-#define diag_mdm_init		diag_hsic_init
-#endif
-
 #define BRIDGE_TO_MUX(x)	(x + DIAG_MUX_BRIDGE_BASE)
 
 struct diagfwd_bridge_info bridge_info[NUM_REMOTE_DEV] = {
@@ -53,18 +41,6 @@ struct diagfwd_bridge_info bridge_info[NUM_REMOTE_DEV] = {
 		.dci_wq = NULL,
 	},
 	{
-		.id = DIAGFWD_SMUX,
-		.type = DIAG_DATA_TYPE,
-		.name = "SMUX",
-		.inited = 0,
-		.ctxt = 0,
-		.dci_read_ptr = NULL,
-		.dev_ops = NULL,
-		.dci_read_buf = NULL,
-		.dci_read_len = 0,
-		.dci_wq = NULL,
-	},
-	{
 		.id = DIAGFWD_MDM_DCI,
 		.type = DIAG_DCI_TYPE,
 		.name = "MDM_DCI",
@@ -253,33 +229,6 @@ int diag_remote_dev_write_done(int id, unsigned char *buf, int len, int ctxt)
 	return err;
 }
 
-int diagfwd_bridge_init(void)
-{
-	int err = 0;
-
-	err = diag_mdm_init();
-	if (err)
-		goto fail;
-	#ifdef USB_QCOM_DIAG_BRIDGE
-	err = diag_smux_init();
-	if (err)
-		goto fail;
-	#endif
-	return 0;
-
-fail:
-	pr_err("diag: Unable to initialze diagfwd bridge, err: %d\n", err);
-	return err;
-}
-
-void diagfwd_bridge_exit(void)
-{
-	#ifdef USB_QCOM_DIAG_BRIDGE
-	diag_hsic_exit();
-	diag_smux_exit();
-	#endif
-}
-
 int diagfwd_bridge_close(int id)
 {
 	if (id < 0 || id >= NUM_REMOTE_DEV)
@@ -317,3 +266,18 @@ uint16_t diag_get_remote_device_mask(void)
 	return remote_dev;
 }
 
+void diag_register_with_bridge(void)
+{
+	if (IS_ENABLED(CONFIG_USB_QCOM_DIAG_BRIDGE))
+		diag_register_with_hsic();
+	else if (IS_ENABLED(CONFIG_MHI_BUS))
+		diag_register_with_mhi();
+}
+
+void diag_unregister_bridge(void)
+{
+	if (IS_ENABLED(CONFIG_USB_QCOM_DIAG_BRIDGE))
+		diag_unregister_hsic();
+	else if (IS_ENABLED(CONFIG_MHI_BUS))
+		diag_unregister_mhi();
+}
diff --git a/drivers/char/diag/diagfwd_bridge.h b/drivers/char/diag/diagfwd_bridge.h
index c8043c4..1b3d132 100644
--- a/drivers/char/diag/diagfwd_bridge.h
+++ b/drivers/char/diag/diagfwd_bridge.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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,8 +18,7 @@
  * bottom half of this list.
  */
 #define DIAGFWD_MDM		0
-#define DIAGFWD_SMUX		1
-#define NUM_REMOTE_DATA_DEV	2
+#define NUM_REMOTE_DATA_DEV	1
 #define DIAGFWD_MDM_DCI		NUM_REMOTE_DATA_DEV
 #define NUM_REMOTE_DCI_DEV	(DIAGFWD_MDM_DCI - NUM_REMOTE_DATA_DEV + 1)
 #define NUM_REMOTE_DEV		(NUM_REMOTE_DATA_DEV + NUM_REMOTE_DCI_DEV)
@@ -52,8 +51,6 @@ struct diagfwd_bridge_info {
 };
 
 extern struct diagfwd_bridge_info bridge_info[NUM_REMOTE_DEV];
-int diagfwd_bridge_init(void);
-void diagfwd_bridge_exit(void);
 int diagfwd_bridge_close(int id);
 int diagfwd_bridge_write(int id, unsigned char *buf, int len);
 uint16_t diag_get_remote_device_mask(void);
@@ -66,4 +63,6 @@ int diag_remote_dev_read_done(int id, unsigned char *buf, int len);
 int diag_remote_dev_write_done(int id, unsigned char *buf, int len, int ctxt);
 int diag_remote_init(void);
 void diag_remote_exit(void);
+void diag_register_with_bridge(void);
+void diag_unregister_bridge(void);
 #endif
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index caf833c..9fc58c9 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.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
@@ -1139,6 +1139,9 @@ void diag_real_time_work_fn(struct work_struct *work)
 		if (peripheral > NUM_PERIPHERALS)
 			peripheral = diag_search_peripheral_by_pd(i);
 
+		if (peripheral < 0 || peripheral > NUM_PERIPHERALS)
+			continue;
+
 		if (!driver->feature[peripheral].peripheral_buffering)
 			continue;
 		switch (driver->buffering_mode[i].mode) {
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index 0a291bb..5027c045 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, 2016-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -50,10 +50,65 @@ struct diag_hsic_info diag_hsic[NUM_HSIC_DEV] = {
 	}
 };
 
+static int hsic_buf_tbl_push(struct diag_hsic_info *ch, void *buf, int len)
+{
+	unsigned long flags;
+	struct diag_hsic_buf_tbl_t *item;
+
+	item = kzalloc(sizeof(struct diag_hsic_buf_tbl_t), GFP_ATOMIC);
+	if (!item)
+		return -ENOMEM;
+	kmemleak_not_leak(item);
+
+	spin_lock_irqsave(&ch->lock, flags);
+	item->buf = buf;
+	item->len = len;
+	list_add_tail(&item->link, &ch->buf_tbl);
+	spin_unlock_irqrestore(&ch->lock, flags);
+
+	return 0;
+}
+
+static struct diag_hsic_buf_tbl_t *hsic_buf_tbl_pop(struct diag_hsic_info *ch)
+{
+	unsigned long flags;
+	struct diag_hsic_buf_tbl_t *item = NULL;
+
+	if (!ch || list_empty(&ch->buf_tbl))
+		return NULL;
+
+	spin_lock_irqsave(&ch->lock, flags);
+	item = list_first_entry(&ch->buf_tbl, struct diag_hsic_buf_tbl_t, link);
+	list_del(&item->link);
+	spin_unlock_irqrestore(&ch->lock, flags);
+
+	return item;
+}
+
+static void hsic_buf_tbl_clear(struct diag_hsic_info *ch)
+{
+	unsigned long flags;
+	struct list_head *start, *temp;
+	struct diag_hsic_buf_tbl_t *item = NULL;
+
+	if (!ch)
+		return;
+
+	/* At this point, the channel should already by closed */
+	spin_lock_irqsave(&ch->lock, flags);
+	list_for_each_safe(start, temp, &ch->buf_tbl) {
+		item = list_entry(start, struct diag_hsic_buf_tbl_t,
+				  link);
+		list_del(&item->link);
+		kfree(item);
+
+	}
+	spin_unlock_irqrestore(&ch->lock, flags);
+}
+
 static void diag_hsic_read_complete(void *ctxt, char *buf, int len,
 				    int actual_size)
 {
-	int err = 0;
 	int index = (int)(uintptr_t)ctxt;
 	struct diag_hsic_info *ch = NULL;
 
@@ -69,11 +124,14 @@ static void diag_hsic_read_complete(void *ctxt, char *buf, int len,
 	 * completes. Also, actual size can be negative error codes - do not
 	 * pass on the buffer.
 	 */
-	if (!ch->opened || actual_size <= 0)
+	if (!ch->opened || !buf || actual_size <= 0)
 		goto fail;
-	err = diag_remote_dev_read_done(ch->dev_id, buf, actual_size);
-	if (err)
+	if (hsic_buf_tbl_push(ch, buf, actual_size)) {
+		pr_err_ratelimited("diag: In %s, OOM! Drop incoming packet\n",
+				   __func__);
 		goto fail;
+	}
+	queue_work(ch->hsic_wq, &ch->read_complete_work);
 	return;
 
 fail:
@@ -183,6 +241,7 @@ static int hsic_open(int id)
 	diagmem_init(driver, ch->mempool);
 	/* Notify the bridge that the channel is open */
 	diag_remote_dev_open(ch->dev_id);
+	INIT_LIST_HEAD(&ch->buf_tbl);
 	queue_work(ch->hsic_wq, &(ch->read_work));
 	return 0;
 }
@@ -220,6 +279,7 @@ static int hsic_close(int id)
 	diag_bridge_close(ch->id);
 	diagmem_exit(driver, ch->mempool);
 	diag_remote_dev_close(ch->dev_id);
+	hsic_buf_tbl_clear(ch);
 	return 0;
 }
 
@@ -261,6 +321,30 @@ static void hsic_read_work_fn(struct work_struct *work)
 		queue_work(ch->hsic_wq, &ch->read_work);
 }
 
+static void hsic_read_complete_work_fn(struct work_struct *work)
+{
+	struct diag_hsic_info *ch = container_of(work, struct diag_hsic_info,
+						 read_complete_work);
+	struct diag_hsic_buf_tbl_t *item;
+
+	do {
+		item = hsic_buf_tbl_pop(ch);
+		if (item) {
+			if (diag_remote_dev_read_done(ch->dev_id,
+						      item->buf, item->len))
+				goto fail;
+			kfree(item);
+		}
+	} while (item);
+
+	return;
+
+fail:
+	diagmem_free(driver, item->buf, ch->mempool);
+	queue_work(ch->hsic_wq, &ch->read_work);
+	kfree(item);
+}
+
 static int diag_hsic_probe(struct platform_device *pdev)
 {
 	unsigned long flags;
@@ -406,6 +490,8 @@ int diag_hsic_init(void)
 		ch = &diag_hsic[i];
 		spin_lock_init(&ch->lock);
 		INIT_WORK(&(ch->read_work), hsic_read_work_fn);
+		INIT_WORK(&(ch->read_complete_work),
+			  hsic_read_complete_work_fn);
 		INIT_WORK(&(ch->open_work), hsic_open_work_fn);
 		INIT_WORK(&(ch->close_work), hsic_close_work_fn);
 		strlcpy(wq_name, "DIAG_HSIC_", sizeof(wq_name));
@@ -447,6 +533,24 @@ void diag_hsic_exit(void)
 		if (ch->hsic_wq)
 			destroy_workqueue(ch->hsic_wq);
 	}
-	platform_driver_unregister(&msm_hsic_ch_driver);
 }
 
+void diag_register_with_hsic(void)
+{
+	int ret = 0;
+
+	ret = diag_remote_init();
+	if (ret)
+		return;
+
+	ret = diag_hsic_init();
+	if (ret)
+		diag_remote_exit();
+}
+
+void diag_unregister_hsic(void)
+{
+	platform_driver_unregister(&msm_hsic_ch_driver);
+	diag_hsic_exit();
+	diag_remote_exit();
+}
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index c8e9cf6..6ea27e8 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -12,6 +12,8 @@
 
 #ifndef DIAGFWD_HSIC_H
 #define DIAGFWD_HSIC_H
+
+#include <linux/list.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <linux/usb/usbdiag.h>
 #endif
@@ -23,6 +25,12 @@
 
 #define DIAG_HSIC_NAME_SZ	24
 
+struct diag_hsic_buf_tbl_t {
+	struct list_head link;
+	unsigned char *buf;
+	int len;
+};
+
 struct diag_hsic_info {
 	int id;
 	int dev_id;
@@ -32,16 +40,20 @@ struct diag_hsic_info {
 	uint8_t suspended;
 	char name[DIAG_HSIC_NAME_SZ];
 	struct work_struct read_work;
+	struct work_struct read_complete_work;
 	struct work_struct open_work;
 	struct work_struct close_work;
 	struct workqueue_struct *hsic_wq;
 	spinlock_t lock;
+	struct list_head buf_tbl;
 };
 
 extern struct diag_hsic_info diag_hsic[NUM_HSIC_DEV];
 
 int diag_hsic_init(void);
 void diag_hsic_exit(void);
+void diag_register_with_hsic(void);
+void diag_unregister_hsic(void);
 
 #endif
 
diff --git a/drivers/char/diag/diagfwd_mhi.c b/drivers/char/diag/diagfwd_mhi.c
index 2da564b..b61617f 100644
--- a/drivers/char/diag/diagfwd_mhi.c
+++ b/drivers/char/diag/diagfwd_mhi.c
@@ -764,17 +764,21 @@ void diag_register_with_mhi(void)
 	int ret = 0;
 
 	ret = diag_remote_init();
-	if (ret) {
-		diag_remote_exit();
+	if (ret)
 		return;
-	}
 
-	ret = diagfwd_bridge_init();
+	ret = diag_mhi_init();
 	if (ret) {
-		diagfwd_bridge_exit();
 		diag_remote_exit();
 		return;
 	}
 
 	mhi_driver_register(&diag_mhi_driver);
 }
+
+void diag_unregister_mhi(void)
+{
+	mhi_driver_unregister(&diag_mhi_driver);
+	diag_mhi_exit();
+	diag_remote_exit();
+}
diff --git a/drivers/char/diag/diagfwd_mhi.h b/drivers/char/diag/diagfwd_mhi.h
index 1fcb2e3..7f204cb 100644
--- a/drivers/char/diag/diagfwd_mhi.h
+++ b/drivers/char/diag/diagfwd_mhi.h
@@ -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
@@ -83,4 +83,5 @@ extern struct diag_mhi_info diag_mhi[NUM_MHI_DEV];
 int diag_mhi_init(void);
 void diag_mhi_exit(void);
 void diag_register_with_mhi(void);
+void diag_unregister_mhi(void);
 #endif
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index dabd7a4..e07caeb 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -452,6 +452,7 @@ static void diagfwd_data_read_untag_done(struct diagfwd_info *fwd_info,
 	struct diagfwd_buf_t *temp_fwdinfo_upd = NULL;
 	int flag_buf_1 = 0, flag_buf_2 = 0;
 	uint8_t peripheral, temp_diagid_val;
+	unsigned char *buf_offset = NULL;
 
 	if (!fwd_info || !buf || len <= 0) {
 		diag_ws_release();
@@ -506,9 +507,24 @@ static void diagfwd_data_read_untag_done(struct diagfwd_info *fwd_info,
 		}
 
 		while (processed < len) {
+			/* Debug log to check diag_id header validity*/
 			pr_debug("diag_fr:untagged packet buf contents: %02x %02x %02x %02x\n",
 			 *temp_buf_main, *(temp_buf_main+1),
 			 *(temp_buf_main+2), *(temp_buf_main+3));
+
+			/* Debug log ONLY for CMD channel*/
+			if (fwd_info->type == TYPE_CMD) {
+				/* buf_offset taking into account
+				 * diag_id header and non-hdlc header
+				 */
+				buf_offset = temp_buf_main + 8;
+
+				DIAG_LOG(DIAG_DEBUG_CMD_INFO,
+				"diag: cmd rsp (%02x %02x %02x %02x) received from peripheral: %d\n",
+				*(buf_offset), *(buf_offset+1),
+				*(buf_offset+2), *(buf_offset+3), peripheral);
+			}
+
 			packet_len =
 				*(uint16_t *) (temp_buf_main + 2);
 			if (packet_len > PERIPHERAL_BUF_SZ)
@@ -613,7 +629,7 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
 {
 	int err = 0;
 	int write_len = 0;
-	unsigned char *write_buf = NULL;
+	unsigned char *write_buf = NULL, *buf_offset = NULL;
 	struct diagfwd_buf_t *temp_buf = NULL;
 	uint8_t hdlc_disabled = 0;
 
@@ -639,6 +655,16 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
 
 	hdlc_disabled = driver->p_hdlc_disabled[fwd_info->peripheral];
 
+	if (fwd_info->type == TYPE_CMD) {
+		/*buf_offset taking into account non-hdlc header */
+		buf_offset = buf + 4;
+
+		DIAG_LOG(DIAG_DEBUG_CMD_INFO,
+		"diag: cmd rsp(%02x %02x %02x %02x) received from peripheral: %d\n",
+		*(buf_offset), *(buf_offset+1), *(buf_offset+2),
+		*(buf_offset+3), fwd_info->peripheral);
+	}
+
 	if (!driver->feature[fwd_info->peripheral].encode_hdlc) {
 		if (fwd_info->buf_1 && fwd_info->buf_1->data == buf) {
 			temp_buf = fwd_info->buf_1;
@@ -1132,8 +1158,9 @@ int diagfwd_write(uint8_t peripheral, uint8_t type, void *buf, int len)
 	int err = 0;
 	uint8_t retry_count = 0;
 	uint8_t max_retries = 3;
+	unsigned char *temp_buf = NULL;
 
-	if (peripheral >= NUM_PERIPHERALS || type >= NUM_TYPES)
+	if (peripheral >= NUM_PERIPHERALS || type >= NUM_TYPES || !buf)
 		return -EINVAL;
 
 	if (type == TYPE_CMD || type == TYPE_DCI_CMD) {
@@ -1164,6 +1191,17 @@ int diagfwd_write(uint8_t peripheral, uint8_t type, void *buf, int len)
 	if (!(fwd_info->p_ops && fwd_info->p_ops->write && fwd_info->ctxt))
 		return -EIO;
 
+	if (type == TYPE_CMD) {
+		temp_buf = (unsigned char *)(buf);
+		/* Only raw bytes is sent to peripheral,
+		 * HDLC/NON-HDLC need not be considered
+		 */
+		DIAG_LOG(DIAG_DEBUG_CMD_INFO,
+		"diag: cmd (%02x %02x %02x %02x) ready to be written to p: %d\n",
+		*(temp_buf), *(temp_buf+1), *(temp_buf+2), *(temp_buf+3),
+		peripheral);
+	}
+
 	while (retry_count < max_retries) {
 		err = 0;
 		err = fwd_info->p_ops->write(fwd_info->ctxt, buf, len);
diff --git a/drivers/char/diag/diagfwd_smux.c b/drivers/char/diag/diagfwd_smux.c
deleted file mode 100644
index 4465cc4..0000000
--- a/drivers/char/diag/diagfwd_smux.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/* Copyright (c) 2012, 2014, 2016, 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
- * 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/termios.h>
-#include <linux/slab.h>
-#include <linux/diagchar.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/usb/usbdiag.h>
-
-#include "diagchar.h"
-#include "diagfwd_bridge.h"
-#include "diagfwd_smux.h"
-
-struct diag_smux_info diag_smux[NUM_SMUX_DEV] = {
-	{
-		.id = SMUX_1,
-		.lcid = SMUX_USB_DIAG_0,
-		.dev_id = DIAGFWD_SMUX,
-		.name = "SMUX_1",
-		.read_buf = NULL,
-		.read_len = 0,
-		.in_busy = 0,
-		.enabled = 0,
-		.opened = 0,
-	},
-};
-
-static void diag_smux_event(void *priv, int event_type, const void *metadata)
-{
-	int len = 0;
-	int id = (int)priv;
-	unsigned char *rx_buf = NULL;
-	struct diag_smux_info *ch = NULL;
-
-	if (id < 0 || id >= NUM_SMUX_DEV)
-		return;
-
-	ch = &diag_smux[id];
-	if (metadata) {
-		len = ((struct smux_meta_read *)metadata)->len;
-		rx_buf = ((struct smux_meta_read *)metadata)->buffer;
-	}
-
-	switch (event_type) {
-	case SMUX_CONNECTED:
-		pr_info("diag: SMUX_CONNECTED received, ch: %d\n", ch->id);
-		ch->opened = 1;
-		ch->in_busy = 0;
-		break;
-	case SMUX_DISCONNECTED:
-		ch->opened = 0;
-		msm_smux_close(ch->lcid);
-		pr_info("diag: SMUX_DISCONNECTED received, ch: %d\n", ch->id);
-		break;
-	case SMUX_WRITE_DONE:
-		pr_debug("diag: SMUX Write done, ch: %d\n", ch->id);
-		diag_remote_dev_write_done(ch->dev_id, rx_buf, len, ch->id);
-		break;
-	case SMUX_WRITE_FAIL:
-		pr_info("diag: SMUX Write Failed, ch: %d\n", ch->id);
-		break;
-	case SMUX_READ_FAIL:
-		pr_info("diag: SMUX Read Failed, ch: %d\n", ch->id);
-		break;
-	case SMUX_READ_DONE:
-		ch->read_buf = rx_buf;
-		ch->read_len = len;
-		ch->in_busy = 1;
-		diag_remote_dev_read_done(ch->dev_id, ch->read_buf,
-					  ch->read_len);
-		break;
-	};
-}
-
-static int diag_smux_init_ch(struct diag_smux_info *ch)
-{
-	if (!ch)
-		return -EINVAL;
-
-	if (!ch->enabled) {
-		pr_debug("diag: SMUX channel is not enabled id: %d\n", ch->id);
-		return -ENODEV;
-	}
-
-	if (ch->inited) {
-		pr_debug("diag: SMUX channel %d is already initialize\n",
-			 ch->id);
-		return 0;
-	}
-
-	ch->read_buf = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
-	if (!ch->read_buf)
-		return -ENOMEM;
-
-	ch->inited = 1;
-
-	return 0;
-}
-
-static int smux_get_rx_buffer(void *priv, void **pkt_priv, void **buf,
-			      int size)
-{
-	int id = (int)priv;
-	struct diag_smux_info *ch = NULL;
-
-	if (id < 0 || id >= NUM_SMUX_DEV)
-		return -EINVAL;
-
-	ch = &diag_smux[id];
-
-	if (ch->in_busy) {
-		pr_debug("diag: read buffer for SMUX is BUSY\n");
-		return -EAGAIN;
-	}
-
-	*pkt_priv = (void *)0x1234;
-	*buf = ch->read_buf;
-	ch->in_busy = 1;
-	return 0;
-}
-
-static int smux_open(int id)
-{
-	int err = 0;
-	struct diag_smux_info *ch = NULL;
-
-	if (id < 0 || id >= NUM_SMUX_DEV)
-		return -EINVAL;
-
-	ch = &diag_smux[id];
-	if (ch->opened) {
-		pr_debug("diag: SMUX channel %d is already connected\n",
-			 ch->id);
-		return 0;
-	}
-
-	err = diag_smux_init_ch(ch);
-	if (err) {
-		pr_err("diag: Unable to initialize SMUX channel %d, err: %d\n",
-		       ch->id, err);
-		return err;
-	}
-
-	err = msm_smux_open(ch->lcid, (void *)ch->id, diag_smux_event,
-			    smux_get_rx_buffer);
-	if (err) {
-		pr_err("diag: failed to open SMUX ch %d, err: %d\n",
-		       ch->id, err);
-		return err;
-	}
-	msm_smux_tiocm_set(ch->lcid, TIOCM_DTR, 0);
-	ch->opened = 1;
-	pr_info("diag: SMUX ch %d is connected\n", ch->id);
-	return 0;
-}
-
-static int smux_close(int id)
-{
-	struct diag_smux_info *ch = NULL;
-
-	if (id < 0 || id >= NUM_SMUX_DEV)
-		return -EINVAL;
-
-	ch = &diag_smux[id];
-	if (!ch->enabled) {
-		pr_debug("diag: SMUX channel is not enabled id: %d\n", ch->id);
-		return -ENODEV;
-	}
-
-	msm_smux_close(ch->lcid);
-	ch->opened = 0;
-	ch->in_busy = 1;
-	kfree(ch->read_buf);
-	ch->read_buf = NULL;
-	return 0;
-}
-
-static int smux_queue_read(int id)
-{
-	return 0;
-}
-
-static int smux_write(int id, unsigned char *buf, int len, int ctxt)
-{
-	struct diag_smux_info *ch = NULL;
-
-	if (id < 0 || id >= NUM_SMUX_DEV)
-		return -EINVAL;
-
-	ch = &diag_smux[id];
-	return  msm_smux_write(ch->lcid, NULL, buf, len);
-}
-
-static int smux_fwd_complete(int id, unsigned char *buf, int len, int ctxt)
-{
-	if (id < 0 || id >= NUM_SMUX_DEV)
-		return -EINVAL;
-
-	diag_smux[id].in_busy = 0;
-	return 0;
-}
-
-static int diagfwd_smux_runtime_suspend(struct device *dev)
-{
-	dev_dbg(dev, "pm_runtime: suspending...\n");
-	return 0;
-}
-
-static int diagfwd_smux_runtime_resume(struct device *dev)
-{
-	dev_dbg(dev, "pm_runtime: resuming...\n");
-	return 0;
-}
-
-static const struct dev_pm_ops diagfwd_smux_dev_pm_ops = {
-	.runtime_suspend = diagfwd_smux_runtime_suspend,
-	.runtime_resume = diagfwd_smux_runtime_resume,
-};
-
-static int diagfwd_smux_probe(struct platform_device *pdev)
-{
-	if (!pdev)
-		return -EINVAL;
-
-	pr_debug("diag: SMUX probe called, pdev->id: %d\n", pdev->id);
-	if (pdev->id < 0 || pdev->id >= NUM_SMUX_DEV) {
-		pr_err("diag: No support for SMUX device %d\n", pdev->id);
-		return -EINVAL;
-	}
-
-	diag_smux[pdev->id].enabled = 1;
-	return smux_open(pdev->id);
-}
-
-static int diagfwd_smux_remove(struct platform_device *pdev)
-{
-	if (!pdev)
-		return -EINVAL;
-
-	pr_debug("diag: SMUX probe called, pdev->id: %d\n", pdev->id);
-	if (pdev->id < 0 || pdev->id >= NUM_SMUX_DEV) {
-		pr_err("diag: No support for SMUX device %d\n", pdev->id);
-		return -EINVAL;
-	}
-	if (!diag_smux[pdev->id].enabled) {
-		pr_err("diag: SMUX channel %d is not enabled\n",
-		       diag_smux[pdev->id].id);
-		return -ENODEV;
-	}
-	return smux_close(pdev->id);
-}
-
-static struct platform_driver msm_diagfwd_smux_driver = {
-	.probe = diagfwd_smux_probe,
-	.remove = diagfwd_smux_remove,
-	.driver = {
-		   .name = "SMUX_DIAG",
-		   .owner = THIS_MODULE,
-		   .pm   = &diagfwd_smux_dev_pm_ops,
-		   },
-};
-
-static struct diag_remote_dev_ops diag_smux_fwd_ops = {
-	.open = smux_open,
-	.close = smux_close,
-	.queue_read = smux_queue_read,
-	.write = smux_write,
-	.fwd_complete = smux_fwd_complete,
-	.remote_proc_check = NULL,
-};
-
-int diag_smux_init(void)
-{
-	int i;
-	int err = 0;
-	struct diag_smux_info *ch = NULL;
-	char wq_name[DIAG_SMUX_NAME_SZ + 11];
-
-	for (i = 0; i < NUM_SMUX_DEV; i++) {
-		ch = &diag_smux[i];
-		strlcpy(wq_name, "DIAG_SMUX_", sizeof(wq_name));
-		strlcat(wq_name, ch->name, sizeof(wq_name));
-		ch->smux_wq = create_singlethread_workqueue(wq_name);
-		if (!ch->smux_wq) {
-			err = -ENOMEM;
-			goto fail;
-		}
-		err = diagfwd_bridge_register(ch->dev_id, ch->id,
-					      &diag_smux_fwd_ops);
-		if (err) {
-			pr_err("diag: Unable to register SMUX ch %d with bridge\n",
-			       ch->id);
-			goto fail;
-		}
-	}
-
-	err = platform_driver_register(&msm_diagfwd_smux_driver);
-	if (err) {
-		pr_err("diag: Unable to register SMUX device, err: %d\n", err);
-		goto fail;
-	}
-
-	return 0;
-fail:
-	diag_smux_exit();
-	return err;
-}
-
-void diag_smux_exit(void)
-{
-	int i;
-	struct diag_smux_info *ch = NULL;
-
-	for (i = 0; i < NUM_SMUX_DEV; i++) {
-		ch = &diag_smux[i];
-		kfree(ch->read_buf);
-		ch->read_buf = NULL;
-		ch->enabled = 0;
-		ch->opened = 0;
-		ch->read_len = 0;
-	}
-	platform_driver_unregister(&msm_diagfwd_smux_driver);
-}
diff --git a/drivers/char/diag/diagfwd_smux.h b/drivers/char/diag/diagfwd_smux.h
deleted file mode 100644
index f2514a2..0000000
--- a/drivers/char/diag/diagfwd_smux.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright (c) 2012,2014 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 DIAGFWD_SMUX_H
-#define DIAGFWD_SMUX_H
-
-#include <linux/smux.h>
-
-#define SMUX_1			0
-#define NUM_SMUX_DEV		1
-
-#define DIAG_SMUX_NAME_SZ	24
-
-struct diag_smux_info {
-	int id;
-	int lcid;
-	int dev_id;
-	char name[DIAG_SMUX_NAME_SZ];
-	unsigned char *read_buf;
-	int read_len;
-	int in_busy;
-	int enabled;
-	int inited;
-	int opened;
-	struct work_struct read_work;
-	struct workqueue_struct *smux_wq;
-};
-
-extern struct diag_smux_info diag_smux[NUM_SMUX_DEV];
-
-int diag_smux_init(void);
-void diag_smux_exit(void);
-
-#endif
diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c
index 6e02b08..bad35d6 100644
--- a/drivers/char/diag/diagfwd_socket.c
+++ b/drivers/char/diag/diagfwd_socket.c
@@ -331,6 +331,7 @@ static void diag_state_open_socket(void *ctxt);
 static void diag_state_close_socket(void *ctxt);
 static int diag_socket_write(void *ctxt, unsigned char *buf, int len);
 static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len);
+static void diag_socket_drop_data(struct diag_socket_info *info);
 static void diag_socket_queue_read(void *ctxt);
 
 static struct diag_peripheral_ops socket_ops = {
@@ -593,6 +594,9 @@ static void socket_read_work_fn(struct work_struct *work)
 		return;
 	}
 
+	if (!info->fwd_ctxt && info->port_type == PORT_TYPE_SERVER)
+		diag_socket_drop_data(info);
+
 	if (!atomic_read(&info->opened) && info->port_type == PORT_TYPE_SERVER)
 		diagfwd_buffers_init(info->fwd_ctxt);
 
@@ -663,6 +667,46 @@ static void handle_ctrl_pkt(struct diag_socket_info *info, void *buf, int len)
 	}
 }
 
+static void diag_socket_drop_data(struct diag_socket_info *info)
+{
+	int err = 0;
+	int pkt_len = 0;
+	int read_len = 0;
+	unsigned char *temp = NULL;
+	struct kvec iov;
+	struct msghdr read_msg = {NULL, 0};
+	struct sockaddr_qrtr src_addr = {0};
+	unsigned long flags;
+
+	temp = vzalloc(PERIPHERAL_BUF_SZ);
+	if (!temp)
+		return;
+
+	while (info->data_ready > 0) {
+		iov.iov_base = temp;
+		iov.iov_len = PERIPHERAL_BUF_SZ;
+		read_msg.msg_name = &src_addr;
+		read_msg.msg_namelen = sizeof(src_addr);
+		err = kernel_sock_ioctl(info->hdl, TIOCINQ,
+					(unsigned long)&pkt_len);
+		if (err || pkt_len < 0)
+			break;
+		spin_lock_irqsave(&info->lock, flags);
+		if (info->data_ready > 0) {
+			info->data_ready--;
+		} else {
+			spin_unlock_irqrestore(&info->lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&info->lock, flags);
+		read_len = kernel_recvmsg(info->hdl, &read_msg, &iov, 1,
+					  pkt_len, MSG_DONTWAIT);
+		pr_debug("%s : %s drop total bytes: %d\n", __func__,
+			info->name, read_len);
+	}
+	vfree(temp);
+}
+
 static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
 {
 	int err = 0;
@@ -673,8 +717,8 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
 	int qrtr_ctrl_recd = 0;
 	uint8_t buf_full = 0;
 	unsigned char *temp = NULL;
-	struct kvec iov = {0};
-	struct msghdr read_msg = {0};
+	struct kvec iov;
+	struct msghdr read_msg = {NULL, 0};
 	struct sockaddr_qrtr src_addr = {0};
 	struct diag_socket_info *info;
 	struct mutex *channel_mutex;
@@ -749,7 +793,13 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
 		}
 
 		spin_lock_irqsave(&info->lock, flags);
-		info->data_ready--;
+		if (info->data_ready > 0) {
+			info->data_ready--;
+		} else {
+			spin_unlock_irqrestore(&info->lock, flags);
+			mutex_unlock(&info->socket_info_mutex);
+			break;
+		}
 		spin_unlock_irqrestore(&info->lock, flags);
 
 		read_len = kernel_recvmsg(info->hdl, &read_msg, &iov, 1,
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 9abc067..13498ad 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2447,6 +2447,15 @@ static int ipmi_pci_probe_regspacing(struct smi_info *info)
 	return DEFAULT_REGSPACING;
 }
 
+static struct pci_device_id ipmi_pci_blacklist[] = {
+	/*
+	 * This is a "Virtual IPMI device", whatever that is.  It appears
+	 * as a KCS device by the class, but it is not one.
+	 */
+	{ PCI_VDEVICE(REALTEK, 0x816c) },
+	{ 0, }
+};
+
 static int ipmi_pci_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *ent)
 {
@@ -2454,6 +2463,9 @@ static int ipmi_pci_probe(struct pci_dev *pdev,
 	int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK;
 	struct smi_info *info;
 
+	if (pci_match_id(ipmi_pci_blacklist, pdev))
+		return -ENODEV;
+
 	info = smi_info_alloc();
 	if (!info)
 		return -ENOMEM;
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 0904ab4..ab701f6 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -645,8 +645,9 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
 
 		/* Remove the multi-part read marker. */
 		len -= 2;
+		data += 2;
 		for (i = 0; i < len; i++)
-			ssif_info->data[i] = data[i+2];
+			ssif_info->data[i] = data[i];
 		ssif_info->multi_len = len;
 		ssif_info->multi_pos = 1;
 
@@ -674,8 +675,19 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
 		}
 
 		blocknum = data[0];
+		len--;
+		data++;
 
-		if (ssif_info->multi_len + len - 1 > IPMI_MAX_MSG_LENGTH) {
+		if (blocknum != 0xff && len != 31) {
+		    /* All blocks but the last must have 31 data bytes. */
+			result = -EIO;
+			if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
+				pr_info("Received middle message <31\n");
+
+			goto continue_op;
+		}
+
+		if (ssif_info->multi_len + len > IPMI_MAX_MSG_LENGTH) {
 			/* Received message too big, abort the operation. */
 			result = -E2BIG;
 			if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
@@ -684,16 +696,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
 			goto continue_op;
 		}
 
-		/* Remove the blocknum from the data. */
-		len--;
 		for (i = 0; i < len; i++)
-			ssif_info->data[i + ssif_info->multi_len] = data[i + 1];
+			ssif_info->data[i + ssif_info->multi_len] = data[i];
 		ssif_info->multi_len += len;
 		if (blocknum == 0xff) {
 			/* End of read */
 			len = ssif_info->multi_len;
 			data = ssif_info->data;
-		} else if (blocknum + 1 != ssif_info->multi_pos) {
+		} else if (blocknum != ssif_info->multi_pos) {
 			/*
 			 * Out of sequence block, just abort.  Block
 			 * numbers start at zero for the second block,
@@ -721,6 +731,7 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
 		}
 	}
 
+ continue_op:
 	if (result < 0) {
 		ssif_inc_stat(ssif_info, receive_errors);
 	} else {
@@ -728,8 +739,6 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
 		ssif_inc_stat(ssif_info, received_message_parts);
 	}
 
-
- continue_op:
 	if (ssif_info->ssif_debug & SSIF_DEBUG_STATE)
 		pr_info(PFX "DONE 1: state = %d, result=%d.\n",
 			ssif_info->ssif_state, result);
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index b5e3103..e43c876 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -59,6 +59,7 @@
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/serial_8250.h>
+#include <linux/nospec.h>
 #include "smapi.h"
 #include "mwavedd.h"
 #include "3780i.h"
@@ -289,6 +290,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
 						ipcnum);
 				return -EINVAL;
 			}
+			ipcnum = array_index_nospec(ipcnum,
+						    ARRAY_SIZE(pDrvData->IPCs));
 			PRINTK_3(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
 				" ipcnum %x entry usIntCount %x\n",
@@ -317,6 +320,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
 						" Invalid ipcnum %x\n", ipcnum);
 				return -EINVAL;
 			}
+			ipcnum = array_index_nospec(ipcnum,
+						    ARRAY_SIZE(pDrvData->IPCs));
 			PRINTK_3(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
 				" ipcnum %x, usIntCount %x\n",
@@ -383,6 +388,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
 						ipcnum);
 				return -EINVAL;
 			}
+			ipcnum = array_index_nospec(ipcnum,
+						    ARRAY_SIZE(pDrvData->IPCs));
 			mutex_lock(&mwave_mutex);
 			if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
 				pDrvData->IPCs[ipcnum].bIsEnabled = false;
diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c
index decffb3..a738af8 100644
--- a/drivers/clk/clk-versaclock5.c
+++ b/drivers/clk/clk-versaclock5.c
@@ -262,8 +262,10 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index)
 
 		if (vc5->clk_mux_ins == VC5_MUX_IN_XIN)
 			src = VC5_PRIM_SRC_SHDN_EN_XTAL;
-		if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN)
+		else if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN)
 			src = VC5_PRIM_SRC_SHDN_EN_CLKIN;
+		else /* Invalid; should have been caught by vc5_probe() */
+			return -EINVAL;
 	}
 
 	return regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, mask, src);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 3c7945e..854013b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
  * Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
- * 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 as
@@ -49,6 +49,17 @@ struct clk_handoff_vdd {
 };
 
 static LIST_HEAD(clk_handoff_vdd_list);
+static bool vdd_class_handoff_completed;
+static DEFINE_MUTEX(vdd_class_list_lock);
+/*
+ * clk_rate_change_list is used during clk_core_set_rate_nolock() calls to
+ * handle vdd_class vote tracking.  core->rate_change_node is added to
+ * clk_rate_change_list when core->new_rate requires a different voltage level
+ * (core->new_vdd_class_vote) than core->vdd_class_vote.  Elements are removed
+ * from the list after unvoting core->vdd_class_vote immediately before
+ * returning from clk_core_set_rate_nolock().
+ */
+static LIST_HEAD(clk_rate_change_list);
 
 /***    private data structures    ***/
 
@@ -65,9 +76,7 @@ struct clk_core {
 	unsigned long		rate;
 	unsigned long		req_rate;
 	unsigned long		new_rate;
-	unsigned long		old_rate;
 	struct clk_core		*new_parent;
-	struct clk_core		*old_parent;
 	struct clk_core		*new_child;
 	unsigned long		flags;
 	bool			orphan;
@@ -90,6 +99,9 @@ struct clk_core {
 #endif
 	struct kref		ref;
 	struct clk_vdd_class	*vdd_class;
+	int			vdd_class_vote;
+	int			new_vdd_class_vote;
+	struct list_head	rate_change_node;
 	unsigned long		*rate_max;
 	int			num_rate_max;
 };
@@ -634,9 +646,11 @@ static int clk_unvote_vdd_level(struct clk_vdd_class *vdd_class, int level)
 	mutex_lock(&vdd_class->lock);
 
 	if (WARN(!vdd_class->level_votes[level],
-				"Reference counts are incorrect for %s level %d\n",
-				vdd_class->class_name, level))
+			"Reference counts are incorrect for %s level %d\n",
+			vdd_class->class_name, level)) {
+		rc = -EINVAL;
 		goto out;
+	}
 
 	vdd_class->level_votes[level]--;
 
@@ -700,29 +714,43 @@ static bool clk_is_rate_level_valid(struct clk_core *core, unsigned long rate)
 static int clk_vdd_class_init(struct clk_vdd_class *vdd)
 {
 	struct clk_handoff_vdd *v;
+	int ret = 0;
 
 	if (vdd->skip_handoff)
 		return 0;
 
+	mutex_lock(&vdd_class_list_lock);
+
 	list_for_each_entry(v, &clk_handoff_vdd_list, list) {
 		if (v->vdd_class == vdd)
-			return 0;
+			goto done;
 	}
 
-	pr_debug("voting for vdd_class %s\n", vdd->class_name);
+	if (!vdd_class_handoff_completed) {
+		pr_debug("voting for vdd_class %s\n", vdd->class_name);
 
-	if (clk_vote_vdd_level(vdd, vdd->num_levels - 1))
-		pr_err("failed to vote for %s\n", vdd->class_name);
+		ret = clk_vote_vdd_level(vdd, vdd->num_levels - 1);
+		if (ret) {
+			pr_err("failed to vote for %s, ret=%d\n",
+				vdd->class_name, ret);
+			goto done;
+		}
+	}
 
 	v = kmalloc(sizeof(*v), GFP_KERNEL);
-	if (!v)
-		return -ENOMEM;
+	if (!v) {
+		ret = -ENOMEM;
+		goto done;
+	}
 
 	v->vdd_class = vdd;
 
 	list_add_tail(&v->list, &clk_handoff_vdd_list);
 
-	return 0;
+done:
+	mutex_unlock(&vdd_class_list_lock);
+
+	return ret;
 }
 
 /***        clk api        ***/
@@ -752,7 +780,11 @@ static void clk_core_unprepare(struct clk_core *core)
 
 	trace_clk_unprepare_complete(core);
 
-	clk_unvote_rate_vdd(core, core->rate);
+	if (core->vdd_class) {
+		clk_unvote_vdd_level(core->vdd_class, core->vdd_class_vote);
+		core->vdd_class_vote = 0;
+		core->new_vdd_class_vote = 0;
+	}
 
 	clk_core_unprepare(core->parent);
 }
@@ -805,6 +837,11 @@ static int clk_core_prepare(struct clk_core *core)
 			clk_core_unprepare(core->parent);
 			return ret;
 		}
+		if (core->vdd_class) {
+			core->vdd_class_vote
+				= clk_find_vdd_level(core, core->rate);
+			core->new_vdd_class_vote = core->vdd_class_vote;
+		}
 
 		if (core->ops->prepare)
 			ret = core->ops->prepare(core->hw);
@@ -813,6 +850,8 @@ static int clk_core_prepare(struct clk_core *core)
 
 		if (ret) {
 			clk_unvote_rate_vdd(core, core->rate);
+			core->vdd_class_vote = 0;
+			core->new_vdd_class_vote = 0;
 			clk_core_unprepare(core->parent);
 			return ret;
 		}
@@ -1127,12 +1166,15 @@ static int clk_disable_unused(void)
 	hlist_for_each_entry(core, &clk_orphan_list, child_node)
 		clk_unprepare_unused_subtree(core);
 
+	mutex_lock(&vdd_class_list_lock);
 	list_for_each_entry_safe(v, v_temp, &clk_handoff_vdd_list, list) {
 		clk_unvote_vdd_level(v->vdd_class,
 				v->vdd_class->num_levels - 1);
 		list_del(&v->list);
 		kfree(v);
 	};
+	vdd_class_handoff_completed = true;
+	mutex_unlock(&vdd_class_list_lock);
 
 	clk_prepare_unlock();
 
@@ -1616,12 +1658,59 @@ static int __clk_speculate_rates(struct clk_core *core,
 	return ret;
 }
 
-static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate,
+/*
+ * Vote for the voltage level required for core->new_rate.  Keep track of all
+ * clocks with a changed voltage level in clk_rate_change_list.
+ */
+static int clk_vote_new_rate_vdd(struct clk_core *core)
+{
+	int cur_level, next_level;
+	int ret;
+
+	if (IS_ERR_OR_NULL(core) || !core->vdd_class)
+		return 0;
+
+	if (!clk_core_is_prepared(core))
+		return 0;
+
+	cur_level = core->new_vdd_class_vote;
+	next_level = clk_find_vdd_level(core, core->new_rate);
+	if (cur_level == next_level)
+		return 0;
+
+	ret = clk_vote_vdd_level(core->vdd_class, next_level);
+	if (ret)
+		return ret;
+
+	core->new_vdd_class_vote = next_level;
+
+	if (list_empty(&core->rate_change_node)) {
+		list_add(&core->rate_change_node, &clk_rate_change_list);
+	} else {
+		/*
+		 * A different new_rate has been determined for a clock that
+		 * was already encountered in the clock tree traversal so the
+		 * level that was previously voted for it should be removed.
+		 */
+		ret = clk_unvote_vdd_level(core->vdd_class, cur_level);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int clk_calc_subtree(struct clk_core *core, unsigned long new_rate,
 			     struct clk_core *new_parent, u8 p_index)
 {
 	struct clk_core *child;
+	int ret;
 
 	core->new_rate = new_rate;
+	ret = clk_vote_new_rate_vdd(core);
+	if (ret)
+		return ret;
+
 	core->new_parent = new_parent;
 	core->new_parent_index = p_index;
 	/* include clk in new parent's PRE_RATE_CHANGE notifications */
@@ -1631,8 +1720,12 @@ static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate,
 
 	hlist_for_each_entry(child, &core->children, child_node) {
 		child->new_rate = clk_recalc(child, new_rate);
-		clk_calc_subtree(child, child->new_rate, NULL, 0);
+		ret = clk_calc_subtree(child, child->new_rate, NULL, 0);
+		if (ret)
+			return ret;
 	}
+
+	return 0;
 }
 
 /*
@@ -1736,7 +1829,9 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
 	if (!clk_is_rate_level_valid(core, rate))
 		return NULL;
 
-	clk_calc_subtree(core, new_rate, parent, p_index);
+	ret = clk_calc_subtree(core, new_rate, parent, p_index);
+	if (ret)
+		return NULL;
 
 	return top;
 }
@@ -1795,7 +1890,7 @@ static int clk_change_rate(struct clk_core *core)
 	struct clk_core *parent = NULL;
 	int rc = 0;
 
-	core->old_rate = old_rate = core->rate;
+	old_rate = core->rate;
 
 	if (core->new_parent) {
 		parent = core->new_parent;
@@ -1805,8 +1900,6 @@ static int clk_change_rate(struct clk_core *core)
 		best_parent_rate = core->parent->rate;
 	}
 
-	core->old_parent = core->parent;
-
 	if (core->flags & CLK_SET_RATE_UNGATE) {
 		unsigned long flags;
 
@@ -1820,7 +1913,6 @@ static int clk_change_rate(struct clk_core *core)
 
 	if (core->new_parent && core->new_parent != core->parent) {
 		old_parent = __clk_set_parent_before(core, core->new_parent);
-		core->old_parent = old_parent;
 		trace_clk_set_parent(core, core->new_parent);
 
 		if (core->ops->set_rate_and_parent) {
@@ -1893,72 +1985,68 @@ static int clk_change_rate(struct clk_core *core)
 	return rc;
 }
 
-static int vote_vdd_up(struct clk_core *core)
+/*
+ * Unvote for the voltage level required for each core->new_vdd_class_vote in
+ * clk_rate_change_list.  This is used when undoing voltage requests after an
+ * error is encountered before any physical rate changing.
+ */
+static void clk_unvote_new_rate_vdd(void)
 {
-	struct clk_core *parent = NULL;
-	int ret, cur_level, next_level;
+	struct clk_core *core;
 
-	/* sanity */
-	if (IS_ERR_OR_NULL(core))
-		return 0;
-
-	if (core->vdd_class) {
-		cur_level = clk_find_vdd_level(core, core->rate);
-		next_level = clk_find_vdd_level(core, core->new_rate);
-		if (cur_level == next_level)
-			return 0;
+	list_for_each_entry(core, &clk_rate_change_list, rate_change_node) {
+		clk_unvote_vdd_level(core->vdd_class, core->new_vdd_class_vote);
+		core->new_vdd_class_vote = core->vdd_class_vote;
 	}
+}
 
-	/* save parent rate, if it exists */
-	if (core->new_parent)
-		parent = core->new_parent;
-	else if (core->parent)
-		parent = core->parent;
+/*
+ * Unvote for the voltage level required for each core->vdd_class_vote in
+ * clk_rate_change_list.
+ */
+static int clk_unvote_old_rate_vdd(void)
+{
+	struct clk_core *core;
+	int ret;
 
-	if (core->prepare_count && core->new_rate) {
-		ret = clk_vote_rate_vdd(core, core->new_rate);
+	list_for_each_entry(core, &clk_rate_change_list, rate_change_node) {
+		ret = clk_unvote_vdd_level(core->vdd_class,
+					   core->vdd_class_vote);
 		if (ret)
 			return ret;
 	}
 
-	vote_vdd_up(parent);
-
 	return 0;
 }
 
-static int vote_vdd_down(struct clk_core *core)
+/*
+ * In the case that rate setting fails, apply the max voltage level needed
+ * by either the old or new rate for each changed clock.
+ */
+static void clk_vote_safe_vdd(void)
 {
-	struct clk_core *parent;
-	unsigned long rate;
-	int cur_level, old_level;
+	struct clk_core *core;
 
-	/* sanity */
-	if (IS_ERR_OR_NULL(core))
-		return 0;
-
-	rate = core->old_rate;
-
-	/* New rate set was a failure */
-	if (DIV_ROUND_CLOSEST(core->rate, 1000) !=
-		DIV_ROUND_CLOSEST(core->new_rate, 1000))
-		rate = core->new_rate;
-
-	if (core->vdd_class) {
-		cur_level = clk_find_vdd_level(core, core->rate);
-		old_level = clk_find_vdd_level(core, core->old_rate);
-		if ((cur_level == old_level)
-			|| !core->vdd_class->level_votes[old_level])
-			return 0;
+	list_for_each_entry(core, &clk_rate_change_list, rate_change_node) {
+		if (core->vdd_class_vote > core->new_vdd_class_vote) {
+			clk_vote_vdd_level(core->vdd_class,
+						core->vdd_class_vote);
+			clk_unvote_vdd_level(core->vdd_class,
+						core->new_vdd_class_vote);
+			core->new_vdd_class_vote = core->vdd_class_vote;
+		}
 	}
+}
 
-	parent = core->old_parent;
+static void clk_cleanup_vdd_votes(void)
+{
+	struct clk_core *core, *temp;
 
-	if (core->prepare_count && rate)
-		clk_unvote_rate_vdd(core, rate);
-
-	vote_vdd_down(parent);
-
-	return 0;
+	list_for_each_entry_safe(core, temp, &clk_rate_change_list,
+				 rate_change_node) {
+		core->vdd_class_vote = core->new_vdd_class_vote;
+		list_del_init(&core->rate_change_node);
+	}
 }
 static int clk_core_set_rate_nolock(struct clk_core *core,
 				    unsigned long req_rate)
@@ -1966,6 +2054,15 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 	struct clk_core *top, *fail_clk;
 	unsigned long rate = req_rate;
 	int ret = 0;
+	/*
+	 * The prepare lock ensures mutual exclusion with other tasks.
+	 * set_rate_nesting_count is a static so that it can be incremented in
+	 * the case of reentrancy caused by a set_rate() ops callback itself
+	 * calling clk_set_rate().  That way, the voltage level votes for the
+	 * old rates are safely removed when the original invocation of this
+	 * function completes.
+	 */
+	static unsigned int set_rate_nesting_count;
 
 	if (!core)
 		return 0;
@@ -1979,8 +2076,10 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 
 	/* calculate new rates and get the topmost changed clock */
 	top = clk_calc_new_rates(core, rate);
-	if (!top)
-		return -EINVAL;
+	if (!top) {
+		ret = -EINVAL;
+		goto pre_rate_change_err;
+	}
 
 	/* notify that we are about to change rates */
 	fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
@@ -1988,29 +2087,42 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 		pr_debug("%s: failed to set %s clock to run at %lu\n", __func__,
 				fail_clk->name, req_rate);
 		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
-		return -EBUSY;
+		ret = -EBUSY;
+		goto pre_rate_change_err;
 	}
 
-	/* Enforce the VDD for new frequency */
-	ret = vote_vdd_up(core);
-	if (ret)
-		return ret;
 
 	/* change the rates */
+	set_rate_nesting_count++;
 	ret = clk_change_rate(top);
+	set_rate_nesting_count--;
 	if (ret) {
 		pr_err("%s: failed to set %s clock to run at %lu\n", __func__,
 				top->name, req_rate);
 		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
-		/* Release vdd requirements for new frequency. */
-		vote_vdd_down(core);
-		return ret;
+		clk_vote_safe_vdd();
+		goto post_rate_change_err;
 	}
 
 	core->req_rate = req_rate;
 
-	/* Release vdd requirements for old frequency. */
-	vote_vdd_down(core);
+post_rate_change_err:
+	/*
+	 * Only remove vdd_class level votes for old clock rates after all
+	 * nested clk_set_rate() calls have completed.
+	 */
+	if (set_rate_nesting_count == 0) {
+		ret |= clk_unvote_old_rate_vdd();
+		clk_cleanup_vdd_votes();
+	}
+
+	return ret;
+
+pre_rate_change_err:
+	if (set_rate_nesting_count == 0) {
+		clk_unvote_new_rate_vdd();
+		clk_cleanup_vdd_votes();
+	}
 
 	return ret;
 }
@@ -3756,6 +3868,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 	};
 
 	INIT_HLIST_HEAD(&core->clks);
+	INIT_LIST_HEAD(&core->rate_change_node);
 
 	hw->clk = __clk_create_clk(hw, NULL, NULL);
 	if (IS_ERR(hw->clk)) {
diff --git a/drivers/clk/imgtec/clk-boston.c b/drivers/clk/imgtec/clk-boston.c
index 15af423..f5d54a6 100644
--- a/drivers/clk/imgtec/clk-boston.c
+++ b/drivers/clk/imgtec/clk-boston.c
@@ -73,27 +73,32 @@ static void __init clk_boston_setup(struct device_node *np)
 	hw = clk_hw_register_fixed_rate(NULL, "input", NULL, 0, in_freq);
 	if (IS_ERR(hw)) {
 		pr_err("failed to register input clock: %ld\n", PTR_ERR(hw));
-		return;
+		goto error;
 	}
 	onecell->hws[BOSTON_CLK_INPUT] = hw;
 
 	hw = clk_hw_register_fixed_rate(NULL, "sys", "input", 0, sys_freq);
 	if (IS_ERR(hw)) {
 		pr_err("failed to register sys clock: %ld\n", PTR_ERR(hw));
-		return;
+		goto error;
 	}
 	onecell->hws[BOSTON_CLK_SYS] = hw;
 
 	hw = clk_hw_register_fixed_rate(NULL, "cpu", "input", 0, cpu_freq);
 	if (IS_ERR(hw)) {
 		pr_err("failed to register cpu clock: %ld\n", PTR_ERR(hw));
-		return;
+		goto error;
 	}
 	onecell->hws[BOSTON_CLK_CPU] = hw;
 
 	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
 	if (err)
 		pr_err("failed to add DT provider: %d\n", err);
+
+	return;
+
+error:
+	kfree(onecell);
 }
 
 /*
diff --git a/drivers/clk/imx/clk-busy.c b/drivers/clk/imx/clk-busy.c
index 5cc9959..097625c 100644
--- a/drivers/clk/imx/clk-busy.c
+++ b/drivers/clk/imx/clk-busy.c
@@ -154,7 +154,7 @@ static struct clk_ops clk_busy_mux_ops = {
 
 struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
 			     u8 width, void __iomem *busy_reg, u8 busy_shift,
-			     const char **parent_names, int num_parents)
+			     const char * const *parent_names, int num_parents)
 {
 	struct clk_busy_mux *busy;
 	struct clk *clk;
diff --git a/drivers/clk/imx/clk-fixup-mux.c b/drivers/clk/imx/clk-fixup-mux.c
index c9b327e..44817c1 100644
--- a/drivers/clk/imx/clk-fixup-mux.c
+++ b/drivers/clk/imx/clk-fixup-mux.c
@@ -70,7 +70,7 @@ static const struct clk_ops clk_fixup_mux_ops = {
 };
 
 struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg,
-			      u8 shift, u8 width, const char **parents,
+			      u8 shift, u8 width, const char * const *parents,
 			      int num_parents, void (*fixup)(u32 *val))
 {
 	struct clk_fixup_mux *fixup_mux;
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index 8d518ad..8eb93eb 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -515,8 +515,12 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	 * lvds1_gate and lvds2_gate are pseudo-gates.  Both can be
 	 * independently configured as clock inputs or outputs.  We treat
 	 * the "output_enable" bit as a gate, even though it's really just
-	 * enabling clock output.
+	 * enabling clock output. Initially the gate bits are cleared, as
+	 * otherwise the exclusive configuration gets locked in the setup done
+	 * by software running before the clock driver, with no way to change
+	 * it.
 	 */
+	writel(readl(base + 0x160) & ~0x3c00, base + 0x160);
 	clk[IMX6QDL_CLK_LVDS1_GATE] = imx_clk_gate_exclusive("lvds1_gate", "lvds1_sel", base + 0x160, 10, BIT(12));
 	clk[IMX6QDL_CLK_LVDS2_GATE] = imx_clk_gate_exclusive("lvds2_gate", "lvds2_sel", base + 0x160, 11, BIT(13));
 
diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c
index 9642cdf..c264a74 100644
--- a/drivers/clk/imx/clk-imx6sl.c
+++ b/drivers/clk/imx/clk-imx6sl.c
@@ -17,6 +17,8 @@
 
 #include "clk.h"
 
+#define CCDR				0x4
+#define BM_CCM_CCDR_MMDC_CH0_MASK	(1 << 17)
 #define CCSR			0xc
 #define BM_CCSR_PLL1_SW_CLK_SEL	(1 << 2)
 #define CACRR			0x10
@@ -414,6 +416,10 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 	clks[IMX6SL_CLK_USDHC3]       = imx_clk_gate2("usdhc3",       "usdhc3_podf",       base + 0x80, 6);
 	clks[IMX6SL_CLK_USDHC4]       = imx_clk_gate2("usdhc4",       "usdhc4_podf",       base + 0x80, 8);
 
+	/* Ensure the MMDC CH0 handshake is bypassed */
+	writel_relaxed(readl_relaxed(base + CCDR) |
+		BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
+
 	imx_check_clocks(clks, ARRAY_SIZE(clks));
 
 	clk_data.clks = clks;
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index d69c4bb..b03fbd5 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -63,14 +63,14 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
 
 struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
 			     u8 width, void __iomem *busy_reg, u8 busy_shift,
-			     const char **parent_names, int num_parents);
+			     const char * const *parent_names, int num_parents);
 
 struct clk *imx_clk_fixup_divider(const char *name, const char *parent,
 				  void __iomem *reg, u8 shift, u8 width,
 				  void (*fixup)(u32 *val));
 
 struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg,
-			      u8 shift, u8 width, const char **parents,
+			      u8 shift, u8 width, const char * const *parents,
 			      int num_parents, void (*fixup)(u32 *val));
 
 static inline struct clk *imx_clk_fixed(const char *name, int rate)
@@ -79,7 +79,8 @@ static inline struct clk *imx_clk_fixed(const char *name, int rate)
 }
 
 static inline struct clk *imx_clk_mux_ldb(const char *name, void __iomem *reg,
-		u8 shift, u8 width, const char **parents, int num_parents)
+			u8 shift, u8 width, const char * const *parents,
+			int num_parents)
 {
 	return clk_register_mux(NULL, name, parents, num_parents,
 			CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, reg,
@@ -178,7 +179,8 @@ static inline struct clk *imx_clk_gate4(const char *name, const char *parent,
 }
 
 static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
-		u8 shift, u8 width, const char **parents, int num_parents)
+			u8 shift, u8 width, const char * const *parents,
+			int num_parents)
 {
 	return clk_register_mux(NULL, name, parents, num_parents,
 			CLK_SET_RATE_NO_REPARENT, reg, shift,
@@ -186,7 +188,8 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 }
 
 static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg,
-		u8 shift, u8 width, const char **parents, int num_parents)
+			u8 shift, u8 width, const char * const *parents,
+			int num_parents)
 {
 	return clk_register_mux(NULL, name, parents, num_parents,
 			CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE,
@@ -194,8 +197,9 @@ static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg,
 }
 
 static inline struct clk *imx_clk_mux_flags(const char *name,
-		void __iomem *reg, u8 shift, u8 width, const char **parents,
-		int num_parents, unsigned long flags)
+			void __iomem *reg, u8 shift, u8 width,
+			const char * const *parents, int num_parents,
+			unsigned long flags)
 {
 	return clk_register_mux(NULL, name, parents, num_parents,
 			flags | CLK_SET_RATE_NO_REPARENT, reg, shift, width, 0,
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 49216c3f..876c9aa 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -554,3 +554,11 @@
 	 Support for the CMN BLK PLL on Qualcomm Technologies, Inc QCS405
 	 devices.
 	 Say Y if you want to support the Common Block PLL.
+
+config QCOM_CLK_VIRT
+	tristate "QTI Virtual Clock Frontend Driver"
+	depends on COMMON_CLK_QCOM && MSM_HAB
+	help
+	  This is the virtual clock frontend driver which is based on HAB for
+	  the QTI virtual machine.
+	  Say Y if you want to support virtual clock.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index a13d625..8f09f0c 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -70,6 +70,7 @@
 obj-$(CONFIG_MSM_VIDEOCC_SM8150) += videocc-sm8150.o
 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
+obj-$(CONFIG_QCOM_CLK_VIRT) += clk-virt.o clk-virt-sm8150.o clk-virt-sm6150.o
 obj-$(CONFIG_QCS_CMN_BLK_PLL) += cmn-blk-pll.o
 obj-$(CONFIG_SM_DEBUGCC_TRINKET) += debugcc-trinket.o
 obj-$(CONFIG_SM_DISPCC_TRINKET) += dispcc-trinket.o
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index e7f824b..f4bfbc8 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -158,7 +158,7 @@
 #define LUCID_PLL_STANDBY		0x0
 #define LUCID_PLL_RUN			0x1
 #define LUCID_PLL_OUT_MASK		0x7
-#define LUCID_PCAL_DONE			BIT(26)
+#define LUCID_PCAL_DONE			BIT(27)
 #define LUCID_PLL_RATE_MARGIN		500
 #define LUCID_PLL_ACK_LATCH		BIT(29)
 #define LUCID_PLL_UPDATE		BIT(22)
@@ -2553,8 +2553,7 @@ static int alpha_pll_lucid_prepare(struct clk_hw *hw)
 		return 0;
 
 	/* Return early if calibration is not needed. */
-	ret = regmap_read(pll->clkr.regmap, pll->offset + LUCID_PLL_OFF_STATUS,
-		      &regval);
+	ret = regmap_read(pll->clkr.regmap, pll->offset, &regval);
 	if (regval & LUCID_PCAL_DONE)
 		return ret;
 
@@ -2626,12 +2625,18 @@ static int alpha_pll_lucid_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (ret)
 		return ret;
 
-	/* Wait for 2 reference cycles before checking the ACK bit. */
-	udelay(1);
-	regmap_read(pll->clkr.regmap, pll->offset + PLL_MODE, &regval);
-	if (!(regval & LUCID_PLL_ACK_LATCH)) {
-		WARN(1, "PLL latch failed. Output may be unstable!\n");
-		return -EINVAL;
+	/*
+	 * When PLL_HW_UPDATE_LOGIC_BYPASS bit is not set then waiting for
+	 * pll_ack_latch to return to zero can be bypassed.
+	 */
+	if (!(pll->flags & SUPPORTS_NO_PLL_LATCH)) {
+		/* Wait for 2 reference cycles before checking the ACK bit. */
+		udelay(1);
+		regmap_read(pll->clkr.regmap, pll->offset + PLL_MODE, &regval);
+		if (!(regval & LUCID_PLL_ACK_LATCH)) {
+			WARN(1, "PLL latch failed. Output may be unstable!\n");
+			return -EINVAL;
+		}
 	}
 
 	/* Return the latch input to 0 */
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 47ffbb2..6f23300 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2017-2019, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -77,6 +77,7 @@ struct clk_alpha_pll {
 	/* Associated with soft_vote for multiple PLL software instances */
 #define SUPPORTS_FSM_VOTE	BIT(5)
 #define SUPPORTS_NO_SLEW	BIT(6)
+#define SUPPORTS_NO_PLL_LATCH	BIT(7)
 	u8 flags;
 
 	struct clk_regmap clkr;
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index 3741521..8d49a37 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -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
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <asm/smp_plat.h>
 #include <linux/errno.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
@@ -41,6 +42,7 @@
 #define OSM_INIT_RATE			300000000UL
 #define XO_RATE				19200000UL
 #define OSM_TABLE_SIZE			40
+#define OSM_TABLE_REDUCED_SIZE		12
 #define SINGLE_CORE_COUNT		1
 #define CORE_COUNT_VAL(val)		((val & GENMASK(18, 16)) >> 16)
 
@@ -76,6 +78,7 @@ struct clk_osm {
 	u32 num_entries;
 	u32 cluster_num;
 	u32 core_num;
+	u32 osm_table_size;
 	u64 total_cycle_counter;
 	u32 prev_cycle_counter;
 	unsigned long rate;
@@ -85,6 +88,7 @@ struct clk_osm {
 static bool is_sdmshrike;
 static bool is_sm6150;
 static bool is_sdmmagpie;
+static bool is_trinket;
 
 static inline struct clk_osm *to_clk_osm(struct clk_hw *_hw)
 {
@@ -301,6 +305,7 @@ static struct clk_init_data osm_clks_init[] = {
 
 static struct clk_osm l3_clk = {
 	.cluster_num = 0,
+	.osm_table_size = OSM_TABLE_SIZE,
 	.hw.init = &osm_clks_init[0],
 };
 
@@ -312,6 +317,7 @@ static DEFINE_CLK_VOTER(l3_gpu_vote_clk, l3_clk, 0);
 
 static struct clk_osm pwrcl_clk = {
 	.cluster_num = 1,
+	.osm_table_size = OSM_TABLE_SIZE,
 	.hw.init = &osm_clks_init[1],
 };
 
@@ -389,6 +395,7 @@ static struct clk_osm cpu5_pwrcl_clk = {
 
 static struct clk_osm perfcl_clk = {
 	.cluster_num = 2,
+	.osm_table_size = OSM_TABLE_SIZE,
 	.hw.init = &osm_clks_init[2],
 };
 
@@ -442,6 +449,7 @@ static struct clk_osm cpu7_perfcl_clk = {
 
 static struct clk_osm perfpcl_clk = {
 	.cluster_num = 3,
+	.osm_table_size = OSM_TABLE_SIZE,
 	.hw.init = &osm_clks_init[3],
 };
 
@@ -512,7 +520,11 @@ static struct clk_osm *logical_cpu_to_clk(int cpu)
 		}
 
 		hwid = of_read_number(cell, of_n_addr_cells(cpu_node));
-		hwid = (hwid >> 8) & 0xff;
+		if (is_trinket)
+			hwid = get_logical_index(hwid);
+		else
+			hwid = (hwid >> 8) & 0xff;
+
 		of_node_put(cpu_node);
 		if (hwid >= ARRAY_SIZE(clk_cpu_map)) {
 			pr_err("unsupported CPU number - %d (hw_id - %llu)\n",
@@ -643,11 +655,11 @@ static int osm_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	parent = to_clk_osm(p_hw);
 	c->vbase = parent->vbase;
 
-	table = kcalloc(OSM_TABLE_SIZE + 1, sizeof(*table), GFP_KERNEL);
+	table = kcalloc(parent->osm_table_size + 1, sizeof(*table), GFP_KERNEL);
 	if (!table)
 		return -ENOMEM;
 
-	for (i = 0; i < OSM_TABLE_SIZE; i++) {
+	for (i = 0; i < parent->osm_table_size; i++) {
 		u32 data, src, div, lval, core_count;
 
 		data = clk_osm_read_reg(c, FREQ_REG + i * OSM_REG_SIZE);
@@ -876,7 +888,8 @@ static void populate_opp_table(struct platform_device *pdev)
 					dev_name(cpu_dev));
 	}
 
-	populate_l3_opp_table(np, "l3-devs");
+	if (!is_trinket)
+		populate_l3_opp_table(np, "l3-devs");
 }
 
 static u64 clk_osm_get_cpu_cycle_counter(int cpu)
@@ -920,9 +933,9 @@ static u64 clk_osm_get_cpu_cycle_counter(int cpu)
 
 static int clk_osm_read_lut(struct platform_device *pdev, struct clk_osm *c)
 {
-	u32 data, src, lval, i, j = OSM_TABLE_SIZE;
+	u32 data, src, lval, i, j = c->osm_table_size;
 
-	for (i = 0; i < OSM_TABLE_SIZE; i++) {
+	for (i = 0; i < c->osm_table_size; i++) {
 		data = clk_osm_read_reg(c, FREQ_REG + i * OSM_REG_SIZE);
 		src = ((data & GENMASK(31, 30)) >> 30);
 		lval = (data & GENMASK(7, 0));
@@ -942,8 +955,9 @@ static int clk_osm_read_lut(struct platform_device *pdev, struct clk_osm *c)
 			 c->osm_table[i].virtual_corner,
 			 c->osm_table[i].open_loop_volt);
 
-		if (i > 0 && j == OSM_TABLE_SIZE && c->osm_table[i].frequency ==
-					c->osm_table[i - 1].frequency)
+		if (i > 0 && j == c->osm_table_size &&
+				c->osm_table[i].frequency ==
+				c->osm_table[i - 1].frequency)
 			j = i;
 	}
 
@@ -965,20 +979,23 @@ static int clk_osm_resources_init(struct platform_device *pdev)
 {
 	struct resource *res;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						"osm_l3_base");
-	if (!res) {
-		dev_err(&pdev->dev,
-			"Unable to get platform resource for osm_l3_base");
-		return -ENOMEM;
-	}
+	if (!is_trinket) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+							"osm_l3_base");
+		if (!res) {
+			dev_err(&pdev->dev,
+				"Unable to get platform resource for osm_l3_base");
+			return -ENOMEM;
+		}
 
-	l3_clk.pbase = (unsigned long)res->start;
-	l3_clk.vbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+		l3_clk.pbase = (unsigned long)res->start;
+		l3_clk.vbase = devm_ioremap(&pdev->dev, res->start,
+							resource_size(res));
 
-	if (!l3_clk.vbase) {
-		dev_err(&pdev->dev, "Unable to map osm_l3_base base\n");
-		return -ENOMEM;
+		if (!l3_clk.vbase) {
+			dev_err(&pdev->dev, "Unable to map osm_l3_base base\n");
+			return -ENOMEM;
+		}
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -1014,7 +1031,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	if (is_sdmshrike || is_sm6150 || is_sdmmagpie)
+	if (is_sdmshrike || is_sm6150 || is_sdmmagpie || is_trinket)
 		return 0;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -1056,6 +1073,25 @@ static void clk_cpu_osm_driver_sm6150_fixup(void)
 	clk_cpu_map[7] = &cpu7_perfcl_clk;
 }
 
+static void clk_cpu_osm_driver_trinket_fixup(void)
+{
+	pwrcl_clk.osm_table_size = OSM_TABLE_REDUCED_SIZE;
+	perfcl_clk.osm_table_size = OSM_TABLE_REDUCED_SIZE;
+
+	osm_qcom_clk_hws[L3_CLUSTER0_VOTE_CLK] = NULL,
+	osm_qcom_clk_hws[L3_CLUSTER1_VOTE_CLK] = NULL,
+	osm_qcom_clk_hws[L3_CLUSTER2_VOTE_CLK] = NULL,
+	osm_qcom_clk_hws[L3_MISC_VOTE_CLK] = NULL,
+	osm_qcom_clk_hws[L3_GPU_VOTE_CLK] = NULL,
+	osm_qcom_clk_hws[L3_CLK] = NULL,
+	osm_qcom_clk_hws[CPU7_PERFPCL_CLK] = NULL,
+	osm_qcom_clk_hws[PERFPCL_CLK] = NULL,
+	osm_qcom_clk_hws[CPU4_PWRCL_CLK] = NULL,
+	osm_qcom_clk_hws[CPU5_PWRCL_CLK] = NULL,
+	osm_qcom_clk_hws[CPU7_PERFCL_CLK] = &cpu7_perfcl_clk.hw;
+	clk_cpu_map[7] = &cpu7_perfcl_clk;
+}
+
 static void clk_cpu_osm_driver_sdmshrike_fixup(void)
 {
 	osm_qcom_clk_hws[CPU7_PERFPCL_CLK] = NULL;
@@ -1077,6 +1113,9 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
 		.get_cpu_cycle_counter = clk_osm_get_cpu_cycle_counter,
 	};
 
+	is_trinket = of_device_is_compatible(pdev->dev.of_node,
+				"qcom,clk-cpu-osm-trinket");
+
 	is_sdmmagpie = of_device_is_compatible(pdev->dev.of_node,
 				"qcom,clk-cpu-osm-sdmmagpie");
 
@@ -1089,6 +1128,8 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
 		clk_cpu_osm_driver_sdmshrike_fixup();
 	else if (is_sm6150 || is_sdmmagpie)
 		clk_cpu_osm_driver_sm6150_fixup();
+	else if (is_trinket)
+		clk_cpu_osm_driver_trinket_fixup();
 
 	clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
 								GFP_KERNEL);
@@ -1119,11 +1160,13 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
 	if (val & BIT(0))
 		perfcl_clk.per_core_dcvs = true;
 
-	rc = clk_osm_read_lut(pdev, &l3_clk);
-	if (rc) {
-		dev_err(&pdev->dev, "Unable to read OSM LUT for L3, rc=%d\n",
-			rc);
-		return rc;
+	if (!is_trinket) {
+		rc = clk_osm_read_lut(pdev, &l3_clk);
+		if (rc) {
+			dev_err(&pdev->dev, "Unable to read OSM LUT for L3, rc=%d\n",
+				rc);
+			return rc;
+		}
 	}
 
 	rc = clk_osm_read_lut(pdev, &pwrcl_clk);
@@ -1140,7 +1183,7 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
 		return rc;
 	}
 
-	if (!is_sdmshrike && !is_sm6150 && !is_sdmmagpie) {
+	if (!is_sdmshrike && !is_sm6150 && !is_sdmmagpie && !is_trinket) {
 		rc = clk_osm_read_lut(pdev, &perfpcl_clk);
 		if (rc) {
 			dev_err(&pdev->dev, "Unable to read OSM LUT for perf plus cluster, rc=%d\n",
@@ -1149,10 +1192,12 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
 		}
 	}
 
-	spin_lock_init(&l3_clk.lock);
+	if (!is_trinket)
+		spin_lock_init(&l3_clk.lock);
 	spin_lock_init(&pwrcl_clk.lock);
 	spin_lock_init(&perfcl_clk.lock);
-	spin_lock_init(&perfpcl_clk.lock);
+	if (!is_trinket)
+		spin_lock_init(&perfpcl_clk.lock);
 
 	/* Register OSM l3, pwr and perf clocks with Clock Framework */
 	for (i = 0; i < num_clks; i++) {
@@ -1177,16 +1222,18 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
 
 	get_online_cpus();
 
-	WARN(clk_prepare_enable(l3_cluster0_vote_clk.hw.clk),
+	if (!is_trinket) {
+		WARN(clk_prepare_enable(l3_cluster0_vote_clk.hw.clk),
 			"clk: Failed to enable cluster0 clock for L3\n");
-	WARN(clk_prepare_enable(l3_cluster1_vote_clk.hw.clk),
+		WARN(clk_prepare_enable(l3_cluster1_vote_clk.hw.clk),
 			"clk: Failed to enable cluster1 clock for L3\n");
-	WARN(clk_prepare_enable(l3_cluster2_vote_clk.hw.clk),
+		WARN(clk_prepare_enable(l3_cluster2_vote_clk.hw.clk),
 			"clk: Failed to enable cluster2 clock for L3\n");
-	WARN(clk_prepare_enable(l3_misc_vote_clk.hw.clk),
+		WARN(clk_prepare_enable(l3_misc_vote_clk.hw.clk),
 			"clk: Failed to enable misc clock for L3\n");
-	WARN(clk_prepare_enable(l3_gpu_vote_clk.hw.clk),
+		WARN(clk_prepare_enable(l3_gpu_vote_clk.hw.clk),
 			"clk: Failed to enable gpu clock for L3\n");
+	}
 
 	populate_opp_table(pdev);
 
@@ -1216,6 +1263,7 @@ static const struct of_device_id match_table[] = {
 	{ .compatible = "qcom,clk-cpu-osm" },
 	{ .compatible = "qcom,clk-cpu-osm-sm6150" },
 	{ .compatible = "qcom,clk-cpu-osm-sdmmagpie" },
+	{ .compatible = "qcom,clk-cpu-osm-trinket" },
 	{ .compatible = "qcom,clk-cpu-osm-sdmshrike" },
 	{}
 };
diff --git a/drivers/clk/qcom/clk-cpu-sdxprairie.c b/drivers/clk/qcom/clk-cpu-sdxprairie.c
index 4c4f6e8..be011b4 100644
--- a/drivers/clk/qcom/clk-cpu-sdxprairie.c
+++ b/drivers/clk/qcom/clk-cpu-sdxprairie.c
@@ -186,27 +186,6 @@ static u8 cpucc_clk_get_parent(struct clk_hw *hw)
 	return clk_regmap_mux_div_ops.get_parent(hw);
 }
 
-/*
- * We use the notifier function for switching to a temporary safe configuration
- * (mux and divider), while the APSS pll is reconfigured.
- */
-static int cpucc_notifier_cb(struct notifier_block *nb, unsigned long event,
-			     void *data)
-{
-	struct clk_regmap_mux_div *cpuclk = container_of(nb,
-					struct clk_regmap_mux_div, clk_nb);
-	int ret = 0;
-
-	if (event == PRE_RATE_CHANGE)
-		/* set the mux to safe source(gpll0) & div */
-		ret = __mux_div_set_src_div(cpuclk,  cpuclk->safe_src, 1);
-
-	if (event == ABORT_RATE_CHANGE)
-		pr_err("Error in configuring PLL - stay at safe src only\n");
-
-	return notifier_from_errno(ret);
-}
-
 static const struct clk_ops cpucc_clk_ops = {
 	.enable = cpucc_clk_enable,
 	.disable = cpucc_clk_disable,
@@ -241,7 +220,7 @@ static struct clk_alpha_pll apcs_cpu_pll = {
 	.type = LUCID_PLL,
 	.vco_table = lucid_vco,
 	.num_vco = ARRAY_SIZE(lucid_vco),
-	.flags = SUPPORTS_NO_SLEW,
+	.flags = SUPPORTS_NO_PLL_LATCH,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "apcs_cpu_pll",
 		.parent_names = (const char *[]){ "bi_tcxo_ao" },
@@ -263,10 +242,7 @@ static struct clk_regmap_mux_div apcs_mux_clk = {
 	.hid_shift  = 0,
 	.src_width  = 3,
 	.src_shift  = 8,
-	.safe_src = 1,
-	.safe_div = 1,
 	.parent_map = apcs_mux_clk_parent_map,
-	.clk_nb.notifier_call = cpucc_notifier_cb,
 	.clkr.hw.init = &(struct clk_init_data) {
 		.name = "apcs_mux_clk",
 		.parent_names = apcs_mux_clk_parent_name,
@@ -508,14 +484,7 @@ static int cpucc_driver_probe(struct platform_device *pdev)
 		return PTR_ERR(clk);
 	}
 
-	clk = devm_clk_get(dev, "gpll0");
-	if (IS_ERR(clk)) {
-		if (PTR_ERR(clk) != -EPROBE_DEFER)
-			dev_err(dev, "Unable to get GPLL0 clock\n");
-		return PTR_ERR(clk);
-	}
-
-	 /* Rail Regulator for apcs_cpu_pll & cpuss mux*/
+	/* Rail Regulator for apcs_cpu_pll & cpuss mux*/
 	vdd_lucid_pll.regulator[0] = devm_regulator_get(&pdev->dev,
 							"vdd-lucid-pll");
 	if (IS_ERR(vdd_lucid_pll.regulator[0])) {
@@ -613,13 +582,6 @@ static int cpucc_driver_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = clk_notifier_register(apcs_mux_clk.clkr.hw.clk,
-							&apcs_mux_clk.clk_nb);
-	if (ret) {
-		dev_err(dev, "failed to register clock notifier: %d\n", ret);
-		return ret;
-	}
-
 	/* Set to boot frequency */
 	ret = clk_set_rate(apcs_mux_clk.clkr.hw.clk, cpucc_clk_init_rate);
 	if (ret)
@@ -750,8 +712,6 @@ static int __init cpu_clock_init(void)
 		l_val =  readl_relaxed(base + LUCID_PLL_OFF_L_VAL);
 	}
 
-	writel_relaxed(0xC05, base + LUCID_PLL_OFF_USER_CTL_U);
-
 	cpucc_clk_init_rate = l_val * XO_RATE;
 
 	regval = readl_relaxed(base);
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
index 3c8c3d2..086d467 100644
--- a/drivers/clk/qcom/clk-smd-rpm.c
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -715,8 +715,8 @@ DEFINE_CLK_SMD_RPM_BRANCH(trinket, bi_tcxo, bi_tcxo_ao,
 DEFINE_CLK_SMD_RPM(trinket, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
 DEFINE_CLK_SMD_RPM(trinket, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
 DEFINE_CLK_SMD_RPM(trinket, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
-DEFINE_CLK_SMD_RPM_QDSS(trinket, qdss_clk, qdss_a_clk,
-						QCOM_SMD_RPM_MISC_CLK, 1);
+DEFINE_CLK_SMD_RPM_BRANCH(trinket, qdss_clk, qdss_a_clk,
+					QCOM_SMD_RPM_MISC_CLK, 1, 19200000);
 DEFINE_CLK_SMD_RPM(trinket, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0);
 DEFINE_CLK_SMD_RPM(trinket, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0);
 DEFINE_CLK_SMD_RPM(trinket, qup_clk, qup_a_clk, QCOM_SMD_RPM_QUP_CLK, 0);
diff --git a/drivers/clk/qcom/clk-virt-sm6150.c b/drivers/clk/qcom/clk-virt-sm6150.c
new file mode 100644
index 0000000..93c54b6
--- /dev/null
+++ b/drivers/clk/qcom/clk-virt-sm6150.c
@@ -0,0 +1,294 @@
+/* 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/clk-provider.h>
+#include <dt-bindings/clock/qcom,gcc-sm6150.h>
+#include <dt-bindings/clock/qcom,scc-sm6150.h>
+#include "clk-virt.h"
+
+static struct virt_reset_map sm6150_gcc_virt_resets[] = {
+	[GCC_QUSB2PHY_PRIM_BCR] = { "gcc_qusb2phy_prim_bcr" },
+	[GCC_QUSB2PHY_SEC_BCR] = { "gcc_qusb2phy_sec_bcr" },
+	[GCC_USB30_PRIM_BCR] = { "gcc_usb30_prim_master_clk" },
+	[GCC_USB2_PHY_SEC_BCR] = { "gcc_usb2_phy_sec_bcr" },
+	[GCC_USB3_DP_PHY_SEC_BCR] = { "gcc_usb3_dp_phy_sec_bcr" },
+	[GCC_USB3PHY_PHY_SEC_BCR] = { "gcc_usb3phy_phy_sec_bcr" },
+	[GCC_USB20_SEC_BCR] = { "gcc_usb20_sec_master_clk" },
+	[GCC_USB3_PHY_PRIM_SP0_BCR] = { "gcc_usb3_phy_prim_sp0_bcr" },
+	[GCC_USB3PHY_PHY_PRIM_SP0_BCR] = { "gcc_usb3phy_phy_prim_sp0_bcr" },
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s0_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s0_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s1_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s1_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s2_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s2_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s3_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s3_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s4_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s4_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s5_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s5_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s0_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s0_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s1_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s1_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s2_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s2_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s3_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s3_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s4_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s4_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s5_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s5_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap_0_m_ahb_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap_0_m_ahb_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap_0_s_ahb_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap_0_s_ahb_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap_1_m_ahb_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap_1_m_ahb_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap_1_s_ahb_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap_1_s_ahb_clk",
+	},
+};
+
+static struct clk_virt gcc_cfg_noc_usb3_prim_axi_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_cfg_noc_usb3_prim_axi_clk",
+	},
+};
+
+static struct clk_virt gcc_aggre_usb3_prim_axi_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_aggre_usb3_prim_axi_clk",
+	},
+};
+
+static struct clk_virt gcc_usb30_prim_mock_utmi_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb30_prim_mock_utmi_clk",
+	},
+};
+
+static struct clk_virt gcc_usb30_prim_sleep_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb30_prim_sleep_clk",
+	},
+};
+
+static struct clk_virt gcc_usb3_sec_clkref_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_sec_clkref_en",
+	},
+};
+
+static struct clk_virt gcc_usb3_prim_phy_aux_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_prim_phy_aux_clk",
+	},
+};
+
+static struct clk_virt gcc_usb3_prim_phy_pipe_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_prim_phy_pipe_clk",
+	},
+};
+
+static struct clk_virt gcc_usb3_prim_clkref_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_prim_clkref_en",
+	},
+};
+
+static struct clk_virt gcc_usb3_prim_phy_com_aux_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_prim_phy_com_aux_clk",
+	},
+};
+
+static struct clk_hw *sm6150_gcc_virt_clocks[] = {
+	[GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.hw,
+	[GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.hw,
+	[GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.hw,
+	[GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.hw,
+	[GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.hw,
+	[GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.hw,
+	[GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.hw,
+	[GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.hw,
+	[GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.hw,
+	[GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.hw,
+	[GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.hw,
+	[GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.hw,
+	[GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.hw,
+	[GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.hw,
+	[GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.hw,
+	[GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.hw,
+	[GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.hw,
+	[GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.hw,
+	[GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.hw,
+	[GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.hw,
+	[GCC_USB3_SEC_CLKREF_CLK] = &gcc_usb3_sec_clkref_clk.hw,
+	[GCC_USB3_PRIM_PHY_AUX_CLK] = &gcc_usb3_prim_phy_aux_clk.hw,
+	[GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.hw,
+	[GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.hw,
+	[GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.hw,
+};
+
+const struct clk_virt_desc clk_virt_sm6150_gcc = {
+	.clks = sm6150_gcc_virt_clocks,
+	.num_clks = ARRAY_SIZE(sm6150_gcc_virt_clocks),
+	.resets = sm6150_gcc_virt_resets,
+	.num_resets = ARRAY_SIZE(sm6150_gcc_virt_resets),
+};
+
+static struct clk_virt scc_qupv3_se0_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_se0_clk",
+	},
+};
+
+static struct clk_virt scc_qupv3_se1_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_se1_clk",
+	},
+};
+
+static struct clk_virt scc_qupv3_se2_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_se2_clk",
+	},
+};
+
+static struct clk_virt scc_qupv3_se3_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_se3_clk",
+	},
+};
+
+static struct clk_virt scc_qupv3_m_hclk_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_m_hclk_clk",
+	},
+};
+
+static struct clk_virt scc_qupv3_s_hclk_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_s_hclk_clk",
+	},
+};
+
+static struct clk_hw *sm6150_scc_virt_clocks[] = {
+	[SCC_QUPV3_SE0_CLK] = &scc_qupv3_se0_clk.hw,
+	[SCC_QUPV3_SE1_CLK] = &scc_qupv3_se1_clk.hw,
+	[SCC_QUPV3_SE2_CLK] = &scc_qupv3_se2_clk.hw,
+	[SCC_QUPV3_SE3_CLK] = &scc_qupv3_se3_clk.hw,
+	[SCC_QUPV3_M_HCLK_CLK] = &scc_qupv3_m_hclk_clk.hw,
+	[SCC_QUPV3_S_HCLK_CLK] = &scc_qupv3_s_hclk_clk.hw,
+};
+
+const struct clk_virt_desc clk_virt_sm6150_scc = {
+	.clks = sm6150_scc_virt_clocks,
+	.num_clks = ARRAY_SIZE(sm6150_scc_virt_clocks),
+};
diff --git a/drivers/clk/qcom/clk-virt-sm8150.c b/drivers/clk/qcom/clk-virt-sm8150.c
new file mode 100644
index 0000000..431bc5e0
--- /dev/null
+++ b/drivers/clk/qcom/clk-virt-sm8150.c
@@ -0,0 +1,445 @@
+/* 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <dt-bindings/clock/qcom,gcc-sm8150.h>
+#include <dt-bindings/clock/qcom,scc-sm8150.h>
+#include "clk-virt.h"
+
+static struct virt_reset_map sm8150_gcc_virt_resets[] = {
+	[GCC_QUSB2PHY_PRIM_BCR] = { "gcc_qusb2phy_prim_bcr" },
+	[GCC_QUSB2PHY_SEC_BCR] = { "gcc_qusb2phy_sec_bcr" },
+	[GCC_USB3_PHY_PRIM_BCR] = { "gcc_usb3_phy_prim_bcr" },
+	[GCC_USB3_DP_PHY_PRIM_BCR] = { "gcc_usb3_dp_phy_prim_bcr" },
+	[GCC_USB3_PHY_SEC_BCR] = { "gcc_usb3_phy_sec_bcr" },
+	[GCC_USB3PHY_PHY_SEC_BCR] = { "gcc_usb3phy_phy_sec_bcr" },
+	[GCC_USB30_PRIM_BCR] = { "gcc_usb30_prim_master_clk" },
+	[GCC_USB30_SEC_BCR] = { "gcc_usb30_sec_master_clk" },
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s0_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s0_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s1_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s1_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s2_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s2_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s3_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s3_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s4_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s4_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s5_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s5_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s6_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s6_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap0_s7_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap0_s7_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s0_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s0_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s1_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s1_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s2_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s2_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s3_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s3_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s4_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s4_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap1_s5_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap1_s5_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap2_s0_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap2_s0_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap2_s1_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap2_s1_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap2_s2_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap2_s2_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap2_s3_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap2_s3_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap2_s4_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap2_s4_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap2_s5_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap2_s5_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap_0_m_ahb_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap_0_m_ahb_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap_0_s_ahb_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap_0_s_ahb_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap_1_m_ahb_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap_1_m_ahb_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap_1_s_ahb_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap_1_s_ahb_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap_2_m_ahb_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap_2_m_ahb_clk",
+	},
+};
+
+static struct clk_virt gcc_qupv3_wrap_2_s_ahb_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_qupv3_wrap_2_s_ahb_clk",
+	},
+};
+
+static struct clk_virt gcc_usb30_prim_master_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb30_prim_master_clk",
+	},
+};
+
+static struct clk_virt gcc_cfg_noc_usb3_prim_axi_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_cfg_noc_usb3_prim_axi_clk",
+	},
+};
+
+static struct clk_virt gcc_aggre_usb3_prim_axi_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_aggre_usb3_prim_axi_clk",
+	},
+};
+
+static struct clk_virt gcc_usb30_prim_mock_utmi_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb30_prim_mock_utmi_clk",
+	},
+};
+
+static struct clk_virt gcc_usb30_prim_sleep_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb30_prim_sleep_clk",
+	},
+};
+
+static struct clk_virt gcc_usb3_sec_clkref_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_sec_clkref_en",
+	},
+};
+
+static struct clk_virt gcc_usb3_prim_phy_aux_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_prim_phy_aux_clk",
+	},
+};
+
+static struct clk_virt gcc_usb3_prim_phy_pipe_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_prim_phy_pipe_clk",
+	},
+};
+
+static struct clk_virt gcc_usb3_prim_clkref_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_prim_clkref_en",
+	},
+};
+
+static struct clk_virt gcc_usb3_prim_phy_com_aux_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_prim_phy_com_aux_clk",
+	},
+};
+
+static struct clk_virt gcc_usb30_sec_master_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb30_sec_master_clk",
+	},
+};
+
+static struct clk_virt gcc_cfg_noc_usb3_sec_axi_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_cfg_noc_usb3_sec_axi_clk",
+	},
+};
+
+static struct clk_virt gcc_aggre_usb3_sec_axi_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_aggre_usb3_sec_axi_clk",
+	},
+};
+
+static struct clk_virt gcc_usb30_sec_mock_utmi_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb30_sec_mock_utmi_clk",
+	},
+};
+
+static struct clk_virt gcc_usb30_sec_sleep_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb30_sec_sleep_clk",
+	},
+};
+
+static struct clk_virt gcc_usb3_sec_phy_aux_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_sec_phy_aux_clk",
+	},
+};
+
+static struct clk_virt gcc_usb3_sec_phy_pipe_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_sec_phy_pipe_clk",
+	},
+};
+
+static struct clk_virt gcc_usb3_sec_phy_com_aux_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "gcc_usb3_sec_phy_com_aux_clk",
+	},
+};
+
+static struct clk_hw *sm8150_gcc_virt_clocks[] = {
+	[GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.hw,
+	[GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.hw,
+	[GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.hw,
+	[GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.hw,
+	[GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.hw,
+	[GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.hw,
+	[GCC_QUPV3_WRAP0_S6_CLK] = &gcc_qupv3_wrap0_s6_clk.hw,
+	[GCC_QUPV3_WRAP0_S7_CLK] = &gcc_qupv3_wrap0_s7_clk.hw,
+	[GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.hw,
+	[GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.hw,
+	[GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.hw,
+	[GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.hw,
+	[GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.hw,
+	[GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.hw,
+	[GCC_QUPV3_WRAP2_S0_CLK] = &gcc_qupv3_wrap2_s0_clk.hw,
+	[GCC_QUPV3_WRAP2_S1_CLK] = &gcc_qupv3_wrap2_s1_clk.hw,
+	[GCC_QUPV3_WRAP2_S2_CLK] = &gcc_qupv3_wrap2_s2_clk.hw,
+	[GCC_QUPV3_WRAP2_S3_CLK] = &gcc_qupv3_wrap2_s3_clk.hw,
+	[GCC_QUPV3_WRAP2_S4_CLK] = &gcc_qupv3_wrap2_s4_clk.hw,
+	[GCC_QUPV3_WRAP2_S5_CLK] = &gcc_qupv3_wrap2_s5_clk.hw,
+	[GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.hw,
+	[GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.hw,
+	[GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.hw,
+	[GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.hw,
+	[GCC_QUPV3_WRAP_2_M_AHB_CLK] = &gcc_qupv3_wrap_2_m_ahb_clk.hw,
+	[GCC_QUPV3_WRAP_2_S_AHB_CLK] = &gcc_qupv3_wrap_2_s_ahb_clk.hw,
+	[GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.hw,
+	[GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.hw,
+	[GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.hw,
+	[GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.hw,
+	[GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.hw,
+	[GCC_USB3_SEC_CLKREF_CLK] = &gcc_usb3_sec_clkref_clk.hw,
+	[GCC_USB3_PRIM_PHY_AUX_CLK] = &gcc_usb3_prim_phy_aux_clk.hw,
+	[GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.hw,
+	[GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.hw,
+	[GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.hw,
+	[GCC_USB30_SEC_MASTER_CLK] = &gcc_usb30_sec_master_clk.hw,
+	[GCC_CFG_NOC_USB3_SEC_AXI_CLK] = &gcc_cfg_noc_usb3_sec_axi_clk.hw,
+	[GCC_AGGRE_USB3_SEC_AXI_CLK] = &gcc_aggre_usb3_sec_axi_clk.hw,
+	[GCC_USB30_SEC_MOCK_UTMI_CLK] = &gcc_usb30_sec_mock_utmi_clk.hw,
+	[GCC_USB30_SEC_SLEEP_CLK] = &gcc_usb30_sec_sleep_clk.hw,
+	[GCC_USB3_SEC_PHY_AUX_CLK] = &gcc_usb3_sec_phy_aux_clk.hw,
+	[GCC_USB3_SEC_PHY_PIPE_CLK] = &gcc_usb3_sec_phy_pipe_clk.hw,
+	[GCC_USB3_SEC_PHY_COM_AUX_CLK] = &gcc_usb3_sec_phy_com_aux_clk.hw,
+};
+
+const struct clk_virt_desc clk_virt_sm8150_gcc = {
+	.clks = sm8150_gcc_virt_clocks,
+	.num_clks = ARRAY_SIZE(sm8150_gcc_virt_clocks),
+	.resets = sm8150_gcc_virt_resets,
+	.num_resets = ARRAY_SIZE(sm8150_gcc_virt_resets),
+};
+
+static struct clk_virt scc_qupv3_se0_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_se0_clk",
+	},
+};
+
+static struct clk_virt scc_qupv3_se1_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_se1_clk",
+	},
+};
+
+static struct clk_virt scc_qupv3_se2_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_se2_clk",
+	},
+};
+
+static struct clk_virt scc_qupv3_se3_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_se3_clk",
+	},
+};
+
+static struct clk_virt scc_qupv3_m_hclk_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_m_hclk_clk",
+	},
+};
+
+static struct clk_virt scc_qupv3_s_hclk_clk = {
+	.hw.init = &(struct clk_init_data) {
+		.ops = &clk_virt_ops,
+		.name = "scc_qupv3_s_hclk_clk",
+	},
+};
+
+static struct clk_hw *sm8150_scc_virt_clocks[] = {
+	[SCC_QUPV3_SE0_CLK] = &scc_qupv3_se0_clk.hw,
+	[SCC_QUPV3_SE1_CLK] = &scc_qupv3_se1_clk.hw,
+	[SCC_QUPV3_SE2_CLK] = &scc_qupv3_se2_clk.hw,
+	[SCC_QUPV3_SE3_CLK] = &scc_qupv3_se3_clk.hw,
+	[SCC_QUPV3_M_HCLK_CLK] = &scc_qupv3_m_hclk_clk.hw,
+	[SCC_QUPV3_S_HCLK_CLK] = &scc_qupv3_s_hclk_clk.hw,
+};
+
+const struct clk_virt_desc clk_virt_sm8150_scc = {
+	.clks = sm8150_scc_virt_clocks,
+	.num_clks = ARRAY_SIZE(sm8150_scc_virt_clocks),
+};
diff --git a/drivers/clk/qcom/clk-virt.c b/drivers/clk/qcom/clk-virt.c
new file mode 100644
index 0000000..1b5aa23
--- /dev/null
+++ b/drivers/clk/qcom/clk-virt.c
@@ -0,0 +1,668 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/reset-controller.h>
+#include <linux/delay.h>
+#include <linux/habmm.h>
+#include "clk-virt.h"
+
+enum virtclk_cmd {
+	CLK_MSG_GETID = 1,
+	CLK_MSG_ENABLE,
+	CLK_MSG_DISABLE,
+	CLK_MSG_RESET,
+	CLK_MSG_SETFREQ,
+	CLK_MSG_GETFREQ,
+	CLK_MSG_MAX
+};
+
+struct clk_msg_header {
+	u32 cmd;
+	u32 len;
+	u32 clk_id;
+} __packed;
+
+struct clk_msg_rsp {
+	struct clk_msg_header header;
+	u32 rsp;
+} __packed;
+
+struct clk_msg_setfreq {
+	struct clk_msg_header header;
+	u32 freq;
+} __packed;
+
+struct clk_msg_reset {
+	struct clk_msg_header header;
+	u32 reset;
+} __packed;
+
+struct clk_msg_getid {
+	struct clk_msg_header header;
+	char name[32];
+} __packed;
+
+struct clk_msg_getfreq {
+	struct clk_msg_rsp rsp;
+	u32 freq;
+} __packed;
+
+struct virt_cc {
+	struct reset_controller_dev rcdev;
+	struct virt_reset_map *resets;
+	struct clk_onecell_data data;
+	struct clk *clks[];
+};
+
+static DEFINE_MUTEX(virt_clk_lock);
+static int hab_handle;
+
+static inline struct clk_virt *to_clk_virt(struct clk_hw *_hw)
+{
+	return container_of(_hw, struct clk_virt, hw);
+}
+
+static int clk_virt_init_iface(void)
+{
+	int ret = 0;
+	int handle;
+
+	mutex_lock(&virt_clk_lock);
+
+	if (hab_handle)
+		goto out;
+
+	ret = habmm_socket_open(&handle, MM_CLK_VM1, 0, 0);
+	if (ret) {
+		pr_err("open habmm socket failed (%d)\n", ret);
+		goto out;
+	}
+
+	hab_handle = handle;
+
+out:
+	mutex_unlock(&virt_clk_lock);
+	return ret;
+}
+
+static int clk_virt_get_id(struct clk_hw *hw)
+{
+	struct clk_virt *v = to_clk_virt(hw);
+	struct clk_msg_getid msg;
+	struct clk_msg_rsp rsp;
+	u32 rsp_size = sizeof(rsp);
+	int handle;
+	int ret = 0;
+
+	if (v->id)
+		return ret;
+
+	msg.header.cmd = CLK_MSG_GETID | v->flag;
+	msg.header.len = sizeof(msg);
+	strlcpy(msg.name, clk_hw_get_name(hw), sizeof(msg.name));
+
+	mutex_lock(&virt_clk_lock);
+
+	handle = hab_handle;
+	ret = habmm_socket_send(handle, &msg, sizeof(msg), 0);
+	if (ret) {
+		pr_err("%s: habmm socket send failed (%d)\n",
+				clk_hw_get_name(hw), ret);
+		goto err_out;
+	}
+
+	ret = habmm_socket_recv(handle, &rsp, &rsp_size,
+			UINT_MAX, HABMM_SOCKET_RECV_FLAGS_UNINTERRUPTIBLE);
+	if (ret) {
+		pr_err("%s: habmm socket receive failed (%d)\n",
+				clk_hw_get_name(hw), ret);
+		goto err_out;
+	}
+
+	if (rsp.rsp) {
+		pr_err("%s: error response (%d)\n", clk_hw_get_name(hw),
+				rsp.rsp);
+		ret = -EIO;
+	} else
+		v->id = rsp.header.clk_id;
+
+	mutex_unlock(&virt_clk_lock);
+
+	return ret;
+
+err_out:
+	habmm_socket_close(handle);
+	hab_handle = 0;
+	mutex_unlock(&virt_clk_lock);
+	return ret;
+}
+
+static int clk_virt_prepare(struct clk_hw *hw)
+{
+	struct clk_virt *v = to_clk_virt(hw);
+	struct clk_msg_header msg;
+	struct clk_msg_rsp rsp;
+	u32 rsp_size = sizeof(rsp);
+	int handle;
+	int ret = 0;
+
+	ret = clk_virt_init_iface();
+	if (ret)
+		return ret;
+
+	ret = clk_virt_get_id(hw);
+	if (ret)
+		return ret;
+
+	msg.clk_id = v->id;
+	msg.cmd = CLK_MSG_ENABLE | v->flag;
+	msg.len = sizeof(struct clk_msg_header);
+
+	mutex_lock(&virt_clk_lock);
+
+	handle = hab_handle;
+	ret = habmm_socket_send(handle, &msg, sizeof(msg), 0);
+	if (ret) {
+		pr_err("%s: habmm socket send failed (%d)\n",
+				clk_hw_get_name(hw), ret);
+		goto err_out;
+	}
+
+	ret = habmm_socket_recv(handle, &rsp, &rsp_size, UINT_MAX,
+			HABMM_SOCKET_RECV_FLAGS_UNINTERRUPTIBLE);
+	if (ret) {
+		pr_err("%s: habmm socket receive failed (%d)\n",
+				clk_hw_get_name(hw), ret);
+		goto err_out;
+	}
+
+	if (rsp.rsp) {
+		pr_err("%s: error response (%d)\n", clk_hw_get_name(hw),
+				rsp.rsp);
+		ret = -EIO;
+	}
+
+	mutex_unlock(&virt_clk_lock);
+	return ret;
+
+err_out:
+	habmm_socket_close(handle);
+	hab_handle = 0;
+	mutex_unlock(&virt_clk_lock);
+	return ret;
+}
+
+static void clk_virt_unprepare(struct clk_hw *hw)
+{
+	struct clk_virt *v = to_clk_virt(hw);
+	struct clk_msg_header msg;
+	struct clk_msg_rsp rsp;
+	u32 rsp_size = sizeof(rsp);
+	int handle;
+	int ret = 0;
+
+	ret = clk_virt_init_iface();
+	if (ret)
+		return;
+
+	ret = clk_virt_get_id(hw);
+	if (ret)
+		return;
+
+	msg.clk_id = v->id;
+	msg.cmd = CLK_MSG_DISABLE | v->flag;
+	msg.len = sizeof(struct clk_msg_header);
+
+	mutex_lock(&virt_clk_lock);
+
+	handle = hab_handle;
+	ret = habmm_socket_send(handle, &msg, sizeof(msg), 0);
+	if (ret) {
+		pr_err("%s: habmm socket send failed (%d)\n",
+				clk_hw_get_name(hw), ret);
+		goto err_out;
+	}
+
+	ret = habmm_socket_recv(handle, &rsp, &rsp_size, UINT_MAX,
+			HABMM_SOCKET_RECV_FLAGS_UNINTERRUPTIBLE);
+	if (ret) {
+		pr_err("%s: habmm socket receive failed (%d)\n",
+				clk_hw_get_name(hw), ret);
+		goto err_out;
+	}
+
+	if (rsp.rsp)
+		pr_err("%s: error response (%d)\n", clk_hw_get_name(hw),
+				rsp.rsp);
+
+	mutex_unlock(&virt_clk_lock);
+	return;
+
+err_out:
+	habmm_socket_close(handle);
+	hab_handle = 0;
+	mutex_unlock(&virt_clk_lock);
+}
+
+static int clk_virt_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_virt *v = to_clk_virt(hw);
+	struct clk_msg_setfreq msg;
+	struct clk_msg_rsp rsp;
+	u32 rsp_size = sizeof(rsp);
+	int handle;
+	int ret = 0;
+
+	ret = clk_virt_init_iface();
+	if (ret)
+		return ret;
+
+	ret = clk_virt_get_id(hw);
+	if (ret)
+		return ret;
+
+	msg.header.clk_id = v->id;
+	msg.header.cmd = CLK_MSG_SETFREQ | v->flag;
+	msg.header.len = sizeof(msg);
+	msg.freq = (u32)rate;
+
+	mutex_lock(&virt_clk_lock);
+
+	handle = hab_handle;
+	ret = habmm_socket_send(handle, &msg, sizeof(msg), 0);
+	if (ret) {
+		pr_err("%s: habmm socket send failed (%d)\n",
+				clk_hw_get_name(hw), ret);
+		goto err_out;
+	}
+
+	ret = habmm_socket_recv(handle, &rsp, &rsp_size, UINT_MAX,
+			HABMM_SOCKET_RECV_FLAGS_UNINTERRUPTIBLE);
+	if (ret) {
+		pr_err("%s: habmm socket receive failed (%d)\n",
+				clk_hw_get_name(hw),
+				ret);
+		goto err_out;
+	}
+
+	if (rsp.rsp) {
+		pr_err("%s (%luHz): error response (%d)\n", clk_hw_get_name(hw),
+				rate, rsp.rsp);
+		ret = -EIO;
+	}
+
+	mutex_unlock(&virt_clk_lock);
+	return ret;
+
+err_out:
+	habmm_socket_close(handle);
+	hab_handle = 0;
+	mutex_unlock(&virt_clk_lock);
+	return ret;
+}
+
+static long clk_virt_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	return rate;
+}
+
+static unsigned long clk_virt_get_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_virt *v = to_clk_virt(hw);
+	struct clk_msg_header msg;
+	struct clk_msg_getfreq rsp;
+	u32 rsp_size = sizeof(rsp);
+	int handle;
+	int ret = 0;
+
+	ret = clk_virt_init_iface();
+	if (ret)
+		return 0;
+
+	ret = clk_virt_get_id(hw);
+	if (ret)
+		return 0;
+
+	msg.clk_id = v->id;
+	msg.cmd = CLK_MSG_GETFREQ | v->flag;
+	msg.len = sizeof(msg);
+
+	mutex_lock(&virt_clk_lock);
+
+	handle = hab_handle;
+	ret = habmm_socket_send(handle, &msg, sizeof(msg), 0);
+	if (ret) {
+		ret = 0;
+		pr_err("%s: habmm socket send failed (%d)\n",
+				clk_hw_get_name(hw), ret);
+		goto err_out;
+	}
+
+	ret = habmm_socket_recv(handle, &rsp, &rsp_size, UINT_MAX,
+			HABMM_SOCKET_RECV_FLAGS_UNINTERRUPTIBLE);
+	if (ret) {
+		ret = 0;
+		pr_err("%s: habmm socket receive failed (%d)\n",
+				clk_hw_get_name(hw),
+				ret);
+		goto err_out;
+	}
+
+	if (rsp.rsp.rsp) {
+		pr_err("%s: error response (%d)\n", clk_hw_get_name(hw),
+				rsp.rsp.rsp);
+		ret = 0;
+	} else
+		ret = rsp.freq;
+
+	mutex_unlock(&virt_clk_lock);
+	return ret;
+
+err_out:
+	habmm_socket_close(handle);
+	hab_handle = 0;
+	mutex_unlock(&virt_clk_lock);
+	return ret;
+}
+
+const struct clk_ops clk_virt_ops = {
+	.prepare = clk_virt_prepare,
+	.unprepare = clk_virt_unprepare,
+	.set_rate = clk_virt_set_rate,
+	.round_rate = clk_virt_round_rate,
+	.recalc_rate = clk_virt_get_rate,
+};
+
+#define rc_to_vcc(r) \
+	container_of(r, struct virt_cc, rcdev)
+
+static int virtrc_get_clk_id(struct reset_controller_dev *rcdev,
+		unsigned long id)
+{
+	struct virt_cc *vcc;
+	struct virt_reset_map *map;
+	struct clk_msg_getid msg;
+	struct clk_msg_rsp rsp;
+	u32 rsp_size = sizeof(rsp);
+	int handle;
+	int ret = 0;
+
+	vcc = rc_to_vcc(rcdev);
+	map = &vcc->resets[id];
+	msg.header.cmd = CLK_MSG_GETID;
+	msg.header.len = sizeof(msg);
+	strlcpy(msg.name, map->clk_name, sizeof(msg.name));
+
+	mutex_lock(&virt_clk_lock);
+
+	handle = hab_handle;
+	ret = habmm_socket_send(handle, &msg, sizeof(msg), 0);
+	if (ret) {
+		pr_err("%s: habmm socket send failed (%d)\n", map->clk_name,
+				ret);
+		goto err_out;
+	}
+
+	ret = habmm_socket_recv(handle, &rsp, &rsp_size,
+			UINT_MAX, 0);
+	if (ret) {
+		pr_err("%s: habmm socket receive failed (%d)\n", map->clk_name,
+				ret);
+		goto err_out;
+	}
+
+	if (rsp.rsp) {
+		pr_err("%s: error response (%d)\n", map->clk_name, rsp.rsp);
+		ret = -EIO;
+	} else
+		map->clk_id = rsp.header.clk_id;
+
+	mutex_unlock(&virt_clk_lock);
+
+	return ret;
+
+err_out:
+	habmm_socket_close(handle);
+	hab_handle = 0;
+	mutex_unlock(&virt_clk_lock);
+	return ret;
+}
+
+static int __virtrc_reset(struct reset_controller_dev *rcdev,
+		unsigned long id, unsigned int action)
+{
+	struct virt_cc *vcc;
+	struct virt_reset_map *map;
+	struct clk_msg_reset msg;
+	struct clk_msg_rsp rsp;
+	u32 rsp_size = sizeof(rsp);
+	int handle;
+	int ret = 0;
+
+	vcc = rc_to_vcc(rcdev);
+	map = &vcc->resets[id];
+
+	ret = clk_virt_init_iface();
+	if (ret)
+		return ret;
+
+	ret = virtrc_get_clk_id(rcdev, id);
+	if (ret)
+		return ret;
+
+	msg.header.clk_id = map->clk_id;
+	msg.header.cmd = CLK_MSG_RESET;
+	msg.header.len = sizeof(struct clk_msg_header);
+	msg.reset = action;
+
+	mutex_lock(&virt_clk_lock);
+
+	handle = hab_handle;
+	ret = habmm_socket_send(handle, &msg, sizeof(msg), 0);
+	if (ret) {
+		pr_err("%s: habmm socket send failed (%d)\n", map->clk_name,
+				ret);
+		goto err_out;
+	}
+
+	ret = habmm_socket_recv(handle, &rsp, &rsp_size, UINT_MAX, 0);
+	if (ret) {
+		pr_err("%s: habmm socket receive failed (%d)\n", map->clk_name,
+				ret);
+		goto err_out;
+	}
+
+	if (rsp.rsp) {
+		pr_err("%s: error response (%d)\n", map->clk_name, rsp.rsp);
+		ret = -EIO;
+	}
+
+	mutex_unlock(&virt_clk_lock);
+
+	pr_debug("%s(%lu): do %s\n", map->clk_name, id,
+			action == 1 ? "assert" : "deassert");
+
+	return ret;
+
+err_out:
+	habmm_socket_close(handle);
+	hab_handle = 0;
+	mutex_unlock(&virt_clk_lock);
+	return ret;
+}
+
+static int virtrc_reset(struct reset_controller_dev *rcdev,
+		unsigned long id)
+{
+	int ret = 0;
+
+	ret = __virtrc_reset(rcdev, id, 1);
+	if (ret)
+		return ret;
+
+	udelay(1);
+
+	return __virtrc_reset(rcdev, id, 0);
+}
+
+static int virtrc_reset_assert(struct reset_controller_dev *rcdev,
+		unsigned long id)
+{
+	return __virtrc_reset(rcdev, id, 1);
+}
+
+static int virtrc_reset_deassert(struct reset_controller_dev *rcdev,
+		unsigned long id)
+{
+	return __virtrc_reset(rcdev, id, 0);
+}
+
+static const struct reset_control_ops virtrc_ops = {
+	.reset = virtrc_reset,
+	.assert = virtrc_reset_assert,
+	.deassert = virtrc_reset_deassert,
+};
+
+static const struct of_device_id clk_virt_match_table[] = {
+	{
+		.compatible = "qcom,virt-clk-sm8150-gcc",
+		.data = &clk_virt_sm8150_gcc
+	},
+	{
+		.compatible = "qcom,virt-clk-sm8150-scc",
+		.data = &clk_virt_sm8150_scc
+	},
+	{
+		.compatible = "qcom,virt-clk-sm6150-gcc",
+		.data = &clk_virt_sm6150_gcc
+	},
+	{
+		.compatible = "qcom,virt-clk-sm6150-scc",
+		.data = &clk_virt_sm6150_scc
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, clk_virt_match_table);
+
+static int clk_virt_probe(struct platform_device *pdev)
+{
+	struct clk **clks;
+	struct clk *clk;
+	struct virt_cc *vcc;
+	struct clk_onecell_data *data;
+	int ret;
+	size_t num_clks, num_resets, i;
+	struct clk_hw **hw_clks;
+	struct virt_reset_map *resets;
+	struct clk_virt *virt_clk;
+	const struct clk_virt_desc *desc;
+
+	desc = of_device_get_match_data(&pdev->dev);
+	if (!desc) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	hw_clks = desc->clks;
+	num_clks = desc->num_clks;
+	resets = desc->resets;
+	num_resets = desc->num_resets;
+
+	vcc = devm_kzalloc(&pdev->dev, sizeof(*vcc) + sizeof(*clks) * num_clks,
+			GFP_KERNEL);
+	if (!vcc) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	clks = vcc->clks;
+	data = &vcc->data;
+	data->clks = clks;
+	data->clk_num = num_clks;
+
+	for (i = 0; i < num_clks; i++) {
+		if (!hw_clks[i]) {
+			clks[i] = ERR_PTR(-ENOENT);
+			continue;
+		}
+
+		virt_clk = to_clk_virt(hw_clks[i]);
+
+		clk = devm_clk_register(&pdev->dev, hw_clks[i]);
+		if (IS_ERR(clk)) {
+			ret = PTR_ERR(clk);
+			goto err;
+		}
+
+		clks[i] = clk;
+	}
+
+	ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
+				  data);
+	if (ret)
+		goto err;
+
+	vcc->rcdev.of_node = pdev->dev.of_node;
+	vcc->rcdev.ops = &virtrc_ops;
+	vcc->rcdev.owner = pdev->dev.driver->owner;
+	vcc->rcdev.nr_resets = desc->num_resets;
+	vcc->resets = desc->resets;
+
+	ret = devm_reset_controller_register(&pdev->dev, &vcc->rcdev);
+	if (ret)
+		return ret;
+
+	dev_info(&pdev->dev, "Registered virtual clocks\n");
+
+	return ret;
+err:
+	dev_err(&pdev->dev, "Error registering virtual clock driver (%d)\n",
+			ret);
+	return ret;
+}
+
+static struct platform_driver clk_virt_driver = {
+	.probe		= clk_virt_probe,
+	.driver		= {
+		.name	= "clk-virt",
+		.of_match_table = clk_virt_match_table,
+	},
+};
+
+static int __init clk_virt_init(void)
+{
+	return platform_driver_register(&clk_virt_driver);
+}
+fs_initcall(clk_virt_init);
+
+static void __exit clk_virt_exit(void)
+{
+	platform_driver_unregister(&clk_virt_driver);
+}
+module_exit(clk_virt_exit);
+
+MODULE_DESCRIPTION("QTI Virtual Clock Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:clk-virt");
diff --git a/drivers/clk/qcom/clk-virt.h b/drivers/clk/qcom/clk-virt.h
new file mode 100644
index 0000000..16c799a
--- /dev/null
+++ b/drivers/clk/qcom/clk-virt.h
@@ -0,0 +1,61 @@
+/* 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.
+ */
+
+#ifndef __QCOM_CLK_VIRT_H__
+#define __QCOM_CLK_VIRT_H__
+
+/* remote clock flag */
+#define CLOCK_FLAG_NODE_TYPE_REMOTE	0xff00
+
+/**
+ * struct clk_virt - virtual clock
+ * id: clock id
+ * hw: hardware clock
+ * flag: clock flag
+ */
+struct clk_virt {
+	int id;
+	struct clk_hw hw;
+	u32 flag;
+};
+
+/**
+ * struct virt_reset_map - virtual clock map
+ * clk_name: clock name
+ * clk_id: clock id
+ */
+struct virt_reset_map {
+	const char *clk_name;
+	int clk_id;
+};
+
+/**
+ * struct clk_virt_desc - virtual clock descriptor
+ * clks: clock list pointer
+ * num_clks: number of clocks
+ * resets: reset map
+ * num_resets: number of resets
+ */
+struct clk_virt_desc {
+	struct clk_hw **clks;
+	size_t num_clks;
+	struct virt_reset_map *resets;
+	size_t num_resets;
+};
+
+extern const struct clk_ops clk_virt_ops;
+extern const struct clk_virt_desc clk_virt_sm8150_gcc;
+extern const struct clk_virt_desc clk_virt_sm8150_scc;
+extern const struct clk_virt_desc clk_virt_sm6150_gcc;
+extern const struct clk_virt_desc clk_virt_sm6150_scc;
+
+#endif
diff --git a/drivers/clk/qcom/debugcc-sdxprairie.c b/drivers/clk/qcom/debugcc-sdxprairie.c
index 0c7c77e..a72c9fb 100644
--- a/drivers/clk/qcom/debugcc-sdxprairie.c
+++ b/drivers/clk/qcom/debugcc-sdxprairie.c
@@ -103,6 +103,7 @@ static struct clk_debug_mux gcc_debug_mux = {
 	.src_sel_shift = 0,
 	.post_div_mask = 0xF,
 	.post_div_shift = 0,
+	.period_offset = 0x50,
 	MUX_SRC_LIST(
 		{ "gcc_ahb_pcie_link_clk", 0xCF, 4, GCC,
 			0xCF, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
@@ -214,7 +215,7 @@ static struct clk_debug_mux gcc_debug_mux = {
 			0x63, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
 		{ "gcc_xo_pcie_link_clk", 0x77, 4, GCC,
 			0x77, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
-		{ "measure_only_bimc_clk", 0x73, 4, GCC,
+		{ "measure_only_bimc_clk", 0x73, 4, MC_CC,
 			0x73, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
 		{ "measure_only_ipa_2x_clk", 0xAC, 4, GCC,
 			0xAC, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
@@ -280,6 +281,10 @@ static int clk_debug_sdxprairie_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	ret = map_debug_bases(pdev, "qcom,mccc", MC_CC);
+	if (ret)
+		return ret;
+
 	clk = devm_clk_register(&pdev->dev, &gcc_debug_mux.hw);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "Unable to register GCC debug mux\n");
diff --git a/drivers/clk/qcom/debugcc-trinket.c b/drivers/clk/qcom/debugcc-trinket.c
index 13491b0..148fec8 100644
--- a/drivers/clk/qcom/debugcc-trinket.c
+++ b/drivers/clk/qcom/debugcc-trinket.c
@@ -226,6 +226,8 @@ static const char *const debug_mux_parent_names[] = {
 	"video_cc_venus_ctl_axi_clk",
 	"video_cc_venus_ctl_core_clk",
 	"video_cc_xo_clk",
+	"pwrcl_clk",
+	"perfcl_clk",
 };
 
 static struct clk_debug_mux gcc_debug_mux = {
@@ -625,6 +627,10 @@ static struct clk_debug_mux gcc_debug_mux = {
 			0x1, 0x3F, 0, 0x7, 0, 5, 0xA4C, 0xA30, 0xA38 },
 		{ "video_cc_xo_clk", 0x42, 1, VIDEO_CC,
 			0xC, 0x3F, 0, 0x7, 0, 5, 0xA4C, 0xA30, 0xA38 },
+		{ "pwrcl_clk", 0xAB, 4, CPU_CC,
+			0x0, 0x3FF, 8, 0xF, 28, 1, 0x0, 0x0, U32_MAX, 8 },
+		{ "perfcl_clk", 0xAB, 4, CPU_CC,
+			0x1, 0x3FF, 8, 0xF, 28, 1, 0x0, 0x0, U32_MAX, 8 },
 	),
 	.hw.init = &(struct clk_init_data){
 		.name = "gcc_debug_mux",
@@ -698,6 +704,10 @@ static int clk_debug_trinket_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	ret = map_debug_bases(pdev, "qcom,cpucc", CPU_CC);
+	if (ret)
+		return ret;
+
 	clk = devm_clk_register(&pdev->dev, &gcc_debug_mux.hw);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "Unable to register GCC debug mux\n");
diff --git a/drivers/clk/qcom/dispcc-trinket.c b/drivers/clk/qcom/dispcc-trinket.c
index 0d24183..02ae154 100644
--- a/drivers/clk/qcom/dispcc-trinket.c
+++ b/drivers/clk/qcom/dispcc-trinket.c
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 
@@ -344,7 +345,7 @@ static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
 		.rate_max = (unsigned long[VDD_NUM]) {
 			[VDD_LOWER] = 192000000,
 			[VDD_LOW] = 256000000,
-			[VDD_LOW_L1] = 307000000},
+			[VDD_LOW_L1] = 307200000},
 	},
 };
 
@@ -385,7 +386,7 @@ static struct clk_rcg2 disp_cc_mdss_rot_clk_src = {
 		.rate_max = (unsigned long[VDD_NUM]) {
 			[VDD_LOWER] = 192000000,
 			[VDD_LOW] = 256000000,
-			[VDD_LOW_L1] = 307000000},
+			[VDD_LOW_L1] = 307200000},
 	},
 };
 
@@ -744,6 +745,7 @@ MODULE_DEVICE_TABLE(of, disp_cc_trinket_match_table);
 static int disp_cc_trinket_probe(struct platform_device *pdev)
 {
 	struct regmap *regmap;
+	struct clk *clk;
 	int ret;
 
 	vdd_cx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_cx");
@@ -753,6 +755,14 @@ static int disp_cc_trinket_probe(struct platform_device *pdev)
 		return PTR_ERR(vdd_cx.regulator[0]);
 	}
 
+	clk = devm_clk_get(&pdev->dev, "cfg_ahb_clk");
+	if (IS_ERR(clk)) {
+		if (PTR_ERR(clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Unable to get ahb clock handle\n");
+		return PTR_ERR(clk);
+	}
+	devm_clk_put(&pdev->dev, clk);
+
 	regmap = qcom_cc_map(pdev, &disp_cc_trinket_desc);
 	if (IS_ERR(regmap)) {
 		pr_err("Failed to map the disp_cc registers\n");
diff --git a/drivers/clk/qcom/gcc-sdxprairie.c b/drivers/clk/qcom/gcc-sdxprairie.c
index a3069bd..869cf9e 100644
--- a/drivers/clk/qcom/gcc-sdxprairie.c
+++ b/drivers/clk/qcom/gcc-sdxprairie.c
@@ -567,13 +567,6 @@ static struct clk_rcg2 gcc_cpuss_ahb_clk_src = {
 		.parent_names = gcc_parent_names_0_ao,
 		.num_parents = 4,
 		.ops = &clk_rcg2_ops,
-		.vdd_class = &vdd_cx_ao,
-		.num_rate_max = VDD_NUM,
-		.rate_max = (unsigned long[VDD_NUM]) {
-			[VDD_MIN] = 19200000,
-			[VDD_LOWER] = 50000000,
-			[VDD_NOMINAL] = 100000000,
-			[VDD_HIGH] = 133333333},
 	},
 };
 
@@ -842,6 +835,7 @@ static struct clk_rcg2 gcc_usb30_master_clk_src = {
 };
 
 static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk_src[] = {
+	F(19200000, P_BI_TCXO, 1, 0, 0),
 	F(60000000, P_GPLL0_OUT_EVEN, 5, 0, 0),
 	{ }
 };
@@ -1933,6 +1927,9 @@ static int gcc_sdxprairie_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	clk_set_rate(gcc_cpuss_ahb_clk.clkr.hw.clk, 19200000);
+	clk_set_rate(gcc_sys_noc_cpuss_ahb_clk.clkr.hw.clk, 19200000);
+
 	dev_info(&pdev->dev, "Registered GCC clocks\n");
 
 	return ret;
diff --git a/drivers/clk/qcom/gcc-sm6150.c b/drivers/clk/qcom/gcc-sm6150.c
index 0008af6..1867574 100644
--- a/drivers/clk/qcom/gcc-sm6150.c
+++ b/drivers/clk/qcom/gcc-sm6150.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
@@ -233,13 +233,13 @@ static struct clk_fixed_factor gpll0_out_aux2 = {
 	},
 };
 
-static struct clk_alpha_pll gpll6_out_main = {
+static struct clk_alpha_pll gpll6_out_early = {
 	.offset = 0x13000,
 	.clkr = {
 		.enable_reg = 0x52000,
 		.enable_mask = BIT(6),
 		.hw.init = &(struct clk_init_data){
-			.name = "gpll6_out_main",
+			.name = "gpll6_out_early",
 			.parent_names = (const char *[]){ "bi_tcxo" },
 			.num_parents = 1,
 			.ops = &clk_alpha_pll_ops,
@@ -247,6 +247,17 @@ static struct clk_alpha_pll gpll6_out_main = {
 	},
 };
 
+static struct clk_fixed_factor gpll6_out_main = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll6_out_main",
+		.parent_names = (const char *[]){ "gpll6_out_early" },
+		.num_parents = 1,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
 static struct clk_alpha_pll gpll7_out_main = {
 	.offset = 0x1a000,
 	.clkr = {
@@ -261,13 +272,13 @@ static struct clk_alpha_pll gpll7_out_main = {
 	},
 };
 
-static struct clk_alpha_pll gpll8_out_main = {
+static struct clk_alpha_pll gpll8_out_early = {
 	.offset = 0x1b000,
 	.clkr = {
 		.enable_reg = 0x52000,
 		.enable_mask = BIT(8),
 		.hw.init = &(struct clk_init_data){
-			.name = "gpll8_out_main",
+			.name = "gpll8_out_early",
 			.parent_names = (const char *[]){ "bi_tcxo" },
 			.num_parents = 1,
 			.ops = &clk_alpha_pll_ops,
@@ -275,6 +286,17 @@ static struct clk_alpha_pll gpll8_out_main = {
 	},
 };
 
+static struct clk_fixed_factor gpll8_out_main = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll8_out_main",
+		.parent_names = (const char *[]){ "gpll8_out_early" },
+		.num_parents = 1,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
 static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = {
 	F(19200000, P_BI_TCXO, 1, 0, 0),
 	{ }
@@ -3259,6 +3281,8 @@ static struct clk_dummy measure_only_snoc_clk = {
 
 struct clk_hw *gcc_sm6150_hws[] = {
 	[GPLL0_OUT_AUX2] = &gpll0_out_aux2.hw,
+	[GPLL6_OUT_MAIN] = &gpll6_out_main.hw,
+	[GPLL8_OUT_MAIN] = &gpll8_out_main.hw,
 	[MEASURE_ONLY_MMCC_CLK] = &measure_only_mccc_clk.hw,
 	[MEASURE_ONLY_CNOC_CLK] = &measure_only_cnoc_clk.hw,
 	[MEASURE_ONLY_IPA_2X_CLK] = &measure_only_ipa_2x_clk.hw,
@@ -3434,9 +3458,9 @@ static struct clk_regmap *gcc_sm6150_clocks[] = {
 	[GCC_VSENSOR_CLK_SRC] = &gcc_vsensor_clk_src.clkr,
 	[GCC_WCSS_VS_CLK] = &gcc_wcss_vs_clk.clkr,
 	[GPLL0_OUT_MAIN] = &gpll0_out_main.clkr,
-	[GPLL6_OUT_MAIN] = &gpll6_out_main.clkr,
+	[GPLL6_OUT_EARLY] = &gpll6_out_early.clkr,
 	[GPLL7_OUT_MAIN] = &gpll7_out_main.clkr,
-	[GPLL8_OUT_MAIN] = &gpll8_out_main.clkr,
+	[GPLL8_OUT_EARLY] = &gpll8_out_early.clkr,
 	[GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr,
 	[GCC_RX3_USB2_CLKREF_CLK] = &gcc_rx3_usb2_clkref_clk.clkr,
 	[GCC_USB2_PRIM_CLKREF_CLK] = &gcc_usb2_prim_clkref_clk.clkr,
diff --git a/drivers/clk/qcom/gcc-trinket.c b/drivers/clk/qcom/gcc-trinket.c
index fd174fb..fc2cf8b 100644
--- a/drivers/clk/qcom/gcc-trinket.c
+++ b/drivers/clk/qcom/gcc-trinket.c
@@ -405,13 +405,13 @@ static struct clk_fixed_factor gpll6_out_main = {
 	},
 };
 
-static struct clk_alpha_pll gpll7_out_main = {
+static struct clk_alpha_pll gpll7_out_early = {
 	.offset = 0x7000,
 	.clkr = {
 		.enable_reg = 0x79000,
 		.enable_mask = BIT(7),
 		.hw.init = &(struct clk_init_data){
-			.name = "gpll7_out_main",
+			.name = "gpll7_out_early",
 			.parent_names = (const char *[]){ "bi_tcxo" },
 			.num_parents = 1,
 			.ops = &clk_alpha_pll_ops,
@@ -419,6 +419,17 @@ static struct clk_alpha_pll gpll7_out_main = {
 	},
 };
 
+static struct clk_fixed_factor gpll7_out_main = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll7_out_main",
+		.parent_names = (const char *[]){ "gpll7_out_early" },
+		.num_parents = 1,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
 static struct clk_alpha_pll gpll8_out_early = {
 	.offset = 0x8000,
 	.clkr = {
@@ -526,10 +537,9 @@ static struct clk_rcg2 gcc_camss_cci_clk_src = {
 
 static const struct freq_tbl ftbl_gcc_camss_cpp_clk_src[] = {
 	F(120000000, P_GPLL8_OUT_MAIN, 4, 0, 0),
-	F(256000000, P_GPLL6_OUT_EARLY, 3, 0, 0),
-	F(384000000, P_GPLL6_OUT_EARLY, 2, 0, 0),
+	F(240000000, P_GPLL8_OUT_MAIN, 2, 0, 0),
+	F(320000000, P_GPLL8_OUT_MAIN, 1.5, 0, 0),
 	F(480000000, P_GPLL8_OUT_MAIN, 1, 0, 0),
-	F(533000000, P_GPLL3_OUT_EARLY, 2, 0, 0),
 	F(576000000, P_GPLL9_OUT_MAIN, 1, 0, 0),
 	{ }
 };
@@ -550,10 +560,9 @@ static struct clk_rcg2 gcc_camss_cpp_clk_src = {
 		.num_rate_max = VDD_NUM,
 		.rate_max = (unsigned long[VDD_NUM]) {
 			[VDD_LOWER] = 120000000,
-			[VDD_LOW] = 256000000,
-			[VDD_LOW_L1] = 384000000,
+			[VDD_LOW] = 240000000,
+			[VDD_LOW_L1] = 320000000,
 			[VDD_NOMINAL] = 480000000,
-			[VDD_NOMINAL_L1] = 533000000,
 			[VDD_HIGH] = 576000000},
 	},
 };
@@ -967,31 +976,6 @@ static struct clk_rcg2 gcc_camss_vfe1_clk_src = {
 	},
 };
 
-static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = {
-	F(19200000, P_BI_TCXO, 1, 0, 0),
-	{ }
-};
-
-static struct clk_rcg2 gcc_cpuss_ahb_clk_src = {
-	.cmd_rcgr = 0x2b13c,
-	.mnd_width = 0,
-	.hid_width = 5,
-	.parent_map = gcc_parent_map_0,
-	.freq_tbl = ftbl_gcc_cpuss_ahb_clk_src,
-	.clkr.hw.init = &(struct clk_init_data){
-		.name = "gcc_cpuss_ahb_clk_src",
-		.parent_names = gcc_parent_names_0_ao,
-		.num_parents = 4,
-		.ops = &clk_rcg2_ops,
-		.vdd_class = &vdd_cx_ao,
-		.num_rate_max = VDD_NUM,
-		.rate_max = (unsigned long[VDD_NUM]) {
-			[VDD_LOWER] = 19200000,
-			[VDD_LOW] = 50000000,
-			[VDD_NOMINAL] = 100000000},
-	},
-};
-
 static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = {
 	F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0),
 	F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0),
@@ -2868,24 +2852,6 @@ static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = {
 	},
 };
 
-static struct clk_branch gcc_cpuss_ahb_clk = {
-	.halt_reg = 0x2b000,
-	.halt_check = BRANCH_HALT_VOTED,
-	.clkr = {
-		.enable_reg = 0x79004,
-		.enable_mask = BIT(21),
-		.hw.init = &(struct clk_init_data){
-			.name = "gcc_cpuss_ahb_clk",
-			.parent_names = (const char *[]){
-				"gcc_cpuss_ahb_clk_src",
-			},
-			.num_parents = 1,
-			.flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_branch gcc_cpuss_gnoc_clk = {
 	.halt_reg = 0x2b004,
 	.halt_check = BRANCH_HALT_VOTED,
@@ -3674,7 +3640,7 @@ static struct clk_branch gcc_sdcc1_apps_clk = {
 				"gcc_sdcc1_apps_clk_src",
 			},
 			.num_parents = 1,
-			.flags = CLK_SET_RATE_PARENT,
+			.flags = CLK_SET_RATE_PARENT | CLK_ENABLE_HAND_OFF,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -4206,6 +4172,7 @@ struct clk_hw *gcc_trinket_hws[] = {
 	[GPLL0_OUT_AUX2] = &gpll0_out_aux2.hw,
 	[GPLL0_OUT_MAIN] = &gpll0_out_main.hw,
 	[GPLL6_OUT_MAIN] = &gpll6_out_main.hw,
+	[GPLL7_OUT_MAIN] = &gpll7_out_main.hw,
 	[GPLL8_OUT_MAIN] = &gpll8_out_main.hw,
 	[GPLL9_OUT_MAIN] = &gpll9_out_main.hw,
 	[MEASURE_ONLY_MMCC_CLK] = &measure_only_mccc_clk.hw,
@@ -4302,8 +4269,6 @@ static struct clk_regmap *gcc_trinket_clocks[] = {
 	[GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr,
 	[GCC_CE1_CLK] = &gcc_ce1_clk.clkr,
 	[GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr,
-	[GCC_CPUSS_AHB_CLK] = &gcc_cpuss_ahb_clk.clkr,
-	[GCC_CPUSS_AHB_CLK_SRC] = &gcc_cpuss_ahb_clk_src.clkr,
 	[GCC_CPUSS_GNOC_CLK] = &gcc_cpuss_gnoc_clk.clkr,
 	[GCC_CPUSS_THROTTLE_CORE_CLK] = &gcc_cpuss_throttle_core_clk.clkr,
 	[GCC_CPUSS_THROTTLE_XO_CLK] = &gcc_cpuss_throttle_xo_clk.clkr,
@@ -4420,7 +4385,7 @@ static struct clk_regmap *gcc_trinket_clocks[] = {
 	[GPLL4_OUT_MAIN] = &gpll4_out_main.clkr,
 	[GPLL5_OUT_MAIN] = &gpll5_out_main.clkr,
 	[GPLL6_OUT_EARLY] = &gpll6_out_early.clkr,
-	[GPLL7_OUT_MAIN] = &gpll7_out_main.clkr,
+	[GPLL7_OUT_EARLY] = &gpll7_out_early.clkr,
 	[GPLL8_OUT_EARLY] = &gpll8_out_early.clkr,
 	[GPLL9_OUT_EARLY] = &gpll9_out_early.clkr,
 	[GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.clkr,
diff --git a/drivers/clk/qcom/gpucc-trinket.c b/drivers/clk/qcom/gpucc-trinket.c
index 2cd2b75..b92f00c 100644
--- a/drivers/clk/qcom/gpucc-trinket.c
+++ b/drivers/clk/qcom/gpucc-trinket.c
@@ -389,6 +389,19 @@ static struct clk_branch gpu_cc_ahb_clk = {
 	},
 };
 
+static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
+	.halt_reg = 0x5000,
+	.halt_check = BRANCH_VOTED,
+	.clkr = {
+		.enable_reg = 0x5000,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
 static struct clk_regmap *gpu_cc_trinket_clocks[] = {
 	[GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
 	[GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr,
@@ -405,6 +418,7 @@ static struct clk_regmap *gpu_cc_trinket_clocks[] = {
 	[GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr,
 	[GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr,
 	[GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
+	[GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
 };
 
 static const struct regmap_config gpu_cc_trinket_regmap_config = {
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c
index 30d2cdc..def1d27 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c
@@ -1145,7 +1145,7 @@ void pll_vco_unprepare_14nm(struct clk_hw *hw)
 		return;
 	}
 
-	pll->vco_cached_rate = clk_hw_get_rate(hw);
+	pll->vco_cached_rate = clk_get_rate(hw->clk);
 	dsi_pll_disable(hw);
 }
 
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c
index c57c90e..ea020e7 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c
@@ -80,6 +80,7 @@ static struct dsi_pll_vco_clk dsi0pll_vco_clk = {
 			.name = "dsi0pll_vco_clk_14nm",
 			.parent_names = (const char *[]){ "bi_tcxo" },
 			.num_parents = 1,
+			.flags = CLK_GET_RATE_NOCACHE,
 			.ops = &clk_ops_dsi_vco,
 		},
 };
@@ -92,6 +93,7 @@ static struct dsi_pll_vco_clk dsi0pll_shadow_vco_clk = {
 			.name = "dsi0pll_shadow_vco_clk_14nm",
 			.parent_names = (const char *[]){ "bi_tcxo" },
 			.num_parents = 1,
+			.flags = CLK_GET_RATE_NOCACHE,
 			.ops = &clk_ops_shadow_dsi_vco,
 		},
 };
@@ -106,6 +108,7 @@ static struct dsi_pll_vco_clk dsi1pll_vco_clk = {
 			.name = "dsi1pll_vco_clk_14nm",
 			.parent_names = (const char *[]){ "bi_tcxo" },
 			.num_parents = 1,
+			.flags = CLK_GET_RATE_NOCACHE,
 			.ops = &clk_ops_dsi_vco,
 		},
 };
@@ -120,6 +123,7 @@ static struct dsi_pll_vco_clk dsi1pll_shadow_vco_clk = {
 			.name = "dsi1pll_shadow_vco_clk_14nm",
 			.parent_names = (const char *[]){ "bi_tcxo" },
 			.num_parents = 1,
+			.flags = CLK_GET_RATE_NOCACHE,
 			.ops = &clk_ops_shadow_dsi_vco,
 		},
 };
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
index 13eb5b2..c40d572 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
@@ -366,10 +366,10 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
 static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
 					    "pll-audio-2x", "pll-audio" };
 static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
-			       0x0b0, 16, 2, BIT(31), 0);
+			       0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
-			       0x0b4, 16, 2, BIT(31), 0);
+			       0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 /* TODO: the parent for most of the USB clocks is not known */
 static SUNXI_CCU_GATE(usb_phy0_clk,	"usb-phy0",	"osc24M",
@@ -446,7 +446,7 @@ static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
 static SUNXI_CCU_GATE(ac_dig_clk,	"ac-dig",	"pll-audio",
 		      0x140, BIT(31), CLK_SET_RATE_PARENT);
 static SUNXI_CCU_GATE(ac_dig_4x_clk,	"ac-dig-4x",	"pll-audio-4x",
-		      0x140, BIT(30), 0);
+		      0x140, BIT(30), CLK_SET_RATE_PARENT);
 static SUNXI_CCU_GATE(avs_clk,		"avs",		"osc24M",
 		      0x144, BIT(31), 0);
 
diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c
index 62d2469..9701107 100644
--- a/drivers/clocksource/timer-integrator-ap.c
+++ b/drivers/clocksource/timer-integrator-ap.c
@@ -181,8 +181,7 @@ static int __init integrator_ap_timer_init_of(struct device_node *node)
 	int irq;
 	struct clk *clk;
 	unsigned long rate;
-	struct device_node *pri_node;
-	struct device_node *sec_node;
+	struct device_node *alias_node;
 
 	base = of_io_request_and_map(node, 0, "integrator-timer");
 	if (IS_ERR(base))
@@ -204,7 +203,18 @@ static int __init integrator_ap_timer_init_of(struct device_node *node)
 		return err;
 	}
 
-	pri_node = of_find_node_by_path(path);
+	alias_node = of_find_node_by_path(path);
+
+	/*
+	 * The pointer is used as an identifier not as a pointer, we
+	 * can drop the refcount on the of__node immediately after
+	 * getting it.
+	 */
+	of_node_put(alias_node);
+
+	if (node == alias_node)
+		/* The primary timer lacks IRQ, use as clocksource */
+		return integrator_clocksource_init(rate, base);
 
 	err = of_property_read_string(of_aliases,
 				"arm,timer-secondary", &path);
@@ -213,14 +223,11 @@ static int __init integrator_ap_timer_init_of(struct device_node *node)
 		return err;
 	}
 
+	alias_node = of_find_node_by_path(path);
 
-	sec_node = of_find_node_by_path(path);
+	of_node_put(alias_node);
 
-	if (node == pri_node)
-		/* The primary timer lacks IRQ, use as clocksource */
-		return integrator_clocksource_init(rate, base);
-
-	if (node == sec_node) {
+	if (node == alias_node) {
 		/* The secondary timer will drive the clock event */
 		irq = irq_of_parse_and_map(node, 0);
 		return integrator_clockevent_init(rate, base, irq);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 7bb10ae..dfb6f8d 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1532,17 +1532,16 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy)
 {
 	unsigned int ret_freq = 0;
 
-	if (!cpufreq_driver->get)
+	if (unlikely(policy_is_inactive(policy)) || !cpufreq_driver->get)
 		return ret_freq;
 
 	ret_freq = cpufreq_driver->get(policy->cpu);
 
 	/*
-	 * Updating inactive policies is invalid, so avoid doing that.  Also
-	 * if fast frequency switching is used with the given policy, the check
+	 * If fast frequency switching is used with the given policy, the check
 	 * against policy->cur is pointless, so skip it in that case too.
 	 */
-	if (unlikely(policy_is_inactive(policy)) || policy->fast_switch_enabled)
+	if (policy->fast_switch_enabled)
 		return ret_freq;
 
 	if (ret_freq && policy->cur &&
@@ -1571,10 +1570,7 @@ unsigned int cpufreq_get(unsigned int cpu)
 
 	if (policy) {
 		down_read(&policy->rwsem);
-
-		if (!policy_is_inactive(policy))
-			ret_freq = __cpufreq_get(policy);
-
+		ret_freq = __cpufreq_get(policy);
 		up_read(&policy->rwsem);
 
 		cpufreq_cpu_put(policy);
@@ -1685,6 +1681,9 @@ void cpufreq_resume(void)
 	if (!cpufreq_driver)
 		return;
 
+	if (unlikely(!cpufreq_suspended))
+		return;
+
 	cpufreq_suspended = false;
 
 	if (!has_target() && !cpufreq_driver->resume)
diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
index db2ede5..b44476a 100644
--- a/drivers/cpuidle/cpuidle-big_little.c
+++ b/drivers/cpuidle/cpuidle-big_little.c
@@ -167,6 +167,7 @@ static int __init bl_idle_init(void)
 {
 	int ret;
 	struct device_node *root = of_find_node_by_path("/");
+	const struct of_device_id *match_id;
 
 	if (!root)
 		return -ENODEV;
@@ -174,7 +175,11 @@ static int __init bl_idle_init(void)
 	/*
 	 * Initialize the driver just for a compliant set of machines
 	 */
-	if (!of_match_node(compatible_machine_match, root))
+	match_id = of_match_node(compatible_machine_match, root);
+
+	of_node_put(root);
+
+	if (!match_id)
 		return -ENODEV;
 
 	if (!mcpm_is_available())
diff --git a/drivers/cpuidle/cpuidle-pseries.c b/drivers/cpuidle/cpuidle-pseries.c
index a187a39..7f21c6a 100644
--- a/drivers/cpuidle/cpuidle-pseries.c
+++ b/drivers/cpuidle/cpuidle-pseries.c
@@ -239,7 +239,13 @@ static int pseries_idle_probe(void)
 		return -ENODEV;
 
 	if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
-		if (lppaca_shared_proc(get_lppaca())) {
+		/*
+		 * Use local_paca instead of get_lppaca() since
+		 * preemption is not disabled, and it is not required in
+		 * fact, since lppaca_ptr does not need to be the value
+		 * associated to the current CPU, it can be from any CPU.
+		 */
+		if (lppaca_shared_proc(local_paca->lppaca_ptr)) {
 			cpuidle_state_table = shared_states;
 			max_idle_state = ARRAY_SIZE(shared_states);
 		} else {
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index fe89328..113cd78 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -721,6 +721,7 @@
 	depends on ARCH_BCM_IPROC
 	depends on MAILBOX
 	default m
+	select CRYPTO_AUTHENC
 	select CRYPTO_DES
 	select CRYPTO_MD5
 	select CRYPTO_SHA1
diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c
index ee52c35..b6be383 100644
--- a/drivers/crypto/bcm/cipher.c
+++ b/drivers/crypto/bcm/cipher.c
@@ -2846,44 +2846,28 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
 	struct spu_hw *spu = &iproc_priv.spu;
 	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
 	struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
-	struct rtattr *rta = (void *)key;
-	struct crypto_authenc_key_param *param;
-	const u8 *origkey = key;
-	const unsigned int origkeylen = keylen;
-
-	int ret = 0;
+	struct crypto_authenc_keys keys;
+	int ret;
 
 	flow_log("%s() aead:%p key:%p keylen:%u\n", __func__, cipher, key,
 		 keylen);
 	flow_dump("  key: ", key, keylen);
 
-	if (!RTA_OK(rta, keylen))
-		goto badkey;
-	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-		goto badkey;
-	if (RTA_PAYLOAD(rta) < sizeof(*param))
+	ret = crypto_authenc_extractkeys(&keys, key, keylen);
+	if (ret)
 		goto badkey;
 
-	param = RTA_DATA(rta);
-	ctx->enckeylen = be32_to_cpu(param->enckeylen);
-
-	key += RTA_ALIGN(rta->rta_len);
-	keylen -= RTA_ALIGN(rta->rta_len);
-
-	if (keylen < ctx->enckeylen)
-		goto badkey;
-	if (ctx->enckeylen > MAX_KEY_SIZE)
+	if (keys.enckeylen > MAX_KEY_SIZE ||
+	    keys.authkeylen > MAX_KEY_SIZE)
 		goto badkey;
 
-	ctx->authkeylen = keylen - ctx->enckeylen;
+	ctx->enckeylen = keys.enckeylen;
+	ctx->authkeylen = keys.authkeylen;
 
-	if (ctx->authkeylen > MAX_KEY_SIZE)
-		goto badkey;
-
-	memcpy(ctx->enckey, key + ctx->authkeylen, ctx->enckeylen);
+	memcpy(ctx->enckey, keys.enckey, keys.enckeylen);
 	/* May end up padding auth key. So make sure it's zeroed. */
 	memset(ctx->authkey, 0, sizeof(ctx->authkey));
-	memcpy(ctx->authkey, key, ctx->authkeylen);
+	memcpy(ctx->authkey, keys.authkey, keys.authkeylen);
 
 	switch (ctx->alg->cipher_info.alg) {
 	case CIPHER_ALG_DES:
@@ -2891,7 +2875,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
 			u32 tmp[DES_EXPKEY_WORDS];
 			u32 flags = CRYPTO_TFM_RES_WEAK_KEY;
 
-			if (des_ekey(tmp, key) == 0) {
+			if (des_ekey(tmp, keys.enckey) == 0) {
 				if (crypto_aead_get_flags(cipher) &
 				    CRYPTO_TFM_REQ_WEAK_KEY) {
 					crypto_aead_set_flags(cipher, flags);
@@ -2906,7 +2890,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
 		break;
 	case CIPHER_ALG_3DES:
 		if (ctx->enckeylen == (DES_KEY_SIZE * 3)) {
-			const u32 *K = (const u32 *)key;
+			const u32 *K = (const u32 *)keys.enckey;
 			u32 flags = CRYPTO_TFM_RES_BAD_KEY_SCHED;
 
 			if (!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
@@ -2957,9 +2941,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
 		ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
 		ctx->fallback_cipher->base.crt_flags |=
 		    tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
-		ret =
-		    crypto_aead_setkey(ctx->fallback_cipher, origkey,
-				       origkeylen);
+		ret = crypto_aead_setkey(ctx->fallback_cipher, key, keylen);
 		if (ret) {
 			flow_log("  fallback setkey() returned:%d\n", ret);
 			tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 698580b..8fa35bc 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -1109,13 +1109,16 @@ static int ahash_final_no_ctx(struct ahash_request *req)
 
 	desc = edesc->hw_desc;
 
-	state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
-	if (dma_mapping_error(jrdev, state->buf_dma)) {
-		dev_err(jrdev, "unable to map src\n");
-		goto unmap;
-	}
+	if (buflen) {
+		state->buf_dma = dma_map_single(jrdev, buf, buflen,
+						DMA_TO_DEVICE);
+		if (dma_mapping_error(jrdev, state->buf_dma)) {
+			dev_err(jrdev, "unable to map src\n");
+			goto unmap;
+		}
 
-	append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+		append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+	}
 
 	edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
 						digestsize);
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 0f21a0a..1fe96df 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1,7 +1,7 @@
 /*
  * QTI CE device driver.
  *
- * 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
@@ -1676,12 +1676,15 @@ static inline long qcedev_ioctl(struct file *file,
 	if (podev == NULL || podev->magic != QCEDEV_MAGIC) {
 		pr_err("%s: invalid handle %pK\n",
 			__func__, podev);
-		return -ENOENT;
+		err = -ENOENT;
+		goto exit_free_qcedev_areq;
 	}
 
 	/* Verify user arguments. */
-	if (_IOC_TYPE(cmd) != QCEDEV_IOC_MAGIC)
-		return -ENOTTY;
+	if (_IOC_TYPE(cmd) != QCEDEV_IOC_MAGIC) {
+		err = -ENOTTY;
+		goto exit_free_qcedev_areq;
+	}
 
 	init_completion(&qcedev_areq->complete);
 	pstat = &_qcedev_stat;
@@ -1691,21 +1694,27 @@ static inline long qcedev_ioctl(struct file *file,
 	case QCEDEV_IOCTL_DEC_REQ:
 		if (copy_from_user(&qcedev_areq->cipher_op_req,
 				(void __user *)arg,
-				sizeof(struct qcedev_cipher_op_req)))
-			return -EFAULT;
+				sizeof(struct qcedev_cipher_op_req))) {
+			err = -EFAULT;
+			goto exit_free_qcedev_areq;
+		}
 		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_CIPHER;
 
 		if (qcedev_check_cipher_params(&qcedev_areq->cipher_op_req,
-				podev))
-			return -EINVAL;
+				podev)) {
+			err = -EINVAL;
+			goto exit_free_qcedev_areq;
+		}
 
 		err = qcedev_vbuf_ablk_cipher(qcedev_areq, handle);
 		if (err)
-			return err;
+			goto exit_free_qcedev_areq;
 		if (copy_to_user((void __user *)arg,
 					&qcedev_areq->cipher_op_req,
-					sizeof(struct qcedev_cipher_op_req)))
-			return -EFAULT;
+					sizeof(struct qcedev_cipher_op_req))) {
+			err = -EFAULT;
+			goto exit_free_qcedev_areq;
+		}
 		break;
 
 	case QCEDEV_IOCTL_SHA_INIT_REQ:
@@ -1714,41 +1723,51 @@ static inline long qcedev_ioctl(struct file *file,
 
 		if (copy_from_user(&qcedev_areq->sha_op_req,
 					(void __user *)arg,
-					sizeof(struct qcedev_sha_op_req)))
-			return -EFAULT;
+					sizeof(struct qcedev_sha_op_req))) {
+			err = -EFAULT;
+			goto exit_free_qcedev_areq;
+		}
 		mutex_lock(&hash_access_lock);
 		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
 			mutex_unlock(&hash_access_lock);
-			return -EINVAL;
+			err = -EINVAL;
+			goto exit_free_qcedev_areq;
 		}
 		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
 		err = qcedev_hash_init(qcedev_areq, handle, &sg_src);
 		if (err) {
 			mutex_unlock(&hash_access_lock);
-			return err;
+			goto exit_free_qcedev_areq;
 		}
 		mutex_unlock(&hash_access_lock);
 		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
-					sizeof(struct qcedev_sha_op_req)))
-			return -EFAULT;
+					sizeof(struct qcedev_sha_op_req))) {
+			err = -EFAULT;
+			goto exit_free_qcedev_areq;
 		}
 		handle->sha_ctxt.init_done = true;
+		}
 		break;
 	case QCEDEV_IOCTL_GET_CMAC_REQ:
-		if (!podev->ce_support.cmac)
-			return -ENOTTY;
+		if (!podev->ce_support.cmac) {
+			err = -ENOTTY;
+			goto exit_free_qcedev_areq;
+		}
 	case QCEDEV_IOCTL_SHA_UPDATE_REQ:
 		{
 		struct scatterlist sg_src;
 
 		if (copy_from_user(&qcedev_areq->sha_op_req,
 					(void __user *)arg,
-					sizeof(struct qcedev_sha_op_req)))
-			return -EFAULT;
+					sizeof(struct qcedev_sha_op_req))) {
+			err = -EFAULT;
+			goto exit_free_qcedev_areq;
+		}
 		mutex_lock(&hash_access_lock);
 		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
 			mutex_unlock(&hash_access_lock);
-			return -EINVAL;
+			err = -EINVAL;
+			goto exit_free_qcedev_areq;
 		}
 		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
 
@@ -1756,18 +1775,19 @@ static inline long qcedev_ioctl(struct file *file,
 			err = qcedev_hash_cmac(qcedev_areq, handle, &sg_src);
 			if (err) {
 				mutex_unlock(&hash_access_lock);
-				return err;
+				goto exit_free_qcedev_areq;
 			}
 		} else {
 			if (handle->sha_ctxt.init_done == false) {
 				pr_err("%s Init was not called\n", __func__);
 				mutex_unlock(&hash_access_lock);
-				return -EINVAL;
+				err = -EINVAL;
+				goto exit_free_qcedev_areq;
 			}
 			err = qcedev_hash_update(qcedev_areq, handle, &sg_src);
 			if (err) {
 				mutex_unlock(&hash_access_lock);
-				return err;
+				goto exit_free_qcedev_areq;
 			}
 		}
 
@@ -1775,7 +1795,8 @@ static inline long qcedev_ioctl(struct file *file,
 			pr_err("Invalid sha_ctxt.diglen %d\n",
 					handle->sha_ctxt.diglen);
 			mutex_unlock(&hash_access_lock);
-			return -EINVAL;
+			err = -EINVAL;
+			goto exit_free_qcedev_areq;
 		}
 		memcpy(&qcedev_areq->sha_op_req.digest[0],
 				&handle->sha_ctxt.digest[0],
@@ -1783,7 +1804,8 @@ static inline long qcedev_ioctl(struct file *file,
 		mutex_unlock(&hash_access_lock);
 		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
 					sizeof(struct qcedev_sha_op_req)))
-			return -EFAULT;
+			err = -EFAULT;
+			goto exit_free_qcedev_areq;
 		}
 		break;
 
@@ -1791,28 +1813,33 @@ static inline long qcedev_ioctl(struct file *file,
 
 		if (handle->sha_ctxt.init_done == false) {
 			pr_err("%s Init was not called\n", __func__);
-			return -EINVAL;
+			err = -EINVAL;
+			goto exit_free_qcedev_areq;
 		}
 		if (copy_from_user(&qcedev_areq->sha_op_req,
 					(void __user *)arg,
-					sizeof(struct qcedev_sha_op_req)))
-			return -EFAULT;
+					sizeof(struct qcedev_sha_op_req))) {
+			err = -EFAULT;
+			goto exit_free_qcedev_areq;
+		}
 		mutex_lock(&hash_access_lock);
 		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
 			mutex_unlock(&hash_access_lock);
-			return -EINVAL;
+			err = -EINVAL;
+			goto exit_free_qcedev_areq;
 		}
 		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
 		err = qcedev_hash_final(qcedev_areq, handle);
 		if (err) {
 			mutex_unlock(&hash_access_lock);
-			return err;
+			goto exit_free_qcedev_areq;
 		}
 		if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
 			pr_err("Invalid sha_ctxt.diglen %d\n",
 					handle->sha_ctxt.diglen);
 			mutex_unlock(&hash_access_lock);
-			return -EINVAL;
+			err = -EINVAL;
+			goto exit_free_qcedev_areq;
 		}
 		qcedev_areq->sha_op_req.diglen = handle->sha_ctxt.diglen;
 		memcpy(&qcedev_areq->sha_op_req.digest[0],
@@ -1820,8 +1847,10 @@ static inline long qcedev_ioctl(struct file *file,
 				handle->sha_ctxt.diglen);
 		mutex_unlock(&hash_access_lock);
 		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
-					sizeof(struct qcedev_sha_op_req)))
-			return -EFAULT;
+					sizeof(struct qcedev_sha_op_req))) {
+			err = -EFAULT;
+			goto exit_free_qcedev_areq;
+		}
 		handle->sha_ctxt.init_done = false;
 		break;
 
@@ -1831,30 +1860,34 @@ static inline long qcedev_ioctl(struct file *file,
 
 		if (copy_from_user(&qcedev_areq->sha_op_req,
 					(void __user *)arg,
-					sizeof(struct qcedev_sha_op_req)))
-			return -EFAULT;
+					sizeof(struct qcedev_sha_op_req))) {
+			err = -EFAULT;
+			goto exit_free_qcedev_areq;
+		}
 		mutex_lock(&hash_access_lock);
 		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
 			mutex_unlock(&hash_access_lock);
-			return -EINVAL;
+			err = -EINVAL;
+			goto exit_free_qcedev_areq;
 		}
 		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
 		qcedev_hash_init(qcedev_areq, handle, &sg_src);
 		err = qcedev_hash_update(qcedev_areq, handle, &sg_src);
 		if (err) {
 			mutex_unlock(&hash_access_lock);
-			return err;
+			goto exit_free_qcedev_areq;
 		}
 		err = qcedev_hash_final(qcedev_areq, handle);
 		if (err) {
 			mutex_unlock(&hash_access_lock);
-			return err;
+			goto exit_free_qcedev_areq;
 		}
 		if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
 			pr_err("Invalid sha_ctxt.diglen %d\n",
 					handle->sha_ctxt.diglen);
 			mutex_unlock(&hash_access_lock);
-			return -EINVAL;
+			err = -EINVAL;
+			goto exit_free_qcedev_areq;
 		}
 		qcedev_areq->sha_op_req.diglen =	handle->sha_ctxt.diglen;
 		memcpy(&qcedev_areq->sha_op_req.digest[0],
@@ -1863,7 +1896,8 @@ static inline long qcedev_ioctl(struct file *file,
 		mutex_unlock(&hash_access_lock);
 		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
 					sizeof(struct qcedev_sha_op_req)))
-			return -EFAULT;
+			err = -EFAULT;
+			goto exit_free_qcedev_areq;
 		}
 		break;
 
@@ -1874,8 +1908,10 @@ static inline long qcedev_ioctl(struct file *file,
 			int i = 0;
 
 			if (copy_from_user(&map_buf,
-					(void __user *)arg, sizeof(map_buf)))
-				return -EFAULT;
+					(void __user *)arg, sizeof(map_buf))) {
+				err = -EFAULT;
+				goto exit_free_qcedev_areq;
+			}
 
 			for (i = 0; i < map_buf.num_fds; i++) {
 				err = qcedev_check_and_map_buffer(handle,
@@ -1887,7 +1923,7 @@ static inline long qcedev_ioctl(struct file *file,
 					pr_err(
 						"%s: err: failed to map fd(%d) - %d\n",
 						__func__, map_buf.fd[i], err);
-					return err;
+					goto exit_free_qcedev_areq;
 				}
 				map_buf.buf_vaddr[i] = vaddr;
 				pr_info("%s: info: vaddr = %llx\n",
@@ -1895,8 +1931,10 @@ static inline long qcedev_ioctl(struct file *file,
 			}
 
 			if (copy_to_user((void __user *)arg, &map_buf,
-					sizeof(map_buf)))
-				return -EFAULT;
+					sizeof(map_buf))) {
+				err = -EFAULT;
+				goto exit_free_qcedev_areq;
+			}
 			break;
 		}
 
@@ -1906,8 +1944,10 @@ static inline long qcedev_ioctl(struct file *file,
 			int i = 0;
 
 			if (copy_from_user(&unmap_buf,
-					(void __user *)arg, sizeof(unmap_buf)))
-				return -EFAULT;
+				(void __user *)arg, sizeof(unmap_buf))) {
+				err = -EFAULT;
+				goto exit_free_qcedev_areq;
+			}
 
 			for (i = 0; i < unmap_buf.num_fds; i++) {
 				err = qcedev_check_and_unmap_buffer(handle,
@@ -1917,16 +1957,19 @@ static inline long qcedev_ioctl(struct file *file,
 						"%s: err: failed to unmap fd(%d) - %d\n",
 						 __func__,
 						unmap_buf.fd[i], err);
-					return err;
+					goto exit_free_qcedev_areq;
 				}
 			}
 			break;
 		}
 
 	default:
-		return -ENOTTY;
+		err = -ENOTTY;
+		goto exit_free_qcedev_areq;
 	}
 
+exit_free_qcedev_areq:
+	kfree(qcedev_areq);
 	return err;
 }
 
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 57e1b203..4388f4e 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -1347,23 +1347,18 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	bool is_sec1 = has_ftr_sec1(priv);
 	int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
-	void *err;
 
 	if (cryptlen + authsize > max_len) {
 		dev_err(dev, "length exceeds h/w max limit\n");
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (ivsize)
-		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
-
 	if (!dst || dst == src) {
 		src_len = assoclen + cryptlen + authsize;
 		src_nents = sg_nents_for_len(src, src_len);
 		if (src_nents < 0) {
 			dev_err(dev, "Invalid number of src SG.\n");
-			err = ERR_PTR(-EINVAL);
-			goto error_sg;
+			return ERR_PTR(-EINVAL);
 		}
 		src_nents = (src_nents == 1) ? 0 : src_nents;
 		dst_nents = dst ? src_nents : 0;
@@ -1373,16 +1368,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 		src_nents = sg_nents_for_len(src, src_len);
 		if (src_nents < 0) {
 			dev_err(dev, "Invalid number of src SG.\n");
-			err = ERR_PTR(-EINVAL);
-			goto error_sg;
+			return ERR_PTR(-EINVAL);
 		}
 		src_nents = (src_nents == 1) ? 0 : src_nents;
 		dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
 		dst_nents = sg_nents_for_len(dst, dst_len);
 		if (dst_nents < 0) {
 			dev_err(dev, "Invalid number of dst SG.\n");
-			err = ERR_PTR(-EINVAL);
-			goto error_sg;
+			return ERR_PTR(-EINVAL);
 		}
 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
 	}
@@ -1405,12 +1398,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 		dma_len = 0;
 		alloc_len += icv_stashing ? authsize : 0;
 	}
+	alloc_len += ivsize;
 
 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
-	if (!edesc) {
-		dev_err(dev, "could not allocate edescriptor\n");
-		err = ERR_PTR(-ENOMEM);
-		goto error_sg;
+	if (!edesc)
+		return ERR_PTR(-ENOMEM);
+	if (ivsize) {
+		iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
+		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
 	}
 
 	edesc->src_nents = src_nents;
@@ -1423,10 +1418,6 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 						     DMA_BIDIRECTIONAL);
 
 	return edesc;
-error_sg:
-	if (iv_dma)
-		dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
-	return err;
 }
 
 static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index 790f7ca..efebc484 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -555,7 +555,7 @@ static int cryp_set_dma_transfer(struct cryp_ctx *ctx,
 		desc = dmaengine_prep_slave_sg(channel,
 				ctx->device->dma.sg_src,
 				ctx->device->dma.sg_src_len,
-				direction, DMA_CTRL_ACK);
+				DMA_MEM_TO_DEV, DMA_CTRL_ACK);
 		break;
 
 	case DMA_FROM_DEVICE:
@@ -579,7 +579,7 @@ static int cryp_set_dma_transfer(struct cryp_ctx *ctx,
 		desc = dmaengine_prep_slave_sg(channel,
 				ctx->device->dma.sg_dst,
 				ctx->device->dma.sg_dst_len,
-				direction,
+				DMA_DEV_TO_MEM,
 				DMA_CTRL_ACK |
 				DMA_PREP_INTERRUPT);
 
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 9acccad2..17c8e2b 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -165,7 +165,7 @@ static int hash_set_dma_transfer(struct hash_ctx *ctx, struct scatterlist *sg,
 		__func__);
 	desc = dmaengine_prep_slave_sg(channel,
 			ctx->device->dma.sg, ctx->device->dma.sg_len,
-			direction, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+			DMA_MEM_TO_DEV, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
 	if (!desc) {
 		dev_err(ctx->device->dev,
 			"%s: dmaengine_prep_slave_sg() failed!\n", __func__);
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 4ba9e8a..aba1c8e 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -39,7 +39,7 @@
 #include <linux/sched/signal.h>
 #include <linux/fdtable.h>
 #include <linux/list_sort.h>
-
+#include <linux/hashtable.h>
 #include <uapi/linux/dma-buf.h>
 
 static atomic_long_t name_counter;
@@ -53,14 +53,14 @@ struct dma_buf_list {
 
 struct dma_info {
 	struct dma_buf *dmabuf;
-	struct list_head head;
+	struct hlist_node head;
 };
 
 struct dma_proc {
 	char name[TASK_COMM_LEN];
 	pid_t pid;
 	size_t size;
-	struct list_head dma_bufs;
+	struct hlist_head dma_bufs[1 << 10];
 	struct list_head head;
 };
 
@@ -1298,17 +1298,6 @@ static const struct file_operations dma_buf_debug_fops = {
 	.release        = single_release,
 };
 
-static bool list_contains(struct list_head *list, struct dma_buf *info)
-{
-	struct dma_info *curr;
-
-	list_for_each_entry(curr, list, head)
-		if (curr->dmabuf == info)
-			return true;
-
-	return false;
-}
-
 static int get_dma_info(const void *data, struct file *file, unsigned int n)
 {
 	struct dma_proc *dma_proc;
@@ -1318,8 +1307,10 @@ static int get_dma_info(const void *data, struct file *file, unsigned int n)
 	if (!is_dma_buf_file(file))
 		return 0;
 
-	if (list_contains(&dma_proc->dma_bufs, file->private_data))
-		return 0;
+	hash_for_each_possible(dma_proc->dma_bufs, dma_info,
+			       head, (unsigned long)file->private_data)
+		if (file->private_data == dma_info->dmabuf)
+			return 0;
 
 	dma_info = kzalloc(sizeof(*dma_info), GFP_ATOMIC);
 	if (!dma_info)
@@ -1328,20 +1319,22 @@ static int get_dma_info(const void *data, struct file *file, unsigned int n)
 	get_file(file);
 	dma_info->dmabuf = file->private_data;
 	dma_proc->size += dma_info->dmabuf->size / SZ_1K;
-	list_add(&dma_info->head, &dma_proc->dma_bufs);
+	hash_add(dma_proc->dma_bufs, &dma_info->head,
+			(unsigned long)dma_info->dmabuf);
 	return 0;
 }
 
 static void write_proc(struct seq_file *s, struct dma_proc *proc)
 {
 	struct dma_info *tmp;
+	int i;
 
 	seq_printf(s, "\n%s (PID %ld) size: %ld\nDMA Buffers:\n",
 		proc->name, proc->pid, proc->size);
 	seq_printf(s, "%-8s\t%-8s\t%-8s\n",
 		"Name", "Size (KB)", "Time Alive (sec)");
 
-	list_for_each_entry(tmp, &proc->dma_bufs, head) {
+	hash_for_each(proc->dma_bufs, i, tmp, head) {
 		struct dma_buf *dmabuf = tmp->dmabuf;
 		ktime_t elapmstime = ktime_ms_delta(ktime_get(), dmabuf->ktime);
 
@@ -1355,25 +1348,18 @@ static void write_proc(struct seq_file *s, struct dma_proc *proc)
 
 static void free_proc(struct dma_proc *proc)
 {
-	struct dma_info *tmp, *n;
+	struct dma_info *tmp;
+	struct hlist_node *n;
+	int i;
 
-	list_for_each_entry_safe(tmp, n, &proc->dma_bufs, head) {
-		dma_buf_put(tmp->dmabuf);
-		list_del(&tmp->head);
+	hash_for_each_safe(proc->dma_bufs, i, n, tmp, head) {
+		fput(tmp->dmabuf->file);
+		hash_del(&tmp->head);
 		kfree(tmp);
 	}
 	kfree(proc);
 }
 
-static int dmacmp(void *unused, struct list_head *a, struct list_head *b)
-{
-	struct dma_info *a_buf, *b_buf;
-
-	a_buf = list_entry(a, struct dma_info, head);
-	b_buf = list_entry(b, struct dma_info, head);
-	return b_buf->dmabuf->size - a_buf->dmabuf->size;
-}
-
 static int proccmp(void *unused, struct list_head *a, struct list_head *b)
 {
 	struct dma_proc *a_proc, *b_proc;
@@ -1391,17 +1377,17 @@ static int dma_procs_debug_show(struct seq_file *s, void *unused)
 	struct dma_proc *tmp, *n;
 	LIST_HEAD(plist);
 
-	read_lock(&tasklist_lock);
+	rcu_read_lock();
 	for_each_process(task) {
 		struct files_struct *group_leader_files = NULL;
 
 		tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
 		if (!tmp) {
 			ret = -ENOMEM;
-			read_unlock(&tasklist_lock);
+			rcu_read_unlock();
 			goto mem_err;
 		}
-		INIT_LIST_HEAD(&tmp->dma_bufs);
+		hash_init(tmp->dma_bufs);
 		for_each_thread(task, thread) {
 			task_lock(thread);
 			if (unlikely(!group_leader_files))
@@ -1412,9 +1398,8 @@ static int dma_procs_debug_show(struct seq_file *s, void *unused)
 				ret = iterate_fd(files, 0, get_dma_info, tmp);
 			task_unlock(thread);
 		}
-		if (ret || list_empty(&tmp->dma_bufs))
+		if (ret || hash_empty(tmp->dma_bufs))
 			goto skip;
-		list_sort(NULL, &tmp->dma_bufs, dmacmp);
 		get_task_comm(tmp->name, task);
 		tmp->pid = task->tgid;
 		list_add(&tmp->head, &plist);
@@ -1422,7 +1407,7 @@ static int dma_procs_debug_show(struct seq_file *s, void *unused)
 skip:
 		free_proc(tmp);
 	}
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 
 	list_sort(NULL, &plist, proccmp);
 	list_for_each_entry(tmp, &plist, head)
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index 6204cc3..6ba53bb 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -415,38 +415,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
 	}
 }
 
-static int bcm2835_dma_abort(void __iomem *chan_base)
+static int bcm2835_dma_abort(struct bcm2835_chan *c)
 {
-	unsigned long cs;
+	void __iomem *chan_base = c->chan_base;
 	long int timeout = 10000;
 
-	cs = readl(chan_base + BCM2835_DMA_CS);
-	if (!(cs & BCM2835_DMA_ACTIVE))
+	/*
+	 * A zero control block address means the channel is idle.
+	 * (The ACTIVE flag in the CS register is not a reliable indicator.)
+	 */
+	if (!readl(chan_base + BCM2835_DMA_ADDR))
 		return 0;
 
 	/* Write 0 to the active bit - Pause the DMA */
 	writel(0, chan_base + BCM2835_DMA_CS);
 
 	/* Wait for any current AXI transfer to complete */
-	while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) {
+	while ((readl(chan_base + BCM2835_DMA_CS) &
+		BCM2835_DMA_WAITING_FOR_WRITES) && --timeout)
 		cpu_relax();
-		cs = readl(chan_base + BCM2835_DMA_CS);
-	}
 
-	/* We'll un-pause when we set of our next DMA */
+	/* Peripheral might be stuck and fail to signal AXI write responses */
 	if (!timeout)
-		return -ETIMEDOUT;
+		dev_err(c->vc.chan.device->dev,
+			"failed to complete outstanding writes\n");
 
-	if (!(cs & BCM2835_DMA_ACTIVE))
-		return 0;
-
-	/* Terminate the control block chain */
-	writel(0, chan_base + BCM2835_DMA_NEXTCB);
-
-	/* Abort the whole DMA */
-	writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE,
-	       chan_base + BCM2835_DMA_CS);
-
+	writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS);
 	return 0;
 }
 
@@ -485,8 +479,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
 
 	spin_lock_irqsave(&c->vc.lock, flags);
 
-	/* Acknowledge interrupt */
-	writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS);
+	/*
+	 * Clear the INT flag to receive further interrupts. Keep the channel
+	 * active in case the descriptor is cyclic or in case the client has
+	 * already terminated the descriptor and issued a new one. (May happen
+	 * if this IRQ handler is threaded.) If the channel is finished, it
+	 * will remain idle despite the ACTIVE flag being set.
+	 */
+	writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
+	       c->chan_base + BCM2835_DMA_CS);
 
 	d = c->desc;
 
@@ -494,11 +495,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
 		if (d->cyclic) {
 			/* call the cyclic callback */
 			vchan_cyclic_callback(&d->vd);
-
-			/* Keep the DMA engine running */
-			writel(BCM2835_DMA_ACTIVE,
-			       c->chan_base + BCM2835_DMA_CS);
-		} else {
+		} else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) {
 			vchan_cookie_complete(&c->desc->vd);
 			bcm2835_dma_start_desc(c);
 		}
@@ -796,7 +793,6 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
 	struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
 	struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device);
 	unsigned long flags;
-	int timeout = 10000;
 	LIST_HEAD(head);
 
 	spin_lock_irqsave(&c->vc.lock, flags);
@@ -806,27 +802,11 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
 	list_del_init(&c->node);
 	spin_unlock(&d->lock);
 
-	/*
-	 * Stop DMA activity: we assume the callback will not be called
-	 * after bcm_dma_abort() returns (even if it does, it will see
-	 * c->desc is NULL and exit.)
-	 */
+	/* stop DMA activity */
 	if (c->desc) {
 		bcm2835_dma_desc_free(&c->desc->vd);
 		c->desc = NULL;
-		bcm2835_dma_abort(c->chan_base);
-
-		/* Wait for stopping */
-		while (--timeout) {
-			if (!(readl(c->chan_base + BCM2835_DMA_CS) &
-						BCM2835_DMA_ACTIVE))
-				break;
-
-			cpu_relax();
-		}
-
-		if (!timeout)
-			dev_err(d->ddev.dev, "DMA transfer could not be terminated\n");
+		bcm2835_dma_abort(c);
 	}
 
 	vchan_get_all_descriptors(&c->vc, &head);
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index f681df8..cb37730 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -623,7 +623,7 @@ static void imxdma_tasklet(unsigned long data)
 {
 	struct imxdma_channel *imxdmac = (void *)data;
 	struct imxdma_engine *imxdma = imxdmac->imxdma;
-	struct imxdma_desc *desc;
+	struct imxdma_desc *desc, *next_desc;
 	unsigned long flags;
 
 	spin_lock_irqsave(&imxdma->lock, flags);
@@ -653,10 +653,10 @@ static void imxdma_tasklet(unsigned long data)
 	list_move_tail(imxdmac->ld_active.next, &imxdmac->ld_free);
 
 	if (!list_empty(&imxdmac->ld_queue)) {
-		desc = list_first_entry(&imxdmac->ld_queue, struct imxdma_desc,
-					node);
+		next_desc = list_first_entry(&imxdmac->ld_queue,
+					     struct imxdma_desc, node);
 		list_move_tail(imxdmac->ld_queue.next, &imxdmac->ld_active);
-		if (imxdma_xfer_desc(desc) < 0)
+		if (imxdma_xfer_desc(next_desc) < 0)
 			dev_warn(imxdma->dev, "%s: channel: %d couldn't xfer desc\n",
 				 __func__, imxdmac->channel);
 	}
diff --git a/drivers/dma/qcom/pci-edma.c b/drivers/dma/qcom/pci-edma.c
index 096d97e..ea1288a 100644
--- a/drivers/dma/qcom/pci-edma.c
+++ b/drivers/dma/qcom/pci-edma.c
@@ -1071,5 +1071,5 @@ int qcom_edma_init(struct device *dev)
 }
 EXPORT_SYMBOL(qcom_edma_init);
 
-MODULE_DESCRIPTION("QCOM PCIe eDMA driver");
+MODULE_DESCRIPTION("QTI PCIe eDMA driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index 5cc8ed3..6d86d05 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -159,7 +159,7 @@ struct zynqmp_dma_desc_ll {
 	u32 ctrl;
 	u64 nxtdscraddr;
 	u64 rsvd;
-}; __aligned(64)
+};
 
 /**
  * struct zynqmp_dma_desc_sw - Per Transaction structure
diff --git a/drivers/edac/qcom_llcc_edac.c b/drivers/edac/qcom_llcc_edac.c
index 2bd15ba..ddf6776 100644
--- a/drivers/edac/qcom_llcc_edac.c
+++ b/drivers/edac/qcom_llcc_edac.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
@@ -79,6 +79,22 @@
 #define DRP_TRP_INT_CLEAR	0x3
 #define DRP_TRP_CNT_CLEAR	0x3
 
+/* Config registers offsets*/
+#define DRP_ECC_ERROR_CFG	0x00040000
+
+/* TRP, DRP interrupt register offsets */
+#define CMN_INTERRUPT_0_ENABLE		0x0003001C
+#define CMN_INTERRUPT_2_ENABLE		0x0003003C
+#define TRP_INTERRUPT_0_ENABLE		0x00020488
+#define DRP_INTERRUPT_ENABLE		0x0004100C
+
+#define SB_ERROR_THRESHOLD	0x1
+#define SB_ERROR_THRESHOLD_SHIFT	24
+#define SB_DB_TRP_INTERRUPT_ENABLE	0x3
+#define TRP0_INTERRUPT_ENABLE	0x1
+#define DRP0_INTERRUPT_ENABLE	BIT(6)
+#define SB_DB_DRP_INTERRUPT_ENABLE	0x3
+
 static int poll_msec = 5000;
 module_param(poll_msec, int, 0444);
 
@@ -345,9 +361,34 @@ static irqreturn_t llcc_ecc_irq_handler
 	return qcom_llcc_check_cache_errors(edev_ctl);
 }
 
+static void qcom_llcc_core_setup(struct regmap *llcc_regmap, uint32_t b_off)
+{
+	u32 sb_err_threshold;
+
+	/* Enable TRP in instance 2 of common interrupt enable register */
+	regmap_update_bits(llcc_regmap, b_off + CMN_INTERRUPT_2_ENABLE,
+			   TRP0_INTERRUPT_ENABLE, TRP0_INTERRUPT_ENABLE);
+
+	/* Enable ECC interrupts on Tag Ram */
+	regmap_update_bits(llcc_regmap, b_off + TRP_INTERRUPT_0_ENABLE,
+		SB_DB_TRP_INTERRUPT_ENABLE, SB_DB_TRP_INTERRUPT_ENABLE);
+
+	/* Enable SB error for Data RAM */
+	sb_err_threshold = (SB_ERROR_THRESHOLD << SB_ERROR_THRESHOLD_SHIFT);
+	regmap_write(llcc_regmap, b_off + DRP_ECC_ERROR_CFG, sb_err_threshold);
+
+	/* Enable DRP in instance 2 of common interrupt enable register */
+	regmap_update_bits(llcc_regmap, b_off + CMN_INTERRUPT_2_ENABLE,
+			   DRP0_INTERRUPT_ENABLE, DRP0_INTERRUPT_ENABLE);
+
+	/* Enable ECC interrupts on Data Ram */
+	regmap_write(llcc_regmap, b_off + DRP_INTERRUPT_ENABLE,
+		     SB_DB_DRP_INTERRUPT_ENABLE);
+}
+
 static int qcom_llcc_erp_probe(struct platform_device *pdev)
 {
-	int rc = 0;
+	int irq, rc = 0;
 	struct erp_drvdata *drv;
 	struct edac_device_ctl_info *edev_ctl;
 	struct device *dev = &pdev->dev;
@@ -410,17 +451,8 @@ static int qcom_llcc_erp_probe(struct platform_device *pdev)
 	}
 
 
-	rc = platform_get_irq_byname(pdev, "ecc_irq");
-	if (rc > 0) {
-		drv->ecc_irq = rc;
-		rc = devm_request_irq(dev, drv->ecc_irq, llcc_ecc_irq_handler,
-				IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
-				"llcc_ecc", edev_ctl);
-		if (rc) {
-			dev_err(dev, "failed to request ecc irq\n");
-			goto out_mem;
-		}
-	} else {
+	irq = platform_get_irq_byname(pdev, "ecc_irq");
+	if (irq <= 0) {
 		dev_info(dev, "No ECC IRQ; defaulting to polling mode\n");
 		edev_ctl->poll_msec = poll_msec;
 		edev_ctl->edac_check = qcom_llcc_poll_cache_errors;
@@ -432,8 +464,21 @@ static int qcom_llcc_erp_probe(struct platform_device *pdev)
 		goto out_mem;
 
 	platform_set_drvdata(pdev, edev_ctl);
-	return 0;
+	if (irq > 0) {
+		qcom_llcc_core_setup(llcc_map, drv->b_off);
+		drv->ecc_irq = irq;
+		rc = devm_request_irq(dev, drv->ecc_irq, llcc_ecc_irq_handler,
+				IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
+				"llcc_ecc", edev_ctl);
+		if (rc) {
+			dev_err(dev, "failed to request ecc irq\n");
+			goto del_dev;
+		}
+	}
 
+	return 0;
+del_dev:
+	edac_device_del_device(edev_ctl->dev);
 out_mem:
 	edac_device_free_ctl_info(edev_ctl);
 
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
index ae54870b..dd7f633 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -50,6 +50,13 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
 }
 
 /*
+ * Expose the EFI runtime lock to the UV platform
+ */
+#ifdef CONFIG_X86_UV
+extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock);
+#endif
+
+/*
  * According to section 7.1 of the UEFI spec, Runtime Services are not fully
  * reentrant, and there are particular combinations of calls that need to be
  * serialized. (source: UEFI Specification v2.4A)
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
index 9336ffd..fceaafd 100644
--- a/drivers/firmware/efi/vars.c
+++ b/drivers/firmware/efi/vars.c
@@ -318,7 +318,12 @@ EXPORT_SYMBOL_GPL(efivar_variable_is_removable);
 static efi_status_t
 check_var_size(u32 attributes, unsigned long size)
 {
-	const struct efivar_operations *fops = __efivars->ops;
+	const struct efivar_operations *fops;
+
+	if (!__efivars)
+		return EFI_UNSUPPORTED;
+
+	fops = __efivars->ops;
 
 	if (!fops->query_variable_store)
 		return EFI_UNSUPPORTED;
@@ -329,7 +334,12 @@ check_var_size(u32 attributes, unsigned long size)
 static efi_status_t
 check_var_size_nonblocking(u32 attributes, unsigned long size)
 {
-	const struct efivar_operations *fops = __efivars->ops;
+	const struct efivar_operations *fops;
+
+	if (!__efivars)
+		return EFI_UNSUPPORTED;
+
+	fops = __efivars->ops;
 
 	if (!fops->query_variable_store)
 		return EFI_UNSUPPORTED;
@@ -429,13 +439,18 @@ static void dup_variable_bug(efi_char16_t *str16, efi_guid_t *vendor_guid,
 int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
 		void *data, bool duplicates, struct list_head *head)
 {
-	const struct efivar_operations *ops = __efivars->ops;
+	const struct efivar_operations *ops;
 	unsigned long variable_name_size = 1024;
 	efi_char16_t *variable_name;
 	efi_status_t status;
 	efi_guid_t vendor_guid;
 	int err = 0;
 
+	if (!__efivars)
+		return -EFAULT;
+
+	ops = __efivars->ops;
+
 	variable_name = kzalloc(variable_name_size, GFP_KERNEL);
 	if (!variable_name) {
 		printk(KERN_ERR "efivars: Memory allocation failed.\n");
@@ -583,12 +598,14 @@ static void efivar_entry_list_del_unlock(struct efivar_entry *entry)
  */
 int __efivar_entry_delete(struct efivar_entry *entry)
 {
-	const struct efivar_operations *ops = __efivars->ops;
 	efi_status_t status;
 
-	status = ops->set_variable(entry->var.VariableName,
-				   &entry->var.VendorGuid,
-				   0, 0, NULL);
+	if (!__efivars)
+		return -EINVAL;
+
+	status = __efivars->ops->set_variable(entry->var.VariableName,
+					      &entry->var.VendorGuid,
+					      0, 0, NULL);
 
 	return efi_status_to_err(status);
 }
@@ -607,12 +624,17 @@ EXPORT_SYMBOL_GPL(__efivar_entry_delete);
  */
 int efivar_entry_delete(struct efivar_entry *entry)
 {
-	const struct efivar_operations *ops = __efivars->ops;
+	const struct efivar_operations *ops;
 	efi_status_t status;
 
 	if (down_interruptible(&efivars_lock))
 		return -EINTR;
 
+	if (!__efivars) {
+		up(&efivars_lock);
+		return -EINVAL;
+	}
+	ops = __efivars->ops;
 	status = ops->set_variable(entry->var.VariableName,
 				   &entry->var.VendorGuid,
 				   0, 0, NULL);
@@ -650,13 +672,19 @@ EXPORT_SYMBOL_GPL(efivar_entry_delete);
 int efivar_entry_set(struct efivar_entry *entry, u32 attributes,
 		     unsigned long size, void *data, struct list_head *head)
 {
-	const struct efivar_operations *ops = __efivars->ops;
+	const struct efivar_operations *ops;
 	efi_status_t status;
 	efi_char16_t *name = entry->var.VariableName;
 	efi_guid_t vendor = entry->var.VendorGuid;
 
 	if (down_interruptible(&efivars_lock))
 		return -EINTR;
+
+	if (!__efivars) {
+		up(&efivars_lock);
+		return -EINVAL;
+	}
+	ops = __efivars->ops;
 	if (head && efivar_entry_find(name, vendor, head, false)) {
 		up(&efivars_lock);
 		return -EEXIST;
@@ -687,12 +715,17 @@ static int
 efivar_entry_set_nonblocking(efi_char16_t *name, efi_guid_t vendor,
 			     u32 attributes, unsigned long size, void *data)
 {
-	const struct efivar_operations *ops = __efivars->ops;
+	const struct efivar_operations *ops;
 	efi_status_t status;
 
 	if (down_trylock(&efivars_lock))
 		return -EBUSY;
 
+	if (!__efivars) {
+		up(&efivars_lock);
+		return -EINVAL;
+	}
+
 	status = check_var_size_nonblocking(attributes,
 					    size + ucs2_strsize(name, 1024));
 	if (status != EFI_SUCCESS) {
@@ -700,6 +733,7 @@ efivar_entry_set_nonblocking(efi_char16_t *name, efi_guid_t vendor,
 		return -ENOSPC;
 	}
 
+	ops = __efivars->ops;
 	status = ops->set_variable_nonblocking(name, &vendor, attributes,
 					       size, data);
 
@@ -727,9 +761,13 @@ efivar_entry_set_nonblocking(efi_char16_t *name, efi_guid_t vendor,
 int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
 			  bool block, unsigned long size, void *data)
 {
-	const struct efivar_operations *ops = __efivars->ops;
+	const struct efivar_operations *ops;
 	efi_status_t status;
 
+	if (!__efivars)
+		return -EINVAL;
+
+	ops = __efivars->ops;
 	if (!ops->query_variable_store)
 		return -ENOSYS;
 
@@ -829,13 +867,18 @@ EXPORT_SYMBOL_GPL(efivar_entry_find);
  */
 int efivar_entry_size(struct efivar_entry *entry, unsigned long *size)
 {
-	const struct efivar_operations *ops = __efivars->ops;
+	const struct efivar_operations *ops;
 	efi_status_t status;
 
 	*size = 0;
 
 	if (down_interruptible(&efivars_lock))
 		return -EINTR;
+	if (!__efivars) {
+		up(&efivars_lock);
+		return -EINVAL;
+	}
+	ops = __efivars->ops;
 	status = ops->get_variable(entry->var.VariableName,
 				   &entry->var.VendorGuid, NULL, size, NULL);
 	up(&efivars_lock);
@@ -861,12 +904,14 @@ EXPORT_SYMBOL_GPL(efivar_entry_size);
 int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
 		       unsigned long *size, void *data)
 {
-	const struct efivar_operations *ops = __efivars->ops;
 	efi_status_t status;
 
-	status = ops->get_variable(entry->var.VariableName,
-				   &entry->var.VendorGuid,
-				   attributes, size, data);
+	if (!__efivars)
+		return -EINVAL;
+
+	status = __efivars->ops->get_variable(entry->var.VariableName,
+					      &entry->var.VendorGuid,
+					      attributes, size, data);
 
 	return efi_status_to_err(status);
 }
@@ -882,14 +927,19 @@ EXPORT_SYMBOL_GPL(__efivar_entry_get);
 int efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
 		     unsigned long *size, void *data)
 {
-	const struct efivar_operations *ops = __efivars->ops;
 	efi_status_t status;
 
 	if (down_interruptible(&efivars_lock))
 		return -EINTR;
-	status = ops->get_variable(entry->var.VariableName,
-				   &entry->var.VendorGuid,
-				   attributes, size, data);
+
+	if (!__efivars) {
+		up(&efivars_lock);
+		return -EINVAL;
+	}
+
+	status = __efivars->ops->get_variable(entry->var.VariableName,
+					      &entry->var.VendorGuid,
+					      attributes, size, data);
 	up(&efivars_lock);
 
 	return efi_status_to_err(status);
@@ -921,7 +971,7 @@ EXPORT_SYMBOL_GPL(efivar_entry_get);
 int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
 			      unsigned long *size, void *data, bool *set)
 {
-	const struct efivar_operations *ops = __efivars->ops;
+	const struct efivar_operations *ops;
 	efi_char16_t *name = entry->var.VariableName;
 	efi_guid_t *vendor = &entry->var.VendorGuid;
 	efi_status_t status;
@@ -940,6 +990,11 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
 	if (down_interruptible(&efivars_lock))
 		return -EINTR;
 
+	if (!__efivars) {
+		err = -EINVAL;
+		goto out;
+	}
+
 	/*
 	 * Ensure that the available space hasn't shrunk below the safe level
 	 */
@@ -956,6 +1011,8 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
 		}
 	}
 
+	ops = __efivars->ops;
+
 	status = ops->set_variable(name, vendor, attributes, *size, data);
 	if (status != EFI_SUCCESS) {
 		err = efi_status_to_err(status);
diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c
index 00e73d2..b7558ac 100644
--- a/drivers/fpga/altera-cvp.c
+++ b/drivers/fpga/altera-cvp.c
@@ -404,6 +404,7 @@ static int altera_cvp_probe(struct pci_dev *pdev,
 {
 	struct altera_cvp_conf *conf;
 	u16 cmd, val;
+	u32 regval;
 	int ret;
 
 	/*
@@ -417,6 +418,14 @@ static int altera_cvp_probe(struct pci_dev *pdev,
 		return -ENODEV;
 	}
 
+	pci_read_config_dword(pdev, VSE_CVP_STATUS, &regval);
+	if (!(regval & VSE_CVP_STATUS_CVP_EN)) {
+		dev_err(&pdev->dev,
+			"CVP is disabled for this device: CVP_STATUS Reg 0x%x\n",
+			regval);
+		return -ENODEV;
+	}
+
 	conf = devm_kzalloc(&pdev->dev, sizeof(*conf), GFP_KERNEL);
 	if (!conf)
 		return -ENOMEM;
diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c
index 6b11f13..7f9e030 100644
--- a/drivers/gpio/gpio-altera-a10sr.c
+++ b/drivers/gpio/gpio-altera-a10sr.c
@@ -66,8 +66,10 @@ static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
 static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
 					    unsigned int nr, int value)
 {
-	if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
+	if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) {
+		altr_a10sr_gpio_set(gc, nr, value);
 		return 0;
+	}
 	return -EINVAL;
 }
 
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 45c65f8..be85d4b 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -777,9 +777,6 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
 				     "marvell,armada-370-gpio"))
 		return 0;
 
-	if (IS_ERR(mvchip->clk))
-		return PTR_ERR(mvchip->clk);
-
 	/*
 	 * There are only two sets of PWM configuration registers for
 	 * all the GPIO lines on those SoCs which this driver reserves
@@ -790,6 +787,9 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
 	if (!res)
 		return 0;
 
+	if (IS_ERR(mvchip->clk))
+		return PTR_ERR(mvchip->clk);
+
 	/*
 	 * Use set A for lines of GPIO chip with id 0, B for GPIO chip
 	 * with id 1. Don't allow further GPIO chips to be used for PWM.
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index a4fd78b..e94c349 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table);
  */
 struct pcf857x {
 	struct gpio_chip	chip;
+	struct irq_chip		irqchip;
 	struct i2c_client	*client;
 	struct mutex		lock;		/* protect 'out' */
 	unsigned		out;		/* software latch */
@@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data *data)
 	mutex_unlock(&gpio->lock);
 }
 
-static struct irq_chip pcf857x_irq_chip = {
-	.name		= "pcf857x",
-	.irq_enable	= pcf857x_irq_enable,
-	.irq_disable	= pcf857x_irq_disable,
-	.irq_ack	= noop,
-	.irq_mask	= noop,
-	.irq_unmask	= noop,
-	.irq_set_wake	= pcf857x_irq_set_wake,
-	.irq_bus_lock		= pcf857x_irq_bus_lock,
-	.irq_bus_sync_unlock	= pcf857x_irq_bus_sync_unlock,
-};
-
 /*-------------------------------------------------------------------------*/
 
 static int pcf857x_probe(struct i2c_client *client,
@@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client,
 
 	/* Enable irqchip if we have an interrupt */
 	if (client->irq) {
+		gpio->irqchip.name = "pcf857x",
+		gpio->irqchip.irq_enable = pcf857x_irq_enable,
+		gpio->irqchip.irq_disable = pcf857x_irq_disable,
+		gpio->irqchip.irq_ack = noop,
+		gpio->irqchip.irq_mask = noop,
+		gpio->irqchip.irq_unmask = noop,
+		gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake,
+		gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock,
+		gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
 		status = gpiochip_irqchip_add_nested(&gpio->chip,
-						     &pcf857x_irq_chip,
+						     &gpio->irqchip,
 						     0, handle_level_irq,
 						     IRQ_TYPE_NONE);
 		if (status) {
@@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client,
 		if (status)
 			goto fail;
 
-		gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip,
+		gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip,
 					    client->irq);
 		gpio->irq_parent = client->irq;
 	}
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 6aaaab7..f6e1e0e 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -54,6 +54,7 @@ struct pl061 {
 
 	void __iomem		*base;
 	struct gpio_chip	gc;
+	struct irq_chip		irq_chip;
 	int			parent_irq;
 
 #ifdef CONFIG_PM
@@ -281,15 +282,6 @@ static int pl061_irq_set_wake(struct irq_data *d, unsigned int state)
 	return irq_set_irq_wake(pl061->parent_irq, state);
 }
 
-static struct irq_chip pl061_irqchip = {
-	.name		= "pl061",
-	.irq_ack	= pl061_irq_ack,
-	.irq_mask	= pl061_irq_mask,
-	.irq_unmask	= pl061_irq_unmask,
-	.irq_set_type	= pl061_irq_type,
-	.irq_set_wake	= pl061_irq_set_wake,
-};
-
 static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct device *dev = &adev->dev;
@@ -328,6 +320,13 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 	/*
 	 * irq_chip support
 	 */
+	pl061->irq_chip.name = dev_name(dev);
+	pl061->irq_chip.irq_ack	= pl061_irq_ack;
+	pl061->irq_chip.irq_mask = pl061_irq_mask;
+	pl061->irq_chip.irq_unmask = pl061_irq_unmask;
+	pl061->irq_chip.irq_set_type = pl061_irq_type;
+	pl061->irq_chip.irq_set_wake = pl061_irq_set_wake;
+
 	writeb(0, pl061->base + GPIOIE); /* disable irqs */
 	irq = adev->irq[0];
 	if (irq < 0) {
@@ -336,14 +335,14 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 	}
 	pl061->parent_irq = irq;
 
-	ret = gpiochip_irqchip_add(&pl061->gc, &pl061_irqchip,
+	ret = gpiochip_irqchip_add(&pl061->gc, &pl061->irq_chip,
 				   0, handle_bad_irq,
 				   IRQ_TYPE_NONE);
 	if (ret) {
 		dev_info(&adev->dev, "could not add irqchip\n");
 		return ret;
 	}
-	gpiochip_set_chained_irqchip(&pl061->gc, &pl061_irqchip,
+	gpiochip_set_chained_irqchip(&pl061->gc, &pl061->irq_chip,
 				     irq, pl061_irq_handler);
 
 	amba_set_drvdata(adev, pl061);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
index e343df1..05bb87a 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
@@ -32,6 +32,7 @@
 #include "vega10_pptable.h"
 
 #define NUM_DSPCLK_LEVELS 8
+#define VEGA10_ENGINECLOCK_HARDMAX 198000
 
 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
 		enum phm_platform_caps cap)
@@ -258,7 +259,26 @@ static int init_over_drive_limits(
 		struct pp_hwmgr *hwmgr,
 		const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
 {
-	hwmgr->platform_descriptor.overdriveLimit.engineClock =
+	const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
+			(const ATOM_Vega10_GFXCLK_Dependency_Table *)
+			(((unsigned long) powerplay_table) +
+			le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
+	bool is_acg_enabled = false;
+	ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2;
+
+	if (gfxclk_dep_table->ucRevId == 1) {
+		patom_record_v2 =
+			(ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries;
+		is_acg_enabled =
+			(bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable;
+	}
+
+	if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX &&
+		!is_acg_enabled)
+		hwmgr->platform_descriptor.overdriveLimit.engineClock =
+			VEGA10_ENGINECLOCK_HARDMAX;
+	else
+		hwmgr->platform_descriptor.overdriveLimit.engineClock =
 			le32_to_cpu(powerplay_table->ulMaxODEngineClock);
 	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
 			le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
diff --git a/drivers/gpu/drm/bridge/analogix-anx7625.c b/drivers/gpu/drm/bridge/analogix-anx7625.c
index b16d6de..352d7a4 100644
--- a/drivers/gpu/drm/bridge/analogix-anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix-anx7625.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  *
  * Copyright(c) 2016, Analogix Semiconductor. All rights reserved.
  *
@@ -1253,10 +1253,14 @@ static void anx7625_bridge_disable(struct drm_bridge *bridge)
 
 	mutex_lock(&anx7625->lock);
 
-	anx7625_stop(anx7625);
-
 	anx7625->enabled = false;
 
+	if (!anx7625->powered)
+		goto out;
+
+	anx7625_stop(anx7625);
+
+out:
 	mutex_unlock(&anx7625->lock);
 
 	TRACE("anx7625 disabled\n");
@@ -1291,6 +1295,9 @@ static void anx7625_bridge_enable(struct drm_bridge *bridge)
 
 	anx7625->enabled = true;
 
+	if (!anx7625->powered)
+		goto out;
+
 	if (!anx7625->connected)
 		DRM_ERROR("cable is not connected\n");
 
@@ -1301,6 +1308,7 @@ static void anx7625_bridge_enable(struct drm_bridge *bridge)
 	if (err)
 		DRM_ERROR("Failed to start: %d\n", err);
 
+out:
 	mutex_unlock(&anx7625->lock);
 
 	TRACE("anx7625 enabled\n");
@@ -1512,10 +1520,48 @@ static const struct of_device_id anx7625_id_match_table[] = {
 MODULE_DEVICE_TABLE(of, anx7625_id_match_table);
 #endif
 
+#ifdef CONFIG_PM_SLEEP
+static int anx7625_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct anx7625 *anx7625 = i2c_get_clientdata(client);
+
+	mutex_lock(&anx7625->lock);
+
+	anx7625_poweroff(anx7625);
+
+	mutex_unlock(&anx7625->lock);
+
+	return 0;
+}
+
+static int anx7625_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct anx7625 *anx7625 = i2c_get_clientdata(client);
+
+	mutex_lock(&anx7625->lock);
+
+	anx7625->last_read_DevAddr = 0;
+
+	anx7625_poweron(anx7625);
+
+	if (anx7625->enabled)
+		anx7625_start(anx7625);
+
+	mutex_unlock(&anx7625->lock);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(anx7625_pm, anx7625_suspend, anx7625_resume);
+
 static struct i2c_driver anx7625_driver = {
 	.driver = {
 		.name = "anx7625",
 		.owner = THIS_MODULE,
+		.pm = &anx7625_pm,
 #ifdef CONFIG_OF
 		.of_match_table = anx7625_id_match_table,
 #endif
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 8636e7e..6eebd8a 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -96,6 +96,8 @@
 #define DP0_STARTVAL		0x064c
 #define DP0_ACTIVEVAL		0x0650
 #define DP0_SYNCVAL		0x0654
+#define SYNCVAL_HS_POL_ACTIVE_LOW	(1 << 15)
+#define SYNCVAL_VS_POL_ACTIVE_LOW	(1 << 31)
 #define DP0_MISC		0x0658
 #define TU_SIZE_RECOMMENDED		(63) /* LSCLK cycles per TU */
 #define BPC_6				(0 << 5)
@@ -140,6 +142,8 @@
 #define DP0_LTLOOPCTRL		0x06d8
 #define DP0_SNKLTCTRL		0x06e4
 
+#define DP1_SRCCTRL		0x07a0
+
 /* PHY */
 #define DP_PHY_CTRL		0x0800
 #define DP_PHY_RST			BIT(28)  /* DP PHY Global Soft Reset */
@@ -148,6 +152,7 @@
 #define PHY_M1_RST			BIT(12)  /* Reset PHY1 Main Channel */
 #define PHY_RDY				BIT(16)  /* PHY Main Channels Ready */
 #define PHY_M0_RST			BIT(8)   /* Reset PHY0 Main Channel */
+#define PHY_2LANE			BIT(2)   /* PHY Enable 2 lanes */
 #define PHY_A0_EN			BIT(1)   /* PHY Aux Channel0 Enable */
 #define PHY_M0_EN			BIT(0)   /* PHY Main Channel0 Enable */
 
@@ -538,6 +543,7 @@ static int tc_aux_link_setup(struct tc_data *tc)
 	unsigned long rate;
 	u32 value;
 	int ret;
+	u32 dp_phy_ctrl;
 
 	rate = clk_get_rate(tc->refclk);
 	switch (rate) {
@@ -562,7 +568,10 @@ static int tc_aux_link_setup(struct tc_data *tc)
 	value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
 	tc_write(SYS_PLLPARAM, value);
 
-	tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN);
+	dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN;
+	if (tc->link.base.num_lanes == 2)
+		dp_phy_ctrl |= PHY_2LANE;
+	tc_write(DP_PHY_CTRL, dp_phy_ctrl);
 
 	/*
 	 * Initially PLLs are in bypass. Force PLL parameter update,
@@ -717,7 +726,9 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
 
 	tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay));
 
-	tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0));
+	tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) |
+		 ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) |
+		 ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0));
 
 	tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
 		 DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888);
@@ -827,12 +838,11 @@ static int tc_main_link_setup(struct tc_data *tc)
 	if (!tc->mode)
 		return -EINVAL;
 
-	/* from excel file - DP0_SrcCtrl */
-	tc_write(DP0_SRCCTRL, DP0_SRCCTRL_SCRMBLDIS | DP0_SRCCTRL_EN810B |
-		 DP0_SRCCTRL_LANESKEW | DP0_SRCCTRL_LANES_2 |
-		 DP0_SRCCTRL_BW27 | DP0_SRCCTRL_AUTOCORRECT);
-	/* from excel file - DP1_SrcCtrl */
-	tc_write(0x07a0, 0x00003083);
+	tc_write(DP0_SRCCTRL, tc_srcctrl(tc));
+	/* SSCG and BW27 on DP1 must be set to the same as on DP0 */
+	tc_write(DP1_SRCCTRL,
+		 (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) |
+		 ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0));
 
 	rate = clk_get_rate(tc->refclk);
 	switch (rate) {
@@ -853,8 +863,11 @@ static int tc_main_link_setup(struct tc_data *tc)
 	}
 	value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
 	tc_write(SYS_PLLPARAM, value);
+
 	/* Setup Main Link */
-	dp_phy_ctrl = BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN |  PHY_M0_EN;
+	dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN;
+	if (tc->link.base.num_lanes == 2)
+		dp_phy_ctrl |= PHY_2LANE;
 	tc_write(DP_PHY_CTRL, dp_phy_ctrl);
 	msleep(100);
 
@@ -1103,10 +1116,20 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
 static int tc_connector_mode_valid(struct drm_connector *connector,
 				   struct drm_display_mode *mode)
 {
+	struct tc_data *tc = connector_to_tc(connector);
+	u32 req, avail;
+	u32 bits_per_pixel = 24;
+
 	/* DPI interface clock limitation: upto 154 MHz */
 	if (mode->clock > 154000)
 		return MODE_CLOCK_HIGH;
 
+	req = mode->clock * bits_per_pixel / 8;
+	avail = tc->link.base.num_lanes * tc->link.base.rate;
+
+	if (req > avail)
+		return MODE_BAD;
+
 	return MODE_OK;
 }
 
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 1f08d59..d05ed05 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2899,7 +2899,7 @@ EXPORT_SYMBOL(drm_atomic_helper_suspend);
 int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
 					      struct drm_modeset_acquire_ctx *ctx)
 {
-	int i;
+	int i, ret;
 	struct drm_plane *plane;
 	struct drm_plane_state *new_plane_state;
 	struct drm_connector *connector;
@@ -2918,7 +2918,11 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
 	for_each_new_connector_in_state(state, connector, new_conn_state, i)
 		state->connectors[i].old_state = connector->state;
 
-	return drm_atomic_commit(state);
+	ret = drm_atomic_commit(state);
+
+	state->acquire_ctx = NULL;
+
+	return ret;
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_duplicated_state);
 
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 1ee84dd..0f05b8d 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -36,6 +36,8 @@
 #include <drm/drmP.h>
 #include "drm_legacy.h"
 
+#include <linux/nospec.h>
+
 static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
 						  struct drm_local_map *map)
 {
@@ -1417,6 +1419,7 @@ int drm_legacy_freebufs(struct drm_device *dev, void *data,
 				  idx, dma->buf_count - 1);
 			return -EINVAL;
 		}
+		idx = array_index_nospec(idx, dma->buf_count);
 		buf = dma->buflist[idx];
 		if (buf->file_priv != file_priv) {
 			DRM_ERROR("Process %d freeing buffer not owned\n",
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 8959459..b76bd57 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -119,18 +119,32 @@ u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SI
 EXPORT_SYMBOL(drm_dp_get_adjust_request_pre_emphasis);
 
 void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) {
-	if (dpcd[DP_TRAINING_AUX_RD_INTERVAL] == 0)
+	int rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
+			  DP_TRAINING_AUX_RD_MASK;
+
+	if (rd_interval > 4)
+		DRM_DEBUG_KMS("AUX interval %d, out of range (max 4)\n",
+			      rd_interval);
+
+	if (rd_interval == 0 || dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14)
 		udelay(100);
 	else
-		mdelay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4);
+		mdelay(rd_interval * 4);
 }
 EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
 
 void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) {
-	if (dpcd[DP_TRAINING_AUX_RD_INTERVAL] == 0)
+	int rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
+			  DP_TRAINING_AUX_RD_MASK;
+
+	if (rd_interval > 4)
+		DRM_DEBUG_KMS("AUX interval %d, out of range (max 4)\n",
+			      rd_interval);
+
+	if (rd_interval == 0)
 		udelay(400);
 	else
-		mdelay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4);
+		mdelay(rd_interval * 4);
 }
 EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
 
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 98a7abc..d95fae3 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -51,10 +51,6 @@ static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
 				     int id,
 				     struct drm_dp_payload *payload);
 
-static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
-				  struct drm_dp_mst_port *port,
-				  int offset, int size, u8 *bytes);
-
 static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
 				     struct drm_dp_mst_branch *mstb);
 static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
@@ -1212,9 +1208,8 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
 			drm_dp_put_port(port);
 			goto out;
 		}
-		if ((port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV ||
-		     port->pdt == DP_PEER_DEVICE_SST_SINK) &&
-		    port->port_num >= DP_MST_LOGICAL_PORT_0) {
+		if (port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV ||
+		     port->pdt == DP_PEER_DEVICE_SST_SINK) {
 			port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
 			drm_mode_connector_set_tile_property(port->connector);
 		}
@@ -1252,6 +1247,13 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
 		}
 	}
 	if (old_pdt != port->pdt && !port->input) {
+		if ((old_pdt == DP_PEER_DEVICE_DP_LEGACY_CONV ||
+		     old_pdt == DP_PEER_DEVICE_SST_SINK) &&
+		    port->port_num < DP_MST_LOGICAL_PORT_0) {
+			kfree(port->cached_edid);
+			port->cached_edid = NULL;
+		}
+
 		drm_dp_port_teardown_pdt(port, old_pdt);
 
 		if (drm_dp_port_setup_pdt(port))
@@ -1403,7 +1405,6 @@ static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
 	return false;
 }
 
-#if 0
 static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes)
 {
 	struct drm_dp_sideband_msg_req_body req;
@@ -1416,7 +1417,6 @@ static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32
 
 	return 0;
 }
-#endif
 
 static int drm_dp_send_sideband_msg(struct drm_dp_mst_topology_mgr *mgr,
 				    bool up, u8 *msg, int len)
@@ -1982,8 +1982,7 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
 }
 EXPORT_SYMBOL(drm_dp_update_payload_part2);
 
-#if 0 /* unused as of yet */
-static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
+int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
 				 struct drm_dp_mst_port *port,
 				 int offset, int size, u8 *bytes)
 {
@@ -2037,11 +2036,11 @@ static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
 	drm_dp_put_mst_branch_device(mstb);
 	return ret;
 }
-#endif
+EXPORT_SYMBOL(drm_dp_send_dpcd_read);
 
-static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
-				  struct drm_dp_mst_port *port,
-				  int offset, int size, u8 *bytes)
+int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
+			   struct drm_dp_mst_port *port,
+			   int offset, int size, u8 *bytes)
 {
 	int len;
 	int ret;
@@ -2075,6 +2074,7 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
 	drm_dp_put_mst_branch_device(mstb);
 	return ret;
 }
+EXPORT_SYMBOL(drm_dp_send_dpcd_write);
 
 static int drm_dp_encode_up_ack_reply(struct drm_dp_sideband_msg_tx *msg, u8 req_type)
 {
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 29d1d3d..f1259a0 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1509,6 +1509,64 @@ static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1,
 	       var_1->transp.msb_right == var_2->transp.msb_right;
 }
 
+static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var,
+					 u8 depth)
+{
+	switch (depth) {
+	case 8:
+		var->red.offset = 0;
+		var->green.offset = 0;
+		var->blue.offset = 0;
+		var->red.length = 8; /* 8bit DAC */
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 15:
+		var->red.offset = 10;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 5;
+		var->blue.length = 5;
+		var->transp.offset = 15;
+		var->transp.length = 1;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		break;
+	case 24:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	default:
+		break;
+	}
+}
+
 /**
  * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var
  * @var: screeninfo to check
@@ -1520,9 +1578,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
 	struct drm_fb_helper *fb_helper = info->par;
 	struct drm_framebuffer *fb = fb_helper->fb;
 
-	if (var->pixclock != 0 || in_dbg_master())
+	if (in_dbg_master())
 		return -EINVAL;
 
+	if (var->pixclock != 0) {
+		DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
+		var->pixclock = 0;
+	}
+
 	/*
 	 * Changes struct fb_var_screeninfo are currently not pushed back
 	 * to KMS, hence fail if different settings are requested.
@@ -1539,6 +1602,20 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
 	}
 
 	/*
+	 * Workaround for SDL 1.2, which is known to be setting all pixel format
+	 * fields values to zero in some cases. We treat this situation as a
+	 * kind of "use some reasonable autodetected values".
+	 */
+	if (!var->red.offset     && !var->green.offset    &&
+	    !var->blue.offset    && !var->transp.offset   &&
+	    !var->red.length     && !var->green.length    &&
+	    !var->blue.length    && !var->transp.length   &&
+	    !var->red.msb_right  && !var->green.msb_right &&
+	    !var->blue.msb_right && !var->transp.msb_right) {
+		drm_fb_helper_fill_pixel_fmt(var, fb->format->depth);
+	}
+
+	/*
 	 * drm fbdev emulation doesn't support changing the pixel format at all,
 	 * so reject all pixel format changing requests.
 	 */
@@ -1848,59 +1925,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
 	info->var.yoffset = 0;
 	info->var.activate = FB_ACTIVATE_NOW;
 
-	switch (fb->format->depth) {
-	case 8:
-		info->var.red.offset = 0;
-		info->var.green.offset = 0;
-		info->var.blue.offset = 0;
-		info->var.red.length = 8; /* 8bit DAC */
-		info->var.green.length = 8;
-		info->var.blue.length = 8;
-		info->var.transp.offset = 0;
-		info->var.transp.length = 0;
-		break;
-	case 15:
-		info->var.red.offset = 10;
-		info->var.green.offset = 5;
-		info->var.blue.offset = 0;
-		info->var.red.length = 5;
-		info->var.green.length = 5;
-		info->var.blue.length = 5;
-		info->var.transp.offset = 15;
-		info->var.transp.length = 1;
-		break;
-	case 16:
-		info->var.red.offset = 11;
-		info->var.green.offset = 5;
-		info->var.blue.offset = 0;
-		info->var.red.length = 5;
-		info->var.green.length = 6;
-		info->var.blue.length = 5;
-		info->var.transp.offset = 0;
-		break;
-	case 24:
-		info->var.red.offset = 16;
-		info->var.green.offset = 8;
-		info->var.blue.offset = 0;
-		info->var.red.length = 8;
-		info->var.green.length = 8;
-		info->var.blue.length = 8;
-		info->var.transp.offset = 0;
-		info->var.transp.length = 0;
-		break;
-	case 32:
-		info->var.red.offset = 16;
-		info->var.green.offset = 8;
-		info->var.blue.offset = 0;
-		info->var.red.length = 8;
-		info->var.green.length = 8;
-		info->var.blue.length = 8;
-		info->var.transp.offset = 24;
-		info->var.transp.length = 8;
-		break;
-	default:
-		break;
-	}
+	drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth);
 
 	info->var.xres = fb_width;
 	info->var.yres = fb_height;
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 4a3f68a..3e3035c 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -751,7 +751,7 @@ int drm_mode_hsync(const struct drm_display_mode *mode)
 	if (mode->hsync)
 		return mode->hsync;
 
-	if (mode->htotal < 0)
+	if (mode->htotal <= 0)
 		return 0;
 
 	calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 73c672f..9834b7c 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -807,11 +807,18 @@ static ssize_t intel_vgpu_write(struct mdev_device *mdev,
 	return -EFAULT;
 }
 
+static inline bool intel_vgpu_in_aperture(struct intel_vgpu *vgpu,
+					  unsigned long off)
+{
+	return off >= vgpu_aperture_offset(vgpu) &&
+		off < vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu);
+}
+
 static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
 {
 	unsigned int index;
 	u64 virtaddr;
-	unsigned long req_size, pgoff = 0;
+	unsigned long req_size, pgoff, req_start;
 	pgprot_t pg_prot;
 	struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
 
@@ -829,7 +836,17 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
 	pg_prot = vma->vm_page_prot;
 	virtaddr = vma->vm_start;
 	req_size = vma->vm_end - vma->vm_start;
-	pgoff = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT;
+	pgoff = vma->vm_pgoff &
+		((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+	req_start = pgoff << PAGE_SHIFT;
+
+	if (!intel_vgpu_in_aperture(vgpu, req_start))
+		return -EINVAL;
+	if (req_start + req_size >
+	    vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu))
+		return -EINVAL;
+
+	pgoff = (gvt_aperture_pa_base(vgpu->gvt) >> PAGE_SHIFT) + pgoff;
 
 	return remap_pfn_range(vma, virtaddr, pgoff, req_size, pg_prot);
 }
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1f19e6d..5d8a67c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1633,6 +1633,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
 	return 0;
 }
 
+static inline bool
+__vma_matches(struct vm_area_struct *vma, struct file *filp,
+	      unsigned long addr, unsigned long size)
+{
+	if (vma->vm_file != filp)
+		return false;
+
+	return vma->vm_start == addr && (vma->vm_end - vma->vm_start) == size;
+}
+
 /**
  * i915_gem_mmap_ioctl - Maps the contents of an object, returning the address
  *			 it is mapped to.
@@ -1691,7 +1701,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 			return -EINTR;
 		}
 		vma = find_vma(mm, addr);
-		if (vma)
+		if (vma && __vma_matches(vma, obj->base.filp, addr, args->size))
 			vma->vm_page_prot =
 				pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
 		else
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index da2d309..14eb8a0 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -326,8 +326,8 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
 				    bool *enabled, int width, int height)
 {
 	struct drm_i915_private *dev_priv = to_i915(fb_helper->dev);
-	unsigned long conn_configured, conn_seq, mask;
 	unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
+	unsigned long conn_configured, conn_seq;
 	int i, j;
 	bool *save_enabled;
 	bool fallback = true, ret = true;
@@ -345,10 +345,9 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
 		drm_modeset_backoff(&ctx);
 
 	memcpy(save_enabled, enabled, count);
-	mask = GENMASK(count - 1, 0);
+	conn_seq = GENMASK(count - 1, 0);
 	conn_configured = 0;
 retry:
-	conn_seq = conn_configured;
 	for (i = 0; i < count; i++) {
 		struct drm_fb_helper_connector *fb_conn;
 		struct drm_connector *connector;
@@ -361,7 +360,8 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
 		if (conn_configured & BIT(i))
 			continue;
 
-		if (conn_seq == 0 && !connector->has_tile)
+		/* First pass, only consider tiled connectors */
+		if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile)
 			continue;
 
 		if (connector->status == connector_status_connected)
@@ -465,8 +465,10 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
 		conn_configured |= BIT(i);
 	}
 
-	if ((conn_configured & mask) != mask && conn_configured != conn_seq)
+	if (conn_configured != conn_seq) { /* repeat until no more are found */
+		conn_seq = conn_configured;
 		goto retry;
+	}
 
 	/*
 	 * If the BIOS didn't enable everything it could, fall back to have the
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 4ad8223..5deb44a 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -345,8 +345,10 @@ static int meson_probe_remote(struct platform_device *pdev,
 		remote_node = of_graph_get_remote_port_parent(ep);
 		if (!remote_node ||
 		    remote_node == parent || /* Ignore parent endpoint */
-		    !of_device_is_available(remote_node))
+		    !of_device_is_available(remote_node)) {
+			of_node_put(remote_node);
 			continue;
+		}
 
 		count += meson_probe_remote(pdev, match, remote, remote_node);
 
@@ -365,10 +367,13 @@ static int meson_drv_probe(struct platform_device *pdev)
 
 	for_each_endpoint_of_node(np, ep) {
 		remote = of_graph_get_remote_port_parent(ep);
-		if (!remote || !of_device_is_available(remote))
+		if (!remote || !of_device_is_available(remote)) {
+			of_node_put(remote);
 			continue;
+		}
 
 		count += meson_probe_remote(pdev, &match, np, remote);
+		of_node_put(remote);
 	}
 
 	if (count && !match)
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 36e0be9..548906d 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -152,6 +152,16 @@
 	  the output image is written back to memory in the format
 	  selected by the connector's mode and property settings.
 
+config DRM_SDE_SHD
+	bool "Enable Shared display support in SDE DRM"
+	depends on DRM_MSM
+	help
+	  Choose this option for shared display support.
+	  This option enables multiple logical displays
+	  to share one base physical encoder/connector.
+	  Each logical display will appear as different
+	  connectors and report back to user.
+
 config DRM_MSM_DSI_14NM_PHY
 	bool "Enable DSI 14nm PHY driver in MSM DRM (used by MSM8996/APQ8096)"
 	depends on DRM_MSM_DSI
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index e9856c0..2516cc5 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -6,6 +6,7 @@
 ccflags-y += -Idrivers/gpu/drm/msm/sde
 ccflags-y += -Idrivers/media/platform/msm/sde/rotator
 ccflags-y += -Idrivers/gpu/drm/msm/hdmi
+ccflags-$(CONFIG_DRM_SDE_SHD) += -Idrivers/gpu/drm/msm/shd
 
 msm_drm-y := \
 	dp/dp_usbpd.o \
@@ -186,6 +187,10 @@
 msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \
 	sde/sde_encoder_phys_wb.o
 
+msm_drm-$(CONFIG_DRM_SDE_SHD) += shd/shd_drm.o \
+	shd/shd_hw.o \
+	shd/sde_encoder_phys_shd.o
+
 msm_drm-$(CONFIG_DRM_MSM) += \
 	msm_atomic.o \
 	msm_drv.o \
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 8758db5..6d89a20 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -379,7 +379,7 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
 	struct dp_catalog_private *catalog;
 	struct drm_msm_ext_hdr_metadata *hdr;
 	struct dp_io_data *io_data;
-	u32 header, parity, data;
+	u32 header, parity, data, mst_offset = 0;
 	u8 buf[SZ_128], off = 0;
 
 	if (!panel) {
@@ -387,6 +387,14 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
 		return;
 	}
 
+	if (panel->stream_id >= DP_STREAM_MAX) {
+		pr_err("invalid stream_id:%d\n", panel->stream_id);
+		return;
+	}
+
+	if (panel->stream_id == DP_STREAM_1)
+		mst_offset = MMSS_DP1_VSCEXT_0 - MMSS_DP_VSCEXT_0;
+
 	catalog = dp_catalog_get_priv(panel);
 	hdr = &panel->hdr_data.hdr_meta;
 	io_data = catalog->io.dp_link;
@@ -396,7 +404,8 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_1_BIT)
 			| (parity << PARITY_BYTE_1_BIT));
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_0, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_0 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -405,22 +414,26 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_2_BIT)
 			| (parity << PARITY_BYTE_2_BIT));
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_1, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_1 + mst_offset,
+			data);
 
 	/* HEADER BYTE 3 */
 	header = panel->hdr_data.vscext_header_byte3;
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_3_BIT)
 			| (parity << PARITY_BYTE_3_BIT));
-	data |= dp_read(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_1);
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_1, data);
+	data |= dp_read(catalog->exe_mode, io_data,
+			MMSS_DP_VSCEXT_1 + mst_offset);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_1 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
 	data = panel->hdr_data.version;
 	data |= panel->hdr_data.length << 8;
 	data |= hdr->eotf << 16;
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_2, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_2 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -428,7 +441,8 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
 		(DP_GET_MSB(hdr->display_primaries_x[0]) << 8) |
 		(DP_GET_LSB(hdr->display_primaries_y[0]) << 16) |
 		(DP_GET_MSB(hdr->display_primaries_y[0]) << 24));
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_3, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_3 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -436,7 +450,8 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
 		(DP_GET_MSB(hdr->display_primaries_x[1]) << 8) |
 		(DP_GET_LSB(hdr->display_primaries_y[1]) << 16) |
 		(DP_GET_MSB(hdr->display_primaries_y[1]) << 24));
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_4, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_4 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -444,7 +459,8 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
 		(DP_GET_MSB(hdr->display_primaries_x[2]) << 8) |
 		(DP_GET_LSB(hdr->display_primaries_y[2]) << 16) |
 		(DP_GET_MSB(hdr->display_primaries_y[2]) << 24));
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_5, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_5 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -452,7 +468,8 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
 		(DP_GET_MSB(hdr->white_point_x) << 8) |
 		(DP_GET_LSB(hdr->white_point_y) << 16) |
 		(DP_GET_MSB(hdr->white_point_y) << 24));
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_6, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_6 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -460,7 +477,8 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
 		(DP_GET_MSB(hdr->max_luminance) << 8) |
 		(DP_GET_LSB(hdr->min_luminance) << 16) |
 		(DP_GET_MSB(hdr->min_luminance) << 24));
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_7, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_7 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -468,12 +486,14 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
 		(DP_GET_MSB(hdr->max_content_light_level) << 8) |
 		(DP_GET_LSB(hdr->max_average_light_level) << 16) |
 		(DP_GET_MSB(hdr->max_average_light_level) << 24));
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_8, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_8 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
 	data = 0;
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_9, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_9 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -485,7 +505,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 {
 	struct dp_catalog_private *catalog;
 	struct dp_io_data *io_data;
-	u32 header, parity, data;
+	u32 header, parity, data, mst_offset = 0;
 	u8 bpc, off = 0;
 	u8 buf[SZ_128];
 
@@ -494,6 +514,14 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 		return;
 	}
 
+	if (panel->stream_id >= DP_STREAM_MAX) {
+		pr_err("invalid stream_id:%d\n", panel->stream_id);
+		return;
+	}
+
+	if (panel->stream_id == DP_STREAM_1)
+		mst_offset = MMSS_DP1_GENERIC0_0 - MMSS_DP_GENERIC0_0;
+
 	catalog = dp_catalog_get_priv(panel);
 	io_data = catalog->io.dp_link;
 
@@ -502,7 +530,8 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_1_BIT)
 			| (parity << PARITY_BYTE_1_BIT));
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_0, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_0 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -511,32 +540,39 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_2_BIT)
 			| (parity << PARITY_BYTE_2_BIT));
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_1, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_1 + mst_offset,
+			data);
 
 	/* HEADER BYTE 3 */
 	header = panel->hdr_data.vsc_header_byte3;
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_3_BIT)
 			| (parity << PARITY_BYTE_3_BIT));
-	data |= dp_read(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_1);
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_1, data);
+	data |= dp_read(catalog->exe_mode, io_data,
+			MMSS_DP_GENERIC0_1 + mst_offset);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_1 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
 	data = 0;
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_2, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_2 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_3, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_3 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_4, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_4 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_5, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_5 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -559,20 +595,24 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 		((panel->hdr_data.dynamic_range & 0x1) << 15) |
 		((panel->hdr_data.content_type & 0x7) << 16);
 
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_6, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_6 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
 	data = 0;
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_7, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_7 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_8, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_8 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_9, data);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_9 + mst_offset,
+			data);
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 
@@ -924,12 +964,10 @@ static void dp_catalog_panel_config_misc(struct dp_catalog_panel *panel)
 }
 
 static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel,
-					u32 rate, u32 stream_rate_khz,
-					bool fixed_nvid)
+					u32 rate, u32 stream_rate_khz)
 {
 	u32 pixel_m, pixel_n;
 	u32 mvid, nvid;
-	u64 mvid_calc;
 	u32 const nvid_fixed = 0x8000;
 	u32 const link_rate_hbr2 = 540000;
 	u32 const link_rate_hbr3 = 810000;
@@ -949,57 +987,39 @@ static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel,
 	}
 
 	catalog = dp_catalog_get_priv(panel);
-	if (fixed_nvid) {
-		pr_debug("use fixed NVID=0x%x\n", nvid_fixed);
-		nvid = nvid_fixed;
+	io_data = catalog->io.dp_mmss_cc;
 
-		pr_debug("link rate=%dkbps, stream_rate_khz=%uKhz",
-			rate, stream_rate_khz);
+	if (panel->stream_id == DP_STREAM_1)
+		strm_reg_off = MMSS_DP_PIXEL1_M - MMSS_DP_PIXEL_M;
 
-		/*
-		 * For intermediate results, use 64 bit arithmetic to avoid
-		 * loss of precision.
-		 */
-		mvid_calc = (u64) stream_rate_khz * nvid;
-		mvid_calc = div_u64(mvid_calc, rate);
+	pixel_m = dp_read(catalog->exe_mode, io_data,
+			MMSS_DP_PIXEL_M + strm_reg_off);
+	pixel_n = dp_read(catalog->exe_mode, io_data,
+			MMSS_DP_PIXEL_N + strm_reg_off);
+	pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
 
-		/*
-		 * truncate back to 32 bits as this final divided value will
-		 * always be within the range of a 32 bit unsigned int.
-		 */
-		mvid = (u32) mvid_calc;
+	mvid = (pixel_m & 0xFFFF) * 5;
+	nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
 
-		if (panel->widebus_en) {
-			mvid <<= 1;
-			nvid <<= 1;
-		}
-	} else {
-		io_data = catalog->io.dp_mmss_cc;
+	if (nvid < nvid_fixed) {
+		u32 temp;
 
-		if (panel->stream_id == DP_STREAM_1)
-			strm_reg_off = MMSS_DP_PIXEL1_M - MMSS_DP_PIXEL_M;
-
-		pixel_m = dp_read(catalog->exe_mode, io_data,
-				MMSS_DP_PIXEL_M + strm_reg_off);
-		pixel_n = dp_read(catalog->exe_mode, io_data,
-				MMSS_DP_PIXEL_N + strm_reg_off);
-		pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
-
-		mvid = (pixel_m & 0xFFFF) * 5;
-		nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
-
-		pr_debug("rate = %d\n", rate);
-
-		if (panel->widebus_en)
-			mvid <<= 1;
-
-		if (link_rate_hbr2 == rate)
-			nvid *= 2;
-
-		if (link_rate_hbr3 == rate)
-			nvid *= 3;
+		temp = (nvid_fixed / nvid) * nvid;
+		mvid = (nvid_fixed / nvid) * mvid;
+		nvid = temp;
 	}
 
+	pr_debug("rate = %d\n", rate);
+
+	if (panel->widebus_en)
+		mvid <<= 1;
+
+	if (link_rate_hbr2 == rate)
+		nvid *= 2;
+
+	if (link_rate_hbr3 == rate)
+		nvid *= 3;
+
 	io_data = catalog->io.dp_link;
 
 	if (panel->stream_id == DP_STREAM_1) {
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index d3d9cc4..b554942 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -232,7 +232,7 @@ struct dp_catalog_panel {
 	void (*config_spd)(struct dp_catalog_panel *panel);
 	void (*config_misc)(struct dp_catalog_panel *panel);
 	void (*config_msa)(struct dp_catalog_panel *panel,
-			u32 rate, u32 stream_rate_khz, bool fixed_nvid);
+			u32 rate, u32 stream_rate_khz);
 	void (*update_transfer_unit)(struct dp_catalog_panel *panel);
 	void (*config_ctrl)(struct dp_catalog_panel *panel, u32 cfg);
 	void (*config_dto)(struct dp_catalog_panel *panel, bool ack);
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog_v200.c b/drivers/gpu/drm/msm/dp/dp_catalog_v200.c
index 797528f..3bece35 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog_v200.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog_v200.c
@@ -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
@@ -127,12 +127,10 @@ static void dp_catalog_aux_setup_v200(struct dp_catalog_aux *aux,
 }
 
 static void dp_catalog_panel_config_msa_v200(struct dp_catalog_panel *panel,
-					u32 rate, u32 stream_rate_khz,
-					bool fixed_nvid)
+					u32 rate, u32 stream_rate_khz)
 {
 	u32 pixel_m, pixel_n;
 	u32 mvid, nvid;
-	u64 mvid_calc;
 	u32 const nvid_fixed = 0x8000;
 	u32 const link_rate_hbr2 = 540000;
 	u32 const link_rate_hbr3 = 810000;
@@ -152,58 +150,40 @@ static void dp_catalog_panel_config_msa_v200(struct dp_catalog_panel *panel,
 	}
 
 	catalog = dp_catalog_get_priv_v200(panel);
-	if (fixed_nvid) {
-		pr_debug("use fixed NVID=0x%x\n", nvid_fixed);
-		nvid = nvid_fixed;
+	io_data = catalog->io->dp_mmss_cc;
 
-		pr_debug("link rate=%dkbps, stream_rate_khz=%uKhz",
-			rate, stream_rate_khz);
+	if (panel->stream_id == DP_STREAM_1)
+		strm_reg_off = MMSS_DP_PIXEL1_M_V200 -
+					MMSS_DP_PIXEL_M_V200;
 
-		/*
-		 * For intermediate results, use 64 bit arithmetic to avoid
-		 * loss of precision.
-		 */
-		mvid_calc = (u64) stream_rate_khz * nvid;
-		mvid_calc = div_u64(mvid_calc, rate);
+	pixel_m = dp_read(catalog->exe_mode, io_data,
+			MMSS_DP_PIXEL_M_V200 + strm_reg_off);
+	pixel_n = dp_read(catalog->exe_mode, io_data,
+			MMSS_DP_PIXEL_N_V200 + strm_reg_off);
+	pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
 
-		/*
-		 * truncate back to 32 bits as this final divided value will
-		 * always be within the range of a 32 bit unsigned int.
-		 */
-		mvid = (u32) mvid_calc;
+	mvid = (pixel_m & 0xFFFF) * 5;
+	nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
 
-		if (panel->widebus_en) {
-			mvid <<= 1;
-			nvid <<= 1;
-		}
-	} else {
-		io_data = catalog->io->dp_mmss_cc;
+	if (nvid < nvid_fixed) {
+		u32 temp;
 
-		if (panel->stream_id == DP_STREAM_1)
-			strm_reg_off = MMSS_DP_PIXEL1_M_V200 -
-						MMSS_DP_PIXEL_M_V200;
-
-		pixel_m = dp_read(catalog->exe_mode, io_data,
-				MMSS_DP_PIXEL_M_V200 + strm_reg_off);
-		pixel_n = dp_read(catalog->exe_mode, io_data,
-				MMSS_DP_PIXEL_N_V200 + strm_reg_off);
-		pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
-
-		mvid = (pixel_m & 0xFFFF) * 5;
-		nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
-
-		pr_debug("rate = %d\n", rate);
-
-		if (panel->widebus_en)
-			mvid <<= 1;
-
-		if (link_rate_hbr2 == rate)
-			nvid *= 2;
-
-		if (link_rate_hbr3 == rate)
-			nvid *= 3;
+		temp = (nvid_fixed / nvid) * nvid;
+		mvid = (nvid_fixed / nvid) * mvid;
+		nvid = temp;
 	}
 
+	pr_debug("rate = %d\n", rate);
+
+	if (panel->widebus_en)
+		mvid <<= 1;
+
+	if (link_rate_hbr2 == rate)
+		nvid *= 2;
+
+	if (link_rate_hbr3 == rate)
+		nvid *= 3;
+
 	io_data = catalog->io->dp_link;
 
 	if (panel->stream_id == DP_STREAM_1) {
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog_v420.c b/drivers/gpu/drm/msm/dp/dp_catalog_v420.c
index c7a3b8a..3d3d545 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog_v420.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog_v420.c
@@ -131,12 +131,10 @@ static void dp_catalog_aux_clear_hw_interrupts_v420(struct dp_catalog_aux *aux)
 }
 
 static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel,
-					u32 rate, u32 stream_rate_khz,
-					bool fixed_nvid)
+					u32 rate, u32 stream_rate_khz)
 {
 	u32 pixel_m, pixel_n;
 	u32 mvid, nvid, reg_off = 0, mvid_off = 0, nvid_off = 0;
-	u64 mvid_calc;
 	u32 const nvid_fixed = 0x8000;
 	u32 const link_rate_hbr2 = 540000;
 	u32 const link_rate_hbr3 = 810000;
@@ -154,57 +152,39 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel,
 	}
 
 	catalog = dp_catalog_get_priv_v420(panel);
-	if (fixed_nvid) {
-		pr_debug("use fixed NVID=0x%x\n", nvid_fixed);
-		nvid = nvid_fixed;
+	io_data = catalog->io->dp_mmss_cc;
 
-		pr_debug("link rate=%dkbps, stream_rate_khz=%uKhz",
-			rate, stream_rate_khz);
+	if (panel->stream_id == DP_STREAM_1)
+		reg_off = MMSS_DP_PIXEL1_M_V420 - MMSS_DP_PIXEL_M_V420;
 
-		/*
-		 * For intermediate results, use 64 bit arithmetic to avoid
-		 * loss of precision.
-		 */
-		mvid_calc = (u64) stream_rate_khz * nvid;
-		mvid_calc = div_u64(mvid_calc, rate);
+	pixel_m = dp_read(catalog->exe_mode, io_data,
+			MMSS_DP_PIXEL_M_V420 + reg_off);
+	pixel_n = dp_read(catalog->exe_mode, io_data,
+			MMSS_DP_PIXEL_N_V420 + reg_off);
+	pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
 
-		/*
-		 * truncate back to 32 bits as this final divided value will
-		 * always be within the range of a 32 bit unsigned int.
-		 */
-		mvid = (u32) mvid_calc;
+	mvid = (pixel_m & 0xFFFF) * 5;
+	nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
 
-		if (panel->widebus_en) {
-			mvid <<= 1;
-			nvid <<= 1;
-		}
-	} else {
-		io_data = catalog->io->dp_mmss_cc;
+	if (nvid < nvid_fixed) {
+		u32 temp;
 
-		if (panel->stream_id == DP_STREAM_1)
-			reg_off = MMSS_DP_PIXEL1_M_V420 - MMSS_DP_PIXEL_M_V420;
-
-		pixel_m = dp_read(catalog->exe_mode, io_data,
-				MMSS_DP_PIXEL_M_V420 + reg_off);
-		pixel_n = dp_read(catalog->exe_mode, io_data,
-				MMSS_DP_PIXEL_N_V420 + reg_off);
-		pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
-
-		mvid = (pixel_m & 0xFFFF) * 5;
-		nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
-
-		pr_debug("rate = %d\n", rate);
-
-		if (panel->widebus_en)
-			mvid <<= 1;
-
-		if (link_rate_hbr2 == rate)
-			nvid *= 2;
-
-		if (link_rate_hbr3 == rate)
-			nvid *= 3;
+		temp = (nvid_fixed / nvid) * nvid;
+		mvid = (nvid_fixed / nvid) * mvid;
+		nvid = temp;
 	}
 
+	pr_debug("rate = %d\n", rate);
+
+	if (panel->widebus_en)
+		mvid <<= 1;
+
+	if (link_rate_hbr2 == rate)
+		nvid *= 2;
+
+	if (link_rate_hbr3 == rate)
+		nvid *= 3;
+
 	io_data = catalog->io->dp_link;
 
 	if (panel->stream_id == DP_STREAM_1) {
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index b6160f9..6b649c6 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -241,16 +241,64 @@ static void dp_display_check_source_hdcp_caps(struct dp_display_private *dp)
 		struct sde_hdcp_ops *ops = dev->ops;
 		void *fd = dev->fd;
 
-		if (!fd || !ops || (dp->hdcp.source_cap & dev->ver))
+		if (!fd || !ops)
 			continue;
 
-		if (ops->feature_supported(fd))
+		if (ops->set_mode && ops->set_mode(fd, dp->mst.mst_active))
+			continue;
+
+		if (!(dp->hdcp.source_cap & dev->ver) &&
+				ops->feature_supported &&
+				ops->feature_supported(fd))
 			dp->hdcp.source_cap |= dev->ver;
 	}
 
 	dp_display_update_hdcp_status(dp, false);
 }
 
+static void dp_display_hdcp_register_streams(struct dp_display_private *dp)
+{
+	int rc;
+	size_t i;
+	struct sde_hdcp_ops *ops = dp->hdcp.ops;
+	void *data = dp->hdcp.data;
+
+	if (dp_display_is_ready(dp) && dp->mst.mst_active && ops &&
+			ops->register_streams){
+		struct stream_info streams[DP_STREAM_MAX];
+		int index = 0;
+
+		pr_debug("Registering all active panel streams with HDCP\n");
+		for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) {
+			if (!dp->active_panels[i])
+				continue;
+			streams[index].stream_id = i;
+			streams[index].virtual_channel =
+				dp->active_panels[i]->vcpi;
+			index++;
+		}
+
+		if (index > 0) {
+			rc = ops->register_streams(data, index, streams);
+			if (rc)
+				pr_err("failed to register streams. rc = %d\n",
+					rc);
+		}
+	}
+}
+
+static void dp_display_hdcp_deregister_stream(struct dp_display_private *dp,
+		enum dp_stream_id stream_id)
+{
+	if (dp->hdcp.ops->deregister_streams) {
+		struct stream_info stream = {stream_id,
+				dp->active_panels[stream_id]->vcpi};
+
+		pr_debug("Deregistering stream within HDCP library");
+		dp->hdcp.ops->deregister_streams(dp->hdcp.data, 1, &stream);
+	}
+}
+
 static void dp_display_hdcp_cb_work(struct work_struct *work)
 {
 	struct dp_display_private *dp;
@@ -260,12 +308,21 @@ static void dp_display_hdcp_cb_work(struct work_struct *work)
 	void *data;
 	int rc = 0;
 	u32 hdcp_auth_state;
+	u8 sink_status = 0;
 
 	dp = container_of(dw, struct dp_display_private, hdcp_cb_work);
 
 	if (!dp->power_on || !dp->is_connected || atomic_read(&dp->aborted))
 		return;
 
+	drm_dp_dpcd_readb(dp->aux->drm_aux, DP_SINK_STATUS, &sink_status);
+	sink_status &= (DP_RECEIVE_PORT_0_STATUS | DP_RECEIVE_PORT_1_STATUS);
+	if (sink_status < 1) {
+		pr_debug("Sink not synchronized. Queuing again then exiting\n");
+		queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ);
+		return;
+	}
+
 	status = &dp->link->hdcp_status;
 
 	if (status->hdcp_state == HDCP_STATE_INACTIVE) {
@@ -273,6 +330,11 @@ static void dp_display_hdcp_cb_work(struct work_struct *work)
 		dp_display_update_hdcp_info(dp);
 
 		if (dp_display_is_hdcp_enabled(dp)) {
+			if (dp->hdcp.ops && dp->hdcp.ops->on &&
+					dp->hdcp.ops->on(dp->hdcp.data)) {
+				dp_display_update_hdcp_status(dp, true);
+				return;
+			}
 			status->hdcp_state = HDCP_STATE_AUTHENTICATING;
 		} else {
 			dp_display_update_hdcp_status(dp, true);
@@ -299,11 +361,18 @@ static void dp_display_hdcp_cb_work(struct work_struct *work)
 
 	switch (status->hdcp_state) {
 	case HDCP_STATE_AUTHENTICATING:
+		dp_display_hdcp_register_streams(dp);
 		if (dp->hdcp.ops && dp->hdcp.ops->authenticate)
 			rc = dp->hdcp.ops->authenticate(data);
 		break;
 	case HDCP_STATE_AUTH_FAIL:
 		if (dp_display_is_ready(dp) && dp->power_on) {
+			if (ops && ops->on && ops->on(data)) {
+				dp_display_update_hdcp_status(dp, true);
+				return;
+			}
+			dp_display_hdcp_register_streams(dp);
+			status->hdcp_state = HDCP_STATE_AUTHENTICATING;
 			if (ops && ops->reauthenticate) {
 				rc = ops->reauthenticate(data);
 				if (rc)
@@ -314,6 +383,7 @@ static void dp_display_hdcp_cb_work(struct work_struct *work)
 		}
 		break;
 	default:
+		dp_display_hdcp_register_streams(dp);
 		break;
 	}
 }
@@ -721,14 +791,22 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp)
 {
 	int rc = 0, idx;
 	struct dp_panel *dp_panel;
+	struct dp_link_hdcp_status *status;
 
 	mutex_lock(&dp->session_lock);
 
+	status = &dp->link->hdcp_status;
 	dp->is_connected = false;
 	dp->process_hpd_connect = false;
 
-	if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->off)
-		dp->hdcp.ops->off(dp->hdcp.data);
+	if (dp_display_is_hdcp_enabled(dp) &&
+			status->hdcp_state != HDCP_STATE_INACTIVE) {
+		cancel_delayed_work_sync(&dp->hdcp_cb_work);
+		if (dp->hdcp.ops->off)
+			dp->hdcp.ops->off(dp->hdcp.data);
+
+		dp_display_update_hdcp_status(dp, true);
+	}
 
 	for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) {
 		if (!dp->active_panels[idx])
@@ -823,8 +901,10 @@ static void dp_display_clean(struct dp_display_private *dp)
 {
 	int idx;
 	struct dp_panel *dp_panel;
+	struct dp_link_hdcp_status *status = &dp->link->hdcp_status;
 
-	if (dp_display_is_hdcp_enabled(dp)) {
+	if (dp_display_is_hdcp_enabled(dp) &&
+			status->hdcp_state != HDCP_STATE_INACTIVE) {
 		cancel_delayed_work_sync(&dp->hdcp_cb_work);
 		if (dp->hdcp.ops->off)
 			dp->hdcp.ops->off(dp->hdcp.data);
@@ -1583,7 +1663,8 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
 {
 	struct dp_display_private *dp;
 	struct dp_panel *dp_panel = panel;
-	int rc = 0;
+	struct dp_link_hdcp_status *status;
+	int i, rc = 0;
 
 	if (!dp_display || !panel) {
 		pr_err("invalid input\n");
@@ -1594,19 +1675,35 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
 
 	mutex_lock(&dp->session_lock);
 
+	status = &dp->link->hdcp_status;
+
 	if (!dp->power_on) {
 		pr_debug("stream already powered off, return\n");
 		goto end;
 	}
 
-	if (dp_display_is_hdcp_enabled(dp)) {
-		cancel_delayed_work_sync(&dp->hdcp_cb_work);
+	if (dp_display_is_hdcp_enabled(dp) &&
+			status->hdcp_state != HDCP_STATE_INACTIVE) {
+		flush_delayed_work(&dp->hdcp_cb_work);
+		if (dp->mst.mst_active) {
+			dp_display_hdcp_deregister_stream(dp,
+				dp_panel->stream_id);
+			for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) {
+				if (i != dp_panel->stream_id &&
+						dp->active_panels[i]) {
+					pr_debug("Streams are still active. Skip disabling HDCP\n");
+					goto stream;
+				}
+			}
+		}
+
 		if (dp->hdcp.ops->off)
 			dp->hdcp.ops->off(dp->hdcp.data);
 
 		dp_display_update_hdcp_status(dp, true);
 	}
 
+stream:
 	if (dp_panel->audio_supported)
 		dp_panel->audio->off(dp_panel->audio);
 
@@ -2276,6 +2373,77 @@ static int dp_display_update_pps(struct dp_display *dp_display,
 	return 0;
 }
 
+static int dp_display_mst_connector_update_link_info(
+			struct dp_display *dp_display,
+			struct drm_connector *connector)
+{
+	int rc = 0;
+	struct sde_connector *sde_conn;
+	struct dp_panel *dp_panel;
+	struct dp_display_private *dp;
+
+	if (!dp_display || !connector) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	dp = container_of(dp_display, struct dp_display_private, dp_display);
+
+	if (!dp->mst.drm_registered) {
+		pr_debug("drm mst not registered\n");
+		return -EPERM;
+	}
+
+	sde_conn = to_sde_connector(connector);
+	if (!sde_conn->drv_panel) {
+		pr_err("invalid panel for connector:%d\n", connector->base.id);
+		return -EINVAL;
+	}
+
+	dp_panel = sde_conn->drv_panel;
+
+	memcpy(dp_panel->dpcd, dp->panel->dpcd,
+			DP_RECEIVER_CAP_SIZE + 1);
+	memcpy(dp_panel->dsc_dpcd, dp->panel->dsc_dpcd,
+			DP_RECEIVER_DSC_CAP_SIZE + 1);
+	memcpy(&dp_panel->link_info, &dp->panel->link_info,
+			sizeof(dp_panel->link_info));
+
+	DP_MST_DEBUG("dp mst connector:%d link info updated\n");
+
+	return rc;
+}
+
+static int dp_display_mst_get_fixed_topology_port(
+			struct dp_display *dp_display,
+			u32 strm_id, u32 *port_num)
+{
+	struct dp_display_private *dp;
+	u32 port;
+
+	if (!dp_display) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	if (strm_id >= DP_STREAM_MAX) {
+		pr_err("invalid stream id:%d\n", strm_id);
+		return -EINVAL;
+	}
+
+	dp = container_of(dp_display, struct dp_display_private, dp_display);
+
+	port = dp->parser->mst_fixed_port[strm_id];
+
+	if (!port || port > 255)
+		return -ENOENT;
+
+	if (port_num)
+		*port_num = port;
+
+	return 0;
+}
+
 static int dp_display_get_mst_caps(struct dp_display *dp_display,
 			struct dp_mst_caps *mst_caps)
 {
@@ -2359,12 +2527,16 @@ static int dp_display_probe(struct platform_device *pdev)
 					dp_display_mst_connector_uninstall;
 	g_dp_display->mst_connector_update_edid =
 					dp_display_mst_connector_update_edid;
+	g_dp_display->mst_connector_update_link_info =
+				dp_display_mst_connector_update_link_info;
 	g_dp_display->get_mst_caps = dp_display_get_mst_caps;
 	g_dp_display->set_stream_info = dp_display_set_stream_info;
 	g_dp_display->update_pps = dp_display_update_pps;
 	g_dp_display->convert_to_dp_mode = dp_display_convert_to_dp_mode;
 	g_dp_display->mst_get_connector_info =
 					dp_display_mst_get_connector_info;
+	g_dp_display->mst_get_fixed_topology_port =
+					dp_display_mst_get_fixed_topology_port;
 
 	rc = component_add(&pdev->dev, &dp_display_comp_ops);
 	if (rc) {
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index 85bf4f5..27f0e0b 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -108,9 +108,13 @@ struct dp_display {
 	int (*mst_connector_update_edid)(struct dp_display *dp_display,
 			struct drm_connector *connector,
 			struct edid *edid);
+	int (*mst_connector_update_link_info)(struct dp_display *dp_display,
+			struct drm_connector *connector);
 	int (*mst_get_connector_info)(struct dp_display *dp_display,
 			struct drm_connector *connector,
 			struct dp_mst_connector *mst_conn);
+	int (*mst_get_fixed_topology_port)(struct dp_display *dp_display,
+			u32 strm_id, u32 *port_num);
 	int (*get_mst_caps)(struct dp_display *dp_display,
 			struct dp_mst_caps *mst_caps);
 	int (*set_stream_info)(struct dp_display *dp_display, void *panel,
diff --git a/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c b/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c
index 51818a3..9fdd355 100644
--- a/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c
+++ b/drivers/gpu/drm/msm/dp/dp_hdcp2p2.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
@@ -76,6 +76,25 @@ struct dp_hdcp2p2_interrupts {
 	struct dp_hdcp2p2_int_set *int_set;
 };
 
+static inline int dp_hdcp2p2_valid_handle(struct dp_hdcp2p2_ctrl *ctrl)
+{
+	if (!ctrl) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	if (!ctrl->lib_ctx) {
+		pr_err("HDCP library needs to be acquired\n");
+		return -EINVAL;
+	}
+
+	if (!ctrl->lib) {
+		pr_err("invalid lib ops data\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static inline bool dp_hdcp2p2_is_valid_state(struct dp_hdcp2p2_ctrl *ctrl)
 {
 	if (ctrl->wakeup_cmd == HDCP_TRANSPORT_CMD_AUTHENTICATE)
@@ -255,20 +274,57 @@ static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl)
 	atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE);
 }
 
+static int dp_hdcp2p2_register(void *input, bool mst_enabled)
+{
+	int rc;
+	enum sde_hdcp_2x_device_type device_type;
+	struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
+
+	rc = dp_hdcp2p2_valid_handle(ctrl);
+	if (rc)
+		return rc;
+
+	if (mst_enabled)
+		device_type = HDCP_TXMTR_DP_MST;
+	else
+		device_type = HDCP_TXMTR_DP;
+
+	return sde_hdcp_2x_enable(ctrl->lib_ctx, device_type);
+}
+
+static int dp_hdcp2p2_on(void *input)
+{
+	int rc = 0;
+	struct dp_hdcp2p2_ctrl *ctrl = input;
+	struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID};
+
+	rc = dp_hdcp2p2_valid_handle(ctrl);
+	if (rc)
+		return rc;
+
+	cdata.cmd = HDCP_2X_CMD_START;
+	cdata.context = ctrl->lib_ctx;
+	rc = ctrl->lib->wakeup(&cdata);
+	if (rc)
+		pr_err("Unable to start the HDCP 2.2 library. Error - %d", rc);
+
+	return rc;
+}
+
 static void dp_hdcp2p2_off(void *input)
 {
+	int rc;
 	struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
-	struct hdcp_transport_wakeup_data cdata = {
-					HDCP_TRANSPORT_CMD_AUTHENTICATE};
+	struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID};
 
-	if (!ctrl) {
-		pr_err("invalid input\n");
+	rc = dp_hdcp2p2_valid_handle(ctrl);
+	if (rc)
 		return;
-	}
 
-	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
-		pr_err("hdcp is off\n");
-		return;
+	if (atomic_read(&ctrl->auth_state) != HDCP_STATE_AUTH_FAIL) {
+		cdata.cmd = HDCP_2X_CMD_STOP;
+		cdata.context = ctrl->lib_ctx;
+		dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
 	}
 
 	dp_hdcp2p2_set_interrupts(ctrl, false);
@@ -277,16 +333,18 @@ static void dp_hdcp2p2_off(void *input)
 
 	kthread_flush_worker(&ctrl->worker);
 
-	cdata.context = input;
-	dp_hdcp2p2_wakeup(&cdata);
+	sde_hdcp_2x_disable(ctrl->lib_ctx);
 }
 
 static int dp_hdcp2p2_authenticate(void *input)
 {
+	int rc;
 	struct dp_hdcp2p2_ctrl *ctrl = input;
 	struct hdcp_transport_wakeup_data cdata = {
 					HDCP_TRANSPORT_CMD_AUTHENTICATE};
-	int rc = 0;
+	rc = dp_hdcp2p2_valid_handle(ctrl);
+	if (rc)
+		return rc;
 
 	kthread_flush_worker(&ctrl->worker);
 
@@ -407,44 +465,34 @@ static int dp_hdcp2p2_aux_write_message(struct dp_hdcp2p2_ctrl *ctrl,
 
 static bool dp_hdcp2p2_feature_supported(void *input)
 {
+	int rc;
 	struct dp_hdcp2p2_ctrl *ctrl = input;
 	struct sde_hdcp_2x_ops *lib = NULL;
 	bool supported = false;
 
-	if (!ctrl) {
-		pr_err("invalid input\n");
-		goto end;
-	}
+	rc = dp_hdcp2p2_valid_handle(ctrl);
+	if (rc)
+		return supported;
 
 	lib = ctrl->lib;
-	if (!lib) {
-		pr_err("invalid lib ops data\n");
-		goto end;
-	}
-
 	if (lib->feature_supported)
 		supported = lib->feature_supported(
 			ctrl->lib_ctx);
-end:
+
 	return supported;
 }
 
 static void dp_hdcp2p2_force_encryption(void *data, bool enable)
 {
+	int rc;
 	struct dp_hdcp2p2_ctrl *ctrl = data;
 	struct sde_hdcp_2x_ops *lib = NULL;
 
-	if (!ctrl) {
-		pr_err("invalid input\n");
+	rc = dp_hdcp2p2_valid_handle(ctrl);
+	if (rc)
 		return;
-	}
 
 	lib = ctrl->lib;
-	if (!lib) {
-		pr_err("invalid lib ops data\n");
-		return;
-	}
-
 	if (lib->force_encryption)
 		lib->force_encryption(ctrl->lib_ctx, enable);
 }
@@ -594,18 +642,16 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work)
 
 static void dp_hdcp2p2_auth_work(struct kthread_work *work)
 {
-	struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID};
 	struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
 		struct dp_hdcp2p2_ctrl, auth);
 
-	cdata.context = ctrl->lib_ctx;
+	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTHENTICATING) {
+		struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID};
 
-	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTHENTICATING)
-		cdata.cmd = HDCP_2X_CMD_START;
-	else
-		cdata.cmd = HDCP_2X_CMD_STOP;
-
-	dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
+		cdata.context = ctrl->lib_ctx;
+		cdata.cmd = HDCP_2X_CMD_START_AUTH;
+		dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
+	}
 }
 
 static int dp_hdcp2p2_read_rx_status(struct dp_hdcp2p2_ctrl *ctrl,
@@ -651,41 +697,36 @@ static int dp_hdcp2p2_read_rx_status(struct dp_hdcp2p2_ctrl *ctrl,
 
 static int dp_hdcp2p2_cp_irq(void *input)
 {
-	int rc = 0;
+	int rc;
 	struct dp_hdcp2p2_ctrl *ctrl = input;
 
-	if (!ctrl) {
-		pr_err("invalid input\n");
-		return -EINVAL;
-	}
+	rc = dp_hdcp2p2_valid_handle(ctrl);
+	if (rc)
+		return rc;
 
 	if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL ||
 		atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
 		pr_err("invalid hdcp state\n");
-		rc = -EINVAL;
-		goto error;
+		return -EINVAL;
 	}
 
 	ctrl->sink_rx_status = 0;
 	rc = dp_hdcp2p2_read_rx_status(ctrl, &ctrl->sink_rx_status);
 	if (rc) {
 		pr_err("failed to read rx status\n");
-		goto error;
+		return rc;
 	}
 
 	pr_debug("sink_rx_status=0x%x\n", ctrl->sink_rx_status);
 
 	if (!ctrl->sink_rx_status) {
 		pr_debug("not a hdcp 2.2 irq\n");
-		rc = -EINVAL;
-		goto error;
+		return -EINVAL;
 	}
 
 	kthread_queue_work(&ctrl->worker, &ctrl->link);
 
 	return 0;
-error:
-	return rc;
 }
 
 static int dp_hdcp2p2_isr(void *input)
@@ -753,6 +794,51 @@ static bool dp_hdcp2p2_supported(void *input)
 	return false;
 }
 
+static int dp_hdcp2p2_change_streams(struct dp_hdcp2p2_ctrl *ctrl,
+		struct sde_hdcp_2x_wakeup_data *cdata)
+{
+	if (!ctrl || cdata->num_streams == 0 || !cdata->streams) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	if (!ctrl->lib_ctx) {
+		pr_err("HDCP library needs to be acquired\n");
+		return -EINVAL;
+	}
+
+	if (!ctrl->lib) {
+		pr_err("invalid lib ops data\n");
+		return -EINVAL;
+	}
+
+	cdata->context = ctrl->lib_ctx;
+	return ctrl->lib->wakeup(cdata);
+}
+
+
+static int dp_hdcp2p2_register_streams(void *input, u8 num_streams,
+			struct stream_info *streams)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = input;
+	struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_OPEN_STREAMS};
+
+	cdata.streams = streams;
+	cdata.num_streams = num_streams;
+	return dp_hdcp2p2_change_streams(ctrl, &cdata);
+}
+
+static int dp_hdcp2p2_deregister_streams(void *input, u8 num_streams,
+			struct stream_info *streams)
+{
+	struct dp_hdcp2p2_ctrl *ctrl = input;
+	struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_CLOSE_STREAMS};
+
+	cdata.streams = streams;
+	cdata.num_streams = num_streams;
+	return dp_hdcp2p2_change_streams(ctrl, &cdata);
+}
+
 void sde_dp_hdcp2p2_deinit(void *input)
 {
 	struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
@@ -763,9 +849,13 @@ void sde_dp_hdcp2p2_deinit(void *input)
 		return;
 	}
 
-	cdata.cmd = HDCP_2X_CMD_STOP;
-	cdata.context = ctrl->lib_ctx;
-	dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
+	if (atomic_read(&ctrl->auth_state) != HDCP_STATE_AUTH_FAIL) {
+		cdata.cmd = HDCP_2X_CMD_STOP;
+		cdata.context = ctrl->lib_ctx;
+		dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
+	}
+
+	sde_hdcp_2x_deregister(ctrl->lib_ctx);
 
 	kthread_stop(ctrl->thread);
 
@@ -786,8 +876,12 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data)
 		.feature_supported = dp_hdcp2p2_feature_supported,
 		.force_encryption = dp_hdcp2p2_force_encryption,
 		.sink_support = dp_hdcp2p2_supported,
+		.set_mode = dp_hdcp2p2_register,
+		.on = dp_hdcp2p2_on,
 		.off = dp_hdcp2p2_off,
 		.cp_irq = dp_hdcp2p2_cp_irq,
+		.register_streams = dp_hdcp2p2_register_streams,
+		.deregister_streams = dp_hdcp2p2_deregister_streams,
 	};
 
 	static struct hdcp_transport_ops client_ops = {
@@ -840,7 +934,6 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data)
 	register_data.hdcp_data = &ctrl->lib_ctx;
 	register_data.client_ops = &client_ops;
 	register_data.ops = &hdcp2x_ops;
-	register_data.device_type = HDCP_TXMTR_DP;
 	register_data.client_data = ctrl;
 
 	rc = sde_hdcp_2x_register(&register_data);
diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c
index 534190a..863790b 100644
--- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c
@@ -32,7 +32,6 @@
 #define DP_MST_DEBUG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__)
 #define DP_MST_INFO_LOG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__)
 
-#define MAX_DP_MST_STREAMS		2
 #define MAX_DP_MST_DRM_ENCODERS		2
 #define MAX_DP_MST_DRM_BRIDGES		2
 #define HPD_STRING_SIZE			30
@@ -111,6 +110,10 @@ struct dp_mst_bridge {
 	int pbn;
 	int num_slots;
 	int start_slot;
+
+	u32 fixed_port_num;
+	bool fixed_port_added;
+	struct drm_connector *fixed_connector;
 };
 
 struct dp_mst_private {
@@ -180,10 +183,13 @@ static void dp_mst_sim_add_port(struct dp_mst_private *mst,
 			mutex_lock(&mstb->mgr->lock);
 			list_del(&port->next);
 			mutex_unlock(&mstb->mgr->lock);
-			return;
+			goto put_port;
 		}
 		(*mstb->mgr->cbs->register_connector)(port->connector);
 	}
+
+put_port:
+	kref_put(&port->kref, NULL);
 }
 
 static void dp_mst_sim_link_probe_work(struct work_struct *work)
@@ -908,6 +914,10 @@ static void dp_mst_bridge_mode_set(struct drm_bridge *drm_bridge,
 
 /* DP MST Bridge APIs */
 
+static struct drm_connector *
+dp_mst_drm_fixed_connector_init(struct dp_display *dp_display,
+				struct drm_encoder *encoder);
+
 static const struct drm_bridge_funcs dp_mst_bridge_ops = {
 	.attach       = dp_mst_bridge_attach,
 	.mode_fixup   = dp_mst_bridge_mode_fixup,
@@ -975,6 +985,23 @@ int dp_mst_drm_bridge_init(void *data, struct drm_encoder *encoder)
 
 	DP_MST_DEBUG("mst drm bridge init. bridge id:%d\n", i);
 
+	/*
+	 * If fixed topology port is defined, connector will be created
+	 * immediately.
+	 */
+	rc = display->mst_get_fixed_topology_port(display, bridge->id,
+			&bridge->fixed_port_num);
+	if (!rc) {
+		bridge->fixed_connector =
+			dp_mst_drm_fixed_connector_init(display,
+				bridge->encoder);
+		if (bridge->fixed_connector == NULL) {
+			pr_err("failed to create fixed connector\n");
+			rc = -ENOMEM;
+			goto end;
+		}
+	}
+
 	return 0;
 
 end:
@@ -1167,7 +1194,8 @@ dp_mst_atomic_best_encoder(struct drm_connector *connector,
 	}
 
 	for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) {
-		if (!mst->mst_bridge[i].encoder_active_sts) {
+		if (!mst->mst_bridge[i].encoder_active_sts &&
+			!mst->mst_bridge[i].fixed_connector) {
 			mst->mst_bridge[i].encoder_active_sts = true;
 			mst->mst_bridge[i].connector = connector;
 			mst->mst_bridge[i].dp_panel = conn->drv_panel;
@@ -1374,6 +1402,7 @@ dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr,
 
 	if (!connector) {
 		pr_err("mst sde_connector_init failed\n");
+		drm_modeset_unlock_all(dev);
 		return connector;
 	}
 
@@ -1381,6 +1410,7 @@ dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr,
 	if (rc) {
 		pr_err("mst connector install failed\n");
 		sde_connector_destroy(connector);
+		drm_modeset_unlock_all(dev);
 		return NULL;
 	}
 
@@ -1430,6 +1460,291 @@ static void dp_mst_destroy_connector(struct drm_dp_mst_topology_mgr *mgr,
 	drm_connector_unreference(connector);
 }
 
+static enum drm_connector_status
+dp_mst_fixed_connector_detect(struct drm_connector *connector, bool force,
+			void *display)
+{
+	struct dp_display *dp_display = display;
+	struct dp_mst_private *mst = dp_display->dp_mst_prv_info;
+	int i;
+
+	for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) {
+		if (mst->mst_bridge[i].fixed_connector != connector)
+			continue;
+
+		if (!mst->mst_bridge[i].fixed_port_added)
+			break;
+
+		return dp_mst_connector_detect(connector, force, display);
+	}
+
+	return connector_status_disconnected;
+}
+
+static struct drm_encoder *
+dp_mst_fixed_atomic_best_encoder(struct drm_connector *connector,
+			void *display, struct drm_connector_state *state)
+{
+	struct dp_display *dp_display = display;
+	struct dp_mst_private *mst = dp_display->dp_mst_prv_info;
+	struct sde_connector *conn = to_sde_connector(connector);
+	struct drm_encoder *enc = NULL;
+	u32 i;
+
+	for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) {
+		if (mst->mst_bridge[i].connector == connector) {
+			enc = mst->mst_bridge[i].encoder;
+			goto end;
+		}
+	}
+
+	for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) {
+		if (mst->mst_bridge[i].fixed_connector == connector) {
+			mst->mst_bridge[i].encoder_active_sts = true;
+			mst->mst_bridge[i].connector = connector;
+			mst->mst_bridge[i].dp_panel = conn->drv_panel;
+			enc = mst->mst_bridge[i].encoder;
+			break;
+		}
+	}
+
+end:
+	if (enc)
+		DP_MST_DEBUG("mst connector:%d atomic best encoder:%d\n",
+			connector->base.id, i);
+	else
+		DP_MST_DEBUG("mst connector:%d atomic best encoder failed\n",
+				connector->base.id);
+
+	return enc;
+}
+
+static u32 dp_mst_find_fixed_port_num(struct drm_dp_mst_branch *mstb,
+		struct drm_dp_mst_port *target)
+{
+	struct drm_dp_mst_port *port;
+	u32 port_num = 0;
+
+	/*
+	 * search through reversed order of adding sequence, so the port number
+	 * will be unique once topology is fixed
+	 */
+	list_for_each_entry_reverse(port, &mstb->ports, next) {
+		if (port->mstb)
+			port_num += dp_mst_find_fixed_port_num(port->mstb,
+						target);
+		else if (!port->input) {
+			++port_num;
+			if (port == target)
+				break;
+		}
+	}
+
+	return port_num;
+}
+
+static struct drm_connector *
+dp_mst_find_fixed_connector(struct dp_mst_private *dp_mst,
+		struct drm_dp_mst_port *port)
+{
+	struct dp_display *dp_display = dp_mst->dp_display;
+	struct drm_connector *connector = NULL;
+	struct sde_connector *c_conn;
+	u32 port_num;
+	int i;
+
+	mutex_lock(&port->mgr->lock);
+	port_num = dp_mst_find_fixed_port_num(port->mgr->mst_primary, port);
+	mutex_unlock(&port->mgr->lock);
+
+	if (!port_num)
+		return NULL;
+
+	for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) {
+		if (dp_mst->mst_bridge[i].fixed_port_num == port_num) {
+			connector = dp_mst->mst_bridge[i].fixed_connector;
+			c_conn = to_sde_connector(connector);
+			c_conn->mst_port = port;
+			dp_display->mst_connector_update_link_info(dp_display,
+					connector);
+			dp_mst->mst_bridge[i].fixed_port_added = true;
+			DP_MST_DEBUG("found fixed connector %d\n",
+					DRMID(connector));
+			break;
+		}
+	}
+
+	return connector;
+}
+
+static int
+dp_mst_find_first_available_encoder_idx(struct dp_mst_private *dp_mst)
+{
+	int enc_idx = MAX_DP_MST_DRM_BRIDGES;
+	int i;
+
+	for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) {
+		if (!dp_mst->mst_bridge[i].fixed_connector) {
+			enc_idx = i;
+			break;
+		}
+	}
+
+	return enc_idx;
+}
+
+static struct drm_connector *
+dp_mst_add_fixed_connector(struct drm_dp_mst_topology_mgr *mgr,
+		struct drm_dp_mst_port *port, const char *pathprop)
+{
+	struct dp_mst_private *dp_mst;
+	struct drm_device *dev;
+	struct dp_display *dp_display;
+	struct drm_connector *connector;
+	int i, enc_idx;
+
+	DP_MST_DEBUG("enter\n");
+
+	dp_mst = container_of(mgr, struct dp_mst_private, mst_mgr);
+
+	dp_display = dp_mst->dp_display;
+	dev = dp_display->drm_dev;
+
+	if (port->input || port->mstb)
+		enc_idx = MAX_DP_MST_DRM_BRIDGES;
+	else {
+		/* if port is already reserved, return immediately */
+		connector = dp_mst_find_fixed_connector(dp_mst, port);
+		if (connector != NULL)
+			return connector;
+
+		/* first available bridge index for non-reserved port */
+		enc_idx = dp_mst_find_first_available_encoder_idx(dp_mst);
+	}
+
+	/* add normal connector */
+	connector = dp_mst_add_connector(mgr, port, pathprop);
+	if (!connector) {
+		DP_MST_DEBUG("failed to add connector\n");
+		return NULL;
+	}
+
+	drm_modeset_lock_all(dev);
+
+	/* clear encoder list */
+	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
+		connector->encoder_ids[i] = 0;
+
+	/* re-attach encoders from first available encoders */
+	for (i = enc_idx; i < MAX_DP_MST_DRM_BRIDGES; i++)
+		drm_mode_connector_attach_encoder(connector,
+				dp_mst->mst_bridge[i].encoder);
+
+	drm_modeset_unlock_all(dev);
+
+	DP_MST_DEBUG("add mst connector:%d\n", connector->base.id);
+
+	return connector;
+}
+
+static void dp_mst_register_fixed_connector(struct drm_connector *connector)
+{
+	struct sde_connector *c_conn = to_sde_connector(connector);
+	struct dp_display *dp_display = c_conn->display;
+	struct dp_mst_private *dp_mst = dp_display->dp_mst_prv_info;
+	int i;
+
+	DP_MST_DEBUG("enter\n");
+
+	/* skip connector registered for fixed topology ports */
+	for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) {
+		if (dp_mst->mst_bridge[i].fixed_connector == connector) {
+			DP_MST_DEBUG("found fixed connector %d\n",
+					DRMID(connector));
+			return;
+		}
+	}
+
+	dp_mst_register_connector(connector);
+}
+
+static void dp_mst_destroy_fixed_connector(struct drm_dp_mst_topology_mgr *mgr,
+					   struct drm_connector *connector)
+{
+	struct dp_mst_private *dp_mst;
+	int i;
+
+	DP_MST_DEBUG("enter\n");
+
+	dp_mst = container_of(mgr, struct dp_mst_private, mst_mgr);
+
+	/* skip connector destroy for fixed topology ports */
+	for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) {
+		if (dp_mst->mst_bridge[i].fixed_connector == connector) {
+			dp_mst->mst_bridge[i].fixed_port_added = false;
+			DP_MST_DEBUG("destroy fixed connector %d\n",
+					DRMID(connector));
+			return;
+		}
+	}
+
+	dp_mst_destroy_connector(mgr, connector);
+}
+
+static struct drm_connector *
+dp_mst_drm_fixed_connector_init(struct dp_display *dp_display,
+			struct drm_encoder *encoder)
+{
+	static const struct sde_connector_ops dp_mst_connector_ops = {
+		.post_init  = NULL,
+		.detect     = dp_mst_fixed_connector_detect,
+		.get_modes  = dp_mst_connector_get_modes,
+		.mode_valid = dp_mst_connector_mode_valid,
+		.get_info   = dp_mst_connector_get_info,
+		.get_mode_info  = dp_mst_connector_get_mode_info,
+		.atomic_best_encoder = dp_mst_fixed_atomic_best_encoder,
+		.atomic_check = dp_mst_connector_atomic_check,
+		.config_hdr = dp_mst_connector_config_hdr,
+		.pre_destroy = dp_mst_connector_pre_destroy,
+	};
+	struct drm_device *dev;
+	struct drm_connector *connector;
+	int rc;
+
+	DP_MST_DEBUG("enter\n");
+
+	dev = dp_display->drm_dev;
+
+	connector = sde_connector_init(dev,
+				encoder,
+				NULL,
+				dp_display,
+				&dp_mst_connector_ops,
+				DRM_CONNECTOR_POLL_HPD,
+				DRM_MODE_CONNECTOR_DisplayPort);
+
+	if (!connector) {
+		pr_err("mst sde_connector_init failed\n");
+		return NULL;
+	}
+
+	rc = dp_display->mst_connector_install(dp_display, connector);
+	if (rc) {
+		pr_err("mst connector install failed\n");
+		sde_connector_destroy(connector);
+		return NULL;
+	}
+
+	drm_object_attach_property(&connector->base,
+			dev->mode_config.path_property, 0);
+	drm_object_attach_property(&connector->base,
+			dev->mode_config.tile_property, 0);
+
+	DP_MST_DEBUG("add mst fixed connector:%d\n", connector->base.id);
+
+	return connector;
+}
+
 static void dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
 {
 	struct dp_mst_private *mst = container_of(mgr, struct dp_mst_private,
@@ -1575,6 +1890,13 @@ static const struct drm_dp_mst_topology_cbs dp_mst_drm_cbs = {
 	.hotplug = dp_mst_hotplug,
 };
 
+static const struct drm_dp_mst_topology_cbs dp_mst_fixed_drm_cbs = {
+	.add_connector = dp_mst_add_fixed_connector,
+	.register_connector = dp_mst_register_fixed_connector,
+	.destroy_connector = dp_mst_destroy_fixed_connector,
+	.hotplug = dp_mst_hotplug,
+};
+
 static void dp_mst_sim_init(struct dp_mst_private *mst)
 {
 	INIT_WORK(&mst->simulator.probe_work, dp_mst_sim_link_probe_work);
@@ -1639,6 +1961,10 @@ int dp_mst_init(struct dp_display *dp_display)
 	}
 	memset(&dp_mst_enc_cache, 0, sizeof(dp_mst_enc_cache));
 
+	/* choose fixed callback function if fixed topology is found */
+	if (!dp_display->mst_get_fixed_topology_port(dp_display, 0, NULL))
+		dp_mst.mst_mgr.cbs = &dp_mst_fixed_drm_cbs;
+
 	DP_MST_INFO_LOG("dp drm mst topology manager init completed\n");
 
 	return ret;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 8ebdc63..aca94e1 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -1512,12 +1512,14 @@ static int dp_panel_dsc_prepare_basic_params(
 	struct dp_dsc_slices_per_line *rec;
 	int slice_width;
 	u32 ppr = dp_mode->timing.pixel_clk_khz/1000;
+	int max_slice_width;
 
 	comp_info->dsc_info.slice_per_pkt = 0;
 	for (i = 0; i < ARRAY_SIZE(slice_per_line_tbl); i++) {
 		rec = &slice_per_line_tbl[i];
 		if ((ppr > rec->min_ppr) && (ppr <= rec->max_ppr)) {
 			comp_info->dsc_info.slice_per_pkt = rec->num_slices;
+			i++;
 			break;
 		}
 	}
@@ -1525,9 +1527,21 @@ static int dp_panel_dsc_prepare_basic_params(
 	if (comp_info->dsc_info.slice_per_pkt == 0)
 		return -EINVAL;
 
+	max_slice_width = dp_panel->dsc_dpcd[12] * 320;
 	slice_width = (dp_mode->timing.h_active /
 				comp_info->dsc_info.slice_per_pkt);
 
+	while (slice_width >= max_slice_width) {
+		if (i == ARRAY_SIZE(slice_per_line_tbl))
+			return -EINVAL;
+
+		rec = &slice_per_line_tbl[i];
+		comp_info->dsc_info.slice_per_pkt = rec->num_slices;
+		slice_width = (dp_mode->timing.h_active /
+				comp_info->dsc_info.slice_per_pkt);
+		i++;
+	}
+
 	comp_info->dsc_info.block_pred_enable =
 			dp_panel->sink_dsc_caps.block_pred_en;
 	comp_info->dsc_info.vbr_enable = 0;
@@ -2577,47 +2591,22 @@ static void dp_panel_config_misc(struct dp_panel *dp_panel)
 	catalog->config_misc(catalog);
 }
 
-static bool dp_panel_use_fixed_nvid(struct dp_panel *dp_panel)
-{
-	u8 *dpcd = dp_panel->dpcd;
-	struct sde_connector *c_conn = to_sde_connector(dp_panel->connector);
-
-	/* use fixe mvid and nvid for MST streams */
-	if (c_conn->mst_port)
-		return true;
-
-	/*
-	 * For better interop experience, used a fixed NVID=0x8000
-	 * whenever connected to a VGA dongle downstream.
-	 */
-	if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT) {
-		u8 type = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
-			DP_DWN_STRM_PORT_TYPE_MASK;
-		if (type == DP_DWN_STRM_PORT_TYPE_ANALOG)
-			return true;
-	}
-
-	return false;
-}
-
 static void dp_panel_config_msa(struct dp_panel *dp_panel)
 {
 	struct dp_panel_private *panel;
 	struct dp_catalog_panel *catalog;
 	u32 rate;
 	u32 stream_rate_khz;
-	bool fixed_nvid;
 
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
 	catalog = panel->catalog;
 
 	catalog->widebus_en = dp_panel->widebus_en;
 
-	fixed_nvid = dp_panel_use_fixed_nvid(dp_panel);
 	rate = drm_dp_bw_code_to_link_rate(panel->link->link_params.bw_code);
 	stream_rate_khz = dp_panel->pinfo.pixel_clk_khz;
 
-	catalog->config_msa(catalog, rate, stream_rate_khz, fixed_nvid);
+	catalog->config_msa(catalog, rate, stream_rate_khz);
 }
 
 static int dp_panel_hw_cfg(struct dp_panel *dp_panel, bool enable)
@@ -2832,6 +2821,8 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in)
 	if (in->base_panel) {
 		memcpy(dp_panel->dpcd, in->base_panel->dpcd,
 				DP_RECEIVER_CAP_SIZE + 1);
+		memcpy(dp_panel->dsc_dpcd, in->base_panel->dsc_dpcd,
+				DP_RECEIVER_DSC_CAP_SIZE + 1);
 		memcpy(&dp_panel->link_info, &in->base_panel->link_info,
 				sizeof(dp_panel->link_info));
 		dp_panel->mst_state = in->base_panel->mst_state;
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c
index 225d193..df1b05f 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.c
+++ b/drivers/gpu/drm/msm/dp/dp_parser.c
@@ -712,6 +712,7 @@ static int dp_parser_catalog(struct dp_parser *parser)
 static int dp_parser_mst(struct dp_parser *parser)
 {
 	struct device *dev = &parser->pdev->dev;
+	int i;
 
 	parser->has_mst = of_property_read_bool(dev->of_node,
 			"qcom,mst-enable");
@@ -719,6 +720,12 @@ static int dp_parser_mst(struct dp_parser *parser)
 
 	pr_debug("mst parsing successful. mst:%d\n", parser->has_mst);
 
+	for (i = 0; i < MAX_DP_MST_STREAMS; i++) {
+		of_property_read_u32_index(dev->of_node,
+				"qcom,mst-fixed-topology-ports", i,
+				&parser->mst_fixed_port[i]);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h
index bafc2b9..f190d19 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.h
+++ b/drivers/gpu/drm/msm/dp/dp_parser.h
@@ -21,6 +21,7 @@
 #define AUX_CFG_LEN	10
 #define DP_MAX_PIXEL_CLK_KHZ	675000
 #define DP_MAX_LINK_CLK_KHZ	810000
+#define MAX_DP_MST_STREAMS	2
 
 enum dp_pm_type {
 	DP_CORE_PM,
@@ -204,6 +205,7 @@ static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type)
  * @max_dp_dsc_blks: maximum DSC blks for DP interface
  * @max_dp_dsc_input_width_pixs: Maximum input width for DSC block
  * @has_widebus: widebus (2PPC) feature eanble status
+  *@mst_fixed_port: mst port_num reserved for fixed topology
  * @parse: function to be called by client to parse device tree.
  * @get_io: function to be called by client to get io data.
  * @get_io_buf: function to be called by client to get io buffers.
@@ -233,6 +235,7 @@ struct dp_parser {
 	u32 max_dp_dsc_blks;
 	u32 max_dp_dsc_input_width_pixs;
 	bool lphw_hpd;
+	u32 mst_fixed_port[MAX_DP_MST_STREAMS];
 
 	int (*parse)(struct dp_parser *parser);
 	struct dp_io_data *(*get_io)(struct dp_parser *parser, char *name);
diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
index de68002..5354cbe 100644
--- a/drivers/gpu/drm/msm/dp/dp_reg.h
+++ b/drivers/gpu/drm/msm/dp/dp_reg.h
@@ -266,6 +266,17 @@
 #define MMSS_DP_VSCEXT_8			(0x000002F0)
 #define MMSS_DP_VSCEXT_9			(0x000002F4)
 
+#define MMSS_DP1_VSCEXT_0			(0x00000468)
+#define MMSS_DP1_VSCEXT_1			(0x0000046c)
+#define MMSS_DP1_VSCEXT_2			(0x00000470)
+#define MMSS_DP1_VSCEXT_3			(0x00000474)
+#define MMSS_DP1_VSCEXT_4			(0x00000478)
+#define MMSS_DP1_VSCEXT_5			(0x0000047c)
+#define MMSS_DP1_VSCEXT_6			(0x00000480)
+#define MMSS_DP1_VSCEXT_7			(0x00000484)
+#define MMSS_DP1_VSCEXT_8			(0x00000488)
+#define MMSS_DP1_VSCEXT_9			(0x0000048c)
+
 #define MMSS_DP_BIST_ENABLE			(0x00000000)
 #define MMSS_DP_TIMING_ENGINE_EN		(0x00000010)
 #define MMSS_DP_INTF_CONFIG			(0x00000014)
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 2faccad..0094d4c 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
@@ -1278,23 +1278,15 @@ int dsi_display_link_clk_force_update(void *client)
 		goto error;
 	}
 
-	rc = dsi_display_link_clk_disable(l_clks,
-			(DSI_LINK_LP_CLK | DSI_LINK_HS_CLK),
-			mngr->dsi_ctrl_count, mngr->master_ndx);
-	if (rc) {
-		pr_err("%s, failed to stop link clk, rc = %d\n",
-			__func__, rc);
+	rc = dsi_clk_update_link_clk_state(mngr, l_clks, (DSI_LINK_LP_CLK |
+				DSI_LINK_HS_CLK), DSI_CLK_OFF, false);
+	if (rc)
 		goto error;
-	}
 
-	rc = dsi_display_link_clk_enable(l_clks,
-			(DSI_LINK_LP_CLK | DSI_LINK_HS_CLK),
-			mngr->dsi_ctrl_count, mngr->master_ndx);
-	if (rc) {
-		pr_err("%s, failed to start link clk rc= %d\n",
-			__func__, rc);
+	rc = dsi_clk_update_link_clk_state(mngr, l_clks, (DSI_LINK_LP_CLK |
+				DSI_LINK_HS_CLK), DSI_CLK_ON, true);
+	if (rc)
 		goto error;
-	}
 
 error:
 	mutex_unlock(&mngr->clk_mutex);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 871bbae..3757898 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -40,9 +40,6 @@
 #define TO_ON_OFF(x) ((x) ? "ON" : "OFF")
 
 #define CEIL(x, y)              (((x) + ((y)-1)) / (y))
-
-#define TICKS_IN_MICRO_SECOND    1000000
-
 /**
  * enum dsi_ctrl_driver_ops - controller driver ops
  */
@@ -833,7 +830,7 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
 {
 	int rc = 0;
 	u32 num_of_lanes = 0;
-	u32 bpp, refresh_rate = TICKS_IN_MICRO_SECOND;
+	u32 bpp;
 	u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane,
 	    byte_clk_rate;
 	struct dsi_host_common_cfg *host_cfg = &config->common_config;
@@ -858,13 +855,7 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
 	if (config->bit_clk_rate_hz_override == 0) {
 		h_period = DSI_H_TOTAL_DSC(timing);
 		v_period = DSI_V_TOTAL(timing);
-
-		if (config->panel_mode == DSI_OP_CMD_MODE)
-			do_div(refresh_rate, timing->mdp_transfer_time_us);
-		else
-			refresh_rate = timing->refresh_rate;
-
-		bit_rate = h_period * v_period * refresh_rate * bpp;
+		bit_rate = h_period * v_period * timing->refresh_rate * bpp;
 	} else {
 		bit_rate = config->bit_clk_rate_hz_override * num_of_lanes;
 	}
@@ -1505,7 +1496,7 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl,
 	cmd = buff[0];
 	switch (cmd) {
 	case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
-		pr_err("Rx ACK_ERROR\n");
+		pr_err("Rx ACK_ERROR 0x%x\n", cmd);
 		rc = 0;
 		break;
 	case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
@@ -1521,7 +1512,7 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl,
 		rc = dsi_parse_long_read_resp(msg, buff);
 		break;
 	default:
-		pr_warn("Invalid response\n");
+		pr_warn("Invalid response: 0x%x\n", cmd);
 		rc = 0;
 	}
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index bd3e0a8..18013db 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -577,8 +577,11 @@ static bool dsi_display_validate_reg_read(struct dsi_panel *panel)
 	for (j = 0; j < config->groups; ++j) {
 		for (i = 0; i < len; ++i) {
 			if (config->return_buf[i] !=
-				config->status_value[group + i])
+				config->status_value[group + i]) {
+				DRM_ERROR("mismatch: 0x%x\n",
+					  config->return_buf[i]);
 				break;
+			}
 		}
 
 		if (i == len)
@@ -819,8 +822,13 @@ int dsi_display_check_status(struct drm_connector *connector, void *display,
 	if (te_check_override && gpio_is_valid(dsi_display->disp_te_gpio))
 		status_mode = ESD_MODE_PANEL_TE;
 
+	if (status_mode == ESD_MODE_PANEL_TE) {
+		rc = dsi_display_status_check_te(dsi_display);
+		goto exit;
+	}
+
 	dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
-		DSI_ALL_CLKS, DSI_CLK_ON);
+			     DSI_ALL_CLKS, DSI_CLK_ON);
 
 	/* Mask error interrupts before attempting ESD read */
 	mask = BIT(DSI_FIFO_OVERFLOW) | BIT(DSI_FIFO_UNDERFLOW);
@@ -831,25 +839,24 @@ int dsi_display_check_status(struct drm_connector *connector, void *display,
 		rc = dsi_display_status_reg_read(dsi_display);
 	} else if (status_mode == ESD_MODE_SW_BTA) {
 		rc = dsi_display_status_bta_request(dsi_display);
-	} else if (status_mode == ESD_MODE_PANEL_TE) {
-		rc = dsi_display_status_check_te(dsi_display);
 	} else {
-		pr_warn("unsupported check status mode\n");
+		pr_warn("Unsupported ESD check mode: %d\n", status_mode);
 		panel->esd_config.esd_enabled = false;
 	}
 
-	/* Unmask error interrupts */
+	/* Unmask error interrupts if check passed */
 	if (rc > 0) {
 		dsi_display_set_ctrl_esd_check_flag(dsi_display, false);
-		dsi_display_mask_ctrl_error_interrupts(dsi_display, mask,
-							false);
-	} else {
-		/* Handle Panel failures during display disable sequence */
-		atomic_set(&panel->esd_recovery_pending, 1);
+		dsi_display_mask_ctrl_error_interrupts(dsi_display,
+						       mask, false);
 	}
-
 	dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
-		DSI_ALL_CLKS, DSI_CLK_OFF);
+			     DSI_ALL_CLKS, DSI_CLK_OFF);
+
+exit:
+	/* Handle Panel failures during display disable sequence */
+	if (rc <= 0)
+		atomic_set(&panel->esd_recovery_pending, 1);
 
 release_panel_lock:
 	dsi_panel_release_panel_lock(panel);
@@ -4702,7 +4709,7 @@ static ssize_t sysfs_dynamic_dsi_clk_read(struct device *dev,
 static ssize_t sysfs_dynamic_dsi_clk_write(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
-	int rc = count;
+	int rc = 0;
 	int clk_rate;
 	struct dsi_display *display;
 
@@ -4731,6 +4738,8 @@ static ssize_t sysfs_dynamic_dsi_clk_write(struct device *dev,
 	rc = dsi_display_dynamic_clk_configure_cmd(display, clk_rate);
 	if (rc)
 		pr_err("Failed to configure dynamic clk\n");
+	else
+		rc = count;
 
 	mutex_unlock(&dsi_display_clk_mutex);
 	mutex_unlock(&display->display_lock);
@@ -4854,6 +4863,15 @@ static int dsi_display_bind(struct device *dev,
 	if (!display->disp_node)
 		return 0;
 
+	/* defer bind if ext bridge driver is not loaded */
+	for (i = 0; i < display->ext_bridge_cnt; i++) {
+		if (!of_drm_find_bridge(display->ext_bridge[i].node_of)) {
+			pr_err("defer for bridge[%d] %s\n", i,
+				display->ext_bridge[i].node_of->full_name);
+			return -EPROBE_DEFER;
+		}
+	}
+
 	mutex_lock(&display->display_lock);
 
 	rc = dsi_display_validate_split_link(display);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 57ad888..e5233ed 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -680,13 +680,111 @@ void dsi_connector_put_modes(struct drm_connector *connector,
 	dsi_display->modes = NULL;
 }
 
-int dsi_connector_get_modes(struct drm_connector *connector,
-		void *display)
+
+static int dsi_drm_update_edid_name(struct edid *edid, const char *name)
 {
-	u32 count = 0;
+	u8 *dtd = (u8 *)&edid->detailed_timings[3];
+	u8 standard_header[] = {0x00, 0x00, 0x00, 0xFE, 0x00};
+	u32 dtd_size = 18;
+	u32 header_size = sizeof(standard_header);
+
+	if (!name)
+		return -EINVAL;
+
+	/* Fill standard header */
+	memcpy(dtd, standard_header, header_size);
+
+	dtd_size -= header_size;
+	dtd_size = min_t(u32, dtd_size, strlen(name));
+
+	memcpy(dtd + header_size, name, dtd_size);
+
+	return 0;
+}
+
+static void dsi_drm_update_dtd(struct edid *edid,
+		struct dsi_display_mode *modes, u32 modes_count)
+{
+	u32 i;
+	u32 count = min_t(u32, modes_count, 3);
+
+	for (i = 0; i < count; i++) {
+		struct detailed_timing *dtd = &edid->detailed_timings[i];
+		struct dsi_display_mode *mode = &modes[i];
+		struct dsi_mode_info *timing = &mode->timing;
+		struct detailed_pixel_timing *pd = &dtd->data.pixel_data;
+		u32 h_blank = timing->h_front_porch + timing->h_sync_width +
+				timing->h_back_porch;
+		u32 v_blank = timing->v_front_porch + timing->v_sync_width +
+				timing->v_back_porch;
+		u32 h_img = 0, v_img = 0;
+
+		dtd->pixel_clock = mode->pixel_clk_khz / 10;
+
+		pd->hactive_lo = timing->h_active & 0xFF;
+		pd->hblank_lo = h_blank & 0xFF;
+		pd->hactive_hblank_hi = ((h_blank >> 8) & 0xF) |
+				((timing->h_active >> 8) & 0xF) << 4;
+
+		pd->vactive_lo = timing->v_active & 0xFF;
+		pd->vblank_lo = v_blank & 0xFF;
+		pd->vactive_vblank_hi = ((v_blank >> 8) & 0xF) |
+				((timing->v_active >> 8) & 0xF) << 4;
+
+		pd->hsync_offset_lo = timing->h_front_porch & 0xFF;
+		pd->hsync_pulse_width_lo = timing->h_sync_width & 0xFF;
+		pd->vsync_offset_pulse_width_lo =
+			((timing->v_front_porch & 0xF) << 4) |
+			(timing->v_sync_width & 0xF);
+
+		pd->hsync_vsync_offset_pulse_width_hi =
+			(((timing->h_front_porch >> 8) & 0x3) << 6) |
+			(((timing->h_sync_width >> 8) & 0x3) << 4) |
+			(((timing->v_front_porch >> 4) & 0x3) << 2) |
+			(((timing->v_sync_width >> 4) & 0x3) << 0);
+
+		pd->width_mm_lo = h_img & 0xFF;
+		pd->height_mm_lo = v_img & 0xFF;
+		pd->width_height_mm_hi = (((h_img >> 8) & 0xF) << 4) |
+			((v_img >> 8) & 0xF);
+
+		pd->hborder = 0;
+		pd->vborder = 0;
+		pd->misc = 0;
+	}
+}
+
+static void dsi_drm_update_checksum(struct edid *edid)
+{
+	u8 *data = (u8 *)edid;
+	u32 i, sum = 0;
+
+	for (i = 0; i < EDID_LENGTH - 1; i++)
+		sum += data[i];
+
+	edid->checksum = 0x100 - (sum & 0xFF);
+}
+
+int dsi_connector_get_modes(struct drm_connector *connector, void *data)
+{
+	int rc, i;
+	u32 count = 0, edid_size;
 	struct dsi_display_mode *modes = NULL;
 	struct drm_display_mode drm_mode;
-	int rc, i;
+	struct dsi_display *display = data;
+	struct edid edid;
+	const u8 edid_buf[EDID_LENGTH] = {
+		0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x44, 0x6D,
+		0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1B, 0x10, 0x01, 0x03,
+		0x80, 0x50, 0x2D, 0x78, 0x0A, 0x0D, 0xC9, 0xA0, 0x57, 0x47,
+		0x98, 0x27, 0x12, 0x48, 0x4C, 0x00, 0x00, 0x00, 0x01, 0x01,
+		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+		0x01, 0x01, 0x01, 0x01,
+	};
+
+	edid_size = min_t(u32, sizeof(edid), EDID_LENGTH);
+
+	memcpy(&edid, edid_buf, edid_size);
 
 	if (sde_connector_get_panel(connector)) {
 		/*
@@ -729,6 +827,18 @@ int dsi_connector_get_modes(struct drm_connector *connector,
 			m->type |= DRM_MODE_TYPE_PREFERRED;
 		drm_mode_probed_add(connector, m);
 	}
+
+	rc = dsi_drm_update_edid_name(&edid, display->panel->name);
+	if (rc) {
+		count = 0;
+		goto end;
+	}
+
+	dsi_drm_update_dtd(&edid, modes, count);
+	dsi_drm_update_checksum(&edid);
+	rc = drm_mode_connector_update_edid_property(connector, &edid);
+	if (rc)
+		count = 0;
 end:
 	pr_debug("MODE COUNT =%d\n\n", count);
 	return count;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index 4ca2726..86fc19c 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -3470,6 +3470,9 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
 			goto parse_fail;
 		}
 
+		if (panel->panel_mode == DSI_OP_VIDEO_MODE)
+			mode->priv_info->mdp_transfer_time_us = 0;
+
 		rc = dsi_panel_parse_dsc_params(mode, utils);
 		if (rc) {
 			pr_err("failed to parse dsc params, rc=%d\n", rc);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.c b/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.c
index 3ba54cc..970158d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.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
@@ -73,6 +73,14 @@ static int dsi_pwr_parse_supply_node(struct dsi_parser_utils *utils,
 		regs->vregs[i].disable_load = tmp;
 
 		/* Optional values */
+		rc = utils->read_u32(node, "qcom,supply-off-min-voltage", &tmp);
+		if (rc) {
+			pr_debug("off-min-voltage not specified\n");
+			rc = 0;
+		} else {
+			regs->vregs[i].off_min_voltage = tmp;
+		}
+
 		rc = utils->read_u32(node, "qcom,supply-pre-on-sleep", &tmp);
 		if (rc) {
 			pr_debug("pre-on-sleep not specified\n");
@@ -167,6 +175,11 @@ static int dsi_pwr_enable_vregs(struct dsi_regulator_info *regs, bool enable)
 			if (regs->vregs[i].pre_off_sleep)
 				msleep(regs->vregs[i].pre_off_sleep);
 
+			if (regs->vregs[i].off_min_voltage)
+				(void)regulator_set_voltage(regs->vregs[i].vreg,
+						regs->vregs[i].off_min_voltage,
+						regs->vregs[i].max_voltage);
+
 			(void)regulator_set_load(regs->vregs[i].vreg,
 						regs->vregs[i].disable_load);
 			(void)regulator_disable(regs->vregs[i].vreg);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.h b/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.h
index 35b0601..92b1ecb 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.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
@@ -30,6 +30,7 @@ struct dsi_parser_utils;
  * @max_voltage:     Maximum voltage in uV.
  * @enable_load:     Load, in uA, when enabled.
  * @disable_load:    Load, in uA, when disabled.
+ * @off_min_voltage: Minimum voltage in uV when regulator is disabled.
  * @pre_on_sleep:    Sleep, in ms, before enabling the regulator.
  * @post_on_sleep:   Sleep, in ms, after enabling the regulator.
  * @pre_off_sleep:   Sleep, in ms, before disabling the regulator.
@@ -42,6 +43,7 @@ struct dsi_vreg {
 	u32 max_voltage;
 	u32 enable_load;
 	u32 disable_load;
+	u32 off_min_voltage;
 	u32 pre_on_sleep;
 	u32 post_on_sleep;
 	u32 pre_off_sleep;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index cfeea64..b59acd4 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.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.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -1973,6 +1973,9 @@ static int msm_pdev_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	if (!match)
+		return -ENODEV;
+
 	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 	return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
 }
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 1c28929..e740a9e 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.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.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -65,11 +65,11 @@ struct msm_gem_address_space;
 struct msm_gem_vma;
 
 #define NUM_DOMAINS    4    /* one for KMS, then one per gpu core (?) */
-#define MAX_CRTCS      8
+#define MAX_CRTCS      16
 #define MAX_PLANES     20
-#define MAX_ENCODERS   8
-#define MAX_BRIDGES    8
-#define MAX_CONNECTORS 8
+#define MAX_ENCODERS   16
+#define MAX_BRIDGES    16
+#define MAX_CONNECTORS 16
 
 #define TEARDOWN_DEADLOCK_RETRY_MAX 5
 
@@ -445,6 +445,7 @@ struct msm_display_topology {
  * @wide_bus_en:	wide-bus mode cfg for interface module
  * @mdp_transfer_time_us   Specifies the mdp transfer time for command mode
  *                         panels in microseconds.
+ * @vpadding:        panel stacking height
  */
 struct msm_mode_info {
 	uint32_t frame_rate;
@@ -458,6 +459,7 @@ struct msm_mode_info {
 	struct msm_roi_caps roi_caps;
 	bool wide_bus_en;
 	u32 mdp_transfer_time_us;
+	u32 vpadding;
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index 14c1f44..b89589b 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -113,7 +113,9 @@ static void rd_write(struct msm_rd_state *rd, const void *buf, int sz)
 		char *fptr = &fifo->buf[fifo->head];
 		int n;
 
-		wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0);
+		wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0 || !rd->open);
+		if (!rd->open)
+			return;
 
 		/* Note that smp_load_acquire() is not strictly required
 		 * as CIRC_SPACE_TO_END() does not access the tail more
@@ -238,7 +240,10 @@ static int rd_release(struct inode *inode, struct file *file)
 		return -EINVAL;
 
 	rd = inode->i_private;
+
 	rd->open = false;
+	wake_up_all(&rd->fifo_event);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 218a0b8..190eea48 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -91,6 +91,10 @@ static struct sde_crtc_custom_events custom_events[] = {
 #define MAX_FRAME_COUNT			1000
 #define MILI_TO_MICRO			1000
 
+/* default line padding ratio limitation */
+#define MAX_VPADDING_RATIO_M		63
+#define MAX_VPADDING_RATIO_N		15
+
 static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
 {
 	struct msm_drm_private *priv;
@@ -1058,6 +1062,18 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc,
 						cstate->lm_roi[i].y;
 		}
 
+		/* update dim layer rect for panel stacking crtc */
+		if (cstate->padding_height) {
+			uint32_t padding_y, padding_start, padding_height;
+
+			sde_crtc_calc_vpadding_param(crtc->state,
+				split_dim_layer.rect.y, split_dim_layer.rect.h,
+				&padding_y, &padding_start, &padding_height);
+
+			split_dim_layer.rect.y = padding_y;
+			split_dim_layer.rect.h = padding_height;
+		}
+
 		SDE_EVT32_VERBOSE(DRMID(crtc),
 				cstate->lm_roi[i].x,
 				cstate->lm_roi[i].y,
@@ -1601,6 +1617,84 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc,
 	return 0;
 }
 
+static u32 _sde_crtc_calc_gcd(u32 a, u32 b)
+{
+	if (b == 0)
+		return a;
+
+	return _sde_crtc_calc_gcd(b, a % b);
+}
+
+static int _sde_crtc_check_panel_stacking(struct drm_crtc *crtc,
+		struct drm_crtc_state *state)
+{
+	struct sde_kms *kms;
+	struct sde_crtc *sde_crtc;
+	struct sde_crtc_state *sde_crtc_state;
+	struct drm_connector *conn;
+	struct msm_mode_info mode_info;
+	u32 gcd, m, n;
+	int rc;
+
+	kms = _sde_crtc_get_kms(crtc);
+	if (!kms || !kms->catalog) {
+		SDE_ERROR("invalid kms\n");
+		return -EINVAL;
+	}
+
+	if (!kms->catalog->has_line_insertion)
+		return 0;
+
+	sde_crtc = to_sde_crtc(crtc);
+	sde_crtc_state = to_sde_crtc_state(state);
+
+	/* panel stacking only support single connector */
+	if (sde_crtc_state->num_connectors != 1)
+		return 0;
+
+	conn = sde_crtc_state->connectors[0];
+	rc = sde_connector_get_mode_info(conn->state, &mode_info);
+	if (rc) {
+		SDE_ERROR("failed to get mode info\n");
+		return -EINVAL;
+	}
+
+	if (!mode_info.vpadding)
+		goto done;
+
+	if (mode_info.vpadding < state->mode.vdisplay) {
+		SDE_ERROR("padding height %d is less than vdisplay %d\n",
+			mode_info.vpadding, state->mode.vdisplay);
+		return -EINVAL;
+	}
+
+	/* skip calculation if already cached */
+	if (mode_info.vpadding == sde_crtc_state->padding_height)
+		return 0;
+
+	gcd = _sde_crtc_calc_gcd(mode_info.vpadding, state->mode.vdisplay);
+	if (!gcd) {
+		SDE_ERROR("zero gcd found for padding height %d %d\n",
+			mode_info.vpadding, state->mode.vdisplay);
+		return -EINVAL;
+	}
+
+	m = state->mode.vdisplay / gcd;
+	n = mode_info.vpadding / gcd - m;
+
+	if (m > MAX_VPADDING_RATIO_M || n > MAX_VPADDING_RATIO_N) {
+		SDE_ERROR("unsupported panel stacking pattern %d:%d", m, n);
+		return -EINVAL;
+	}
+
+	sde_crtc_state->padding_active = m;
+	sde_crtc_state->padding_dummy = n;
+
+done:
+	sde_crtc_state->padding_height = mode_info.vpadding;
+	return 0;
+}
+
 static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc)
 {
 	struct sde_crtc *sde_crtc;
@@ -5340,6 +5434,13 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
 		goto end;
 	}
 
+	rc = _sde_crtc_check_panel_stacking(crtc, state);
+	if (rc) {
+		SDE_ERROR("crtc%d failed panel stacking check %d\n",
+				crtc->base.id, rc);
+		goto end;
+	}
+
 end:
 	kfree(pstates);
 	kfree(multirect_plane);
@@ -5613,6 +5714,10 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
 			catalog->perf.amortizable_threshold);
 	sde_kms_info_add_keyint(info, "min_prefill_lines",
 			catalog->perf.min_prefill_lines);
+	sde_kms_info_add_keyint(info, "num_mnoc_ports",
+			catalog->perf.num_mnoc_ports);
+	sde_kms_info_add_keyint(info, "axi_bus_width",
+			catalog->perf.axi_bus_width);
 	sde_kms_info_add_keyint(info, "sec_ui_blendstage",
 			catalog->sui_supported_blendstage);
 
@@ -6872,3 +6977,40 @@ void sde_crtc_update_cont_splash_settings(struct drm_crtc *crtc)
 	sde_crtc = to_sde_crtc(crtc);
 	sde_crtc->cur_perf.core_clk_rate = kms->perf.max_core_clk_rate;
 }
+
+int sde_crtc_calc_vpadding_param(struct drm_crtc_state *state,
+		uint32_t crtc_y, uint32_t crtc_h, uint32_t *padding_y,
+		uint32_t *padding_start, uint32_t *padding_height)
+{
+	struct sde_kms *kms;
+	struct sde_crtc_state *cstate = to_sde_crtc_state(state);
+	u32 y_remain, y_start, y_end;
+	u32 m, n;
+
+	kms = _sde_crtc_get_kms(state->crtc);
+	if (!kms || !kms->catalog) {
+		SDE_ERROR("invalid kms\n");
+		return -EINVAL;
+	}
+
+	if (!kms->catalog->has_line_insertion)
+		return 0;
+
+	if (!cstate->padding_active) {
+		SDE_ERROR("zero padding active value\n");
+		return -EINVAL;
+	}
+
+	m = cstate->padding_active;
+	n = m + cstate->padding_dummy;
+
+	y_remain = crtc_y % m;
+	y_start = y_remain + crtc_y / m * n;
+	y_end = (crtc_y + crtc_h - 1) / m * n + (crtc_y + crtc_h - 1) % m;
+
+	*padding_y = y_start;
+	*padding_start = m - y_remain;
+	*padding_height = y_end - y_start + 1;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 9e9d499..eb644b3 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -186,6 +186,7 @@ struct sde_crtc_fps_info {
  * @output_fence  : output release fence context
  * @stage_cfg     : H/w mixer stage configuration
  * @debugfs_root  : Parent of debugfs node
+ * @priv_handle   : Pointer to external private handle, if present
  * @vblank_cb_count : count of vblank callback since last reset
  * @play_count    : frame count between crtc enable and disable
  * @vblank_cb_time  : ktime at vblank count reset
@@ -249,6 +250,7 @@ struct sde_crtc {
 
 	struct sde_hw_stage_cfg stage_cfg;
 	struct dentry *debugfs_root;
+	void *priv_handle;
 
 	u32 vblank_cb_count;
 	u64 play_count;
@@ -393,6 +395,9 @@ struct sde_crtc_respool {
  * @sbuf_clk_rate : previous and current user specified inline rotator clock
  * @sbuf_clk_shifted : whether or not sbuf_clk_rate has been shifted as part
  *	of crtc atomic check
+ * @padding_height: panel height after line padding
+ * @padding_active: active lines in panel stacking pattern
+ * @padding_dummy: dummy lines in panel stacking pattern
  */
 struct sde_crtc_state {
 	struct drm_crtc_state base;
@@ -427,6 +432,10 @@ struct sde_crtc_state {
 	u64 sbuf_clk_rate[2];
 	bool sbuf_clk_shifted;
 
+	u32 padding_height;
+	u32 padding_active;
+	u32 padding_dummy;
+
 	struct sde_crtc_respool rp;
 };
 
@@ -828,4 +837,17 @@ uint64_t sde_crtc_get_sbuf_clk(struct drm_crtc_state *state);
  */
 void sde_crtc_misr_setup(struct drm_crtc *crtc, bool enable, u32 frame_count);
 
+/**
+ * sde_crtc_calc_vpadding_param - calculate vpadding parameters
+ * @state: Pointer to DRM crtc state object
+ * @crtc_y: Plane's CRTC_Y offset
+ * @crtc_h: Plane's CRTC_H size
+ * @padding_y: Padding Y offset
+ * @padding_start: Padding start offset
+ * @padding_height: Padding height in total
+ */
+int sde_crtc_calc_vpadding_param(struct drm_crtc_state *state,
+		uint32_t crtc_y, uint32_t crtc_h, uint32_t *padding_y,
+		uint32_t *padding_start, uint32_t *padding_height);
+
 #endif /* _SDE_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index a790693..370d9cc 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -168,6 +168,7 @@ enum sde_enc_rc_states {
  * @enc_spin_lock:	Virtual-Encoder-Wide Spin Lock for IRQ purposes
  * @bus_scaling_client:	Client handle to the bus scaling interface
  * @te_source:		vsync source pin information
+ * @ops:		Encoder ops from init function
  * @num_phys_encs:	Actual number of physical encoders contained.
  * @phys_encs:		Container of physical encoders managed.
  * @cur_master:		Pointer to the current master in this mode. Optimization
@@ -231,6 +232,8 @@ struct sde_encoder_virt {
 	uint32_t display_num_of_h_tiles;
 	uint32_t te_source;
 
+	struct sde_encoder_ops ops;
+
 	unsigned int num_phys_encs;
 	struct sde_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL];
 	struct sde_encoder_phys *cur_master;
@@ -2674,6 +2677,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	struct sde_connector *sde_conn = NULL;
 	struct sde_rm_hw_iter dsc_iter, pp_iter;
 	struct sde_rm_hw_request request_hw;
+	bool is_cmd_mode = false;
 	int i = 0, ret;
 
 	if (!drm_enc) {
@@ -2692,6 +2696,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	priv = drm_enc->dev->dev_private;
 	sde_kms = to_sde_kms(priv->kms);
 	connector_list = &sde_kms->dev->mode_config.connector_list;
+	is_cmd_mode = sde_enc->disp_info.capabilities &
+					MSM_DISPLAY_CAP_CMD_MODE;
 
 	SDE_EVT32(DRMID(drm_enc));
 
@@ -2733,7 +2739,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 
 	/* release resources before seamless mode change */
 	if (msm_is_mode_seamless_dms(adj_mode) ||
-			msm_is_mode_seamless_dyn_clk(adj_mode)) {
+			(msm_is_mode_seamless_dyn_clk(adj_mode) &&
+			 is_cmd_mode)) {
 		/* restore resource state before releasing them */
 		ret = sde_encoder_resource_control(drm_enc,
 				SDE_ENC_RC_EVENT_PRE_MODESET);
@@ -2794,7 +2801,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
 
 		if (phys) {
-			if (!sde_enc->hw_pp[i]) {
+			if (!sde_enc->hw_pp[i] && sde_enc->topology.num_intf) {
 				SDE_ERROR_ENC(sde_enc,
 				    "invalid pingpong block for the encoder\n");
 				return;
@@ -2808,7 +2815,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 
 	/* update resources after seamless mode change */
 	if (msm_is_mode_seamless_dms(adj_mode) ||
-			msm_is_mode_seamless_dyn_clk(adj_mode))
+			(msm_is_mode_seamless_dyn_clk(adj_mode) &&
+			is_cmd_mode))
 		sde_encoder_resource_control(&sde_enc->base,
 						SDE_ENC_RC_EVENT_POST_MODESET);
 }
@@ -5111,6 +5119,23 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
 		SDE_DEBUG("h_tile_instance %d = %d, split_role %d\n",
 				i, controller_id, phys_params.split_role);
 
+		if (sde_enc->ops.phys_init) {
+			struct sde_encoder_phys *enc;
+
+			enc = sde_enc->ops.phys_init(intf_type,
+					controller_id,
+					&phys_params);
+			if (enc) {
+				sde_enc->phys_encs[sde_enc->num_phys_encs] =
+					enc;
+				++sde_enc->num_phys_encs;
+			} else
+				SDE_ERROR_ENC(sde_enc,
+						"failed to add phys encs\n");
+
+			continue;
+		}
+
 		if (intf_type == INTF_WB) {
 			phys_params.intf_idx = INTF_MAX;
 			phys_params.wb_idx = sde_encoder_get_wb(
@@ -5176,9 +5201,10 @@ static const struct drm_encoder_funcs sde_encoder_funcs = {
 		.early_unregister = sde_encoder_early_unregister,
 };
 
-struct drm_encoder *sde_encoder_init(
+struct drm_encoder *sde_encoder_init_with_ops(
 		struct drm_device *dev,
-		struct msm_display_info *disp_info)
+		struct msm_display_info *disp_info,
+		const struct sde_encoder_ops *ops)
 {
 	struct msm_drm_private *priv = dev->dev_private;
 	struct sde_kms *sde_kms = to_sde_kms(priv->kms);
@@ -5194,6 +5220,9 @@ struct drm_encoder *sde_encoder_init(
 		goto fail;
 	}
 
+	if (ops)
+		sde_enc->ops = *ops;
+
 	mutex_init(&sde_enc->enc_lock);
 	ret = sde_encoder_setup_display(sde_enc, sde_kms, disp_info,
 			&drm_enc_mode);
@@ -5256,6 +5285,13 @@ struct drm_encoder *sde_encoder_init(
 	return ERR_PTR(ret);
 }
 
+struct drm_encoder *sde_encoder_init(
+		struct drm_device *dev,
+		struct msm_display_info *disp_info)
+{
+	return sde_encoder_init_with_ops(dev, disp_info, NULL);
+}
+
 int sde_encoder_wait_for_event(struct drm_encoder *drm_enc,
 	enum msm_event_wait event)
 {
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h
index 747edd6..8f3d8f2 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -76,6 +76,22 @@ struct sde_encoder_rsc_config {
 };
 
 /**
+ * struct sde_encoder_ops - callback functions for generic sde encoder
+ * Individual callbacks documented below.
+ */
+struct sde_encoder_ops {
+	/**
+	 * phys_init - phys initialization function
+	 * @type: controller type
+	 * @controller_id: controller id
+	 * @phys_init_params: Pointer of structure sde_enc_phys_init_params
+	 * Returns: Pointer of sde_encoder_phys, NULL if failed
+	 */
+	void *(*phys_init)(enum sde_intf_type type,
+			u32 controller_id, void *phys_init_params);
+};
+
+/**
  * sde_encoder_get_hw_resources - Populate table of required hardware resources
  * @encoder:	encoder pointer
  * @hw_res:	resource table to populate with encoder required resources
@@ -220,6 +236,18 @@ struct drm_encoder *sde_encoder_init(
 		struct msm_display_info *disp_info);
 
 /**
+ * sde_encoder_init_with_ops - initialize virtual encoder object with init ops
+ * @dev:        Pointer to drm device structure
+ * @disp_info:  Pointer to display information structure
+ * @ops:        Pointer to encoder ops structure
+ * Returns:     Pointer to newly created drm encoder
+ */
+struct drm_encoder *sde_encoder_init_with_ops(
+		struct drm_device *dev,
+		struct msm_display_info *disp_info,
+		const struct sde_encoder_ops *ops);
+
+/**
  * sde_encoder_destroy - destroy previously initialized virtual encoder
  * @drm_enc:    Pointer to previously created drm encoder structure
  */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index b6f3490..9efc9a9 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -131,6 +131,8 @@
 		"NV12/5/1/1.25 AB24/5/1/1.25 XB24/5/1/1.25"
 #define DEFAULT_MAX_PER_PIPE_BW			2400000
 #define DEFAULT_AMORTIZABLE_THRESHOLD		25
+#define DEFAULT_MNOC_PORTS			2
+#define DEFAULT_AXI_BUS_WIDTH			32
 #define DEFAULT_CPU_MASK			0
 #define DEFAULT_CPU_DMA_LATENCY			PM_QOS_DEFAULT_VALUE
 
@@ -168,6 +170,7 @@ enum sde_prop {
 	UBWC_BW_CALC_VERSION,
 	PIPE_ORDER_VERSION,
 	SEC_SID_MASK,
+	LINE_INSERTION,
 	SDE_PROP_MAX,
 };
 
@@ -203,6 +206,8 @@ enum {
 	PERF_CPU_DMA_LATENCY,
 	PERF_QOS_LUT_MACROTILE_QSEED,
 	PERF_SAFE_LUT_MACROTILE_QSEED,
+	PERF_NUM_MNOC_PORTS,
+	PERF_AXI_BUS_WIDTH,
 	PERF_PROP_MAX,
 };
 
@@ -447,6 +452,7 @@ static struct sde_prop_type sde_prop[] = {
 	{PIPE_ORDER_VERSION, "qcom,sde-pipe-order-version", false,
 			PROP_TYPE_U32},
 	{SEC_SID_MASK, "qcom,sde-secure-sid-mask", false, PROP_TYPE_U32_ARRAY},
+	{LINE_INSERTION, "qcom,sde-has-line-insertion", false, PROP_TYPE_BOOL},
 };
 
 static struct sde_prop_type sde_perf_prop[] = {
@@ -504,6 +510,10 @@ static struct sde_prop_type sde_perf_prop[] = {
 			false, PROP_TYPE_U32_ARRAY},
 	{PERF_SAFE_LUT_MACROTILE_QSEED, "qcom,sde-safe-lut-macrotile-qseed",
 			false, PROP_TYPE_U32_ARRAY},
+	{PERF_NUM_MNOC_PORTS, "qcom,sde-num-mnoc-ports",
+			false, PROP_TYPE_U32},
+	{PERF_AXI_BUS_WIDTH, "qcom,sde-axi-bus-width",
+			false, PROP_TYPE_U32},
 };
 
 static struct sde_prop_type sspp_prop[] = {
@@ -1397,6 +1407,9 @@ static int sde_sspp_parse_dt(struct device_node *np,
 			set_bit(SDE_SSPP_TS_PREFILL_REC1, &sspp->features);
 		}
 
+		if (sde_cfg->has_line_insertion)
+			set_bit(SDE_SSPP_LINE_INSERTION, &sspp->features);
+
 		sblk->smart_dma_priority =
 			PROP_VALUE_ACCESS(prop_value, SSPP_SMART_DMA, i);
 
@@ -3054,6 +3067,8 @@ static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
 	cfg->has_idle_pc = PROP_VALUE_ACCESS(prop_value, IDLE_PC, 0);
 	cfg->pipe_order_type = PROP_VALUE_ACCESS(prop_value,
 		PIPE_ORDER_VERSION, 0);
+	cfg->has_line_insertion = PROP_VALUE_ACCESS(prop_value,
+		LINE_INSERTION, 0);
 end:
 	kfree(prop_value);
 	return rc;
@@ -3264,6 +3279,16 @@ static int sde_perf_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
 			PROP_VALUE_ACCESS(prop_value,
 					PERF_AMORTIZABLE_THRESHOLD, 0) :
 			DEFAULT_AMORTIZABLE_THRESHOLD;
+	cfg->perf.num_mnoc_ports =
+			prop_exists[PERF_NUM_MNOC_PORTS] ?
+			PROP_VALUE_ACCESS(prop_value,
+				PERF_NUM_MNOC_PORTS, 0) :
+			DEFAULT_MNOC_PORTS;
+	cfg->perf.axi_bus_width =
+			prop_exists[PERF_AXI_BUS_WIDTH] ?
+			PROP_VALUE_ACCESS(prop_value,
+				PERF_AXI_BUS_WIDTH, 0) :
+			DEFAULT_AXI_BUS_WIDTH;
 
 	if (prop_exists[PERF_DANGER_LUT] && prop_count[PERF_DANGER_LUT] <=
 			SDE_QOS_LUT_USAGE_MAX) {
@@ -3420,15 +3445,17 @@ static int sde_parse_merge_3d_dt(struct device_node *np,
 	rc = _validate_dt_entry(np, merge_3d_prop, ARRAY_SIZE(merge_3d_prop),
 		prop_count, &off_count);
 	if (rc)
-		goto error;
+		goto end;
 
 	sde_cfg->merge_3d_count = off_count;
 
 	rc = _read_dt_entry(np, merge_3d_prop, ARRAY_SIZE(merge_3d_prop),
 			prop_count,
 			prop_exists, prop_value);
-	if (rc)
-		goto error;
+	if (rc) {
+		sde_cfg->merge_3d_count = 0;
+		goto end;
+	}
 
 	for (i = 0; i < off_count; i++) {
 		merge_3d = sde_cfg->merge_3d + i;
@@ -3439,9 +3466,7 @@ static int sde_parse_merge_3d_dt(struct device_node *np,
 		merge_3d->len = PROP_VALUE_ACCESS(prop_value, HW_LEN, 0);
 	}
 
-	return 0;
-error:
-	sde_cfg->merge_3d_count = 0;
+end:
 	kfree(prop_value);
 fail:
 	return rc;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 2cf635a..e2590c4 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -165,6 +165,7 @@ enum {
  * @SDE_SSPP_BLOCK_SEC_UI    Blocks secure-ui layers
  * @SDE_SSPP_QOS_FL_NOCALC   Avoid fill level calculation for QoS/danger/safe
  * @SDE_SSPP_SCALER_QSEED3LITE Qseed3lite algorithm support
+ * @SDE_SSPP_LINE_INSERTION  Line insertion support
  * @SDE_SSPP_MAX             maximum value
  */
 enum {
@@ -199,6 +200,7 @@ enum {
 	SDE_SSPP_BLOCK_SEC_UI,
 	SDE_SSPP_QOS_FL_NOCALC,
 	SDE_SSPP_SCALER_QSEED3LITE,
+	SDE_SSPP_LINE_INSERTION,
 	SDE_SSPP_MAX
 };
 
@@ -992,6 +994,8 @@ struct sde_perf_cdp_cfg {
  * @cdp_cfg            cdp use case configurations
  * @cpu_mask:          pm_qos cpu mask value
  * @cpu_dma_latency:   pm_qos cpu dma latency value
+ * @axi_bus_width:     axi bus width value in bytes
+ * @num_mnoc_ports:    number of mnoc ports
  */
 struct sde_perf_cfg {
 	u32 max_bw_low;
@@ -1018,6 +1022,8 @@ struct sde_perf_cfg {
 	struct sde_perf_cdp_cfg cdp_cfg[SDE_PERF_CDP_USAGE_MAX];
 	u32 cpu_mask;
 	u32 cpu_dma_latency;
+	u32 axi_bus_width;
+	u32 num_mnoc_ports;
 };
 
 /**
@@ -1109,6 +1115,7 @@ struct sde_mdss_cfg {
 	bool delay_prg_fetch_start;
 	bool has_qsync;
 	bool has_3d_merge_reset;
+	bool has_line_insertion;
 
 	bool sui_misr_supported;
 	u32 sui_block_xin_mask;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index c3f557a..7da2dae 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -48,6 +48,8 @@
 #define SSPP_SRC_CONSTANT_COLOR_REC1       0x180
 #define SSPP_EXCL_REC_SIZE_REC1            0x184
 #define SSPP_EXCL_REC_XY_REC1              0x188
+#define SSPP_LINE_INSERTION_CTRL_REC1      0x1E4
+#define SSPP_LINE_INSERTION_OUT_SIZE_REC1  0x1EC
 
 /* SSPP_DGM */
 #define SSPP_DGM_OP_MODE                   0x804
@@ -98,6 +100,9 @@
 #define SSPP_TRAFFIC_SHAPER_REC1           0x158
 #define SSPP_EXCL_REC_SIZE                 0x1B4
 #define SSPP_EXCL_REC_XY                   0x1B8
+#define SSPP_LINE_INSERTION_CTRL           0x1E0
+#define SSPP_LINE_INSERTION_OUT_SIZE       0x1E8
+
 #define SSPP_VIG_OP_MODE                   0x0
 #define SSPP_VIG_CSC_10_OP_MODE            0x0
 #define SSPP_TRAFFIC_SHAPER_BPC_MAX        0xFF
@@ -1129,6 +1134,39 @@ static void sde_hw_sspp_setup_dgm_csc(struct sde_hw_pipe *ctx,
 	SDE_REG_WRITE(&ctx->hw, offset, op_mode);
 }
 
+static void sde_hw_sspp_setup_line_insertion(struct sde_hw_pipe *ctx,
+		enum sde_sspp_multirect_index rect_index,
+		struct sde_hw_pipe_line_insertion_cfg *cfg)
+{
+	struct sde_hw_blk_reg_map *c;
+	u32 ctl_off, size_off, ctl_val;
+	u32 idx;
+
+	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx) || !cfg)
+		return;
+
+	c = &ctx->hw;
+
+	if (rect_index == SDE_SSPP_RECT_SOLO || rect_index == SDE_SSPP_RECT_0) {
+		ctl_off = SSPP_LINE_INSERTION_CTRL;
+		size_off = SSPP_LINE_INSERTION_OUT_SIZE;
+	} else {
+		ctl_off = SSPP_LINE_INSERTION_CTRL_REC1;
+		size_off = SSPP_LINE_INSERTION_OUT_SIZE_REC1;
+	}
+
+	if (cfg->enable)
+		ctl_val = BIT(31) |
+			(cfg->dummy_lines << 16) |
+			(cfg->first_active_lines << 8) |
+			(cfg->active_lines);
+	else
+		ctl_val = 0;
+
+	SDE_REG_WRITE(c, ctl_off, ctl_val);
+	SDE_REG_WRITE(c, size_off, cfg->dst_h << 16);
+}
+
 static void _setup_layer_ops(struct sde_hw_pipe *c,
 		unsigned long features)
 {
@@ -1204,6 +1242,9 @@ static void _setup_layer_ops(struct sde_hw_pipe *c,
 
 	c->ops.get_ubwc_error = sde_hw_sspp_get_ubwc_error;
 	c->ops.clear_ubwc_error = sde_hw_sspp_clear_ubwc_error;
+
+	if (test_bit(SDE_SSPP_LINE_INSERTION, &features))
+		c->ops.setup_line_insertion = sde_hw_sspp_setup_line_insertion;
 }
 
 static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
index f96149c..e9efb7e 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.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
@@ -290,6 +290,22 @@ struct sde_hw_pipe_sbuf_status {
 };
 
 /**
+ * struct sde_hw_pipe_line_insertion_cfg - line insertion config
+ * @enable: line insertion is enabled
+ * @dummy_lines: dummy lines before active lines
+ * @first_active_lines: number of active lines before first dummy lines
+ * @active_lines: active lines
+ * @dst_h: total active lines plus dummy lines
+ */
+struct sde_hw_pipe_line_insertion_cfg {
+	bool enable;
+	u32 dummy_lines;
+	u32 first_active_lines;
+	u32 active_lines;
+	u32 dst_h;
+};
+
+/**
  * struct sde_hw_sspp_ops - interface to the SSPP Hw driver functions
  * Caller must call the init function to get the pipe context for each pipe
  * Assumption is these functions will be called after clocks are enabled
@@ -605,6 +621,15 @@ struct sde_hw_sspp_ops {
 	 * @ctx: Pointer to pipe context
 	 */
 	u32 (*get_ubwc_error)(struct sde_hw_pipe *ctx);
+
+	/**
+	 * setup_line_insertion - setup line insertion
+	 * @ctx: Pointer to pipe context
+	 * @cfg: Pointer to line insertion configuration
+	 */
+	void (*setup_line_insertion)(struct sde_hw_pipe *ctx,
+		enum sde_sspp_multirect_index index,
+		struct sde_hw_pipe_line_insertion_cfg *cfg);
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 3e20c6c..e5d730d 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>
  *
@@ -1467,6 +1467,17 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
 			SDE_ERROR("dsi %d connector init failed\n", i);
 			dsi_display_drm_bridge_deinit(display);
 			sde_encoder_destroy(encoder);
+			continue;
+		}
+
+		rc = dsi_display_drm_ext_bridge_init(display,
+					encoder,
+					connector);
+		if (rc) {
+			SDE_ERROR("dsi %d ext bridge init failed\n", rc);
+			dsi_display_drm_bridge_deinit(display);
+			sde_encoder_destroy(encoder);
+			sde_connector_destroy(connector);
 		}
 	}
 
@@ -2359,7 +2370,6 @@ static void _sde_kms_post_open(struct msm_kms *kms, struct drm_file *file)
 	struct drm_connector *connector = NULL;
 	struct drm_connector_list_iter conn_iter;
 	struct sde_connector *sde_conn = NULL;
-	int i;
 
 	if (!kms) {
 		SDE_ERROR("invalid kms\n");
@@ -2377,18 +2387,6 @@ static void _sde_kms_post_open(struct msm_kms *kms, struct drm_file *file)
 	if (!dev->mode_config.poll_enabled)
 		return;
 
-	/* init external dsi bridge here to make sure ext bridge is probed*/
-	for (i = 0; i < sde_kms->dsi_display_count; ++i) {
-		struct dsi_display *dsi_display;
-
-		dsi_display = sde_kms->dsi_displays[i];
-		if (dsi_display->bridge) {
-			dsi_display_drm_ext_bridge_init(dsi_display,
-				dsi_display->bridge->base.encoder,
-				dsi_display->drm_conn);
-		}
-	}
-
 	mutex_lock(&dev->mode_config.mutex);
 	drm_connector_list_iter_begin(dev, &conn_iter);
 	drm_for_each_connector_iter(connector, &conn_iter) {
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index d0335bf..721a2ac 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.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>
  *
@@ -107,7 +107,7 @@ struct sde_plane {
 	struct mutex lock;
 
 	enum sde_sspp pipe;
-	uint32_t features;      /* capabilities from catalog */
+	unsigned long features;      /* capabilities from catalog */
 	uint32_t nformats;
 	uint32_t formats[64];
 
@@ -1701,6 +1701,36 @@ static int _sde_plane_color_fill(struct sde_plane *psde,
 	return 0;
 }
 
+static void _sde_plane_setup_panel_stacking(struct sde_plane *psde,
+		struct sde_plane_state *pstate)
+{
+	struct sde_hw_pipe_line_insertion_cfg *cfg;
+	struct sde_crtc_state *cstate;
+	uint32_t h_start, h_total, y_start;
+
+	if (!test_bit(SDE_SSPP_LINE_INSERTION, &psde->features))
+		return;
+
+	cfg = &pstate->line_insertion_cfg;
+	memset(cfg, 0, sizeof(*cfg));
+
+	cstate = to_sde_crtc_state(psde->base.state->crtc->state);
+	if (!cstate->padding_height)
+		return;
+
+	sde_crtc_calc_vpadding_param(psde->base.state->crtc->state,
+		pstate->base.crtc_y, pstate->base.crtc_h,
+		&y_start, &h_start, &h_total);
+
+	cfg->enable = true;
+	cfg->dummy_lines = cstate->padding_dummy;
+	cfg->active_lines = cstate->padding_active;
+	cfg->first_active_lines = h_start;
+	cfg->dst_h = h_total;
+
+	psde->pipe_cfg.dst_rect.y += y_start - pstate->base.crtc_y;
+}
+
 u32 sde_plane_rot_get_prefill(struct drm_plane *plane)
 {
 	struct drm_plane_state *state;
@@ -4021,6 +4051,8 @@ static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
 
 		_sde_plane_setup_scaler(psde, pstate, fmt, false);
 
+		_sde_plane_setup_panel_stacking(psde, pstate);
+
 		/* check for color fill */
 		psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
 				PLANE_PROP_COLOR_FILL);
@@ -4062,6 +4094,13 @@ static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
 					psde->pipe_hw,
 					pstate->multirect_index,
 					pstate->multirect_mode);
+
+		/* update line insertion */
+		if (psde->pipe_hw->ops.setup_line_insertion)
+			psde->pipe_hw->ops.setup_line_insertion(
+					psde->pipe_hw,
+					pstate->multirect_index,
+					&pstate->line_insertion_cfg);
 	}
 
 	if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT ||
@@ -5202,7 +5241,7 @@ static int _sde_plane_init_debugfs(struct drm_plane *plane)
 		return -ENOMEM;
 
 	/* don't error check these */
-	debugfs_create_x32("features", 0600,
+	debugfs_create_ulong("features", 0600,
 			psde->debugfs_root, &psde->features);
 
 	/* add register dump support */
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index dab1d40..b128fb9 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -142,6 +142,7 @@ enum sde_plane_sclcheck_state {
  * @pixel_ext: configuration data for pixel extensions
  * @scaler_check_state: indicates status of user provided pixel extension data
  * @cdp_cfg:	CDP configuration
+ * @line_insertion_cfg: line insertion configuration
  */
 struct sde_plane_state {
 	struct drm_plane_state base;
@@ -169,6 +170,7 @@ struct sde_plane_state {
 	struct sde_plane_rot_state rot;
 
 	struct sde_hw_pipe_cdp_cfg cdp_cfg;
+	struct sde_hw_pipe_line_insertion_cfg line_insertion_cfg;
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index 9a071e4..08d5663 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.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
@@ -816,8 +816,8 @@ static int _sde_rm_reserve_lms(
 	int i, rc = 0;
 
 	if (!reqs->topology->num_lm) {
-		SDE_ERROR("invalid number of lm: %d\n", reqs->topology->num_lm);
-		return -EINVAL;
+		SDE_DEBUG("invalid number of lm: %d\n", reqs->topology->num_lm);
+		return 0;
 	}
 
 	/* Find a primary mixer */
@@ -931,6 +931,11 @@ static int _sde_rm_reserve_ctls(
 	struct sde_rm_hw_iter iter;
 	int i = 0;
 
+	if (!top->num_ctl) {
+		SDE_DEBUG("invalid number of ctl: %d\n", top->num_ctl);
+		return 0;
+	}
+
 	memset(&ctls, 0, sizeof(ctls));
 
 	sde_rm_init_hw_iter(&iter, 0, SDE_HW_BLK_CTL);
@@ -1641,10 +1646,8 @@ void sde_rm_release(struct sde_rm *rm, struct drm_encoder *enc)
 	mutex_lock(&rm->rm_lock);
 
 	rsvp = _sde_rm_get_rsvp(rm, enc);
-	if (!rsvp) {
-		SDE_ERROR("failed to find rsvp for enc %d\n", enc->base.id);
+	if (!rsvp)
 		goto end;
-	}
 
 	conn = _sde_rm_get_connector(enc);
 	if (!conn) {
@@ -1833,3 +1836,100 @@ int sde_rm_reserve(
 
 	return ret;
 }
+
+int sde_rm_ext_blk_create_reserve(struct sde_rm *rm,
+		struct sde_hw_blk *hw, struct drm_encoder *enc)
+{
+	struct sde_rm_hw_blk *blk;
+	struct sde_rm_rsvp *rsvp;
+	int ret = 0;
+
+	if (!rm || !hw || !enc) {
+		SDE_ERROR("invalid parameters\n");
+		return -EINVAL;
+	}
+
+	if (hw->type >= SDE_HW_BLK_MAX) {
+		SDE_ERROR("invalid HW type\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&rm->rm_lock);
+
+	rsvp = _sde_rm_get_rsvp(rm, enc);
+	if (!rsvp) {
+		rsvp = kzalloc(sizeof(*rsvp), GFP_KERNEL);
+		if (!rsvp) {
+			ret = -ENOMEM;
+			goto end;
+		}
+
+		rsvp->seq = ++rm->rsvp_next_seq;
+		rsvp->enc_id = enc->base.id;
+		list_add_tail(&rsvp->list, &rm->rsvps);
+
+		SDE_DEBUG("create rsvp %d for enc %d\n",
+					rsvp->seq, rsvp->enc_id);
+	}
+
+	blk = kzalloc(sizeof(*blk), GFP_KERNEL);
+	if (!blk) {
+		ret = -ENOMEM;
+		goto end;
+	}
+
+	blk->type = hw->type;
+	blk->id = hw->id;
+	blk->hw = hw;
+	blk->rsvp = rsvp;
+	list_add_tail(&blk->list, &rm->hw_blks[hw->type]);
+
+	SDE_DEBUG("create blk %d %d for rsvp %d enc %d\n", blk->type, blk->id,
+					rsvp->seq, rsvp->enc_id);
+
+end:
+	mutex_unlock(&rm->rm_lock);
+	return ret;
+}
+
+int sde_rm_ext_blk_destroy(struct sde_rm *rm,
+		struct drm_encoder *enc)
+{
+	struct sde_rm_hw_blk *blk = NULL, *p;
+	struct sde_rm_rsvp *rsvp;
+	enum sde_hw_blk_type type;
+	int ret = 0;
+
+	if (!rm || !enc) {
+		SDE_ERROR("invalid parameters\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&rm->rm_lock);
+
+	rsvp = _sde_rm_get_rsvp(rm, enc);
+	if (!rsvp) {
+		ret = -ENOENT;
+		SDE_ERROR("failed to find rsvp for enc %d\n", enc->base.id);
+		goto end;
+	}
+
+	for (type = 0; type < SDE_HW_BLK_MAX; type++) {
+		list_for_each_entry_safe(blk, p, &rm->hw_blks[type], list) {
+			if (blk->rsvp == rsvp) {
+				list_del(&blk->list);
+				SDE_DEBUG("del blk %d %d from rsvp %d enc %d\n",
+						blk->type, blk->id,
+						rsvp->seq, rsvp->enc_id);
+				kfree(blk);
+			}
+		}
+	}
+
+	SDE_DEBUG("del rsvp %d\n", rsvp->seq);
+	list_del(&rsvp->list);
+	kfree(rsvp);
+end:
+	mutex_unlock(&rm->rm_lock);
+	return ret;
+}
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.h b/drivers/gpu/drm/msm/sde/sde_rm.h
index 638d69f..7cb3088 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.h
+++ b/drivers/gpu/drm/msm/sde/sde_rm.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
@@ -256,13 +256,6 @@ bool sde_rm_get_hw(struct sde_rm *rm, struct sde_rm_hw_iter *iter);
 bool sde_rm_request_hw_blk(struct sde_rm *rm, struct sde_rm_hw_request *hw);
 
 /**
- * sde_rm_check_property_topctl - validate property bitmask before it is set
- * @val: user's proposed topology control bitmask
- * @Return: 0 on success or error
- */
-int sde_rm_check_property_topctl(uint64_t val);
-
-/**
  * sde_rm_cont_splash_res_init - Read the current MDSS configuration
  *	to update the splash data structure with the topology
  *	configured by the bootloader.
@@ -305,4 +298,26 @@ static inline bool sde_rm_topology_is_dual_ctl(struct sde_rm *rm,
 
 	return rm->topology_tbl[topology].num_ctl == DUAL_CTL;
 }
+
+/**
+ * sde_rm_ext_blk_create_reserve - Create external HW blocks
+ *	in resource manager and reserve for specific encoder.
+ * @rm: SDE Resource Manager handle
+ * @hw: external HW block
+ * @drm_enc: DRM Encoder handle
+ * @Return: 0 on Success otherwise -ERROR
+ */
+int sde_rm_ext_blk_create_reserve(struct sde_rm *rm,
+				struct sde_hw_blk *hw,
+				struct drm_encoder *enc);
+
+/**
+ * sde_rm_ext_blk_destroy - Given the encoder for the display chain, release
+ *	external HW blocks created for that.
+ * @rm: SDE Resource Manager handle
+ * @enc: DRM Encoder handle
+ * @Return: 0 on Success otherwise -ERROR
+ */
+int sde_rm_ext_blk_destroy(struct sde_rm *rm,
+				struct drm_encoder *enc);
 #endif /* __SDE_RM_H__ */
diff --git a/drivers/gpu/drm/msm/sde_hdcp.h b/drivers/gpu/drm/msm/sde_hdcp.h
index 87a2484..4620eb4 100644
--- a/drivers/gpu/drm/msm/sde_hdcp.h
+++ b/drivers/gpu/drm/msm/sde_hdcp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -20,12 +20,15 @@
 #include <linux/debugfs.h>
 #include <linux/of_device.h>
 #include <linux/i2c.h>
+#include <linux/list.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <linux/hdcp_qseecom.h>
 #include "sde_kms.h"
 
+#define MAX_STREAM_COUNT 2
+
 enum sde_hdcp_client_id {
 	HDCP_CLIENT_HDMI,
 	HDCP_CLIENT_DP,
@@ -45,6 +48,18 @@ enum sde_hdcp_version {
 	HDCP_VERSION_MAX = BIT(2),
 };
 
+struct stream_info {
+	u8 stream_id;
+	u8 virtual_channel;
+};
+
+struct sde_hdcp_stream {
+	struct list_head list;
+	u8 stream_id;
+	u8 virtual_channel;
+	u32 stream_handle;
+};
+
 struct sde_hdcp_init_data {
 	struct device *msm_hdcp_dev;
 	struct dss_io_data *core_io;
@@ -74,7 +89,13 @@ struct sde_hdcp_ops {
 	bool (*feature_supported)(void *input);
 	void (*force_encryption)(void *input, bool enable);
 	bool (*sink_support)(void *input);
+	int (*set_mode)(void *input, bool mst_enabled);
+	int (*on)(void *input);
 	void (*off)(void *hdcp_ctrl);
+	int (*register_streams)(void *input, u8 num_streams,
+			struct stream_info *streams);
+	int (*deregister_streams)(void *input, u8 num_streams,
+			struct stream_info *streams);
 };
 
 static inline const char *sde_hdcp_state_name(enum sde_hdcp_state hdcp_state)
diff --git a/drivers/gpu/drm/msm/sde_hdcp_2x.c b/drivers/gpu/drm/msm/sde_hdcp_2x.c
index 68f0a87..78d63cd 100644
--- a/drivers/gpu/drm/msm/sde_hdcp_2x.c
+++ b/drivers/gpu/drm/msm/sde_hdcp_2x.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
@@ -74,12 +74,17 @@ struct sde_hdcp_2x_ctrl {
 	atomic_t hdcp_off;
 	enum sde_hdcp_2x_device_type device_type;
 	u8 min_enc_level;
+	struct list_head stream_handles;
+	u8 stream_count;
+	struct stream_info *streams;
+	u8 num_streams;
 
 	struct task_struct *thread;
 	struct completion response_completion;
 
 	struct kthread_worker worker;
 	struct kthread_work wk_init;
+	struct kthread_work wk_start_auth;
 	struct kthread_work wk_msg_sent;
 	struct kthread_work wk_msg_recvd;
 	struct kthread_work wk_timeout;
@@ -87,6 +92,8 @@ struct sde_hdcp_2x_ctrl {
 	struct kthread_work wk_stream;
 	struct kthread_work wk_wait;
 	struct kthread_work wk_send_type;
+	struct kthread_work wk_open_stream;
+	struct kthread_work wk_close_stream;
 };
 
 static const char *sde_hdcp_2x_message_name(int msg_id)
@@ -376,6 +383,8 @@ static int sde_hdcp_2x_check_valid_state(struct sde_hdcp_2x_ctrl *hdcp)
 
 static void sde_hdcp_2x_clean(struct sde_hdcp_2x_ctrl *hdcp)
 {
+	struct list_head *element;
+	struct sde_hdcp_stream *stream_entry;
 	struct hdcp_transport_wakeup_data cdata = {
 						HDCP_TRANSPORT_CMD_INVALID };
 
@@ -384,10 +393,20 @@ static void sde_hdcp_2x_clean(struct sde_hdcp_2x_ctrl *hdcp)
 	cdata.context = hdcp->client_data;
 	cdata.cmd = HDCP_TRANSPORT_CMD_STATUS_FAILED;
 
-	if (!atomic_read(&hdcp->hdcp_off))
-		sde_hdcp_2x_wakeup_client(hdcp, &cdata);
+	while (!list_empty(&hdcp->stream_handles)) {
+		element = hdcp->stream_handles.next;
+		list_del(element);
 
-	atomic_set(&hdcp->hdcp_off, 1);
+		stream_entry = list_entry(element, struct sde_hdcp_stream,
+			list);
+		hdcp2_close_stream(hdcp->hdcp2_ctx,
+			stream_entry->stream_handle);
+		kzfree(stream_entry);
+		hdcp->stream_count--;
+	}
+
+	if (!atomic_xchg(&hdcp->hdcp_off, 1))
+		sde_hdcp_2x_wakeup_client(hdcp, &cdata);
 
 	hdcp2_app_comm(hdcp->hdcp2_ctx, HDCP2_CMD_STOP, &hdcp->app_data);
 }
@@ -569,11 +588,6 @@ static void sde_hdcp_2x_msg_sent_work(struct kthread_work *work)
 	struct sde_hdcp_2x_ctrl *hdcp =
 		container_of(work, struct sde_hdcp_2x_ctrl, wk_msg_sent);
 
-	if (hdcp->wakeup_cmd != HDCP_2X_CMD_MSG_SEND_SUCCESS) {
-		pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd);
-		return;
-	}
-
 	sde_hdcp_2x_msg_sent(hdcp);
 }
 
@@ -581,20 +595,10 @@ static void sde_hdcp_2x_init(struct sde_hdcp_2x_ctrl *hdcp)
 {
 	int rc = 0;
 
-	if (hdcp->wakeup_cmd != HDCP_2X_CMD_START) {
-		pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd);
-		return;
-	}
-
 	rc = hdcp2_app_comm(hdcp->hdcp2_ctx, HDCP2_CMD_START, &hdcp->app_data);
 	if (rc)
 		goto exit;
 
-	pr_debug("message received from TZ: %s\n",
-		 sde_hdcp_2x_message_name(hdcp->app_data.response.data[0]));
-
-	sde_hdcp_2x_send_message(hdcp);
-
 	return;
 exit:
 	HDCP_2X_EXECUTE(clean);
@@ -608,6 +612,35 @@ static void sde_hdcp_2x_init_work(struct kthread_work *work)
 	sde_hdcp_2x_init(hdcp);
 }
 
+static void sde_hdcp_2x_start_auth(struct sde_hdcp_2x_ctrl *hdcp)
+{
+	int rc = 0;
+
+	rc = hdcp2_app_comm(hdcp->hdcp2_ctx, HDCP2_CMD_START_AUTH,
+		&hdcp->app_data);
+	if (rc)
+		goto exit;
+
+	pr_debug("message received from TZ: %s\n",
+		 sde_hdcp_2x_message_name(hdcp->app_data.response.data[0]));
+
+	sde_hdcp_2x_send_message(hdcp);
+
+	return;
+exit:
+	HDCP_2X_EXECUTE(clean);
+}
+
+
+static void sde_hdcp_2x_start_auth_work(struct kthread_work *work)
+{
+	struct sde_hdcp_2x_ctrl *hdcp =
+		container_of(work, struct sde_hdcp_2x_ctrl, wk_start_auth);
+
+	sde_hdcp_2x_start_auth(hdcp);
+}
+
+
 static void sde_hdcp_2x_timeout(struct sde_hdcp_2x_ctrl *hdcp)
 {
 	int rc = 0;
@@ -664,7 +697,8 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp)
 		goto exit;
 	}
 
-	if (hdcp->device_type == HDCP_TXMTR_DP) {
+	if (hdcp->device_type == HDCP_TXMTR_DP ||
+			hdcp->device_type == HDCP_TXMTR_DP_MST) {
 		msg[0] = hdcp->last_msg;
 		message_id_bytes = 1;
 	}
@@ -796,6 +830,162 @@ static void sde_hdcp_2x_wait_for_response_work(struct kthread_work *work)
 	hdcp->wait_timeout_ms = 0;
 }
 
+static struct list_head *sde_hdcp_2x_stream_present(
+		struct sde_hdcp_2x_ctrl *hdcp, u8 stream_id, u8 virtual_channel)
+{
+	struct sde_hdcp_stream *stream_entry;
+	struct list_head *entry;
+	bool present = false;
+
+	list_for_each(entry, &hdcp->stream_handles) {
+		stream_entry = list_entry(entry,
+			struct sde_hdcp_stream, list);
+		if (stream_entry->virtual_channel == virtual_channel &&
+				stream_entry->stream_id == stream_id) {
+			present = true;
+			break;
+		}
+	}
+
+	if (!present)
+		entry = NULL;
+	return entry;
+}
+
+static void sde_hdcp_2x_open_stream(struct sde_hdcp_2x_ctrl *hdcp)
+{
+	int rc;
+	size_t i, iterations;
+	u8 stream_id;
+	u8 virtual_channel;
+	u32 stream_handle = 0;
+	bool query_streams = false;
+
+	if (!hdcp->streams) {
+		pr_err("Array of streams to register is NULL\n");
+		return;
+	}
+
+	iterations = min(hdcp->num_streams, (u8)(MAX_STREAM_COUNT));
+
+	for (i  = 0; i < iterations; i++) {
+		if (hdcp->stream_count == MAX_STREAM_COUNT) {
+			pr_debug("Registered the maximum amount of streams\n");
+			break;
+		}
+
+		stream_id = hdcp->streams[i].stream_id;
+		virtual_channel = hdcp->streams[i].virtual_channel;
+
+		pr_debug("Opening stream %d, virtual channel %d\n",
+			stream_id, virtual_channel);
+
+		if (sde_hdcp_2x_stream_present(hdcp, stream_id,
+				virtual_channel)) {
+			pr_debug("Stream %d, virtual channel %d already open\n",
+				stream_id, virtual_channel);
+			continue;
+		}
+
+		rc = hdcp2_open_stream(hdcp->hdcp2_ctx, virtual_channel,
+				stream_id, &stream_handle);
+		if (rc) {
+			pr_err("Unable to open stream %d, virtual channel %d\n",
+				stream_id, virtual_channel);
+		} else {
+			struct sde_hdcp_stream *stream =
+				kzalloc(sizeof(struct sde_hdcp_stream),
+					GFP_KERNEL);
+			if (!stream)
+				break;
+
+			INIT_LIST_HEAD(&stream->list);
+			stream->stream_handle = stream_handle;
+			stream->stream_id = stream_id;
+			stream->virtual_channel = virtual_channel;
+
+			list_add(&stream->list, &hdcp->stream_handles);
+			hdcp->stream_count++;
+
+			query_streams = true;
+		}
+	}
+
+	if (query_streams && hdcp->authenticated)
+		HDCP_2X_EXECUTE(stream);
+}
+
+static void sde_hdcp_2x_open_stream_work(struct kthread_work *work)
+{
+	struct sde_hdcp_2x_ctrl *hdcp =
+		container_of(work, struct sde_hdcp_2x_ctrl, wk_open_stream);
+
+	sde_hdcp_2x_open_stream(hdcp);
+}
+
+static void sde_hdcp_2x_close_stream(struct sde_hdcp_2x_ctrl *hdcp)
+{
+	int rc;
+	size_t i, iterations;
+	u8 stream_id;
+	u8 virtual_channel;
+	struct list_head *entry;
+	struct sde_hdcp_stream *stream_entry;
+	bool query_streams = false;
+
+	if (!hdcp->streams) {
+		pr_err("Array of streams to register is NULL\n");
+		return;
+	}
+
+	iterations = min(hdcp->num_streams, (u8)(MAX_STREAM_COUNT));
+
+	for (i = 0; i < iterations; i++) {
+		if (hdcp->stream_count == 0) {
+			pr_debug("No streams are currently registered\n");
+			return;
+		}
+
+		stream_id = hdcp->streams[i].stream_id;
+		virtual_channel = hdcp->streams[i].virtual_channel;
+
+		pr_debug("Closing stream %d, virtual channel %d\n",
+			stream_id, virtual_channel);
+
+		entry = sde_hdcp_2x_stream_present(hdcp, stream_id,
+			virtual_channel);
+
+		if (!entry) {
+			pr_err("Unable to find stream %d, virtual channel %d\n"
+				, stream_id, virtual_channel);
+			continue;
+		}
+
+		stream_entry = list_entry(entry, struct sde_hdcp_stream,
+			list);
+
+		rc = hdcp2_close_stream(hdcp->hdcp2_ctx,
+			stream_entry->stream_handle);
+		if (rc)
+			pr_err("Unable to close stream %d, virtual channel %d\n"
+				, stream_id, virtual_channel);
+		hdcp->stream_count--;
+		list_del(entry);
+		kzfree(stream_entry);
+		query_streams = true;
+	}
+
+	if (query_streams && hdcp->authenticated)
+		HDCP_2X_EXECUTE(stream);
+}
+
+static void sde_hdcp_2x_close_stream_work(struct kthread_work *work)
+{
+	struct sde_hdcp_2x_ctrl *hdcp =
+		container_of(work, struct sde_hdcp_2x_ctrl, wk_close_stream);
+	sde_hdcp_2x_close_stream(hdcp);
+}
+
 static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data)
 {
 	struct sde_hdcp_2x_ctrl *hdcp;
@@ -837,6 +1027,9 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data)
 
 		HDCP_2X_EXECUTE(init);
 		break;
+	case HDCP_2X_CMD_START_AUTH:
+		HDCP_2X_EXECUTE(start_auth);
+		break;
 	case HDCP_2X_CMD_STOP:
 		atomic_set(&hdcp->hdcp_off, 1);
 		HDCP_2X_EXECUTE(clean);
@@ -867,6 +1060,18 @@ static int sde_hdcp_2x_wakeup(struct sde_hdcp_2x_wakeup_data *data)
 
 		HDCP_2X_EXECUTE(stream);
 		break;
+	case HDCP_2X_CMD_OPEN_STREAMS:
+		hdcp->streams = data->streams;
+		hdcp->num_streams = data->num_streams;
+		HDCP_2X_EXECUTE(open_stream);
+		kthread_flush_work(&hdcp->wk_open_stream);
+		break;
+	case HDCP_2X_CMD_CLOSE_STREAMS:
+		hdcp->streams = data->streams;
+		hdcp->num_streams = data->num_streams;
+		HDCP_2X_EXECUTE(close_stream);
+		kthread_flush_work(&hdcp->wk_close_stream);
+		break;
 	default:
 		pr_err("invalid wakeup command %d\n", hdcp->wakeup_cmd);
 	}
@@ -912,19 +1117,18 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data)
 		goto unlock;
 	}
 
+	INIT_LIST_HEAD(&hdcp->stream_handles);
 	hdcp->client_data = data->client_data;
 	hdcp->client_ops = data->client_ops;
-	hdcp->device_type = data->device_type;
 
-	hdcp->hdcp2_ctx = hdcp2_init(hdcp->device_type);
-
-	atomic_set(&hdcp->hdcp_off, 0);
+	atomic_set(&hdcp->hdcp_off, 1);
 
 	mutex_init(&hdcp->wakeup_mutex);
 
 	kthread_init_worker(&hdcp->worker);
 
 	kthread_init_work(&hdcp->wk_init,      sde_hdcp_2x_init_work);
+	kthread_init_work(&hdcp->wk_start_auth, sde_hdcp_2x_start_auth_work);
 	kthread_init_work(&hdcp->wk_msg_sent,  sde_hdcp_2x_msg_sent_work);
 	kthread_init_work(&hdcp->wk_msg_recvd, sde_hdcp_2x_msg_recvd_work);
 	kthread_init_work(&hdcp->wk_timeout,   sde_hdcp_2x_timeout_work);
@@ -932,6 +1136,9 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data)
 	kthread_init_work(&hdcp->wk_stream,    sde_hdcp_2x_query_stream_work);
 	kthread_init_work(&hdcp->wk_wait, sde_hdcp_2x_wait_for_response_work);
 	kthread_init_work(&hdcp->wk_send_type,    sde_hdcp_2x_send_type_work);
+	kthread_init_work(&hdcp->wk_open_stream, sde_hdcp_2x_open_stream_work);
+	kthread_init_work(&hdcp->wk_close_stream,
+				sde_hdcp_2x_close_stream_work);
 
 	init_completion(&hdcp->response_completion);
 
@@ -957,6 +1164,41 @@ int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data)
 	return rc;
 }
 
+int sde_hdcp_2x_enable(void *data, enum sde_hdcp_2x_device_type device_type)
+{
+	int rc =  0;
+	struct sde_hdcp_2x_ctrl *hdcp = data;
+
+	if (!hdcp)
+		return  -EINVAL;
+
+	if (hdcp->hdcp2_ctx) {
+		pr_debug("HDCP library context already acquired\n");
+		return 0;
+	}
+
+	hdcp->device_type = device_type;
+	hdcp->hdcp2_ctx = hdcp2_init(hdcp->device_type);
+	if (!hdcp->hdcp2_ctx) {
+		pr_err("Unable to acquire HDCP library handle\n");
+		return -ENOMEM;
+	}
+
+	return rc;
+}
+
+void sde_hdcp_2x_disable(void *data)
+{
+	struct sde_hdcp_2x_ctrl *hdcp = data;
+
+	if (!hdcp->hdcp2_ctx)
+		return;
+
+	kthread_flush_worker(&hdcp->worker);
+	hdcp2_deinit(hdcp->hdcp2_ctx);
+	hdcp->hdcp2_ctx = NULL;
+}
+
 void sde_hdcp_2x_deregister(void *data)
 {
 	struct sde_hdcp_2x_ctrl *hdcp = data;
@@ -964,8 +1206,8 @@ void sde_hdcp_2x_deregister(void *data)
 	if (!hdcp)
 		return;
 
+	sde_hdcp_2x_disable(data);
 	kthread_stop(hdcp->thread);
 	mutex_destroy(&hdcp->wakeup_mutex);
-	hdcp2_deinit(hdcp->hdcp2_ctx);
 	kzfree(hdcp);
 }
diff --git a/drivers/gpu/drm/msm/sde_hdcp_2x.h b/drivers/gpu/drm/msm/sde_hdcp_2x.h
index ad73db4..fbd955f 100644
--- a/drivers/gpu/drm/msm/sde_hdcp_2x.h
+++ b/drivers/gpu/drm/msm/sde_hdcp_2x.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
@@ -22,8 +22,9 @@
 /**
  * enum sde_hdcp_2x_wakeup_cmd - commands for interacting with HDCP driver
  * @HDCP_2X_CMD_INVALID:           initialization value
- * @HDCP_2X_CMD_START:             start authentication
- * @HDCP_2X_CMD_STOP:              stop authentication
+ * @HDCP_2X_CMD_START:             start HDCP driver
+ * @HDCP_2X_CMD_START_AUTH:        start authentication
+ * @HDCP_2X_CMD_STOP:              stop HDCP driver
  * @HDCP_2X_CMD_MSG_SEND_SUCCESS:  sending message to sink succeeded
  * @HDCP_2X_CMD_MSG_SEND_FAILED:   sending message to sink failed
  * @HDCP_2X_CMD_MSG_SEND_TIMEOUT:  sending message to sink timed out
@@ -33,10 +34,13 @@
  * @HDCP_2X_CMD_QUERY_STREAM_TYPE: start content stream processing
  * @HDCP_2X_CMD_LINK_FAILED:       link failure notification
  * @HDCP_2X_CMD_MIN_ENC_LEVEL:     trigger minimum encryption level change
+ * @HDCP_2X_CMD_OPEN_STREAMS:       open a virtual channel
+ * @HDCP_2X_CMD_CLOSE_STREAMS:      close a virtual channel
  */
 enum sde_hdcp_2x_wakeup_cmd {
 	HDCP_2X_CMD_INVALID,
 	HDCP_2X_CMD_START,
+	HDCP_2X_CMD_START_AUTH,
 	HDCP_2X_CMD_STOP,
 	HDCP_2X_CMD_MSG_SEND_SUCCESS,
 	HDCP_2X_CMD_MSG_SEND_FAILED,
@@ -47,6 +51,8 @@ enum sde_hdcp_2x_wakeup_cmd {
 	HDCP_2X_CMD_QUERY_STREAM_TYPE,
 	HDCP_2X_CMD_LINK_FAILED,
 	HDCP_2X_CMD_MIN_ENC_LEVEL,
+	HDCP_2X_CMD_OPEN_STREAMS,
+	HDCP_2X_CMD_CLOSE_STREAMS,
 };
 
 /**
@@ -71,16 +77,19 @@ enum hdcp_transport_wakeup_cmd {
 
 enum sde_hdcp_2x_device_type {
 	HDCP_TXMTR_HDMI = 0x8001,
-	HDCP_TXMTR_DP = 0x8002
+	HDCP_TXMTR_DP = 0x8002,
+	HDCP_TXMTR_DP_MST = 0x8003
 };
 
 /**
  * struct sde_hdcp_2x_lib_wakeup_data - command and data send to HDCP driver
- * @cmd:       command type
- * @context:   void pointer to the HDCP driver instance
- * @buf:       message received from the sink
- * @buf_len:   length of message received from the sink
- * @timeout:   time out value for timed transactions
+ * @cmd:                       command type
+ * @context:                   void pointer to the HDCP driver instance
+ * @buf:                       message received from the sink
+ * @buf_len:                   length of message received from the sink
+ * @timeout:                   time out value for timed transactions
+ * @streams:                   list indicating which streams need adjustment
+ * @num_streams:               number of entries in streams
  */
 struct sde_hdcp_2x_wakeup_data {
 	enum sde_hdcp_2x_wakeup_cmd cmd;
@@ -88,6 +97,8 @@ struct sde_hdcp_2x_wakeup_data {
 	uint32_t total_message_length;
 	uint32_t timeout;
 	u8 min_enc_level;
+	struct stream_info *streams;
+	u8 num_streams;
 };
 
 /**
@@ -156,6 +167,10 @@ static inline const char *sde_hdcp_2x_cmd_to_str(
 		return TO_STR(HDCP_2X_CMD_MSG_RECV_TIMEOUT);
 	case HDCP_2X_CMD_QUERY_STREAM_TYPE:
 		return TO_STR(HDCP_2X_CMD_QUERY_STREAM_TYPE);
+	case HDCP_2X_CMD_OPEN_STREAMS:
+		return TO_STR(HDCP_2X_CMD_OPEN_STREAMS);
+	case HDCP_2X_CMD_CLOSE_STREAMS:
+		return TO_STR(HDCP_2X_CMD_CLOSE_STREAMS);
 	default:
 		return "UNKNOWN";
 	}
@@ -195,12 +210,13 @@ struct hdcp_transport_ops {
 struct sde_hdcp_2x_register_data {
 	struct hdcp_transport_ops *client_ops;
 	struct sde_hdcp_2x_ops *ops;
-	enum sde_hdcp_2x_device_type device_type;
 	void *client_data;
 	void **hdcp_data;
 };
 
 /* functions for the HDCP 2.2 state machine module */
 int sde_hdcp_2x_register(struct sde_hdcp_2x_register_data *data);
+int sde_hdcp_2x_enable(void *data, enum sde_hdcp_2x_device_type device_type);
+void sde_hdcp_2x_disable(void *data);
 void sde_hdcp_2x_deregister(void *data);
 #endif
diff --git a/drivers/gpu/drm/msm/shd/sde_encoder_phys_shd.c b/drivers/gpu/drm/msm/shd/sde_encoder_phys_shd.c
new file mode 100644
index 0000000..18dcf8f
--- /dev/null
+++ b/drivers/gpu/drm/msm/shd/sde_encoder_phys_shd.c
@@ -0,0 +1,711 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt)	"[drm-shd:%s:%d] " fmt, __func__, __LINE__
+
+#include <linux/debugfs.h>
+#include <uapi/drm/sde_drm.h>
+
+#include "sde_encoder_phys.h"
+#include "sde_formats.h"
+#include "sde_hw_top.h"
+#include "sde_hw_interrupts.h"
+#include "sde_core_irq.h"
+#include "sde_crtc.h"
+#include "sde_trace.h"
+#include "sde_plane.h"
+#include "shd_drm.h"
+#include "shd_hw.h"
+
+#define SDE_ERROR_PHYS(p, fmt, ...) SDE_ERROR("enc%d intf%d " fmt,\
+		(p) ? (p)->parent->base.id : -1, \
+		(p) ? (p)->intf_idx - INTF_0 : -1, \
+	##__VA_ARGS__)
+
+#define SDE_DEBUG_PHYS(p, fmt, ...) SDE_DEBUG("enc%d intf%d " fmt,\
+			(p) ? (p)->parent->base.id : -1, \
+			(p) ? (p)->intf_idx - INTF_0 : -1, \
+	##__VA_ARGS__)
+
+/**
+ * struct sde_encoder_phys_shd - sub-class of sde_encoder_phys to handle shared
+ *	mode specific operations
+ * @base:	Baseclass physical encoder structure
+ * @hw_lm:	HW LM blocks created by this shared encoder
+ * @hw_ctl:	HW CTL blocks created by this shared encoder
+ * @num_mixers:	Number of LM blocks
+ * @num_ctls:	Number of CTL blocks
+ */
+struct sde_encoder_phys_shd {
+	struct sde_encoder_phys base;
+	struct sde_hw_mixer *hw_lm[CRTC_DUAL_MIXERS];
+	struct sde_hw_ctl *hw_ctl[CRTC_DUAL_MIXERS];
+	u32 num_mixers;
+	u32 num_ctls;
+};
+
+#define to_sde_encoder_phys_shd(x) \
+	container_of(x, struct sde_encoder_phys_shd, base)
+
+static inline
+bool sde_encoder_phys_shd_is_master(struct sde_encoder_phys *phys_enc)
+{
+	return true;
+}
+
+static void sde_encoder_phys_shd_vblank_irq(void *arg, int irq_idx)
+{
+	struct sde_encoder_phys *phys_enc = arg;
+	struct sde_hw_ctl *hw_ctl;
+	struct sde_shd_hw_ctl *shd_ctl;
+	unsigned long lock_flags;
+	u32 flush_register = ~0;
+	int new_cnt = -1, old_cnt = -1;
+	u32 event = 0;
+
+	if (!phys_enc)
+		return;
+
+	hw_ctl = phys_enc->hw_ctl;
+	if (!hw_ctl)
+		return;
+
+	SDE_ATRACE_BEGIN("vblank_irq");
+
+	/*
+	 * only decrement the pending flush count if we've actually flushed
+	 * hardware. due to sw irq latency, vblank may have already happened
+	 * so we need to double-check with hw that it accepted the flush bits
+	 */
+	spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
+
+	old_cnt = atomic_read(&phys_enc->pending_kickoff_cnt);
+
+	if (hw_ctl && hw_ctl->ops.get_flush_register)
+		flush_register = hw_ctl->ops.get_flush_register(hw_ctl);
+
+	shd_ctl = container_of(hw_ctl, struct sde_shd_hw_ctl, base);
+
+	if (flush_register)
+		SDE_DEBUG("%d irq flush=0x%x mask=0x%x\n",
+			DRMID(phys_enc->parent),
+			flush_register, shd_ctl->flush_mask);
+
+	if (flush_register & shd_ctl->flush_mask)
+		goto not_flushed;
+
+	new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);
+
+	if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0))
+		event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE |
+			SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
+
+not_flushed:
+	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
+
+	if (event && phys_enc->parent_ops.handle_frame_done)
+		phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
+			phys_enc, event);
+
+	if (phys_enc->parent_ops.handle_vblank_virt)
+		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
+				phys_enc);
+
+	SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0,
+		old_cnt, new_cnt,
+		flush_register, event);
+
+	/* Signal any waiting atomic commit thread */
+	wake_up_all(&phys_enc->pending_kickoff_wq);
+
+	SDE_ATRACE_END("vblank_irq");
+}
+
+static int _sde_encoder_phys_shd_register_irq(
+		struct sde_encoder_phys *phys_enc,
+		enum sde_intr_idx intr_idx,
+		bool enable)
+{
+	struct sde_encoder_irq *irq = &phys_enc->irq[intr_idx];
+	int ret = 0;
+
+	SDE_DEBUG("%d enable %d\n", DRMID(phys_enc->parent), enable);
+
+	if (enable) {
+		if (irq->irq_idx >= 0) {
+			SDE_DEBUG_PHYS(phys_enc,
+				"skipping already registered irq %s type %d\n",
+				irq->name, irq->intr_type);
+			return 0;
+		}
+
+		irq->irq_idx = sde_core_irq_idx_lookup(phys_enc->sde_kms,
+				irq->intr_type, irq->hw_idx);
+		if (irq->irq_idx < 0) {
+			SDE_ERROR_PHYS(phys_enc,
+				"failed to lookup IRQ index for %s type:%d\n",
+				irq->name, irq->intr_type);
+			return -EINVAL;
+		}
+
+		ret = sde_core_irq_register_callback(phys_enc->sde_kms,
+				irq->irq_idx, &irq->cb);
+		if (ret) {
+			SDE_ERROR_PHYS(phys_enc,
+				"failed to register IRQ callback for %s\n",
+				irq->name);
+			irq->irq_idx = -EINVAL;
+		}
+	} else {
+		if (irq->irq_idx < 0) {
+			SDE_DEBUG_PHYS(phys_enc,
+				"extra unregister irq, enc%d intr_idx:0x%x\n",
+				DRMID(phys_enc->parent), INTR_IDX_VSYNC);
+			return 0;
+		}
+
+		ret = sde_core_irq_unregister_callback(phys_enc->sde_kms,
+				irq->irq_idx, &irq->cb);
+		if (ret) {
+			SDE_ERROR_PHYS(phys_enc,
+				"failed to unregister IRQ callback for %s\n",
+				irq->name);
+		}
+
+		irq->irq_idx = -EINVAL;
+	}
+
+	return ret;
+}
+
+static inline
+void _sde_encoder_phys_shd_setup_irq_hw_idx(
+		struct sde_encoder_phys *phys_enc)
+{
+	struct sde_encoder_irq *irq;
+
+	irq = &phys_enc->irq[INTR_IDX_VSYNC];
+
+	if (irq->irq_idx < 0)
+		irq->hw_idx = phys_enc->intf_idx;
+}
+
+static int _sde_encoder_phys_shd_rm_reserve(
+		struct sde_encoder_phys *phys_enc,
+		struct shd_display *display)
+{
+	struct sde_encoder_phys_shd *shd_enc;
+	struct sde_rm *rm;
+	struct sde_rm_hw_iter ctl_iter, lm_iter, pp_iter;
+	struct drm_encoder *encoder;
+	struct sde_shd_hw_ctl *hw_ctl;
+	struct sde_shd_hw_mixer *hw_lm;
+	struct sde_hw_pingpong *hw_pp;
+	int i, rc = 0;
+
+	encoder = display->base->encoder;
+	rm = &phys_enc->sde_kms->rm;
+	shd_enc = to_sde_encoder_phys_shd(phys_enc);
+
+	sde_rm_init_hw_iter(&ctl_iter, encoder->base.id, SDE_HW_BLK_CTL);
+	sde_rm_init_hw_iter(&lm_iter, encoder->base.id, SDE_HW_BLK_LM);
+	sde_rm_init_hw_iter(&pp_iter, encoder->base.id, SDE_HW_BLK_PINGPONG);
+
+	shd_enc->num_mixers = 0;
+	shd_enc->num_ctls = 0;
+
+	for (i = 0; i < CRTC_DUAL_MIXERS; i++) {
+		/* reserve lm */
+		if (!sde_rm_get_hw(rm, &lm_iter))
+			break;
+		hw_lm = container_of(shd_enc->hw_lm[i],
+				struct sde_shd_hw_mixer, base);
+		hw_lm->base = *(struct sde_hw_mixer *)lm_iter.hw;
+		hw_lm->range = display->stage_range;
+		hw_lm->roi = display->roi;
+		hw_lm->orig = lm_iter.hw;
+		sde_shd_hw_lm_init_op(&hw_lm->base);
+
+		SDE_DEBUG("reserve LM%d %pK from enc %d to %d\n",
+			hw_lm->base.idx, hw_lm,
+			DRMID(encoder),
+			DRMID(phys_enc->parent));
+
+		rc = sde_rm_ext_blk_create_reserve(rm,
+			&hw_lm->base.base, phys_enc->parent);
+		if (rc) {
+			SDE_ERROR("failed to create & reserve lm\n");
+			break;
+		}
+		shd_enc->num_mixers++;
+
+		/* reserve ctl */
+		if (!sde_rm_get_hw(rm, &ctl_iter))
+			break;
+		hw_ctl = container_of(shd_enc->hw_ctl[i],
+				struct sde_shd_hw_ctl, base);
+		hw_ctl->base = *(struct sde_hw_ctl *)ctl_iter.hw;
+		hw_ctl->range = display->stage_range;
+		hw_ctl->orig = ctl_iter.hw;
+		sde_shd_hw_ctl_init_op(&hw_ctl->base);
+
+		SDE_DEBUG("reserve CTL%d %pK from enc %d to %d\n",
+			hw_ctl->base.idx, hw_ctl,
+			DRMID(encoder),
+			DRMID(phys_enc->parent));
+
+		rc = sde_rm_ext_blk_create_reserve(rm,
+			&hw_ctl->base.base, phys_enc->parent);
+		if (rc) {
+			SDE_ERROR("failed to create & reserve ctl\n");
+			break;
+		}
+		shd_enc->num_ctls++;
+
+		/* reserve pingpong */
+		if (!sde_rm_get_hw(rm, &pp_iter))
+			break;
+		hw_pp = pp_iter.hw;
+
+		SDE_DEBUG("reserve PP%d from enc %d to %d\n",
+			hw_pp->idx,
+			DRMID(encoder),
+			DRMID(phys_enc->parent));
+
+		rc = sde_rm_ext_blk_create_reserve(rm,
+			&hw_pp->base, phys_enc->parent);
+		if (rc) {
+			SDE_ERROR("failed to create & reserve pingpong\n");
+			break;
+		}
+	}
+
+	return rc;
+}
+
+static inline void _sde_encoder_phys_shd_rm_release(
+		struct sde_encoder_phys *phys_enc,
+		struct shd_display *display)
+{
+	struct sde_rm *rm;
+
+	rm = &phys_enc->sde_kms->rm;
+
+	sde_rm_ext_blk_destroy(rm, phys_enc->parent);
+}
+
+static void sde_encoder_phys_shd_mode_set(
+		struct sde_encoder_phys *phys_enc,
+		struct drm_display_mode *mode,
+		struct drm_display_mode *adj_mode)
+{
+	struct drm_connector *connector;
+	struct sde_connector *sde_conn;
+	struct shd_display *display;
+	struct drm_encoder *encoder;
+	struct sde_rm_hw_iter iter;
+	struct sde_rm *rm;
+
+	SDE_DEBUG("%d\n", phys_enc->parent->base.id);
+
+	phys_enc->cached_mode = *adj_mode;
+
+	connector = phys_enc->connector;
+	if (!connector || connector->encoder != phys_enc->parent) {
+		SDE_ERROR("failed to find connector\n");
+		return;
+	}
+
+	sde_conn = to_sde_connector(connector);
+	display = sde_conn->display;
+	encoder = display->base->encoder;
+
+	if (_sde_encoder_phys_shd_rm_reserve(phys_enc, display))
+		return;
+
+	rm = &phys_enc->sde_kms->rm;
+
+	sde_rm_init_hw_iter(&iter, DRMID(phys_enc->parent), SDE_HW_BLK_CTL);
+	if (sde_rm_get_hw(rm, &iter))
+		phys_enc->hw_ctl = (struct sde_hw_ctl *)iter.hw;
+	if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) {
+		SDE_DEBUG("failed to init ctl, %ld\n",
+				PTR_ERR(phys_enc->hw_ctl));
+		phys_enc->hw_ctl = NULL;
+		return;
+	}
+
+	sde_rm_init_hw_iter(&iter, DRMID(encoder), SDE_HW_BLK_INTF);
+	if (sde_rm_get_hw(rm, &iter))
+		phys_enc->hw_intf = (struct sde_hw_intf *)iter.hw;
+	if (IS_ERR_OR_NULL(phys_enc->hw_intf)) {
+		SDE_DEBUG("failed to init intf: %ld\n",
+				PTR_ERR(phys_enc->hw_intf));
+		phys_enc->hw_intf = NULL;
+		return;
+	}
+
+	sde_rm_init_hw_iter(&iter, DRMID(encoder), SDE_HW_BLK_PINGPONG);
+	if (sde_rm_get_hw(rm, &iter))
+		phys_enc->hw_pp = (struct sde_hw_pingpong *)iter.hw;
+	if (IS_ERR_OR_NULL(phys_enc->hw_pp)) {
+		SDE_DEBUG("failed to init pingpong: %ld\n",
+				PTR_ERR(phys_enc->hw_pp));
+		phys_enc->hw_pp = NULL;
+		return;
+	}
+
+	_sde_encoder_phys_shd_setup_irq_hw_idx(phys_enc);
+}
+
+static int _sde_encoder_phys_shd_wait_for_vblank(
+		struct sde_encoder_phys *phys_enc, bool notify)
+{
+	struct sde_encoder_wait_info wait_info;
+	int ret = 0;
+	u32 event = 0;
+	u32 event_helper = 0;
+
+	if (!phys_enc) {
+		pr_err("invalid encoder\n");
+		return -EINVAL;
+	}
+
+	wait_info.wq = &phys_enc->pending_kickoff_wq;
+	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
+	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
+
+	/* Wait for kickoff to complete */
+	ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC,
+			&wait_info);
+
+	event_helper = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
+			| SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
+
+	if (notify) {
+		if (ret == -ETIMEDOUT) {
+			event = SDE_ENCODER_FRAME_EVENT_ERROR;
+			if (atomic_add_unless(
+				&phys_enc->pending_retire_fence_cnt, -1, 0))
+				event |= event_helper;
+		} else if (!ret) {
+			event = SDE_ENCODER_FRAME_EVENT_DONE;
+		}
+	}
+
+	SDE_EVT32(DRMID(phys_enc->parent), event, notify, ret,
+			ret ? SDE_EVTLOG_FATAL : 0);
+	if (phys_enc->parent_ops.handle_frame_done && event)
+		phys_enc->parent_ops.handle_frame_done(
+				phys_enc->parent, phys_enc,
+				event);
+	return ret;
+}
+
+static inline
+int sde_encoder_phys_shd_wait_for_vblank(
+		struct sde_encoder_phys *phys_enc)
+{
+	return _sde_encoder_phys_shd_wait_for_vblank(phys_enc, true);
+}
+
+static inline
+int sde_encoder_phys_shd_wait_for_vblank_no_notify(
+		struct sde_encoder_phys *phys_enc)
+{
+	return _sde_encoder_phys_shd_wait_for_vblank(phys_enc, false);
+}
+
+static inline
+int sde_encoder_phys_shd_prepare_for_kickoff(
+		struct sde_encoder_phys *phys_enc,
+		struct sde_encoder_kickoff_params *params)
+{
+	return 0;
+}
+
+static inline
+void sde_encoder_phys_shd_handle_post_kickoff(
+	struct sde_encoder_phys *phys_enc)
+{
+	if (!phys_enc || !phys_enc->hw_intf) {
+		SDE_ERROR("invalid encoder\n");
+		return;
+	}
+
+	if (phys_enc->enable_state == SDE_ENC_ENABLING) {
+		SDE_EVT32(DRMID(phys_enc->parent),
+				phys_enc->hw_intf->idx - INTF_0);
+		phys_enc->enable_state = SDE_ENC_ENABLED;
+	}
+}
+
+static inline
+void sde_encoder_phys_shd_trigger_flush(
+	struct sde_encoder_phys *phys_enc)
+{
+	struct sde_encoder_phys_shd *shd_enc;
+
+	shd_enc = container_of(phys_enc, struct sde_encoder_phys_shd, base);
+
+	sde_shd_hw_flush(phys_enc->hw_ctl,
+			shd_enc->hw_lm, shd_enc->num_mixers);
+}
+
+static void sde_encoder_phys_shd_enable(struct sde_encoder_phys *phys_enc)
+{
+	struct drm_connector *connector;
+
+	SDE_DEBUG("%d\n", phys_enc->parent->base.id);
+
+	if (!phys_enc->parent || !phys_enc->parent->dev) {
+		SDE_ERROR("invalid drm device\n");
+		return;
+	}
+
+	connector = phys_enc->connector;
+	if (!connector || connector->encoder != phys_enc->parent) {
+		SDE_ERROR("failed to find connector\n");
+		return;
+	}
+
+	if (phys_enc->enable_state == SDE_ENC_DISABLED)
+		phys_enc->enable_state = SDE_ENC_ENABLING;
+
+	SDE_EVT32(DRMID(phys_enc->parent),
+		atomic_read(&phys_enc->pending_retire_fence_cnt));
+}
+
+static void sde_encoder_phys_shd_disable(struct sde_encoder_phys *phys_enc)
+{
+	struct sde_connector *sde_conn;
+	struct shd_display *display;
+
+	SDE_DEBUG("%d\n", phys_enc->parent->base.id);
+
+	if (!phys_enc || !phys_enc->parent || !phys_enc->parent->dev ||
+			!phys_enc->parent->dev->dev_private) {
+		SDE_ERROR("invalid encoder/device\n");
+		return;
+	}
+
+	if (!phys_enc->hw_intf || !phys_enc->hw_ctl) {
+		SDE_ERROR("invalid hw_intf %d hw_ctl %d\n",
+				phys_enc->hw_intf != 0, phys_enc->hw_ctl != 0);
+		return;
+	}
+
+	if (phys_enc->enable_state == SDE_ENC_DISABLED) {
+		SDE_ERROR("already disabled\n");
+		return;
+	}
+
+	sde_encoder_helper_reset_mixers(phys_enc, NULL);
+
+	sde_encoder_phys_shd_trigger_flush(phys_enc);
+
+	sde_encoder_phys_shd_wait_for_vblank_no_notify(phys_enc);
+
+	phys_enc->enable_state = SDE_ENC_DISABLED;
+
+	if (!phys_enc->connector)
+		return;
+
+	sde_conn = to_sde_connector(phys_enc->connector);
+	display = sde_conn->display;
+
+	_sde_encoder_phys_shd_rm_release(phys_enc, display);
+
+	SDE_EVT32(DRMID(phys_enc->parent),
+		atomic_read(&phys_enc->pending_retire_fence_cnt));
+}
+
+static inline
+void sde_encoder_phys_shd_destroy(struct sde_encoder_phys *phys_enc)
+{
+	struct sde_encoder_phys_shd *shd_enc =
+		to_sde_encoder_phys_shd(phys_enc);
+
+	if (!phys_enc)
+		return;
+
+	kfree(shd_enc);
+}
+
+static int sde_encoder_phys_shd_control_vblank_irq(
+		struct sde_encoder_phys *phys_enc,
+		bool enable)
+{
+	int ret = 0;
+	struct sde_encoder_phys_shd *shd_enc;
+	int refcount;
+
+	if (!phys_enc || !phys_enc->hw_intf) {
+		SDE_ERROR("invalid encoder\n");
+		return -EINVAL;
+	}
+
+	refcount = atomic_read(&phys_enc->vblank_refcount);
+	shd_enc = to_sde_encoder_phys_shd(phys_enc);
+
+	/* protect against negative */
+	if (!enable && refcount == 0) {
+		ret = -EINVAL;
+		goto end;
+	}
+
+	SDE_DEBUG("[%pS] %d enable=%d/%d\n",
+			__builtin_return_address(0), DRMID(phys_enc->parent),
+			enable, atomic_read(&phys_enc->vblank_refcount));
+
+	SDE_EVT32(DRMID(phys_enc->parent), enable,
+			atomic_read(&phys_enc->vblank_refcount));
+
+	if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) {
+		ret = _sde_encoder_phys_shd_register_irq(phys_enc,
+				INTR_IDX_VSYNC, true);
+		if (ret)
+			atomic_dec_return(&phys_enc->vblank_refcount);
+	} else if (!enable &&
+			atomic_dec_return(&phys_enc->vblank_refcount) == 0) {
+		ret = _sde_encoder_phys_shd_register_irq(phys_enc,
+				INTR_IDX_VSYNC, false);
+		if (ret)
+			atomic_inc_return(&phys_enc->vblank_refcount);
+	}
+
+end:
+	if (ret) {
+		SDE_DEBUG("control vblank irq error %d, enable %d\n",
+				ret, enable);
+		SDE_EVT32(DRMID(phys_enc->parent),
+				phys_enc->hw_intf->idx - INTF_0,
+				enable, refcount, SDE_EVTLOG_ERROR);
+	}
+	return ret;
+}
+
+static inline
+void sde_encoder_phys_shd_irq_ctrl(
+		struct sde_encoder_phys *phys_enc, bool enable)
+{
+	sde_encoder_phys_shd_control_vblank_irq(phys_enc, enable);
+}
+
+static inline
+int sde_encoder_phys_shd_get_line_count(
+		struct sde_encoder_phys *phys)
+{
+	return 0;
+}
+
+/**
+ * sde_encoder_phys_shd_init_ops - initialize writeback operations
+ * @ops:	Pointer to encoder operation table
+ */
+static void sde_encoder_phys_shd_init_ops(struct sde_encoder_phys_ops *ops)
+{
+	ops->is_master = sde_encoder_phys_shd_is_master;
+	ops->mode_set = sde_encoder_phys_shd_mode_set;
+	ops->enable = sde_encoder_phys_shd_enable;
+	ops->disable = sde_encoder_phys_shd_disable;
+	ops->destroy = sde_encoder_phys_shd_destroy;
+	ops->wait_for_commit_done = sde_encoder_phys_shd_wait_for_vblank;
+	ops->wait_for_vblank = sde_encoder_phys_shd_wait_for_vblank_no_notify;
+	ops->prepare_for_kickoff = sde_encoder_phys_shd_prepare_for_kickoff;
+	ops->handle_post_kickoff = sde_encoder_phys_shd_handle_post_kickoff;
+	ops->trigger_flush = sde_encoder_phys_shd_trigger_flush;
+	ops->control_vblank_irq = sde_encoder_phys_shd_control_vblank_irq;
+	ops->wait_for_tx_complete = sde_encoder_phys_shd_wait_for_vblank;
+	ops->irq_control = sde_encoder_phys_shd_irq_ctrl;
+	ops->get_line_count = sde_encoder_phys_shd_get_line_count;
+}
+
+void *sde_encoder_phys_shd_init(enum sde_intf_type type,
+			u32 controller_id, void *phys_init_params)
+{
+	struct sde_enc_phys_init_params *p = phys_init_params;
+	struct sde_encoder_phys *phys_enc;
+	struct sde_encoder_phys_shd *shd_enc;
+	struct sde_encoder_irq *irq;
+	struct sde_shd_hw_ctl *hw_ctl;
+	struct sde_shd_hw_mixer *hw_lm;
+	int ret = 0, i;
+
+	SDE_DEBUG("\n");
+
+	shd_enc = kzalloc(sizeof(*shd_enc), GFP_KERNEL);
+	if (!shd_enc) {
+		ret = -ENOMEM;
+		goto fail_alloc;
+	}
+
+	for (i = 0; i < CRTC_DUAL_MIXERS; i++) {
+		hw_ctl = kzalloc(sizeof(*hw_ctl), GFP_KERNEL);
+		if (!hw_ctl) {
+			ret = -ENOMEM;
+			goto fail_ctl;
+		}
+		shd_enc->hw_ctl[i] = &hw_ctl->base;
+
+		hw_lm = kzalloc(sizeof(*hw_lm), GFP_KERNEL);
+		if (!hw_lm) {
+			ret = -ENOMEM;
+			goto fail_ctl;
+		}
+		shd_enc->hw_lm[i] = &hw_lm->base;
+	}
+
+	phys_enc = &shd_enc->base;
+
+	sde_encoder_phys_shd_init_ops(&phys_enc->ops);
+	phys_enc->parent = p->parent;
+	phys_enc->parent_ops = p->parent_ops;
+	phys_enc->sde_kms = p->sde_kms;
+	phys_enc->split_role = p->split_role;
+	phys_enc->intf_mode = INTF_MODE_NONE;
+	phys_enc->intf_idx = INTF_0 + controller_id;
+	phys_enc->enc_spinlock = p->enc_spinlock;
+	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
+
+	irq = &phys_enc->irq[INTR_IDX_VSYNC];
+	irq->name = "vsync_irq";
+	irq->intr_type = SDE_IRQ_TYPE_INTF_VSYNC;
+	irq->intr_idx = INTR_IDX_VSYNC;
+	irq->cb.func = sde_encoder_phys_shd_vblank_irq;
+
+	for (i = 0; i < INTR_IDX_MAX; i++) {
+		irq = &phys_enc->irq[i];
+		INIT_LIST_HEAD(&irq->cb.list);
+		irq->irq_idx = -EINVAL;
+		irq->hw_idx = -EINVAL;
+		irq->cb.arg = phys_enc;
+	}
+
+	atomic_set(&phys_enc->vblank_refcount, 0);
+	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
+	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
+	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
+	phys_enc->enable_state = SDE_ENC_DISABLED;
+
+	return phys_enc;
+
+fail_ctl:
+	for (i = 0; i < CRTC_DUAL_MIXERS; i++) {
+		kfree(shd_enc->hw_ctl[i]);
+		kfree(shd_enc->hw_lm[i]);
+	}
+	kfree(shd_enc);
+fail_alloc:
+	return ERR_PTR(ret);
+}
+
diff --git a/drivers/gpu/drm/msm/shd/shd_drm.c b/drivers/gpu/drm/msm/shd/shd_drm.c
new file mode 100644
index 0000000..23625f1
--- /dev/null
+++ b/drivers/gpu/drm/msm/shd/shd_drm.c
@@ -0,0 +1,1396 @@
+/*
+ * 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.
+ *
+ */
+
+#define pr_fmt(fmt)	"[drm-shd] %s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/component.h>
+#include <linux/of_irq.h>
+#include <linux/kthread.h>
+#include <uapi/linux/sched/types.h>
+#include "sde_connector.h"
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_vblank.h>
+
+#include "msm_drv.h"
+#include "msm_kms.h"
+#include "sde_connector.h"
+#include "sde_encoder.h"
+#include "sde_crtc.h"
+#include "sde_plane.h"
+#include "shd_drm.h"
+
+static LIST_HEAD(g_base_list);
+
+struct shd_crtc {
+	struct drm_crtc_helper_funcs helper_funcs;
+	const struct drm_crtc_helper_funcs *orig_helper_funcs;
+	struct drm_crtc_funcs funcs;
+	const struct drm_crtc_funcs *orig_funcs;
+	struct shd_display *display;
+};
+
+struct shd_bridge {
+	struct drm_bridge base;
+	struct shd_display *display;
+};
+
+struct shd_kms {
+	struct msm_kms_funcs funcs;
+	const struct msm_kms_funcs *orig_funcs;
+};
+
+struct sde_cp_node_dummy {
+	u32 property_id;
+	u32 prop_flags;
+	u32 feature;
+	void *blob_ptr;
+	uint64_t prop_val;
+	const struct sde_pp_blk *pp_blk;
+	struct list_head feature_list;
+	struct list_head active_list;
+	struct list_head dirty_list;
+};
+
+static struct shd_kms *g_shd_kms;
+
+static enum drm_connector_status shd_display_base_detect(
+		struct drm_connector *connector,
+		bool force,
+		void *disp)
+{
+	return connector_status_disconnected;
+}
+
+static int shd_display_init_base_connector(struct drm_device *dev,
+						struct shd_display_base *base)
+{
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	struct sde_connector *sde_conn;
+	struct drm_connector_list_iter conn_iter;
+	int rc = 0;
+
+	drm_connector_list_iter_begin(dev, &conn_iter);
+	drm_for_each_connector_iter(connector, &conn_iter) {
+		encoder = drm_atomic_helper_best_encoder(connector);
+		if (encoder == base->encoder) {
+			base->connector = connector;
+			break;
+		}
+	}
+	drm_connector_list_iter_end(&conn_iter);
+
+	if (!base->connector) {
+		SDE_ERROR("failed to find connector\n");
+		return -ENOENT;
+	}
+
+	/* set base connector disconnected*/
+	sde_conn = to_sde_connector(base->connector);
+	base->ops = sde_conn->ops;
+	sde_conn->ops.detect = shd_display_base_detect;
+
+	SDE_DEBUG("found base connector %d\n", base->connector->base.id);
+
+	return rc;
+}
+
+static int shd_display_init_base_encoder(struct drm_device *dev,
+						struct shd_display_base *base)
+{
+	struct drm_encoder *encoder;
+	struct sde_encoder_hw_resources hw_res;
+	struct sde_connector_state conn_state = {};
+	bool has_mst;
+	int i, rc = 0;
+
+	drm_for_each_encoder(encoder, dev) {
+		sde_encoder_get_hw_resources(encoder,
+				&hw_res, &conn_state.base);
+		has_mst = (encoder->encoder_type == DRM_MODE_ENCODER_DPMST);
+		for (i = INTF_0; i < INTF_MAX; i++) {
+			if (hw_res.intfs[i - INTF_0] != INTF_MODE_NONE &&
+					base->intf_idx == (i - INTF_0) &&
+					base->mst_port == has_mst) {
+				base->encoder = encoder;
+				break;
+			}
+		}
+	}
+
+	if (!base->encoder) {
+		SDE_ERROR("can't find base encoder for intf %d\n",
+			base->intf_idx);
+		return -ENOENT;
+	}
+
+	switch (base->encoder->encoder_type) {
+	case DRM_MODE_ENCODER_DSI:
+		base->connector_type = DRM_MODE_CONNECTOR_DSI;
+		break;
+	case DRM_MODE_ENCODER_TMDS:
+	case DRM_MODE_ENCODER_DPMST:
+		base->connector_type = DRM_MODE_CONNECTOR_DisplayPort;
+		break;
+	default:
+		base->connector_type = DRM_MODE_CONNECTOR_Unknown;
+		break;
+	}
+
+	SDE_DEBUG("found base encoder %d, type %d, connect type %d\n",
+			base->encoder->base.id,
+			base->encoder->encoder_type,
+			base->connector_type);
+
+	return rc;
+}
+
+static int shd_display_init_base_crtc(struct drm_device *dev,
+						struct shd_display_base *base)
+{
+	struct drm_crtc *crtc = NULL;
+	struct msm_drm_private *priv;
+	int crtc_idx;
+	int i;
+
+	priv = dev->dev_private;
+
+	/* find last crtc for base encoder */
+	for (i = priv->num_crtcs - 1; i >= 0; i--) {
+		if (base->encoder->possible_crtcs & (1 << i)) {
+			crtc = priv->crtcs[i];
+			crtc_idx = i;
+			break;
+		}
+	}
+
+	if (!crtc)
+		return -ENOENT;
+
+	/* disable crtc from other encoders */
+	for (i = 0; i < priv->num_encoders; i++) {
+		if (priv->encoders[i] != base->encoder)
+			priv->encoders[i]->possible_crtcs &= ~(1 << crtc_idx);
+	}
+
+	base->crtc = crtc;
+	SDE_DEBUG("found base crtc %d\n", crtc->base.id);
+
+	return 0;
+}
+
+static void shd_display_setup_base_mixer_out(struct shd_display_base *base)
+{
+	struct sde_crtc *sde_crtc;
+	struct sde_hw_mixer_cfg lm_cfg;
+	struct sde_hw_mixer *hw_lm;
+	int i;
+
+	sde_crtc = to_sde_crtc(base->crtc);
+	if (!sde_crtc->num_mixers) {
+		SDE_ERROR("no layer mixer found\n");
+		return;
+	}
+
+	lm_cfg.out_width = base->mode.hdisplay / sde_crtc->num_mixers;
+	lm_cfg.out_height = base->mode.vdisplay;
+	lm_cfg.flags = 0;
+	for (i = 0; i < sde_crtc->num_mixers; i++) {
+		lm_cfg.right_mixer = i;
+		hw_lm = sde_crtc->mixers[i].hw_lm;
+		hw_lm->cfg.out_width = lm_cfg.out_width;
+		hw_lm->cfg.out_height = lm_cfg.out_height;
+		hw_lm->cfg.right_mixer = lm_cfg.right_mixer;
+		hw_lm->ops.setup_mixer_out(hw_lm, &lm_cfg);
+	}
+}
+
+static void shd_display_enable_base(struct drm_device *dev,
+				struct shd_display_base *base)
+{
+	const struct drm_encoder_helper_funcs *enc_funcs;
+	const struct drm_connector_helper_funcs *conn_funcs;
+	struct drm_connector *connector;
+	struct drm_crtc_state *crtc_state;
+	struct drm_connector_state *conn_state;
+
+	SDE_DEBUG("enable base display %d\n", base->intf_idx);
+
+	enc_funcs = base->encoder->helper_private;
+	if (!enc_funcs) {
+		SDE_ERROR("failed to find encoder helper\n");
+		return;
+	}
+
+	conn_funcs = base->connector->helper_private;
+	if (!conn_funcs) {
+		SDE_ERROR("failed to find connector helper\n");
+		return;
+	}
+
+	connector = base->connector;
+	crtc_state = base->crtc->state;
+	conn_state = connector->state;
+
+	crtc_state->active = true;
+	crtc_state->active_changed = true;
+	crtc_state->mode_changed = true;
+	crtc_state->connectors_changed = true;
+
+	base->encoder->crtc = base->crtc;
+	crtc_state->encoder_mask = (1 << drm_encoder_index(base->encoder));
+
+	conn_state->crtc = base->crtc;
+	drm_connector_get(connector);
+	conn_state->best_encoder = base->encoder;
+	connector->encoder = base->encoder;
+
+	drm_atomic_set_mode_for_crtc(crtc_state, &base->mode);
+	drm_mode_copy(&crtc_state->adjusted_mode, &base->mode);
+	drm_mode_copy(&base->crtc->mode, &base->mode);
+
+	if (conn_funcs->atomic_best_encoder) {
+		conn_funcs->atomic_best_encoder(base->connector,
+			conn_state);
+	}
+
+	drm_bridge_mode_fixup(base->encoder->bridge,
+		&crtc_state->mode,
+		&crtc_state->adjusted_mode);
+
+	if (enc_funcs->atomic_check) {
+		enc_funcs->atomic_check(base->encoder,
+			crtc_state,
+			conn_state);
+	}
+
+	if (enc_funcs->mode_fixup) {
+		enc_funcs->mode_fixup(base->encoder,
+			&crtc_state->mode,
+			&crtc_state->adjusted_mode);
+	}
+
+	if (enc_funcs->mode_set) {
+		enc_funcs->mode_set(base->encoder,
+			&crtc_state->mode,
+			&crtc_state->adjusted_mode);
+	}
+
+	sde_crtc_update_cont_splash_settings(base->crtc);
+
+	shd_display_setup_base_mixer_out(base);
+
+	drm_bridge_mode_set(base->encoder->bridge,
+		&crtc_state->mode,
+		&crtc_state->adjusted_mode);
+
+	drm_bridge_pre_enable(base->encoder->bridge);
+
+	if (enc_funcs->enable)
+		enc_funcs->enable(base->encoder);
+
+	sde_encoder_kickoff(base->encoder, false);
+
+	drm_bridge_enable(base->encoder->bridge);
+
+	base->enabled = true;
+}
+
+static void shd_display_disable_base(struct drm_device *dev,
+						struct shd_display_base *base)
+{
+	const struct drm_encoder_helper_funcs *enc_funcs;
+
+	SDE_DEBUG("disable base display %d\n", base->intf_idx);
+
+	enc_funcs = base->encoder->helper_private;
+	if (!enc_funcs) {
+		SDE_ERROR("failed to find encoder helper\n");
+		return;
+	}
+
+	drm_bridge_disable(base->encoder->bridge);
+
+	if (enc_funcs->disable)
+		enc_funcs->disable(base->encoder);
+
+	drm_bridge_post_disable(base->encoder->bridge);
+
+	base->enabled = false;
+	base->connector->state->crtc = NULL;
+	drm_connector_put(base->connector);
+}
+
+static void shd_display_enable(struct shd_display *display)
+{
+	struct drm_device *dev = display->drm_dev;
+	struct shd_display_base *base = display->base;
+
+	SDE_DEBUG("enable %s conn %d\n", display->name,
+					DRMID(base->connector));
+
+	mutex_lock(&base->base_mutex);
+
+	display->enabled = true;
+
+	if (!base->enabled)
+		shd_display_enable_base(dev, base);
+
+	mutex_unlock(&base->base_mutex);
+}
+
+static void shd_display_disable(struct shd_display *display)
+{
+	struct drm_device *dev = display->drm_dev;
+	struct shd_display_base *base = display->base;
+	struct shd_display *p;
+	bool enabled = false;
+
+	SDE_DEBUG("disable %s conn %d\n", display->name,
+					DRMID(base->connector));
+
+	mutex_lock(&base->base_mutex);
+
+	display->enabled = false;
+
+	if (!base->enabled)
+		goto end;
+
+	list_for_each_entry(p, &base->disp_list, head) {
+		if (p->enabled) {
+			enabled = true;
+			break;
+		}
+	}
+
+	if (!enabled)
+		shd_display_disable_base(dev, base);
+
+end:
+	mutex_unlock(&base->base_mutex);
+}
+
+static int shd_crtc_validate_shared_display(struct drm_crtc *crtc,
+		struct drm_crtc_state *state)
+{
+	struct sde_crtc *sde_crtc;
+	struct shd_crtc *shd_crtc;
+	struct sde_crtc_state *sde_crtc_state;
+	struct drm_plane *plane;
+	const struct drm_plane_state *pstate;
+	struct sde_plane_state *sde_pstate;
+	int i;
+
+	sde_crtc = to_sde_crtc(crtc);
+	shd_crtc = sde_crtc->priv_handle;
+	sde_crtc_state = to_sde_crtc_state(state);
+
+	/* check z-pos for all planes */
+	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
+		sde_pstate = to_sde_plane_state(pstate);
+		if (sde_pstate->stage >= shd_crtc->display->stage_range.size) {
+			SDE_ERROR("plane stage %d is larger than maximum %d\n",
+				sde_pstate->stage,
+				shd_crtc->display->stage_range.size);
+			return -EINVAL;
+		}
+	}
+
+	/* check z-pos for all dim layers */
+	for (i = 0; i < sde_crtc_state->num_dim_layers; i++) {
+		if (sde_crtc_state->dim_layer[i].stage >=
+			shd_crtc->display->stage_range.size + SDE_STAGE_0) {
+			SDE_ERROR("dim stage %d is larger than maximum %d\n",
+				sde_crtc_state->dim_layer[i].stage,
+				shd_crtc->display->stage_range.size);
+			return -EINVAL;
+		}
+	}
+
+	/* update crtc_roi */
+	sde_crtc_state->crtc_roi.x = -shd_crtc->display->roi.x;
+	sde_crtc_state->crtc_roi.y = -shd_crtc->display->roi.y;
+	sde_crtc_state->crtc_roi.w = 0;
+	sde_crtc_state->crtc_roi.h = 0;
+
+	return 0;
+}
+
+static int shd_crtc_atomic_check(struct drm_crtc *crtc,
+		struct drm_crtc_state *state)
+{
+	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
+	struct shd_crtc *shd_crtc = sde_crtc->priv_handle;
+	struct sde_crtc_state *sde_crtc_state = to_sde_crtc_state(state);
+	int rc;
+
+	/* disable bw voting if not full size in vertical */
+	if (shd_crtc->display->roi.h != shd_crtc->display->base->mode.vdisplay)
+		sde_crtc_state->bw_control = false;
+
+	rc = shd_crtc->orig_helper_funcs->atomic_check(crtc, state);
+	if (rc)
+		return rc;
+
+	return shd_crtc_validate_shared_display(crtc, state);
+}
+
+static int shd_crtc_atomic_set_property(struct drm_crtc *crtc,
+		struct drm_crtc_state *state,
+		struct drm_property *property,
+		uint64_t val)
+{
+	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
+	struct shd_crtc *shd_crtc = sde_crtc->priv_handle;
+	struct sde_cp_node_dummy *prop_node;
+
+	if (!crtc || !state || !property) {
+		SDE_ERROR("invalid argument(s)\n");
+		return -EINVAL;
+	}
+
+	/* ignore all the dspp properties */
+	list_for_each_entry(prop_node, &sde_crtc->feature_list, feature_list) {
+		if (property->base.id == prop_node->property_id)
+			return 0;
+	}
+
+	return shd_crtc->orig_funcs->atomic_set_property(crtc,
+		state, property, val);
+}
+
+static void shd_display_prepare_commit(struct msm_kms *kms,
+		struct drm_atomic_state *state)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	struct sde_crtc *sde_crtc;
+	struct shd_crtc *shd_crtc;
+	struct sde_kms *sde_kms;
+	struct drm_device *dev;
+	struct msm_drm_private *priv;
+	int i;
+
+	if (!kms)
+		return;
+	sde_kms = to_sde_kms(kms);
+	dev = sde_kms->dev;
+
+	if (!dev || !dev->dev_private)
+		return;
+	priv = dev->dev_private;
+
+	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
+
+	if (sde_kms->first_kickoff) {
+		sde_power_scale_reg_bus(&priv->phandle, sde_kms->core_client,
+			VOTE_INDEX_HIGH, false);
+		sde_kms->first_kickoff = false;
+	}
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		if (crtc->helper_private->atomic_check !=
+				shd_crtc_atomic_check)
+			continue;
+
+		if (!crtc_state->active ||
+		    !drm_atomic_crtc_needs_modeset(crtc_state))
+			continue;
+
+		sde_crtc = to_sde_crtc(crtc);
+		shd_crtc = sde_crtc->priv_handle;
+		shd_display_enable(shd_crtc->display);
+	}
+
+	g_shd_kms->orig_funcs->prepare_commit(kms, state);
+
+	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
+}
+
+static void shd_display_complete_commit(struct msm_kms *kms,
+		struct drm_atomic_state *state)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+	struct sde_crtc *sde_crtc;
+	struct shd_crtc *shd_crtc;
+	struct sde_kms *sde_kms;
+	struct drm_device *dev;
+	struct msm_drm_private *priv;
+	int i;
+
+	if (!kms)
+		return;
+	sde_kms = to_sde_kms(kms);
+	dev = sde_kms->dev;
+
+	if (!dev || !dev->dev_private)
+		return;
+	priv = dev->dev_private;
+
+	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
+
+	g_shd_kms->orig_funcs->complete_commit(kms, state);
+
+	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
+						new_crtc_state, i) {
+		if (crtc->helper_private->atomic_check !=
+				shd_crtc_atomic_check)
+			continue;
+
+		if (!old_crtc_state->active ||
+		    new_crtc_state->active ||
+		    !drm_atomic_crtc_needs_modeset(new_crtc_state))
+			continue;
+
+		sde_crtc = to_sde_crtc(crtc);
+		shd_crtc = sde_crtc->priv_handle;
+		shd_display_disable(shd_crtc->display);
+	}
+
+	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
+}
+
+static int shd_connector_get_info(struct drm_connector *connector,
+		struct msm_display_info *info, void *data)
+{
+	struct shd_display *display = data;
+
+	if (!info || !data || !display->base || !display->drm_dev) {
+		SDE_ERROR("invalid params\n");
+		return -EINVAL;
+	}
+
+	info->intf_type = display->base->connector_type;
+	info->capabilities = MSM_DISPLAY_CAP_VID_MODE |
+				MSM_DISPLAY_CAP_HOT_PLUG |
+				MSM_DISPLAY_CAP_MST_MODE;
+	info->is_connected = true;
+	info->num_of_h_tiles = 1;
+	info->h_tile_instance[0] = display->base->intf_idx;
+
+	return 0;
+}
+
+static int shd_connector_get_mode_info(struct drm_connector *connector,
+		const struct drm_display_mode *drm_mode,
+		struct msm_mode_info *mode_info,
+		u32 max_mixer_width, void *display)
+{
+	struct shd_display *shd_display = display;
+
+	if (!drm_mode || !mode_info || !max_mixer_width || !display) {
+		SDE_ERROR("invalid params\n");
+		return -EINVAL;
+	}
+
+	memset(mode_info, 0, sizeof(*mode_info));
+
+	mode_info->frame_rate = drm_mode->vrefresh;
+	mode_info->vtotal = drm_mode->vtotal;
+	mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
+
+	if (shd_display->src.h != shd_display->roi.h)
+		mode_info->vpadding = shd_display->roi.h;
+
+	return 0;
+}
+
+static
+enum drm_connector_status shd_connector_detect(struct drm_connector *conn,
+		bool force,
+		void *display)
+{
+	struct shd_display *disp = display;
+	struct sde_connector *sde_conn;
+	enum drm_connector_status status = connector_status_disconnected;
+
+	if (!conn || !display || !disp->base) {
+		SDE_ERROR("invalid params\n");
+		goto end;
+	}
+
+	mutex_lock(&disp->base->base_mutex);
+	if (disp->base->connector) {
+		sde_conn = to_sde_connector(disp->base->connector);
+		status = disp->base->ops.detect(disp->base->connector,
+						force, sde_conn->display);
+	}
+	mutex_unlock(&disp->base->base_mutex);
+
+end:
+	return status;
+}
+
+static int shd_connector_get_modes(struct drm_connector *connector,
+		void *display)
+{
+	struct drm_display_mode drm_mode;
+	struct shd_display *disp = display;
+	struct drm_display_mode *m;
+
+	memcpy(&drm_mode, &disp->base->mode, sizeof(drm_mode));
+
+	drm_mode.hdisplay = disp->src.w;
+	drm_mode.hsync_start = drm_mode.hdisplay;
+	drm_mode.hsync_end = drm_mode.hsync_start;
+	drm_mode.htotal = drm_mode.hsync_end;
+
+	drm_mode.vdisplay = disp->src.h;
+	drm_mode.vsync_start = drm_mode.vdisplay;
+	drm_mode.vsync_end = drm_mode.vsync_start;
+	drm_mode.vtotal = drm_mode.vsync_end;
+
+	m = drm_mode_duplicate(disp->drm_dev, &drm_mode);
+	drm_mode_set_name(m);
+	drm_mode_probed_add(connector, m);
+
+	return 1;
+}
+
+static
+enum drm_mode_status shd_connector_mode_valid(struct drm_connector *connector,
+		struct drm_display_mode *mode,
+		void *display)
+{
+	return MODE_OK;
+}
+
+static int shd_conn_set_info_blob(struct drm_connector *connector,
+		void *info,
+		void *display,
+		struct msm_mode_info *mode_info)
+{
+	struct shd_display *shd_display = display;
+
+	if (!info || !shd_display)
+		return -EINVAL;
+
+	sde_kms_info_add_keyint(info, "max_blendstages",
+				shd_display->stage_range.size);
+
+	return 0;
+}
+
+static int shd_conn_set_property(struct drm_connector *connector,
+		struct drm_connector_state *state,
+		int property_index,
+		uint64_t value,
+		void *display)
+{
+	struct sde_connector *c_conn;
+
+	c_conn = to_sde_connector(connector);
+
+	/* overwrite properties that are not supported */
+	switch (property_index) {
+	case CONNECTOR_PROP_BL_SCALE:
+		c_conn->bl_scale_dirty = false;
+		c_conn->unset_bl_level = 0;
+		break;
+	case CONNECTOR_PROP_AD_BL_SCALE:
+		c_conn->bl_scale_dirty = false;
+		c_conn->unset_bl_level = 0;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static inline
+int shd_bridge_attach(struct drm_bridge *shd_bridge)
+{
+	return 0;
+}
+
+static inline
+void shd_bridge_pre_enable(struct drm_bridge *drm_bridge)
+{
+}
+
+static inline
+void shd_bridge_enable(struct drm_bridge *drm_bridge)
+{
+}
+
+static inline
+void shd_bridge_disable(struct drm_bridge *drm_bridge)
+{
+}
+
+static inline
+void shd_bridge_post_disable(struct drm_bridge *drm_bridge)
+{
+}
+
+
+static inline
+void shd_bridge_mode_set(struct drm_bridge *drm_bridge,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+}
+
+static inline
+bool shd_bridge_mode_fixup(struct drm_bridge *drm_bridge,
+				  const struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static const struct drm_bridge_funcs shd_bridge_ops = {
+	.attach       = shd_bridge_attach,
+	.mode_fixup   = shd_bridge_mode_fixup,
+	.pre_enable   = shd_bridge_pre_enable,
+	.enable       = shd_bridge_enable,
+	.disable      = shd_bridge_disable,
+	.post_disable = shd_bridge_post_disable,
+	.mode_set     = shd_bridge_mode_set,
+};
+
+static int shd_drm_bridge_init(void *data, struct drm_encoder *encoder)
+{
+	int rc = 0;
+	struct shd_bridge *bridge;
+	struct drm_device *dev;
+	struct shd_display *display = data;
+	struct msm_drm_private *priv = NULL;
+
+	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
+	if (!bridge) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	dev = display->drm_dev;
+	bridge->display = display;
+	bridge->base.funcs = &shd_bridge_ops;
+	bridge->base.encoder = encoder;
+
+	priv = dev->dev_private;
+
+	rc = drm_bridge_attach(encoder, &bridge->base, NULL);
+	if (rc) {
+		SDE_ERROR("failed to attach bridge, rc=%d\n", rc);
+		goto error_free_bridge;
+	}
+
+	encoder->bridge = &bridge->base;
+	priv->bridges[priv->num_bridges++] = &bridge->base;
+	display->bridge = &bridge->base;
+
+	return 0;
+
+error_free_bridge:
+	kfree(bridge);
+error:
+	return rc;
+}
+
+static void shd_drm_bridge_deinit(void *data)
+{
+	struct shd_display *display = data;
+	struct shd_bridge *bridge = container_of(display->bridge,
+		struct shd_bridge, base);
+
+	if (bridge && bridge->base.encoder)
+		bridge->base.encoder->bridge = NULL;
+
+	kfree(bridge);
+}
+
+static int shd_drm_obj_init(struct shd_display *display)
+{
+	struct msm_drm_private *priv;
+	struct drm_device *dev;
+	struct drm_crtc *crtc;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	struct sde_crtc *sde_crtc;
+	struct shd_crtc *shd_crtc;
+	struct msm_display_info info;
+	int rc = 0;
+	uint32_t i;
+
+	static const struct sde_connector_ops shd_ops = {
+		.set_info_blob = shd_conn_set_info_blob,
+		.detect =       shd_connector_detect,
+		.get_modes =    shd_connector_get_modes,
+		.mode_valid =   shd_connector_mode_valid,
+		.get_info =     shd_connector_get_info,
+		.get_mode_info = shd_connector_get_mode_info,
+		.set_property = shd_conn_set_property,
+	};
+
+	static const struct sde_encoder_ops enc_ops = {
+		.phys_init =    sde_encoder_phys_shd_init,
+	};
+
+	dev = display->drm_dev;
+	priv = dev->dev_private;
+
+	if (priv->num_crtcs >= MAX_CRTCS) {
+		SDE_ERROR("crtc reaches the maximum %d\n", priv->num_crtcs);
+		rc = -ENOENT;
+		goto end;
+	}
+
+	memset(&info, 0x0, sizeof(info));
+	rc = shd_connector_get_info(NULL, &info, display);
+	if (rc) {
+		SDE_ERROR("shd get_info %d failed\n", i);
+		goto end;
+	}
+
+	encoder = sde_encoder_init_with_ops(dev, &info, &enc_ops);
+	if (IS_ERR_OR_NULL(encoder)) {
+		SDE_ERROR("shd encoder init failed %d\n", i);
+		rc = -ENOENT;
+		goto end;
+	}
+
+	SDE_DEBUG("create encoder %d\n", DRMID(encoder));
+
+	rc = shd_drm_bridge_init(display, encoder);
+	if (rc) {
+		SDE_ERROR("shd bridge init failed, %d\n", rc);
+		sde_encoder_destroy(encoder);
+		goto end;
+	}
+
+	connector = sde_connector_init(dev,
+				encoder,
+				NULL,
+				display,
+				&shd_ops,
+				DRM_CONNECTOR_POLL_HPD,
+				info.intf_type);
+	if (connector) {
+		priv->encoders[priv->num_encoders++] = encoder;
+		priv->connectors[priv->num_connectors++] = connector;
+	} else {
+		SDE_ERROR("shd %d connector init failed\n", i);
+		shd_drm_bridge_deinit(display);
+		sde_encoder_destroy(encoder);
+		rc = -ENOENT;
+		goto end;
+	}
+
+	SDE_DEBUG("create connector %d\n", DRMID(connector));
+
+	crtc = sde_crtc_init(dev, priv->planes[0]);
+	if (IS_ERR(crtc)) {
+		rc = PTR_ERR(crtc);
+		goto end;
+	}
+	priv->crtcs[priv->num_crtcs++] = crtc;
+	sde_crtc_post_init(dev, crtc);
+
+	SDE_DEBUG("create crtc %d index %d\n", DRMID(crtc),
+		drm_crtc_index(crtc));
+
+	/* update encoder's possible crtcs */
+	encoder->possible_crtcs = 1 << (priv->num_crtcs - 1);
+
+	/* update plane's possible crtcs */
+	for (i = 0; i < priv->num_planes; i++)
+		priv->planes[i]->possible_crtcs |= 1 << (priv->num_crtcs - 1);
+
+	/* update crtc's check function */
+	shd_crtc = kzalloc(sizeof(*shd_crtc), GFP_KERNEL);
+	if (!shd_crtc) {
+		rc = -ENOMEM;
+		goto end;
+	}
+
+	shd_crtc->helper_funcs = *crtc->helper_private;
+	shd_crtc->orig_helper_funcs = crtc->helper_private;
+	shd_crtc->helper_funcs.atomic_check = shd_crtc_atomic_check;
+	shd_crtc->funcs = *crtc->funcs;
+	shd_crtc->orig_funcs = crtc->funcs;
+	shd_crtc->funcs.atomic_set_property = shd_crtc_atomic_set_property;
+	shd_crtc->display = display;
+	sde_crtc = to_sde_crtc(crtc);
+	sde_crtc->priv_handle = shd_crtc;
+	crtc->helper_private = &shd_crtc->helper_funcs;
+	crtc->funcs = &shd_crtc->funcs;
+
+	/* initialize display thread */
+	i = priv->num_crtcs - 1;
+	priv->disp_thread[i].crtc_id = priv->crtcs[i]->base.id;
+	kthread_init_worker(&priv->disp_thread[i].worker);
+	priv->disp_thread[i].dev = dev;
+	priv->disp_thread[i].thread =
+		kthread_run(kthread_worker_fn,
+			&priv->disp_thread[i].worker,
+			"crtc_commit:%d", priv->disp_thread[i].crtc_id);
+	if (IS_ERR(priv->disp_thread[i].thread)) {
+		dev_err(dev->dev, "failed to create crtc_commit kthread\n");
+		priv->disp_thread[i].thread = NULL;
+	}
+
+	/* initialize event thread */
+	priv->event_thread[i].crtc_id = priv->crtcs[i]->base.id;
+	kthread_init_worker(&priv->event_thread[i].worker);
+	priv->event_thread[i].dev = dev;
+	priv->event_thread[i].thread =
+		kthread_run(kthread_worker_fn,
+			&priv->event_thread[i].worker,
+			"crtc_event:%d", priv->event_thread[i].crtc_id);
+	if (IS_ERR(priv->event_thread[i].thread)) {
+		dev_err(dev->dev, "failed to create crtc_event kthread\n");
+		priv->event_thread[i].thread = NULL;
+	}
+
+	/* re-initialize vblank as num_crtcs changes */
+	drm_vblank_cleanup(dev);
+	rc = drm_vblank_init(dev, priv->num_crtcs);
+	if (rc < 0)
+		dev_err(dev->dev, "failed to initialize vblank\n");
+
+	/* register components */
+	if (crtc->funcs->late_register)
+		crtc->funcs->late_register(crtc);
+	if (encoder->funcs->late_register)
+		encoder->funcs->late_register(encoder);
+	drm_connector_register(connector);
+
+	/* reset components */
+	if (crtc->funcs->reset)
+		crtc->funcs->reset(crtc);
+	if (encoder->funcs->reset)
+		encoder->funcs->reset(encoder);
+	if (connector->funcs->reset)
+		connector->funcs->reset(connector);
+
+end:
+	return rc;
+}
+
+static int shd_drm_base_init(struct drm_device *ddev,
+		struct shd_display_base *base)
+{
+	struct msm_drm_private *priv;
+	int rc;
+
+	rc = shd_display_init_base_encoder(ddev, base);
+	if (rc) {
+		SDE_ERROR("failed to find base encoder\n");
+		return rc;
+	}
+
+	rc = shd_display_init_base_connector(ddev, base);
+	if (rc) {
+		SDE_ERROR("failed to find base connector\n");
+		return rc;
+	}
+
+	rc = shd_display_init_base_crtc(ddev, base);
+	if (rc) {
+		SDE_ERROR("failed to find base crtc\n");
+		return rc;
+	}
+
+	if (!g_shd_kms) {
+		priv = ddev->dev_private;
+		g_shd_kms = kzalloc(sizeof(*g_shd_kms), GFP_KERNEL);
+		g_shd_kms->funcs = *priv->kms->funcs;
+		g_shd_kms->orig_funcs = priv->kms->funcs;
+		g_shd_kms->funcs.prepare_commit = shd_display_prepare_commit;
+		g_shd_kms->funcs.complete_commit = shd_display_complete_commit;
+		priv->kms->funcs = &g_shd_kms->funcs;
+	}
+
+	return rc;
+}
+
+static int shd_parse_display(struct shd_display *display)
+{
+	struct device_node *of_node = display->pdev->dev.of_node;
+	struct device_node *of_src, *of_roi;
+	u32 src_w, src_h, dst_x, dst_y, dst_w, dst_h;
+	u32 range[2];
+	int rc;
+
+	display->name = of_node->full_name;
+
+	display->base_of = of_parse_phandle(of_node,
+		"qcom,shared-display-base", 0);
+	if (!display->base_of) {
+		SDE_ERROR("No base device present\n");
+		rc = -ENODEV;
+		goto error;
+	}
+
+	of_src = of_get_child_by_name(of_node, "qcom,shared-display-src-mode");
+	if (!of_src) {
+		SDE_ERROR("No src mode present\n");
+		rc = -ENODEV;
+		goto error;
+	}
+
+	rc = of_property_read_u32(of_src, "qcom,mode-h-active",
+		&src_w);
+	if (rc) {
+		SDE_ERROR("Failed to parse h active\n");
+		goto error;
+	}
+
+	rc = of_property_read_u32(of_src, "qcom,mode-v-active",
+		&src_h);
+	if (rc) {
+		SDE_ERROR("Failed to parse v active\n");
+		goto error;
+	}
+
+	of_roi = of_get_child_by_name(of_node, "qcom,shared-display-dst-mode");
+	if (!of_roi) {
+		SDE_ERROR("No roi mode present\n");
+		rc = -ENODEV;
+		goto error;
+	}
+
+	rc = of_property_read_u32(of_roi, "qcom,mode-x-offset",
+		&dst_x);
+	if (rc) {
+		SDE_ERROR("Failed to parse x offset\n");
+		goto error;
+	}
+
+	rc = of_property_read_u32(of_roi, "qcom,mode-y-offset",
+		&dst_y);
+	if (rc) {
+		SDE_ERROR("Failed to parse y offset\n");
+		goto error;
+	}
+
+	rc = of_property_read_u32(of_roi, "qcom,mode-width",
+		&dst_w);
+	if (rc) {
+		SDE_ERROR("Failed to parse roi width\n");
+		goto error;
+	}
+
+	rc = of_property_read_u32(of_roi, "qcom,mode-height",
+		&dst_h);
+	if (rc) {
+		SDE_ERROR("Failed to parse roi height\n");
+		goto error;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,blend-stage-range",
+		range, 2);
+	if (rc)
+		SDE_ERROR("Failed to parse blend stage range\n");
+
+	display->src.w = src_w;
+	display->src.h = src_h;
+	display->roi.x = dst_x;
+	display->roi.y = dst_y;
+	display->roi.w = dst_w;
+	display->roi.h = dst_h;
+	display->stage_range.start = range[0];
+	display->stage_range.size = range[1];
+
+	SDE_DEBUG("%s src %dx%d dst %d,%d %dx%d range %d-%d\n", display->name,
+		display->src.w, display->src.h,
+		display->roi.x, display->roi.y,
+		display->roi.w, display->roi.h,
+		display->stage_range.start,
+		display->stage_range.size);
+
+error:
+	return rc;
+}
+
+static int shd_parse_base(struct shd_display_base *base)
+{
+	struct device_node *of_node = base->of_node;
+	struct device_node *node;
+	struct drm_display_mode *mode = &base->mode;
+	u32 h_front_porch, h_pulse_width, h_back_porch;
+	u32 v_front_porch, v_pulse_width, v_back_porch;
+	bool h_active_high, v_active_high;
+	u32 flags = 0;
+	int rc;
+
+	rc = of_property_read_u32(of_node, "qcom,shared-display-base-intf",
+					&base->intf_idx);
+	if (rc) {
+		SDE_ERROR("failed to read base intf, rc=%d\n", rc);
+		goto fail;
+	}
+
+	base->mst_port = of_property_read_bool(of_node,
+					"qcom,shared-display-base-mst");
+
+	node = of_get_child_by_name(of_node, "qcom,shared-display-base-mode");
+	if (!node) {
+		SDE_ERROR("No base mode present\n");
+		rc = -ENODEV;
+		goto fail;
+	}
+
+	rc = of_property_read_u32(node, "qcom,mode-h-active",
+					&mode->hdisplay);
+	if (rc) {
+		SDE_ERROR("failed to read h-active, rc=%d\n", rc);
+		goto fail;
+	}
+
+	rc = of_property_read_u32(node, "qcom,mode-h-front-porch",
+					&h_front_porch);
+	if (rc) {
+		SDE_ERROR("failed to read h-front-porch, rc=%d\n", rc);
+		goto fail;
+	}
+
+	rc = of_property_read_u32(node, "qcom,mode-h-pulse-width",
+					&h_pulse_width);
+	if (rc) {
+		SDE_ERROR("failed to read h-pulse-width, rc=%d\n", rc);
+		goto fail;
+	}
+
+	rc = of_property_read_u32(node, "qcom,mode-h-back-porch",
+					&h_back_porch);
+	if (rc) {
+		SDE_ERROR("failed to read h-back-porch, rc=%d\n", rc);
+		goto fail;
+	}
+
+	h_active_high = of_property_read_bool(node,
+					"qcom,mode-h-active-high");
+
+	rc = of_property_read_u32(node, "qcom,mode-v-active",
+					&mode->vdisplay);
+	if (rc) {
+		SDE_ERROR("failed to read v-active, rc=%d\n", rc);
+		goto fail;
+	}
+
+	rc = of_property_read_u32(node, "qcom,mode-v-front-porch",
+					&v_front_porch);
+	if (rc) {
+		SDE_ERROR("failed to read v-front-porch, rc=%d\n", rc);
+		goto fail;
+	}
+
+	rc = of_property_read_u32(node, "qcom,mode-v-pulse-width",
+					&v_pulse_width);
+	if (rc) {
+		SDE_ERROR("failed to read v-pulse-width, rc=%d\n", rc);
+		goto fail;
+	}
+
+	rc = of_property_read_u32(node, "qcom,mode-v-back-porch",
+					&v_back_porch);
+	if (rc) {
+		SDE_ERROR("failed to read v-back-porch, rc=%d\n", rc);
+		goto fail;
+	}
+
+	v_active_high = of_property_read_bool(node,
+					"qcom,mode-v-active-high");
+
+	rc = of_property_read_u32(node, "qcom,mode-refresh-rate",
+					&mode->vrefresh);
+	if (rc) {
+		SDE_ERROR("failed to read refresh-rate, rc=%d\n", rc);
+		goto fail;
+	}
+
+	rc = of_property_read_u32(node, "qcom,mode-clock-in-khz",
+					&mode->clock);
+	if (rc) {
+		SDE_ERROR("failed to read clock, rc=%d\n", rc);
+		goto fail;
+	}
+
+	mode->hsync_start = mode->hdisplay + h_front_porch;
+	mode->hsync_end = mode->hsync_start + h_pulse_width;
+	mode->htotal = mode->hsync_end + h_back_porch;
+	mode->vsync_start = mode->vdisplay + v_front_porch;
+	mode->vsync_end = mode->vsync_start + v_pulse_width;
+	mode->vtotal = mode->vsync_end + v_back_porch;
+	if (h_active_high)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+	if (v_active_high)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+	mode->flags = flags;
+
+	SDE_DEBUG("base mode h[%d,%d,%d,%d] v[%d,%d,%d,%d] %d %xH %d\n",
+		mode->hdisplay, mode->hsync_start,
+		mode->hsync_end, mode->htotal, mode->vdisplay,
+		mode->vsync_start, mode->vsync_end, mode->vtotal,
+		mode->vrefresh, mode->flags, mode->clock);
+
+fail:
+	return rc;
+}
+
+/**
+ * sde_shd_probe - load shared display module
+ * @pdev:	Pointer to platform device
+ */
+static int sde_shd_probe(struct platform_device *pdev)
+{
+	struct shd_display *shd_dev;
+	struct shd_display_base *base;
+	struct drm_minor *minor;
+	struct drm_device *ddev;
+	int ret;
+
+	/* defer until primary drm is created */
+	minor = drm_minor_acquire(0);
+	if (IS_ERR(minor))
+		return -EPROBE_DEFER;
+
+	ddev = minor->dev;
+	drm_minor_release(minor);
+	if (!ddev)
+		return -EPROBE_DEFER;
+
+	shd_dev = devm_kzalloc(&pdev->dev, sizeof(*shd_dev), GFP_KERNEL);
+	if (!shd_dev)
+		return -ENOMEM;
+
+	shd_dev->pdev = pdev;
+
+	ret = shd_parse_display(shd_dev);
+	if (ret) {
+		SDE_ERROR("failed to parse shared display\n");
+		goto error;
+	}
+
+	platform_set_drvdata(pdev, shd_dev);
+
+	list_for_each_entry(base, &g_base_list, head) {
+		if (base->of_node == shd_dev->base_of)
+			goto next;
+	}
+
+	base = devm_kzalloc(&pdev->dev, sizeof(*base), GFP_KERNEL);
+	if (!base) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	mutex_init(&base->base_mutex);
+	INIT_LIST_HEAD(&base->disp_list);
+	base->of_node = shd_dev->base_of;
+
+	ret = shd_parse_base(base);
+	if (ret) {
+		SDE_ERROR("failed to parse shared display base\n");
+		goto base_error;
+	}
+
+	mutex_lock(&ddev->mode_config.mutex);
+	ret = shd_drm_base_init(ddev, base);
+	mutex_unlock(&ddev->mode_config.mutex);
+	if (ret) {
+		SDE_ERROR("failed to init crtc for shared display base\n");
+		goto base_error;
+	}
+
+	list_add_tail(&base->head, &g_base_list);
+
+next:
+	shd_dev->base = base;
+	shd_dev->drm_dev = ddev;
+
+	mutex_lock(&ddev->mode_config.mutex);
+	ret = shd_drm_obj_init(shd_dev);
+	mutex_unlock(&ddev->mode_config.mutex);
+	if (ret) {
+		SDE_ERROR("failed to init shared drm objects\n");
+		goto error;
+	}
+
+	list_add_tail(&shd_dev->head, &base->disp_list);
+	SDE_DEBUG("add shd to intf %d\n", base->intf_idx);
+
+	return 0;
+
+base_error:
+	devm_kfree(&pdev->dev, base);
+error:
+	devm_kfree(&pdev->dev, shd_dev);
+	return ret;
+}
+
+/**
+ * sde_shd_remove - unload shared display module
+ * @pdev:	Pointer to platform device
+ */
+static int sde_shd_remove(struct platform_device *pdev)
+{
+	struct shd_display *shd_dev;
+
+	shd_dev = platform_get_drvdata(pdev);
+	if (!shd_dev)
+		return 0;
+
+	mutex_lock(&shd_dev->base->base_mutex);
+	list_del_init(&shd_dev->head);
+	if (list_empty(&shd_dev->base->disp_list))
+		list_del_init(&shd_dev->base->head);
+	mutex_unlock(&shd_dev->base->base_mutex);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id dt_match[] = {
+	{ .compatible = "qcom,shared-display"},
+	{},
+};
+
+static struct platform_driver sde_shd_driver = {
+	.probe = sde_shd_probe,
+	.remove = sde_shd_remove,
+	.driver = {
+		.name = "sde_shd",
+		.of_match_table = dt_match,
+		.suppress_bind_attrs = true,
+	},
+};
+
+static int __init sde_shd_register(void)
+{
+	return platform_driver_register(&sde_shd_driver);
+}
+
+static void __exit sde_shd_unregister(void)
+{
+	platform_driver_unregister(&sde_shd_driver);
+}
+
+module_init(sde_shd_register);
+module_exit(sde_shd_unregister);
diff --git a/drivers/gpu/drm/msm/shd/shd_drm.h b/drivers/gpu/drm/msm/shd/shd_drm.h
new file mode 100644
index 0000000..03aa95e
--- /dev/null
+++ b/drivers/gpu/drm/msm/shd/shd_drm.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _SHD_DRM_H_
+#define _SHD_DRM_H_
+
+#include <linux/types.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include "msm_drv.h"
+
+struct shd_mode_info {
+	int x_offset;
+	int y_offset;
+	int width;
+	int height;
+};
+
+struct shd_stage_range {
+	u32 start;
+	u32 size;
+};
+
+struct shd_display_base {
+	struct mutex           base_mutex;
+	struct drm_display_mode mode;
+	struct drm_crtc       *crtc;
+	struct drm_encoder    *encoder;
+	struct drm_connector  *connector;
+	struct list_head       head;
+	struct list_head       disp_list;
+	struct device_node    *of_node;
+	struct sde_connector_ops ops;
+
+	int intf_idx;
+	int connector_type;
+	bool mst_port;
+	bool enabled;
+};
+
+struct shd_display {
+	struct drm_device *drm_dev;
+	const char *name;
+
+	struct shd_display_base *base;
+	struct drm_bridge *bridge;
+
+	struct device_node *base_of;
+	struct sde_rect src;
+	struct sde_rect roi;
+	struct shd_stage_range stage_range;
+
+	struct platform_device *pdev;
+	struct completion vsync_comp;
+	struct list_head head;
+
+	bool enabled;
+};
+
+/* drm internal header */
+struct drm_minor *drm_minor_acquire(unsigned int minor_id);
+void drm_vblank_cleanup(struct drm_device *dev);
+void drm_minor_release(struct drm_minor *minor);
+
+void *sde_encoder_phys_shd_init(enum sde_intf_type type,
+			u32 controller_id, void *phys_init_params);
+
+
+#endif /* _SHD_DRM_H_ */
diff --git a/drivers/gpu/drm/msm/shd/shd_hw.c b/drivers/gpu/drm/msm/shd/shd_hw.c
new file mode 100644
index 0000000..834bad1
--- /dev/null
+++ b/drivers/gpu/drm/msm/shd/shd_hw.c
@@ -0,0 +1,451 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt)	"[drm-shd:%s:%d] " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/component.h>
+#include <linux/of_irq.h>
+#include <linux/kthread.h>
+#include <uapi/linux/sched/types.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_vblank.h>
+#include "msm_drv.h"
+#include "msm_kms.h"
+#include "sde_connector.h"
+#include "sde_encoder.h"
+#include "sde_crtc.h"
+#include "sde_plane.h"
+#include "shd_drm.h"
+#include "shd_hw.h"
+
+#define CTL_SSPP_FLUSH_MASK              0x3041807
+
+#define CTL_MIXER_FLUSH_MASK             0x00207C0
+
+#define   CTL_LAYER(lm)                 \
+		(((lm) == LM_5) ? (0x024) : (((lm) - LM_0) * 0x004))
+#define   CTL_LAYER_EXT(lm)             \
+		(0x40 + (((lm) - LM_0) * 0x004))
+#define   CTL_LAYER_EXT2(lm)             \
+		(0x70 + (((lm) - LM_0) * 0x004))
+#define   CTL_LAYER_EXT3(lm)             \
+		(0xA0 + (((lm) - LM_0) * 0x004))
+
+#define CTL_MIXER_BORDER_OUT            BIT(24)
+
+#define CTL_FLUSH_MASK                   0x090
+
+#define LM_BLEND0_OP                     0x00
+
+#define CTL_NUM_EXT			4
+
+#define CTL_SSPP_MAX_RECTS		2
+
+static DEFINE_SPINLOCK(hw_ctl_lock);
+
+/**
+ * struct ctl_sspp_stage_reg_map: Describes bit layout for a sspp stage cfg
+ * @ext: Index to indicate LAYER_x_EXT id for given sspp
+ * @start: Start position of blend stage bits for given sspp
+ * @bits: Number of bits from @start assigned for given sspp
+ * @sec_bit_mask: Bitmask to add to LAYER_x_EXT1 for missing bit of given sspp
+ */
+struct ctl_sspp_stage_reg_map {
+	u32 ext;
+	u32 start;
+	u32 bits;
+	u32 sec_bit_mask;
+};
+
+/**
+ * list of ctl_sspp_stage_reg_map for all the sppp
+ */
+static const struct ctl_sspp_stage_reg_map
+	sspp_reg_cfg_tbl[SSPP_MAX][CTL_SSPP_MAX_RECTS] = {
+	/* SSPP_NONE */{ {0, 0, 0, 0}, {0, 0, 0, 0} },
+	/* SSPP_VIG0 */{ {0, 0, 3, BIT(0)}, {3, 0, 4, 0} },
+	/* SSPP_VIG1 */{ {0, 3, 3, BIT(2)}, {3, 4, 4, 0} },
+	/* SSPP_VIG2 */{ {0, 6, 3, BIT(4)}, {3, 8, 4, 0} },
+	/* SSPP_VIG3 */{ {0, 26, 3, BIT(6)}, {3, 12, 4, 0} },
+	/* SSPP_RGB0 */{ {0, 9, 3, BIT(8)}, {0, 0, 0, 0} },
+	/* SSPP_RGB1 */{ {0, 12, 3, BIT(10)}, {0, 0, 0, 0} },
+	/* SSPP_RGB2 */{ {0, 15, 3, BIT(12)}, {0, 0, 0, 0} },
+	/* SSPP_RGB3 */{ {0, 29, 3, BIT(14)}, {0, 0, 0, 0} },
+	/* SSPP_DMA0 */{ {0, 18, 3, BIT(16)}, {2, 8, 4, 0} },
+	/* SSPP_DMA1 */{ {0, 21, 3, BIT(18)}, {2, 12, 4, 0} },
+	/* SSPP_DMA2 */{ {2, 0, 4, 0}, {2, 16, 4, 0} },
+	/* SSPP_DMA3 */{ {2, 4, 4, 0}, {2, 20, 4, 0} },
+	/* SSPP_CURSOR0 */ { {1, 20, 4, 0}, {0, 0, 0, 0} },
+	/* SSPP_CURSOR1 */ { {1, 26, 4, 0}, {0, 0, 0, 0} }
+};
+
+static void _sde_shd_hw_ctl_clear_blendstages_in_range(
+	struct sde_shd_hw_ctl *hw_ctl, enum sde_lm lm)
+{
+	struct sde_hw_ctl *ctx = &hw_ctl->base;
+	struct sde_hw_blk_reg_map *c = &ctx->hw;
+	u32 mixercfg[4];
+	u32 mixermask[4] = {0, 0, 0, 0};
+	u32 start = hw_ctl->range.start + SDE_STAGE_0;
+	u32 end = start + hw_ctl->range.size;
+	int pipes_per_stage;
+	int i, j;
+	u32 value, mask;
+	const struct ctl_sspp_stage_reg_map *sspp_cfg;
+
+	mixercfg[0] = SDE_REG_READ(c, CTL_LAYER(lm));
+	mixercfg[1] = SDE_REG_READ(c, CTL_LAYER_EXT(lm));
+	mixercfg[2] = SDE_REG_READ(c, CTL_LAYER_EXT2(lm));
+	mixercfg[3] = SDE_REG_READ(c, CTL_LAYER_EXT3(lm));
+
+	if (!((mixercfg[0] & ~CTL_MIXER_BORDER_OUT) |
+		mixercfg[1] | mixercfg[2] | mixercfg[3]))
+		goto end;
+
+	if (test_bit(SDE_MIXER_SOURCESPLIT,
+		&ctx->mixer_hw_caps->features))
+		pipes_per_stage = PIPES_PER_STAGE;
+	else
+		pipes_per_stage = 1;
+
+	for (i = 1; i < SSPP_MAX; i++) {
+		for (j = 0 ; j < pipes_per_stage; j++) {
+			sspp_cfg = &sspp_reg_cfg_tbl[i][j];
+			if (!sspp_cfg->bits)
+				continue;
+
+			mask = (1 << sspp_cfg->bits) - 1;
+			value = (mixercfg[sspp_cfg->ext] >> sspp_cfg->start);
+			value &= mask;
+			if (mixercfg[1] & sspp_cfg->sec_bit_mask)
+				value |= (1 << sspp_cfg->bits);
+
+			if (value > start && value <= end) {
+				mixermask[sspp_cfg->ext] |=
+					(mask << sspp_cfg->start);
+				mixermask[1] |= sspp_cfg->sec_bit_mask;
+			}
+		}
+	}
+
+end:
+	hw_ctl->mixer_cfg[lm].mixercfg_mask = mixermask[0];
+	hw_ctl->mixer_cfg[lm].mixercfg_ext_mask = mixermask[1];
+	hw_ctl->mixer_cfg[lm].mixercfg_ext2_mask = mixermask[2];
+	hw_ctl->mixer_cfg[lm].mixercfg_ext3_mask = mixermask[3];
+}
+
+static inline
+void _sde_shd_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx)
+{
+	struct sde_shd_hw_ctl *hw_ctl;
+	int i;
+
+	if (!ctx)
+		return;
+
+	hw_ctl = container_of(ctx, struct sde_shd_hw_ctl, base);
+
+	for (i = 0; i < ctx->mixer_count; i++) {
+		int mixer_id = ctx->mixer_hw_caps[i].id;
+
+		_sde_shd_hw_ctl_clear_blendstages_in_range(hw_ctl, mixer_id);
+	}
+}
+
+static inline int _stage_offset(struct sde_hw_mixer *ctx, enum sde_stage stage)
+{
+	const struct sde_lm_sub_blks *sblk = ctx->cap->sblk;
+	int rc;
+
+	if (stage == SDE_STAGE_BASE)
+		rc = -EINVAL;
+	else if (stage <= sblk->maxblendstages)
+		rc = sblk->blendstage_base[stage - SDE_STAGE_0];
+	else
+		rc = -EINVAL;
+
+	return rc;
+}
+
+static void _sde_shd_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
+	enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg)
+{
+	struct sde_shd_hw_ctl *hw_ctl;
+	int i, j;
+	int stages;
+	int pipes_per_stage;
+	int stage_offset = 0;
+	u32 pipe_idx, rect_idx;
+	const struct ctl_sspp_stage_reg_map *sspp_cfg;
+	u32 mixercfg[CTL_NUM_EXT] = {CTL_MIXER_BORDER_OUT, 0, 0, 0};
+	u32 mixermask[CTL_NUM_EXT] = {0, 0, 0, 0};
+	u32 value, mask, stage_value;
+
+	if (!ctx)
+		return;
+
+	hw_ctl = container_of(ctx, struct sde_shd_hw_ctl, base);
+
+	stages = hw_ctl->range.size - 1;
+	if (stages < 0)
+		return;
+
+	if (test_bit(SDE_MIXER_SOURCESPLIT,
+		&ctx->mixer_hw_caps->features))
+		pipes_per_stage = PIPES_PER_STAGE;
+	else
+		pipes_per_stage = 1;
+
+	_sde_shd_hw_ctl_clear_blendstages_in_range(hw_ctl, lm);
+
+	if (!stage_cfg)
+		goto exit;
+
+	stage_offset = hw_ctl->range.start;
+
+	for (i = 0; i <= stages; i++) {
+		for (j = 0 ; j < pipes_per_stage; j++) {
+			pipe_idx = stage_cfg->stage[i][j];
+			if (!pipe_idx || pipe_idx >= SSPP_MAX)
+				continue;
+
+			rect_idx = (stage_cfg->multirect_index[i][j]
+					== SDE_SSPP_RECT_1);
+
+			sspp_cfg = &sspp_reg_cfg_tbl[pipe_idx][rect_idx];
+			if (!sspp_cfg->bits)
+				continue;
+
+			stage_value = i + stage_offset + 1;
+			mask = (1 << sspp_cfg->bits) - 1;
+			value = mask & stage_value;
+			mixercfg[sspp_cfg->ext] |= (value << sspp_cfg->start);
+			if (stage_value > mask)
+				mixercfg[1] |= sspp_cfg->sec_bit_mask;
+
+			mixermask[sspp_cfg->ext] |= (mask << sspp_cfg->start);
+			mixermask[1] |= sspp_cfg->sec_bit_mask;
+		}
+	}
+
+	hw_ctl->mixer_cfg[lm].mixercfg_mask |= mixermask[0];
+	hw_ctl->mixer_cfg[lm].mixercfg_ext_mask |= mixermask[1];
+	hw_ctl->mixer_cfg[lm].mixercfg_ext2_mask |= mixermask[2];
+	hw_ctl->mixer_cfg[lm].mixercfg_ext3_mask |= mixermask[3];
+exit:
+	hw_ctl->mixer_cfg[lm].mixercfg = mixercfg[0];
+	hw_ctl->mixer_cfg[lm].mixercfg_ext = mixercfg[1];
+	hw_ctl->mixer_cfg[lm].mixercfg_ext2 = mixercfg[2];
+	hw_ctl->mixer_cfg[lm].mixercfg_ext3 = mixercfg[3];
+}
+
+static void _sde_shd_flush_hw_ctl(struct sde_hw_ctl *ctx)
+{
+	struct sde_shd_hw_ctl *hw_ctl;
+	struct sde_hw_blk_reg_map *c;
+	u32 mixercfg, mixercfg_ext;
+	u32 mixercfg_ext2, mixercfg_ext3;
+	int i;
+
+	hw_ctl = container_of(ctx, struct sde_shd_hw_ctl, base);
+
+	hw_ctl->flush_mask = ctx->flush.pending_flush_mask;
+
+	hw_ctl->flush_mask &= CTL_SSPP_FLUSH_MASK;
+
+	c = &ctx->hw;
+
+	for (i = 0; i < ctx->mixer_count; i++) {
+		int lm = ctx->mixer_hw_caps[i].id;
+
+		mixercfg = SDE_REG_READ(c, CTL_LAYER(lm));
+		mixercfg_ext = SDE_REG_READ(c, CTL_LAYER_EXT(lm));
+		mixercfg_ext2 = SDE_REG_READ(c, CTL_LAYER_EXT2(lm));
+		mixercfg_ext3 = SDE_REG_READ(c, CTL_LAYER_EXT3(lm));
+
+		mixercfg &= ~hw_ctl->mixer_cfg[lm].mixercfg_mask;
+		mixercfg_ext &= ~hw_ctl->mixer_cfg[lm].mixercfg_ext_mask;
+		mixercfg_ext2 &= ~hw_ctl->mixer_cfg[lm].mixercfg_ext2_mask;
+		mixercfg_ext3 &= ~hw_ctl->mixer_cfg[lm].mixercfg_ext3_mask;
+
+		mixercfg |= hw_ctl->mixer_cfg[lm].mixercfg;
+		mixercfg_ext |= hw_ctl->mixer_cfg[lm].mixercfg_ext;
+		mixercfg_ext2 |= hw_ctl->mixer_cfg[lm].mixercfg_ext2;
+		mixercfg_ext3 |= hw_ctl->mixer_cfg[lm].mixercfg_ext3;
+
+		SDE_REG_WRITE(c, CTL_LAYER(lm), mixercfg);
+		SDE_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg_ext);
+		SDE_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg_ext2);
+		SDE_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg_ext3);
+	}
+}
+
+static void _sde_shd_setup_blend_config(struct sde_hw_mixer *ctx,
+		uint32_t stage,
+		uint32_t fg_alpha, uint32_t bg_alpha, uint32_t blend_op)
+{
+	struct sde_shd_hw_mixer *hw_lm;
+	struct sde_shd_mixer_cfg *cfg;
+
+	if (!ctx)
+		return;
+
+	hw_lm = container_of(ctx, struct sde_shd_hw_mixer, base);
+
+	cfg = &hw_lm->cfg[stage + hw_lm->range.start];
+
+	cfg->fg_alpha = fg_alpha;
+	cfg->bg_alpha = bg_alpha;
+	cfg->blend_op = blend_op;
+	cfg->dirty = true;
+}
+
+static void _sde_shd_setup_dim_layer(struct sde_hw_mixer *ctx,
+		struct sde_hw_dim_layer *dim_layer)
+{
+	struct sde_shd_hw_mixer *hw_lm;
+	struct sde_hw_dim_layer dim_layer2;
+
+	if (!ctx)
+		return;
+
+	hw_lm = container_of(ctx, struct sde_shd_hw_mixer, base);
+
+	dim_layer2 = *dim_layer;
+	dim_layer2.stage += hw_lm->range.start;
+	dim_layer2.rect.x += hw_lm->roi.x;
+	dim_layer2.rect.y += hw_lm->roi.y;
+
+	hw_lm->cfg[dim_layer2.stage].dim_layer = dim_layer2;
+	hw_lm->cfg[dim_layer2.stage].dim_layer_enable = true;
+}
+
+static void _sde_shd_clear_dim_layer(struct sde_hw_mixer *ctx)
+{
+	struct sde_shd_hw_mixer *hw_lm;
+	int i;
+
+	if (!ctx)
+		return;
+
+	hw_lm = container_of(ctx, struct sde_shd_hw_mixer, base);
+
+	for (i = SDE_STAGE_0; i < SDE_STAGE_MAX; i++)
+		hw_lm->cfg[i].dim_layer_enable = false;
+}
+
+static inline
+void _sde_shd_setup_mixer_out(struct sde_hw_mixer *ctx,
+		struct sde_hw_mixer_cfg *cfg)
+{
+	/* do nothing */
+}
+
+static void _sde_shd_flush_hw_lm(struct sde_hw_mixer *ctx)
+{
+	struct sde_shd_hw_mixer *hw_lm;
+	struct sde_hw_blk_reg_map *c = &ctx->hw;
+	int stage_off, i;
+	u32 reset = BIT(16), val;
+	int start, end;
+
+	if (!ctx)
+		return;
+
+	hw_lm = container_of(ctx, struct sde_shd_hw_mixer, base);
+
+	start = SDE_STAGE_0 + hw_lm->range.start;
+	end = start + hw_lm->range.size;
+	reset = ~reset;
+	for (i = start; i < end; i++) {
+		stage_off = _stage_offset(ctx, i);
+		if (WARN_ON(stage_off < 0))
+			return;
+
+		if (hw_lm->cfg[i].dim_layer_enable) {
+			hw_lm->orig->ops.setup_dim_layer(ctx,
+				&hw_lm->cfg[i].dim_layer);
+		} else {
+			val = SDE_REG_READ(c, LM_BLEND0_OP + stage_off);
+			val &= reset;
+			SDE_REG_WRITE(c, LM_BLEND0_OP + stage_off, val);
+		}
+
+		if (hw_lm->cfg[i].dirty) {
+			hw_lm->orig->ops.setup_blend_config(ctx, i,
+				hw_lm->cfg[i].fg_alpha,
+				hw_lm->cfg[i].bg_alpha,
+				hw_lm->cfg[i].blend_op);
+			hw_lm->cfg[i].dirty = false;
+		}
+	}
+}
+
+void sde_shd_hw_flush(struct sde_hw_ctl *ctl_ctx,
+	struct sde_hw_mixer *lm_ctx[CRTC_DUAL_MIXERS], int lm_num)
+{
+	struct sde_hw_blk_reg_map *c;
+	unsigned long lock_flags;
+	int i;
+
+	c = &ctl_ctx->hw;
+
+	spin_lock_irqsave(&hw_ctl_lock, lock_flags);
+
+	SDE_REG_WRITE(c, CTL_FLUSH_MASK, CTL_MIXER_FLUSH_MASK);
+
+	_sde_shd_flush_hw_ctl(ctl_ctx);
+
+	for (i = 0; i < lm_num; i++)
+		_sde_shd_flush_hw_lm(lm_ctx[i]);
+
+	if (ctl_ctx->ops.trigger_flush)
+		ctl_ctx->ops.trigger_flush(ctl_ctx);
+
+	SDE_REG_WRITE(c, CTL_FLUSH_MASK, 0);
+
+	spin_unlock_irqrestore(&hw_ctl_lock, lock_flags);
+}
+
+void sde_shd_hw_ctl_init_op(struct sde_hw_ctl *ctx)
+{
+	ctx->ops.clear_all_blendstages =
+		_sde_shd_hw_ctl_clear_all_blendstages;
+
+	ctx->ops.setup_blendstage =
+		_sde_shd_hw_ctl_setup_blendstage;
+
+	ctx->ops.setup_intf_cfg_v1 = NULL;
+}
+
+void sde_shd_hw_lm_init_op(struct sde_hw_mixer *ctx)
+{
+	ctx->ops.setup_blend_config =
+			_sde_shd_setup_blend_config;
+
+	ctx->ops.setup_dim_layer =
+			_sde_shd_setup_dim_layer;
+
+	ctx->ops.setup_mixer_out =
+			_sde_shd_setup_mixer_out;
+
+	ctx->ops.clear_dim_layer =
+			_sde_shd_clear_dim_layer;
+}
+
diff --git a/drivers/gpu/drm/msm/shd/shd_hw.h b/drivers/gpu/drm/msm/shd/shd_hw.h
new file mode 100644
index 0000000..579a71c
--- /dev/null
+++ b/drivers/gpu/drm/msm/shd/shd_hw.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#define pr_fmt(fmt)	"[drm-shd:%s:%d] " fmt, __func__, __LINE__
+
+#include <uapi/drm/sde_drm.h>
+#include "sde_hw_top.h"
+#include "shd_drm.h"
+
+#ifndef SHD_HW_H
+#define SHD_HW_H
+
+struct sde_shd_ctl_mixer_cfg {
+	u32 mixercfg;
+	u32 mixercfg_ext;
+	u32 mixercfg_ext2;
+	u32 mixercfg_ext3;
+
+	u32 mixercfg_mask;
+	u32 mixercfg_ext_mask;
+	u32 mixercfg_ext2_mask;
+	u32 mixercfg_ext3_mask;
+};
+
+struct sde_shd_hw_ctl {
+	struct sde_hw_ctl base;
+	struct shd_stage_range range;
+	struct sde_hw_ctl *orig;
+	u32 flush_mask;
+	struct sde_shd_ctl_mixer_cfg mixer_cfg[MAX_BLOCKS];
+};
+
+struct sde_shd_mixer_cfg {
+	uint32_t fg_alpha;
+	uint32_t bg_alpha;
+	uint32_t blend_op;
+	bool dirty;
+
+	struct sde_hw_dim_layer dim_layer;
+	bool dim_layer_enable;
+};
+
+struct sde_shd_hw_mixer {
+	struct sde_hw_mixer base;
+	struct shd_stage_range range;
+	struct sde_rect roi;
+	struct sde_hw_mixer *orig;
+	struct sde_shd_mixer_cfg cfg[SDE_STAGE_MAX];
+};
+
+void sde_shd_hw_flush(struct sde_hw_ctl *ctl_ctx,
+	struct sde_hw_mixer *lm_ctx[CRTC_DUAL_MIXERS], int lm_num);
+
+void sde_shd_hw_ctl_init_op(struct sde_hw_ctl *ctx);
+
+void sde_shd_hw_lm_init_op(struct sde_hw_mixer *ctx);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
index 2e7b4e2..62cb376 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
@@ -22,6 +22,7 @@
 #include <engine/falcon.h>
 
 #include <core/gpuobj.h>
+#include <subdev/mc.h>
 #include <subdev/timer.h>
 #include <engine/fifo.h>
 
@@ -107,8 +108,10 @@ nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend)
 		}
 	}
 
-	nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
-	nvkm_wr32(device, base + 0x014, 0xffffffff);
+	if (nvkm_mc_enabled(device, engine->subdev.index)) {
+		nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
+		nvkm_wr32(device, base + 0x014, 0xffffffff);
+	}
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
index 952a7cb..692d4d9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
@@ -131,11 +131,12 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode)
 			duty = nvkm_therm_update_linear(therm);
 			break;
 		case NVBIOS_THERM_FAN_OTHER:
-			if (therm->cstate)
+			if (therm->cstate) {
 				duty = therm->cstate;
-			else
+				poll = false;
+			} else {
 				duty = nvkm_therm_update_linear_fallback(therm);
-			poll = false;
+			}
 			break;
 		}
 		immd = false;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index b14d211..0ed7e91 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -147,7 +147,7 @@ static int cdn_dp_mailbox_validate_receive(struct cdn_dp_device *dp,
 }
 
 static int cdn_dp_mailbox_read_receive(struct cdn_dp_device *dp,
-				       u8 *buff, u8 buff_size)
+				       u8 *buff, u16 buff_size)
 {
 	u32 i;
 	int ret;
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 502c7eb..6277a3f2 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -347,13 +347,16 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
 			vc4_get_scaling_mode(vc4_state->src_h[1],
 					     vc4_state->crtc_h);
 
-		/* YUV conversion requires that horizontal scaling be enabled,
-		 * even on a plane that's otherwise 1:1. Looks like only PPF
-		 * works in that case, so let's pick that one.
+		/* YUV conversion requires that horizontal scaling be enabled
+		 * on the UV plane even if vc4_get_scaling_mode() returned
+		 * VC4_SCALING_NONE (which can happen when the down-scaling
+		 * ratio is 0.5). Let's force it to VC4_SCALING_PPF in this
+		 * case.
 		 */
-		if (vc4_state->is_unity)
-			vc4_state->x_scaling[0] = VC4_SCALING_PPF;
+		if (vc4_state->x_scaling[1] == VC4_SCALING_NONE)
+			vc4_state->x_scaling[1] = VC4_SCALING_PPF;
 	} else {
+		vc4_state->is_yuv = false;
 		vc4_state->x_scaling[1] = VC4_SCALING_NONE;
 		vc4_state->y_scaling[1] = VC4_SCALING_NONE;
 	}
diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c
index 2524ff1..81c7ab1 100644
--- a/drivers/gpu/drm/vgem/vgem_drv.c
+++ b/drivers/gpu/drm/vgem/vgem_drv.c
@@ -472,31 +472,31 @@ static int __init vgem_init(void)
 	if (!vgem_device)
 		return -ENOMEM;
 
-	ret = drm_dev_init(&vgem_device->drm, &vgem_driver, NULL);
-	if (ret)
-		goto out_free;
-
 	vgem_device->platform =
 		platform_device_register_simple("vgem", -1, NULL, 0);
 	if (IS_ERR(vgem_device->platform)) {
 		ret = PTR_ERR(vgem_device->platform);
-		goto out_fini;
+		goto out_free;
 	}
 
 	dma_coerce_mask_and_coherent(&vgem_device->platform->dev,
 				     DMA_BIT_MASK(64));
+	ret = drm_dev_init(&vgem_device->drm, &vgem_driver,
+			   &vgem_device->platform->dev);
+	if (ret)
+		goto out_unregister;
 
 	/* Final step: expose the device/driver to userspace */
 	ret  = drm_dev_register(&vgem_device->drm, 0);
 	if (ret)
-		goto out_unregister;
+		goto out_fini;
 
 	return 0;
 
-out_unregister:
-	platform_device_unregister(vgem_device->platform);
 out_fini:
 	drm_dev_fini(&vgem_device->drm);
+out_unregister:
+	platform_device_unregister(vgem_device->platform);
 out_free:
 	kfree(vgem_device);
 	return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 86d25f1..3bc7915 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -604,13 +604,16 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)
 static int vmw_dma_masks(struct vmw_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
+	int ret = 0;
 
-	if (intel_iommu_enabled &&
+	ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64));
+	if (dev_priv->map_mode != vmw_dma_phys &&
 	    (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {
 		DRM_INFO("Restricting DMA addresses to 44 bits.\n");
-		return dma_set_mask(dev->dev, DMA_BIT_MASK(44));
+		return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44));
 	}
-	return 0;
+
+	return ret;
 }
 #else
 static int vmw_dma_masks(struct vmw_private *dev_priv)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 87e8af5..49c28a4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -3818,7 +3818,7 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv,
 		*p_fence = NULL;
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c
index 524a717..a5e33d5 100644
--- a/drivers/gpu/ipu-v3/ipu-image-convert.c
+++ b/drivers/gpu/ipu-v3/ipu-image-convert.c
@@ -1518,7 +1518,7 @@ int ipu_image_convert_queue(struct ipu_image_convert_run *run)
 EXPORT_SYMBOL_GPL(ipu_image_convert_queue);
 
 /* Abort any active or pending conversions for this context */
-void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
+static void __ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
 {
 	struct ipu_image_convert_chan *chan = ctx->chan;
 	struct ipu_image_convert_priv *priv = chan->priv;
@@ -1545,7 +1545,7 @@ void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
 
 	need_abort = (run_count || active_run);
 
-	ctx->aborting = need_abort;
+	ctx->aborting = true;
 
 	spin_unlock_irqrestore(&chan->irqlock, flags);
 
@@ -1566,7 +1566,11 @@ void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
 		dev_warn(priv->ipu->dev, "%s: timeout\n", __func__);
 		force_abort(ctx);
 	}
+}
 
+void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
+{
+	__ipu_image_convert_abort(ctx);
 	ctx->aborting = false;
 }
 EXPORT_SYMBOL_GPL(ipu_image_convert_abort);
@@ -1580,7 +1584,7 @@ void ipu_image_convert_unprepare(struct ipu_image_convert_ctx *ctx)
 	bool put_res;
 
 	/* make sure no runs are hanging around */
-	ipu_image_convert_abort(ctx);
+	__ipu_image_convert_abort(ctx);
 
 	dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__,
 		chan->ic_task, ctx);
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index 129cd2f6..aecd686 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.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
@@ -1026,6 +1026,7 @@
 #define A6XX_GMU_HOST2GMU_INTR_INFO_1		0x1F99C
 #define A6XX_GMU_HOST2GMU_INTR_INFO_2		0x1F99D
 #define A6XX_GMU_HOST2GMU_INTR_INFO_3		0x1F99E
+#define A6XX_GMU_GENERAL_0			0x1F9C5
 #define A6XX_GMU_GENERAL_1			0x1F9C6
 #define A6XX_GMU_GENERAL_6			0x1F9CB
 #define A6XX_GMU_GENERAL_7			0x1F9CC
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h
index ec6d699..291cf6a 100644
--- a/drivers/gpu/msm/adreno-gpulist.h
+++ b/drivers/gpu/msm/adreno-gpulist.h
@@ -512,5 +512,6 @@ static const struct adreno_gpu_core adreno_gpulist[] = {
 		.gmem_size = (SZ_128K + SZ_4K),
 		.num_protected_regs = 0x20,
 		.busy_mask = 0xFFFFFFFE,
+		.cx_ipeak_gpu_freq = 900000000,
 	},
 };
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 329d72f..a1a41b6 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -633,7 +633,7 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
 	 * This is usually harmless because the GMU will abort power collapse
 	 * and change the fence back to ALLOW. Poll so that this can happen.
 	 */
-	if (gmu_core_isenabled(device)) {
+	if (gmu_core_gpmu_isenabled(device)) {
 		adreno_readreg(adreno_dev,
 				ADRENO_REG_GMU_AO_AHB_FENCE_CTRL,
 				&fence);
@@ -654,6 +654,10 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
 					"Status=0x%x Unmasked status=0x%x Mask=0x%x\n",
 					shadow_status & irq_params->mask,
 					shadow_status, irq_params->mask);
+				adreno_set_gpu_fault(adreno_dev,
+						ADRENO_GMU_FAULT);
+				adreno_dispatcher_schedule(KGSL_DEVICE
+						(adreno_dev));
 				goto done;
 			}
 			fence_retries++;
@@ -2066,7 +2070,8 @@ static int _adreno_start(struct adreno_device *adreno_dev)
 		}
 	}
 
-	if (gmu_core_isenabled(device) && adreno_dev->perfctr_ifpc_lo == 0) {
+	if (gmu_core_gpmu_isenabled(device) &&
+			adreno_dev->perfctr_ifpc_lo == 0) {
 		ret = adreno_perfcounter_get(adreno_dev,
 				KGSL_PERFCOUNTER_GROUP_GPMU_PWR, 4,
 				&adreno_dev->perfctr_ifpc_lo, NULL,
@@ -2695,6 +2700,27 @@ static int adreno_getproperty(struct kgsl_device *device,
 			status = 0;
 		}
 		break;
+
+	case KGSL_PROP_GAMING_BIN:
+	{
+		unsigned int gaming_bin;
+
+		if (sizebytes != sizeof(unsigned int)) {
+			status = -EINVAL;
+			break;
+		}
+
+		gaming_bin = adreno_dev->gaming_bin ? 1 : 0;
+
+		if (copy_to_user(value, &gaming_bin,
+					sizeof(unsigned int))) {
+			status = -EFAULT;
+			break;
+		}
+		status = 0;
+	}
+	break;
+
 	default:
 		status = -EINVAL;
 	}
@@ -3350,7 +3376,7 @@ int adreno_gmu_fenced_write(struct adreno_device *adreno_dev,
 
 	adreno_writereg(adreno_dev, offset, val);
 
-	if (!gmu_core_isenabled(KGSL_DEVICE(adreno_dev)))
+	if (!gmu_core_gpmu_isenabled(KGSL_DEVICE(adreno_dev)))
 		return 0;
 
 	for (i = 0; i < GMU_CORE_LONG_WAKEUP_RETRY_LIMIT; i++) {
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 391786d..2c5902e 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -519,6 +519,7 @@ enum gpu_coresight_sources {
  * @gpuhtw_llc_slice_enable: To enable the GPUHTW system cache slice or not
  * @zap_loaded: Used to track if zap was successfully loaded or not
  * @soc_hw_rev: Indicate which SOC hardware revision to use
+ * @gaming_bin: Indicate whether part is a gaming SKU or not
  */
 struct adreno_device {
 	struct kgsl_device dev;    /* Must be first field in this struct */
@@ -599,6 +600,7 @@ struct adreno_device {
 	bool gpuhtw_llc_slice_enable;
 	unsigned int zap_loaded;
 	unsigned int soc_hw_rev;
+	bool gaming_bin;
 };
 
 /**
@@ -1029,6 +1031,8 @@ struct adreno_gpudev {
 	int (*perfcounter_update)(struct adreno_device *adreno_dev,
 				struct adreno_perfcount_register *reg,
 				bool update_reg);
+	size_t (*snapshot_preemption)(struct kgsl_device *, u8 *,
+				 size_t, void *);
 };
 
 /**
@@ -1356,6 +1360,18 @@ static inline int adreno_is_a640v2(struct adreno_device *adreno_dev)
 		(ADRENO_CHIPID_PATCH(adreno_dev->chipid) == 1);
 }
 
+static inline int adreno_is_a680v1(struct adreno_device *adreno_dev)
+{
+	return (ADRENO_GPUREV(adreno_dev) == ADRENO_REV_A680) &&
+		(ADRENO_CHIPID_PATCH(adreno_dev->chipid) == 0);
+}
+
+static inline int adreno_is_a680v2(struct adreno_device *adreno_dev)
+{
+	return (ADRENO_GPUREV(adreno_dev) == ADRENO_REV_A680) &&
+		(ADRENO_CHIPID_PATCH(adreno_dev->chipid) == 1);
+}
+
 /*
  * adreno_checkreg_off() - Checks the validity of a register enum
  * @adreno_dev:		Pointer to adreno device
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index 032cd34..b0e7d47 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.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
@@ -3635,4 +3635,5 @@ struct adreno_gpudev adreno_a5xx_gpudev = {
 	.preemption_schedule = a5xx_preemption_schedule,
 	.enable_64bit = a5xx_enable_64bit,
 	.clk_set_options = a5xx_clk_set_options,
+	.snapshot_preemption = a5xx_snapshot_preemption,
 };
diff --git a/drivers/gpu/msm/adreno_a5xx.h b/drivers/gpu/msm/adreno_a5xx.h
index 3d89d73..510eff2 100644
--- a/drivers/gpu/msm/adreno_a5xx.h
+++ b/drivers/gpu/msm/adreno_a5xx.h
@@ -237,5 +237,6 @@ unsigned int a5xx_preemption_pre_ibsubmit(
 
 
 void a5xx_preempt_callback(struct adreno_device *adreno_dev, int bit);
-
+size_t a5xx_snapshot_preemption(struct kgsl_device *device, u8 *buf,
+		size_t remain, void *priv);
 #endif
diff --git a/drivers/gpu/msm/adreno_a5xx_snapshot.c b/drivers/gpu/msm/adreno_a5xx_snapshot.c
index 4bde8c6..d8cb99c 100644
--- a/drivers/gpu/msm/adreno_a5xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a5xx_snapshot.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
@@ -739,7 +739,7 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf,
 }
 
 /* Snapshot a preemption record buffer */
-static size_t snapshot_preemption_record(struct kgsl_device *device, u8 *buf,
+size_t a5xx_snapshot_preemption(struct kgsl_device *device, u8 *buf,
 	size_t remain, void *priv)
 {
 	struct kgsl_memdesc *memdesc = priv;
@@ -865,8 +865,7 @@ void a5xx_snapshot(struct adreno_device *adreno_dev,
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
 	struct adreno_snapshot_data *snap_data = gpudev->snapshot_data;
-	unsigned int reg, i;
-	struct adreno_ringbuffer *rb;
+	unsigned int reg;
 	struct registers regs;
 
 	/* Disable Clock gating temporarily for the debug bus to work */
@@ -965,16 +964,6 @@ void a5xx_snapshot(struct adreno_device *adreno_dev,
 	/* Debug bus */
 	a5xx_snapshot_debugbus(device, snapshot);
 
-	/* Preemption record */
-	if (adreno_is_preemption_enabled(adreno_dev)) {
-		FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
-			kgsl_snapshot_add_section(device,
-				KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
-				snapshot, snapshot_preemption_record,
-				&rb->preemption_desc);
-		}
-	}
-
 }
 
 static int _a5xx_crashdump_init_shader(struct a5xx_shader_block *block,
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index b2ea857..d75f5c1 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -787,7 +787,7 @@ static void a6xx_start(struct adreno_device *adreno_dev)
 	static bool patch_reglist;
 
 	/* runtime adjust callbacks based on feature sets */
-	if (!gmu_core_isenabled(device))
+	if (!gmu_core_gpmu_isenabled(device))
 		/* Legacy idle management if gmu is disabled */
 		ADRENO_GPU_DEVICE(adreno_dev)->hw_isidle = NULL;
 	/* enable hardware clockgating */
@@ -865,7 +865,7 @@ static void a6xx_start(struct adreno_device *adreno_dev)
 	kgsl_regwrite(device, A6XX_RBBM_PERFCTR_CNTL, 0x1);
 
 	/* Turn on GX_MEM retention */
-	if (gmu_core_isenabled(device) && adreno_is_a612(adreno_dev)) {
+	if (gmu_core_gpmu_isenabled(device) && adreno_is_a612(adreno_dev)) {
 		kgsl_regwrite(device, A6XX_RBBM_BLOCK_GX_RETENTION_CNTL, 0x7FB);
 		/* For CP IPC interrupt */
 		kgsl_regwrite(device, A6XX_RBBM_INT_2_MASK, 0x00000010);
@@ -918,9 +918,17 @@ static void a6xx_start(struct adreno_device *adreno_dev)
 	kgsl_regwrite(device, A6XX_UCHE_MODE_CNTL, (glbl_inv << 29) |
 						(mal << 23) | (bit << 21));
 
-	/* Set hang detection threshold to 0xCFFFFF * 16 cycles */
-	kgsl_regwrite(device, A6XX_RBBM_INTERFACE_HANG_INT_CNTL,
-					(1 << 30) | 0xcfffff);
+	if (adreno_is_a610(adreno_dev))
+		/*
+		 * Set hang detection threshold to 4 million
+		 * cycles (0x3FFFF*16).
+		 */
+		kgsl_regwrite(device, A6XX_RBBM_INTERFACE_HANG_INT_CNTL,
+						(1 << 30) | 0x3ffff);
+	else
+		/* Set hang detection threshold to 0xCFFFFF * 16 cycles */
+		kgsl_regwrite(device, A6XX_RBBM_INTERFACE_HANG_INT_CNTL,
+						(1 << 30) | 0xcfffff);
 
 	kgsl_regwrite(device, A6XX_UCHE_CLIENT_PF, 1);
 
@@ -1348,7 +1356,7 @@ static int _load_firmware(struct kgsl_device *device, const char *fwfile,
 static inline void a6xx_gpu_keepalive(struct adreno_device *adreno_dev,
 		bool state)
 {
-	if (!gmu_core_isenabled(KGSL_DEVICE(adreno_dev)))
+	if (!gmu_core_gpmu_isenabled(KGSL_DEVICE(adreno_dev)))
 		return;
 
 	adreno_write_gmureg(adreno_dev,
@@ -1386,7 +1394,8 @@ static int a6xx_microcode_read(struct adreno_device *adreno_dev)
 			return ret;
 	}
 
-	if (GMU_DEV_OP_VALID(gmu_dev_ops, load_firmware))
+	if (gmu_core_gpmu_isenabled(device) &&
+			GMU_DEV_OP_VALID(gmu_dev_ops, load_firmware))
 		return gmu_dev_ops->load_firmware(device);
 
 	return 0;
@@ -1403,7 +1412,7 @@ static int a6xx_soft_reset(struct adreno_device *adreno_dev)
 	 * For the soft reset case with GMU enabled this part is done
 	 * by the GMU firmware
 	 */
-	if (gmu_core_isenabled(device) &&
+	if (gmu_core_gpmu_isenabled(device) &&
 		!test_bit(ADRENO_DEVICE_HARD_RESET, &adreno_dev->priv))
 		return 0;
 
@@ -1498,7 +1507,7 @@ static int a6xx_reset(struct kgsl_device *device, int fault)
 	int i = 0;
 
 	/* Use the regular reset sequence for No GMU */
-	if (!gmu_core_isenabled(device))
+	if (!gmu_core_gpmu_isenabled(device))
 		return adreno_reset(device, fault);
 
 	/* Transition from ACTIVE to RESET state */
@@ -2836,6 +2845,22 @@ static int a6xx_enable_pwr_counters(struct adreno_device *adreno_dev,
 	return 0;
 }
 
+static void a6xx_efuse_gaming_bin(struct adreno_device *adreno_dev)
+{
+	unsigned int val;
+	unsigned int gaming_bin[3];
+	struct kgsl_device *device = &adreno_dev->dev;
+
+	if (of_property_read_u32_array(device->pdev->dev.of_node,
+		"qcom,gpu-gaming-bin", gaming_bin, 3))
+		return;
+
+	adreno_efuse_read_u32(adreno_dev, gaming_bin[0], &val);
+
+	/* If fuse bit is set that means its not a gaming bin */
+	adreno_dev->gaming_bin = !((val & gaming_bin[1]) >> gaming_bin[2]);
+}
+
 static void a6xx_efuse_speed_bin(struct adreno_device *adreno_dev)
 {
 	unsigned int val;
@@ -2858,6 +2883,7 @@ static const struct {
 	{ adreno_is_a615_family, a6xx_efuse_speed_bin },
 	{ adreno_is_a612, a6xx_efuse_speed_bin },
 	{ adreno_is_a610, a6xx_efuse_speed_bin },
+	{ adreno_is_a610, a6xx_efuse_gaming_bin },
 };
 
 static void a6xx_check_features(struct adreno_device *adreno_dev)
@@ -3230,4 +3256,5 @@ struct adreno_gpudev adreno_a6xx_gpudev = {
 	.perfcounter_update = a6xx_perfcounter_update,
 	.coresight = {&a6xx_coresight, &a6xx_coresight_cx},
 	.clk_set_options = a6xx_clk_set_options,
+	.snapshot_preemption = a6xx_snapshot_preemption,
 };
diff --git a/drivers/gpu/msm/adreno_a6xx.h b/drivers/gpu/msm/adreno_a6xx.h
index 55e573e..f2869b6 100644
--- a/drivers/gpu/msm/adreno_a6xx.h
+++ b/drivers/gpu/msm/adreno_a6xx.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
@@ -195,4 +195,6 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev);
 int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev);
 void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev);
 bool a6xx_gmu_sptprac_is_on(struct adreno_device *adreno_dev);
+size_t a6xx_snapshot_preemption(struct kgsl_device *device, u8 *buf,
+		size_t remain, void *priv);
 #endif
diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c
index c00c59b..f1c9795 100644
--- a/drivers/gpu/msm/adreno_a6xx_gmu.c
+++ b/drivers/gpu/msm/adreno_a6xx_gmu.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
@@ -86,7 +86,7 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device)
 	unsigned int cfg_offset, seq_offset;
 
 	/* Offsets from the base PDC (if no PDC subsections in the DTSI) */
-	if (adreno_is_a640v2(adreno_dev)) {
+	if ((adreno_is_a640v2(adreno_dev)) || (adreno_is_a680v2(adreno_dev))) {
 		cfg_offset = 0x90000;
 		seq_offset = 0x290000;
 	} else {
@@ -556,7 +556,7 @@ static int a6xx_gmu_oob_set(struct adreno_device *adreno_dev,
 	int ret = 0;
 	int set, check;
 
-	if (!gmu_core_isenabled(device))
+	if (!gmu_core_gpmu_isenabled(device))
 		return 0;
 
 	if (!adreno_is_a630(adreno_dev) && !adreno_is_a615_family(adreno_dev)) {
@@ -609,7 +609,7 @@ static inline void a6xx_gmu_oob_clear(struct adreno_device *adreno_dev,
 	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
 	int clear;
 
-	if (!gmu_core_isenabled(device))
+	if (!gmu_core_gpmu_isenabled(device))
 		return;
 
 	if (!adreno_is_a630(adreno_dev) && !adreno_is_a615_family(adreno_dev)) {
@@ -660,6 +660,9 @@ static int a6xx_gmu_hfi_start_msg(struct adreno_device *adreno_dev)
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct hfi_start_cmd req;
 
+	if (!gmu_core_gpmu_isenabled(device))
+		return 0;
+
 	if (adreno_is_a640(adreno_dev) || adreno_is_a680(adreno_dev))
 		return hfi_send_req(KGSL_GMU_DEVICE(device),
 					 H2F_MSG_START, &req);
@@ -704,7 +707,7 @@ static int a6xx_complete_rpmh_votes(struct kgsl_device *device)
 {
 	int ret = 0;
 
-	if (!gmu_core_isenabled(device))
+	if (!gmu_core_gpmu_isenabled(device))
 		return ret;
 
 	ret |= timed_poll_check(device, A6XX_RSCC_TCS0_DRV0_STATUS, BIT(0),
@@ -735,7 +738,7 @@ int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev)
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
 
-	if (!gmu_core_gpmu_isenabled(device) ||
+	if (!gmu_core_isenabled(device) ||
 			!adreno_has_sptprac_gdsc(adreno_dev))
 		return 0;
 
@@ -763,7 +766,7 @@ void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev)
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
 
-	if (!gmu_core_gpmu_isenabled(device) ||
+	if (!gmu_core_isenabled(device) ||
 			!adreno_has_sptprac_gdsc(adreno_dev))
 		return;
 
@@ -798,6 +801,9 @@ static bool a6xx_gmu_gx_is_on(struct adreno_device *adreno_dev)
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	unsigned int val;
 
+	if (!gmu_core_isenabled(device))
+		return true;
+
 	gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val);
 	return is_on(val);
 }
@@ -871,7 +877,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct adreno_device *adreno_dev)
 	unsigned long t;
 	uint64_t ts1, ts2, ts3;
 
-	if (!gmu_core_isenabled(device))
+	if (!gmu_core_gpmu_isenabled(device))
 		return 0;
 
 	ts1 = read_AO_counter(device);
@@ -1076,10 +1082,6 @@ static int a6xx_gmu_load_firmware(struct kgsl_device *device)
 	const struct adreno_gpu_core *gpucore = adreno_dev->gpucore;
 	int ret =  -EINVAL;
 
-	/* there is no GMU */
-	if (!gmu_core_isenabled(device))
-		return 0;
-
 	/* GMU fw already saved and verified so do nothing new */
 	if (gmu->fw_image)
 		return 0;
@@ -1395,7 +1397,7 @@ static int a6xx_gmu_ifpc_store(struct adreno_device *adreno_dev,
 	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
 	unsigned int requested_idle_level;
 
-	if (!gmu_core_isenabled(device) ||
+	if (!gmu_core_gpmu_isenabled(device) ||
 			!ADRENO_FEATURE(adreno_dev, ADRENO_IFPC))
 		return -EINVAL;
 
@@ -1429,7 +1431,8 @@ static unsigned int a6xx_gmu_ifpc_show(struct adreno_device *adreno_dev)
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
 
-	return gmu_core_isenabled(device) && gmu->idle_level  >= GPU_HW_IFPC;
+	return gmu_core_gpmu_isenabled(device) &&
+			gmu->idle_level  >= GPU_HW_IFPC;
 }
 
 struct gmu_mem_type_desc {
@@ -1518,7 +1521,7 @@ static int a6xx_gmu_wait_for_active_transition(
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
 
-	if (!gmu_core_isenabled(device))
+	if (!gmu_core_gpmu_isenabled(device))
 		return 0;
 
 	gmu_core_regread(device,
diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c
index 5d94063..a00d64d 100644
--- a/drivers/gpu/msm/adreno_a6xx_preempt.c
+++ b/drivers/gpu/msm/adreno_a6xx_preempt.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
@@ -318,42 +318,48 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
 	 * free when the GPU is already powered on, whereas an OOB requires an
 	 * unconditional handshake with the GMU.
 	 */
-	if (gmu_core_isenabled(device))
+	if (gmu_core_gpmu_isenabled(device))
 		gmu_core_regrmw(device, A6XX_GMU_AO_SPARE_CNTL, 0x0, 0x2);
 
 	/*
 	 * Fenced writes on this path will make sure the GPU is woken up
 	 * in case it was power collapsed by the GMU.
 	 */
-	adreno_gmu_fenced_write(adreno_dev,
+	if (adreno_gmu_fenced_write(adreno_dev,
 		ADRENO_REG_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR_LO,
 		lower_32_bits(next->preemption_desc.gpuaddr),
-		FENCE_STATUS_WRITEDROPPED1_MASK);
+		FENCE_STATUS_WRITEDROPPED1_MASK))
+		goto err;
 
-	adreno_gmu_fenced_write(adreno_dev,
+	if (adreno_gmu_fenced_write(adreno_dev,
 		ADRENO_REG_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR_HI,
 		upper_32_bits(next->preemption_desc.gpuaddr),
-		FENCE_STATUS_WRITEDROPPED1_MASK);
+		FENCE_STATUS_WRITEDROPPED1_MASK))
+		goto err;
 
-	adreno_gmu_fenced_write(adreno_dev,
+	if (adreno_gmu_fenced_write(adreno_dev,
 		ADRENO_REG_CP_CONTEXT_SWITCH_PRIV_SECURE_RESTORE_ADDR_LO,
 		lower_32_bits(next->secure_preemption_desc.gpuaddr),
-		FENCE_STATUS_WRITEDROPPED1_MASK);
+		FENCE_STATUS_WRITEDROPPED1_MASK))
+		goto err;
 
-	adreno_gmu_fenced_write(adreno_dev,
+	if (adreno_gmu_fenced_write(adreno_dev,
 		ADRENO_REG_CP_CONTEXT_SWITCH_PRIV_SECURE_RESTORE_ADDR_HI,
 		upper_32_bits(next->secure_preemption_desc.gpuaddr),
-		FENCE_STATUS_WRITEDROPPED1_MASK);
+		FENCE_STATUS_WRITEDROPPED1_MASK))
+		goto err;
 
-	adreno_gmu_fenced_write(adreno_dev,
+	if (adreno_gmu_fenced_write(adreno_dev,
 		ADRENO_REG_CP_CONTEXT_SWITCH_NON_PRIV_RESTORE_ADDR_LO,
 		lower_32_bits(gpuaddr),
-		FENCE_STATUS_WRITEDROPPED1_MASK);
+		FENCE_STATUS_WRITEDROPPED1_MASK))
+		goto err;
 
-	adreno_gmu_fenced_write(adreno_dev,
+	if (adreno_gmu_fenced_write(adreno_dev,
 		ADRENO_REG_CP_CONTEXT_SWITCH_NON_PRIV_RESTORE_ADDR_HI,
 		upper_32_bits(gpuaddr),
-		FENCE_STATUS_WRITEDROPPED1_MASK);
+		FENCE_STATUS_WRITEDROPPED1_MASK))
+		goto err;
 
 	/*
 	 * Above fence writes will make sure GMU comes out of
@@ -364,16 +370,9 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
 	 * preemption. This is require to make sure CP doesn't
 	 * interrupt GMU during wake-up from IFPC.
 	 */
-	if (GMU_DEV_OP_VALID(gmu_dev_ops, wait_for_active_transition)) {
-		if (gmu_dev_ops->wait_for_active_transition(adreno_dev)) {
-			adreno_set_preempt_state(adreno_dev,
-				ADRENO_PREEMPT_NONE);
-
-			adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
-			adreno_dispatcher_schedule(device);
-			return;
-		}
-	}
+	if (GMU_DEV_OP_VALID(gmu_dev_ops, wait_for_active_transition))
+		if (gmu_dev_ops->wait_for_active_transition(adreno_dev))
+			goto err;
 
 	adreno_dev->next_rb = next;
 
@@ -381,14 +380,28 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
 	mod_timer(&adreno_dev->preempt.timer,
 		jiffies + msecs_to_jiffies(ADRENO_PREEMPT_TIMEOUT));
 
-	trace_adreno_preempt_trigger(adreno_dev->cur_rb, adreno_dev->next_rb,
-		cntl);
-
 	adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_TRIGGERED);
 
 	/* Trigger the preemption */
-	adreno_gmu_fenced_write(adreno_dev, ADRENO_REG_CP_PREEMPT, cntl,
-		FENCE_STATUS_WRITEDROPPED1_MASK);
+	if (adreno_gmu_fenced_write(adreno_dev, ADRENO_REG_CP_PREEMPT, cntl,
+				FENCE_STATUS_WRITEDROPPED1_MASK)) {
+		adreno_dev->next_rb = NULL;
+		del_timer(&adreno_dev->preempt.timer);
+		goto err;
+	}
+
+	trace_adreno_preempt_trigger(adreno_dev->cur_rb, adreno_dev->next_rb,
+		cntl);
+
+	return;
+err:
+
+	/* If fenced write fails, set the fault and trigger recovery */
+	adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE);
+	adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
+	adreno_dispatcher_schedule(device);
+	/* Clear the keep alive */
+	gmu_core_regrmw(device, A6XX_GMU_AO_SPARE_CNTL, 0x2, 0x0);
 }
 
 void a6xx_preemption_callback(struct adreno_device *adreno_dev, int bit)
@@ -422,7 +435,7 @@ void a6xx_preemption_callback(struct adreno_device *adreno_dev, int bit)
 	 * We can now safely clear the preemption keepalive bit, allowing
 	 * power collapse to resume its regular activity.
 	 */
-	if (gmu_core_isenabled(KGSL_DEVICE(adreno_dev)))
+	if (gmu_core_gpmu_isenabled(KGSL_DEVICE(adreno_dev)))
 		gmu_core_regrmw(KGSL_DEVICE(adreno_dev),
 				A6XX_GMU_AO_SPARE_CNTL, 0x2, 0x0);
 
diff --git a/drivers/gpu/msm/adreno_a6xx_rgmu.c b/drivers/gpu/msm/adreno_a6xx_rgmu.c
index bd3f8fd..7035223 100644
--- a/drivers/gpu/msm/adreno_a6xx_rgmu.c
+++ b/drivers/gpu/msm/adreno_a6xx_rgmu.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
@@ -31,6 +31,8 @@
 #define GLM_SLEEP_TIMEOUT		10	/* ms */
 
 static const unsigned int a6xx_rgmu_registers[] = {
+	/*GPUCX_TCM */
+	0x1B400, 0x1B7FF,
 	/* GMU CX */
 	0x1F80F, 0x1F83D, 0x1F840, 0x1F8D8, 0x1F990, 0x1F99E, 0x1F9C0, 0x1F9CC,
 	/* GMU AO */
@@ -112,7 +114,7 @@ static int a6xx_rgmu_oob_set(struct adreno_device *adreno_dev,
 	struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device);
 	int ret, set, check;
 
-	if (!gmu_core_isenabled(device))
+	if (!gmu_core_gpmu_isenabled(device))
 		return 0;
 
 	set = BIT(req + 16);
@@ -151,7 +153,7 @@ static inline void a6xx_rgmu_oob_clear(struct adreno_device *adreno_dev,
 {
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 
-	if (!gmu_core_isenabled(device))
+	if (!gmu_core_gpmu_isenabled(device))
 		return;
 
 	gmu_core_regwrite(device, A6XX_GMU_HOST2GMU_INTR_SET, BIT(req + 24));
@@ -216,7 +218,7 @@ static int a6xx_rgmu_ifpc_store(struct adreno_device *adreno_dev,
 	struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device);
 	unsigned int requested_idle_level;
 
-	if (!gmu_core_isenabled(device) ||
+	if (!gmu_core_gpmu_isenabled(device) ||
 		!ADRENO_FEATURE(adreno_dev, ADRENO_IFPC))
 		return -EINVAL;
 
@@ -245,7 +247,8 @@ static unsigned int a6xx_rgmu_ifpc_show(struct adreno_device *adreno_dev)
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device);
 
-	return gmu_core_isenabled(device) && rgmu->idle_level == GPU_HW_IFPC;
+	return gmu_core_gpmu_isenabled(device) &&
+			rgmu->idle_level == GPU_HW_IFPC;
 }
 
 
@@ -280,7 +283,7 @@ static int a6xx_rgmu_wait_for_lowest_idle(struct adreno_device *adreno_dev)
 	unsigned long t;
 	uint64_t ts1, ts2, ts3;
 
-	if (!gmu_core_isenabled(device) ||
+	if (!gmu_core_gpmu_isenabled(device) ||
 			rgmu->idle_level != GPU_HW_IFPC)
 		return 0;
 
@@ -434,6 +437,9 @@ static int a6xx_rgmu_fw_start(struct kgsl_device *device,
 		return -ETIMEDOUT;
 	}
 
+	/* Read the RGMU firmware version from registers */
+	gmu_core_regread(device, A6XX_GMU_GENERAL_0, &rgmu->ver);
+
 	return 0;
 }
 
@@ -481,7 +487,7 @@ static int a6xx_rgmu_gpu_pwrctrl(struct adreno_device *adreno_dev,
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	int ret = 0;
 
-	if (!gmu_core_isenabled(device))
+	if (!gmu_core_gpmu_isenabled(device))
 		return 0;
 
 	switch (mode) {
@@ -521,9 +527,6 @@ static int a6xx_rgmu_load_firmware(struct kgsl_device *device)
 	const struct adreno_gpu_core *gpucore = adreno_dev->gpucore;
 	int ret;
 
-	if (!gmu_core_isenabled(device))
-		return 0;
-
 	/* RGMU fw already saved and verified so do nothing new */
 	if (rgmu->fw_hostptr)
 		return 0;
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index 85025a6..2a75c75 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -25,6 +25,9 @@
 #define A6XX_NUM_XIN_AXI_BLOCKS 5
 #define A6XX_NUM_XIN_CORE_BLOCKS 4
 
+/* Snapshot section size of each CP preemption record for A6XX  */
+#define A6XX_SNAPSHOT_CP_CTXRECORD_SIZE_IN_BYTES (64 * 1024)
+
 static const unsigned int a6xx_gras_cluster[] = {
 	0x8000, 0x8006, 0x8010, 0x8092, 0x8094, 0x809D, 0x80A0, 0x80A6,
 	0x80AF, 0x80F1, 0x8100, 0x8107, 0x8109, 0x8109, 0x8110, 0x8110,
@@ -1504,6 +1507,32 @@ static void _a6xx_do_crashdump(struct kgsl_device *device)
 	crash_dump_valid = true;
 }
 
+/* Snapshot the preemption related buffers */
+size_t a6xx_snapshot_preemption(struct kgsl_device *device,
+	u8 *buf, size_t remain, void *priv)
+{
+	struct kgsl_memdesc *memdesc = priv;
+	struct kgsl_snapshot_gpu_object_v2 *header =
+		(struct kgsl_snapshot_gpu_object_v2 *)buf;
+	u8 *ptr = buf + sizeof(*header);
+
+	if (remain < (A6XX_SNAPSHOT_CP_CTXRECORD_SIZE_IN_BYTES +
+						sizeof(*header))) {
+		SNAPSHOT_ERR_NOMEM(device, "PREEMPTION RECORD");
+		return 0;
+	}
+
+	header->size = A6XX_SNAPSHOT_CP_CTXRECORD_SIZE_IN_BYTES >> 2;
+	header->gpuaddr = memdesc->gpuaddr;
+	header->ptbase =
+		kgsl_mmu_pagetable_get_ttbr0(device->mmu.defaultpagetable);
+	header->type = SNAPSHOT_GPU_OBJECT_GLOBAL;
+
+	memcpy(ptr, memdesc->hostptr, A6XX_SNAPSHOT_CP_CTXRECORD_SIZE_IN_BYTES);
+
+	return A6XX_SNAPSHOT_CP_CTXRECORD_SIZE_IN_BYTES + sizeof(*header);
+}
+
 /*
  * a6xx_snapshot() - A6XX GPU snapshot function
  * @adreno_dev: Device being snapshotted
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index aef802c..1b05411 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,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
@@ -132,7 +132,7 @@ static void sync_event_print(struct seq_file *s,
 {
 	switch (sync_event->type) {
 	case KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP: {
-		seq_printf(s, "sync: ctx: %d ts: %d",
+		seq_printf(s, "sync: ctx: %u ts: %u",
 				sync_event->context->id, sync_event->timestamp);
 		break;
 	}
@@ -231,7 +231,7 @@ static void cmdobj_print(struct seq_file *s,
 	else
 		seq_puts(s, " markerobj ");
 
-	seq_printf(s, "\t %d ", drawobj->timestamp);
+	seq_printf(s, "\t %u ", drawobj->timestamp);
 
 	seq_puts(s, " priv: ");
 	print_flags(s, cmdobj_priv, ARRAY_SIZE(cmdobj_priv),
@@ -276,7 +276,7 @@ static int ctx_print(struct seq_file *s, void *unused)
 	struct kgsl_event *event;
 	unsigned int queued = 0, consumed = 0, retired = 0;
 
-	seq_printf(s, "id: %d type: %s priority: %d process: %s (%d) tid: %d\n",
+	seq_printf(s, "id: %u type: %s priority: %d process: %s (%d) tid: %d\n",
 		   drawctxt->base.id,
 		   ctx_type_str(drawctxt->type),
 		   drawctxt->base.priority,
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 25f9131..2c078f6 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.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
@@ -1674,13 +1674,25 @@ static inline const char *_kgsl_context_comm(struct kgsl_context *context)
 
 
 static void adreno_fault_header(struct kgsl_device *device,
-		struct adreno_ringbuffer *rb, struct kgsl_drawobj_cmd *cmdobj)
+		struct adreno_ringbuffer *rb, struct kgsl_drawobj_cmd *cmdobj,
+		int fault, bool gx_on)
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct kgsl_drawobj *drawobj = DRAWOBJ(cmdobj);
 	unsigned int status, rptr, wptr, ib1sz, ib2sz;
 	uint64_t ib1base, ib2base;
 
+	/*
+	 * GPU registers can't be accessed if the gx headswitch is off.
+	 * During the gx off case access to GPU gx blocks will show data
+	 * as 0x5c00bd00. Hence skip adreno fault header dump.
+	 */
+	if (!gx_on) {
+		dev_err(device->dev, "%s fault and gx is off\n",
+				fault & ADRENO_GMU_FAULT ? "GMU" : "GPU");
+		return;
+	}
+
 	adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, &status);
 	adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &rptr);
 	adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_WPTR, &wptr);
@@ -2036,13 +2048,14 @@ static void recover_dispatch_q(struct kgsl_device *device,
 }
 
 static void do_header_and_snapshot(struct kgsl_device *device, int fault,
-		struct adreno_ringbuffer *rb, struct kgsl_drawobj_cmd *cmdobj)
+		struct adreno_ringbuffer *rb, struct kgsl_drawobj_cmd *cmdobj,
+		bool gx_on)
 {
 	struct kgsl_drawobj *drawobj = DRAWOBJ(cmdobj);
 
 	/* Always dump the snapshot on a non-drawobj failure */
 	if (cmdobj == NULL) {
-		adreno_fault_header(device, rb, NULL);
+		adreno_fault_header(device, rb, NULL, fault, gx_on);
 		kgsl_device_snapshot(device, NULL, fault & ADRENO_GMU_FAULT);
 		return;
 	}
@@ -2052,7 +2065,7 @@ static void do_header_and_snapshot(struct kgsl_device *device, int fault,
 		return;
 
 	/* Print the fault header */
-	adreno_fault_header(device, rb, cmdobj);
+	adreno_fault_header(device, rb, cmdobj, fault, gx_on);
 
 	if (!(drawobj->context->flags & KGSL_CONTEXT_NO_SNAPSHOT))
 		kgsl_device_snapshot(device, drawobj->context,
@@ -2080,8 +2093,24 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
 	if (fault == 0)
 		return 0;
 
+	mutex_lock(&device->mutex);
+
+	/*
+	 * In the very unlikely case that the power is off, do nothing - the
+	 * state will be reset on power up and everybody will be happy
+	 */
+	if (!kgsl_state_is_awake(device)) {
+		mutex_unlock(&device->mutex);
+		if (fault & ADRENO_SOFT_FAULT) {
+			/* Clear the existing register values */
+			memset(adreno_ft_regs_val, 0,
+				adreno_ft_regs_num * sizeof(unsigned int));
+		}
+		return 0;
+	}
+
 	/* Mask all GMU interrupts */
-	if (gmu_core_isenabled(device)) {
+	if (gmu_core_gpmu_isenabled(device)) {
 		adreno_write_gmureg(adreno_dev,
 			ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
 			0xFFFFFFFF);
@@ -2093,17 +2122,6 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
 	if (GMU_DEV_OP_VALID(gmu_dev_ops, gx_is_on))
 		gx_on = gmu_dev_ops->gx_is_on(adreno_dev);
 
-	/*
-	 * In the very unlikely case that the power is off, do nothing - the
-	 * state will be reset on power up and everybody will be happy
-	 */
-
-	if (!kgsl_state_is_awake(device) && (fault & ADRENO_SOFT_FAULT)) {
-		/* Clear the existing register values */
-		memset(adreno_ft_regs_val, 0,
-				adreno_ft_regs_num * sizeof(unsigned int));
-		return 0;
-	}
 
 	/*
 	 * On A5xx and A6xx, read RBBM_STATUS3:SMMU_STALLED_ON_FAULT (BIT 24)
@@ -2116,11 +2134,11 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
 		gx_on) {
 		unsigned int val;
 
-		mutex_lock(&device->mutex);
 		adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS3, &val);
-		mutex_unlock(&device->mutex);
-		if (val & BIT(24))
+		if (val & BIT(24)) {
+			mutex_unlock(&device->mutex);
 			return 0;
+		}
 	}
 
 	/* Turn off all the timers */
@@ -2133,8 +2151,6 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
 	if (adreno_is_preemption_enabled(adreno_dev))
 		del_timer_sync(&adreno_dev->preempt.timer);
 
-	mutex_lock(&device->mutex);
-
 	if (gx_on)
 		adreno_readreg64(adreno_dev, ADRENO_REG_CP_RB_BASE,
 			ADRENO_REG_CP_RB_BASE_HI, &base);
@@ -2177,7 +2193,7 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
 		adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB1_BASE,
 			ADRENO_REG_CP_IB1_BASE_HI, &base);
 
-	do_header_and_snapshot(device, fault, hung_rb, cmdobj);
+	do_header_and_snapshot(device, fault, hung_rb, cmdobj, gx_on);
 
 	/* Turn off the KEEPALIVE vote from the ISR for hard fault */
 	if (gpudev->gpu_keepalive && fault & ADRENO_HARD_FAULT)
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index a769915..694a243 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -74,13 +74,13 @@ void adreno_drawctxt_dump(struct kgsl_device *device,
 	 * deadlock. To prevent this use spin_trylock_bh.
 	 */
 	if (!spin_trylock_bh(&drawctxt->lock)) {
-		dev_err(device->dev, "  context[%d]: could not get lock\n",
+		dev_err(device->dev, "  context[%u]: could not get lock\n",
 			context->id);
 		return;
 	}
 
 	dev_err(device->dev,
-		"  context[%d]: queue=%d, submit=%d, start=%d, retire=%d\n",
+		"  context[%u]: queue=%u, submit=%u, start=%u, retire=%u\n",
 		context->id, queue, drawctxt->submitted_timestamp,
 		start, retire);
 
@@ -90,7 +90,7 @@ void adreno_drawctxt_dump(struct kgsl_device *device,
 
 		if (test_bit(ADRENO_CONTEXT_FENCE_LOG, &context->priv)) {
 			dev_err(device->dev,
-				"  possible deadlock. Context %d might be blocked for itself\n",
+				"  possible deadlock. Context %u might be blocked for itself\n",
 				context->id);
 			goto stats;
 		}
@@ -103,7 +103,7 @@ void adreno_drawctxt_dump(struct kgsl_device *device,
 
 			if (kgsl_drawobj_events_pending(syncobj)) {
 				dev_err(device->dev,
-					"  context[%d] (ts=%d) Active sync points:\n",
+					"  context[%u] (ts=%u) Active sync points:\n",
 					context->id, drawobj->timestamp);
 
 				kgsl_dump_syncpoints(device, syncobj);
@@ -127,10 +127,10 @@ void adreno_drawctxt_dump(struct kgsl_device *device,
 		msecs = drawctxt->submit_retire_ticks[index] * 10;
 		usecs = do_div(msecs, 192);
 		usecs = do_div(msecs, 1000);
-		pos += snprintf(buf + pos, sizeof(buf) - pos, "%d.%0d ",
+		pos += snprintf(buf + pos, sizeof(buf) - pos, "%u.%0u ",
 			(unsigned int)msecs, usecs);
 	}
-	dev_err(device->dev, "  context[%d]: submit times: %s\n",
+	dev_err(device->dev, "  context[%u]: submit times: %s\n",
 		context->id, buf);
 
 	spin_unlock_bh(&drawctxt->lock);
@@ -534,7 +534,7 @@ void adreno_drawctxt_detach(struct kgsl_context *context)
 	 */
 	if (ret && ret != -EAGAIN) {
 		KGSL_DRV_ERR(device,
-				"Wait for global ctx=%d ts=%d type=%d error=%d\n",
+				"Wait for global ctx=%u ts=%u type=%d error=%d\n",
 				drawctxt->base.id, drawctxt->internal_timestamp,
 				drawctxt->type, ret);
 
diff --git a/drivers/gpu/msm/adreno_llc.h b/drivers/gpu/msm/adreno_llc.h
index 2fa2202..fc8e226 100644
--- a/drivers/gpu/msm/adreno_llc.h
+++ b/drivers/gpu/msm/adreno_llc.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
@@ -80,7 +80,7 @@ static inline bool adreno_llc_supported(void)
 static inline void *adreno_llc_getd(struct device *dev,
 		const char *name)
 {
-	return NULL;
+	return ERR_PTR(-ENODEV);
 }
 
 static inline void adreno_llc_putd(void *desc)
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index f604e76..3ed79af 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.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
@@ -805,6 +805,8 @@ static void adreno_snapshot_iommu(struct kgsl_device *device,
 static void adreno_snapshot_ringbuffer(struct kgsl_device *device,
 		struct kgsl_snapshot *snapshot, struct adreno_ringbuffer *rb)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
 	struct snapshot_rb_params params = {
 		.snapshot = snapshot,
 		.rb = rb,
@@ -815,6 +817,16 @@ static void adreno_snapshot_ringbuffer(struct kgsl_device *device,
 
 	kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_RB_V2, snapshot,
 		snapshot_rb, &params);
+
+	/* Add preemption context records for the ringbuffer */
+	if (adreno_is_preemption_enabled(adreno_dev)) {
+		if (gpudev->snapshot_preemption)
+			kgsl_snapshot_add_section(device,
+				KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2, snapshot,
+				gpudev->snapshot_preemption,
+				&rb->preemption_desc);
+	}
+
 }
 
 /* adreno_snapshot - Snapshot the Adreno GPU state
@@ -839,9 +851,6 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
 
 	snapshot_frozen_objsize = 0;
 
-	setup_fault_process(device, snapshot,
-			context ? context->proc_priv : NULL);
-
 	/* Add GPU specific sections - registers mainly, but other stuff too */
 	if (gpudev->snapshot)
 		gpudev->snapshot(adreno_dev, snapshot);
@@ -851,6 +860,9 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
 			!gmu_dev_ops->gx_is_on(adreno_dev))
 		return;
 
+	setup_fault_process(device, snapshot,
+			context ? context->proc_priv : NULL);
+
 	adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB1_BASE,
 			ADRENO_REG_CP_IB1_BASE_HI, &snapshot->ib1base);
 	adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BUFSZ, &snapshot->ib1size);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 26243c5..08f13fb 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.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
@@ -559,7 +559,7 @@ void kgsl_context_dump(struct kgsl_context *context)
 	device = context->device;
 
 	if (kgsl_context_detached(context)) {
-		dev_err(device->dev, "  context[%d]: context detached\n",
+		dev_err(device->dev, "  context[%u]: context detached\n",
 			context->id);
 	} else if (device->ftbl->drawctxt_dump != NULL)
 		device->ftbl->drawctxt_dump(device, context);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 9cf2597..b5b7c26 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -656,7 +656,7 @@ static inline int kgsl_state_is_awake(struct kgsl_device *device)
 	if (device->state == KGSL_STATE_ACTIVE ||
 		device->state == KGSL_STATE_AWARE)
 		return true;
-	else if (gmu_core_isenabled(device) &&
+	else if (gmu_core_gpmu_isenabled(device) &&
 			test_bit(GMU_CLK_ON, &device->gmu_core.flags))
 		return true;
 	else
diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c
index 7e89ac1..dc6d835 100644
--- a/drivers/gpu/msm/kgsl_drawobj.c
+++ b/drivers/gpu/msm/kgsl_drawobj.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
@@ -101,7 +101,7 @@ void kgsl_dump_syncpoints(struct kgsl_device *device,
 				&retired);
 
 			dev_err(device->dev,
-				"  [timestamp] context %d timestamp %d (retired %d)\n",
+				"  [timestamp] context %u timestamp %u (retired %u)\n",
 				event->context->id, event->timestamp,
 				retired);
 			break;
@@ -143,7 +143,7 @@ static void syncobj_timer(unsigned long data)
 	device = drawobj->context->device;
 
 	dev_err(device->dev,
-		"kgsl: possible gpu syncpoint deadlock for context %d timestamp %d\n",
+		"kgsl: possible gpu syncpoint deadlock for context %u timestamp %u\n",
 		drawobj->context->id, drawobj->timestamp);
 
 	set_bit(ADRENO_CONTEXT_FENCE_LOG, &drawobj->context->priv);
@@ -160,7 +160,7 @@ static void syncobj_timer(unsigned long data)
 
 		switch (event->type) {
 		case KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP:
-			dev_err(device->dev, "       [%d] TIMESTAMP %d:%d\n",
+			dev_err(device->dev, "       [%u] TIMESTAMP %u:%u\n",
 				i, event->context->id, event->timestamp);
 			break;
 		case KGSL_CMD_SYNCPOINT_TYPE_FENCE: {
@@ -168,7 +168,7 @@ static void syncobj_timer(unsigned long data)
 			struct event_fence_info *info = &event->info;
 
 			for (j = 0; j < info->num_fences; j++)
-				dev_err(device->dev, "       [%d] FENCE %s\n",
+				dev_err(device->dev, "       [%u] FENCE %s\n",
 					i, info->fences[j].name);
 			break;
 		}
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index cda0ad17..9bdd05a 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.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
@@ -390,7 +390,7 @@ static void events_debugfs_print_group(struct seq_file *s,
 		group->readtimestamp(event->device, group->priv,
 			KGSL_TIMESTAMP_RETIRED, &retired);
 
-		seq_printf(s, "\t%d:%d age=%lu func=%ps [retired=%d]\n",
+		seq_printf(s, "\t%u:%u age=%lu func=%ps [retired=%u]\n",
 			group->context ? group->context->id :
 						KGSL_MEMSTORE_GLOBAL,
 			event->timestamp, jiffies  - event->created,
diff --git a/drivers/gpu/msm/kgsl_gmu_core.c b/drivers/gpu/msm/kgsl_gmu_core.c
index c73069b..6e98bb5 100644
--- a/drivers/gpu/msm/kgsl_gmu_core.c
+++ b/drivers/gpu/msm/kgsl_gmu_core.c
@@ -108,7 +108,7 @@ bool gmu_core_isenabled(struct kgsl_device *device)
 
 bool gmu_core_gpmu_isenabled(struct kgsl_device *device)
 {
-	return test_bit(GMU_GPMU, &device->gmu_core.flags);
+	return test_bit(GMU_GPMU, &device->gmu_core.flags) && !nogmu;
 }
 
 bool gmu_core_scales_bandwidth(struct kgsl_device *device)
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 2b845cc..927406e 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.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
@@ -749,7 +749,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
 	struct kgsl_mmu *mmu = pt->mmu;
 	struct kgsl_iommu *iommu;
 	struct kgsl_iommu_context *ctx;
-	u64 ptbase;
+	u64 ptbase, proc_ptbase;
 	u32 contextidr;
 	pid_t pid = 0;
 	pid_t ptname;
@@ -861,6 +861,17 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
 			"GPU PAGE FAULT: addr = %lX pid= %d name=%s\n", addr,
 			ptname,
 			context != NULL ? context->proc_priv->comm : "unknown");
+
+		if (context != NULL) {
+			proc_ptbase = kgsl_mmu_pagetable_get_ttbr0(
+					context->proc_priv->pagetable);
+
+			if (ptbase != proc_ptbase)
+				KGSL_MEM_CRIT(ctx->kgsldev,
+				"Pagetable address mismatch: HW address is 0x%llx but SW expected 0x%llx\n",
+				ptbase, proc_ptbase);
+		}
+
 		KGSL_MEM_CRIT(ctx->kgsldev,
 			"context=%s ctx_type=%s TTBR0=0x%llx CIDR=0x%x (%s %s fault)\n",
 			ctx->name, api_str, ptbase, contextidr,
@@ -1257,7 +1268,7 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
 		if (ret) {
 			pr_err("SMMU aperture programming call failed with error %d\n",
 									ret);
-			return ret;
+			goto done;
 		}
 	}
 
@@ -1812,15 +1823,19 @@ static unsigned int _get_protection_flags(struct kgsl_pagetable *pt,
 {
 	unsigned int flags = IOMMU_READ | IOMMU_WRITE |
 		IOMMU_NOEXEC;
-	int ret, llc_nwa = 0;
+	int ret, llc_nwa = 0, upstream_hint = 0;
 	struct kgsl_iommu_pt *iommu_pt = pt->priv;
 
 	ret = iommu_domain_get_attr(iommu_pt->domain,
+				DOMAIN_ATTR_USE_UPSTREAM_HINT, &upstream_hint);
+
+	if (!ret && upstream_hint)
+		flags |= IOMMU_USE_UPSTREAM_HINT;
+
+	ret = iommu_domain_get_attr(iommu_pt->domain,
 				DOMAIN_ATTR_USE_LLC_NWA, &llc_nwa);
 
-	if (ret || (llc_nwa == 0))
-		flags |= IOMMU_USE_UPSTREAM_HINT;
-	else
+	if (!ret && llc_nwa)
 		flags |= IOMMU_USE_LLC_NWA;
 
 	if (memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY)
@@ -2288,6 +2303,7 @@ static int _insert_gpuaddr(struct kgsl_pagetable *pagetable,
 		else {
 			/* Duplicate entry */
 			WARN(1, "duplicate gpuaddr: 0x%llx\n", gpuaddr);
+			kmem_cache_free(addr_entry_cache, new);
 			return -EEXIST;
 		}
 	}
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 9519016..513e8ec 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.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
@@ -61,7 +61,8 @@ static const char * const clocks[] = {
 	"rbcpr_clk",
 	"iref_clk",
 	"gmu_clk",
-	"ahb_clk"
+	"ahb_clk",
+	"smmu_vote",
 };
 
 static unsigned int ib_votes[KGSL_MAX_BUSLEVELS];
@@ -2840,7 +2841,7 @@ _aware(struct kgsl_device *device)
 		break;
 	case KGSL_STATE_INIT:
 		/* if GMU already in FAULT */
-		if (gmu_core_isenabled(device) &&
+		if (gmu_core_gpmu_isenabled(device) &&
 			test_bit(GMU_FAULT, &device->gmu_core.flags)) {
 			status = -EINVAL;
 			break;
@@ -2857,7 +2858,7 @@ _aware(struct kgsl_device *device)
 		break;
 	case KGSL_STATE_SLUMBER:
 		/* if GMU already in FAULT */
-		if (gmu_core_isenabled(device) &&
+		if (gmu_core_gpmu_isenabled(device) &&
 			test_bit(GMU_FAULT, &device->gmu_core.flags)) {
 			status = -EINVAL;
 			break;
@@ -2870,7 +2871,7 @@ _aware(struct kgsl_device *device)
 	}
 
 	if (status) {
-		if (gmu_core_isenabled(device)) {
+		if (gmu_core_gpmu_isenabled(device)) {
 			/* GMU hang recovery */
 			kgsl_pwrctrl_set_state(device, KGSL_STATE_RESET);
 			set_bit(GMU_FAULT, &device->gmu_core.flags);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 421e8d2dd..5f1637b 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -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
@@ -26,7 +26,7 @@
 
 #define KGSL_PWR_ON	0xFFFF
 
-#define KGSL_MAX_CLKS 16
+#define KGSL_MAX_CLKS 17
 #define KGSL_MAX_REGULATORS 2
 
 #define KGSL_MAX_PWRLEVELS 10
diff --git a/drivers/gpu/msm/kgsl_rgmu.c b/drivers/gpu/msm/kgsl_rgmu.c
index 425ce8d..bd4069f 100644
--- a/drivers/gpu/msm/kgsl_rgmu.c
+++ b/drivers/gpu/msm/kgsl_rgmu.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
@@ -312,7 +312,6 @@ static void rgmu_stop(struct kgsl_device *device)
 	 * that hang recovery is needed to power on GPU
 	 */
 	set_bit(GMU_FAULT, &device->gmu_core.flags);
-	gmu_dev_ops->irq_disable(device);
 	rgmu_snapshot(device);
 }
 
@@ -447,7 +446,6 @@ static int rgmu_start(struct kgsl_device *device)
 
 error_rgmu:
 	set_bit(GMU_FAULT, &device->gmu_core.flags);
-	gmu_dev_ops->irq_disable(device);
 	rgmu_snapshot(device);
 	return ret;
 }
@@ -489,4 +487,5 @@ struct gmu_core_ops rgmu_ops = {
 	.dcvs_set = rgmu_dcvs_set,
 	.snapshot = rgmu_snapshot,
 	.regulator_isenabled = rgmu_regulator_isenabled,
+	.suspend = rgmu_suspend,
 };
diff --git a/drivers/gpu/msm/kgsl_rgmu.h b/drivers/gpu/msm/kgsl_rgmu.h
index 23dac44..c5d80c6 100644
--- a/drivers/gpu/msm/kgsl_rgmu.h
+++ b/drivers/gpu/msm/kgsl_rgmu.h
@@ -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
@@ -25,6 +25,7 @@
 
 /**
  * struct rgmu_device - rGMU device structure
+ * @ver: RGMU firmware version
  * @reg_phys: RGMU CSR physical address
  * @reg_virt: RGMU CSR virtual address
  * @reg_len: RGMU CSR range
@@ -44,6 +45,7 @@
  * @fault_count: RGMU fault count
  */
 struct rgmu_device {
+	u32 ver;
 	struct platform_device *pdev;
 	unsigned long reg_phys;
 	unsigned int reg_len;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index ca49afd..952099d 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -510,9 +510,14 @@ static int kgsl_unlock_sgt(struct sg_table *sgt)
 
 	ret = hyp_assign_table(sgt, &source_vm, 1, &dest_vm, &dest_perms, 1);
 
+	if (ret) {
+		pr_err("kgsl: hyp_assign_table failed ret: %d\n", ret);
+		return ret;
+	}
+
 	for_each_sg_page(sgt->sgl, &sg_iter, sgt->nents, 0)
 		ClearPagePrivate(sg_page_iter_page(&sg_iter));
-	return ret;
+	return 0;
 }
 
 static void kgsl_page_alloc_free(struct kgsl_memdesc *memdesc)
@@ -527,23 +532,18 @@ static void kgsl_page_alloc_free(struct kgsl_memdesc *memdesc)
 
 		ret = kgsl_unlock_sgt(memdesc->sgt);
 		if (ret) {
-			pr_err("Secure buf unlock failed: gpuaddr: %llx size: %llx ret: %d\n",
-					memdesc->gpuaddr, memdesc->size, ret);
+			pr_err("Failure to unlock secure GPU memory 0x%llx. %llx bytes will not be recoverable\n",
+					memdesc->gpuaddr, memdesc->size);
+			return;
 		}
 
+		kgsl_pool_free_sgt(memdesc->sgt);
 		atomic_long_sub(memdesc->size, &kgsl_driver.stats.secure);
 	} else {
 		atomic_long_add(memdesc->size,
 			&kgsl_driver.stats.page_free_pending);
-	}
-
-	/* Free pages using the pages array for non secure paged memory */
-	if (memdesc->pages != NULL)
+		/* Free pages using pages array for non secure paged memory */
 		kgsl_pool_free_pages(memdesc->pages, memdesc->page_count);
-	else
-		kgsl_pool_free_sgt(memdesc->sgt);
-
-	if (!(memdesc->priv & KGSL_MEMDESC_TZ_LOCKED)) {
 		atomic_long_sub(memdesc->size, &kgsl_driver.stats.page_alloc);
 		atomic_long_sub(memdesc->size,
 			&kgsl_driver.stats.page_free_pending);
@@ -1043,8 +1043,8 @@ void kgsl_free_secure_page(struct page *page)
 	sg_init_table(&sgl, 1);
 	sg_set_page(&sgl, page, PAGE_SIZE, 0);
 
-	kgsl_unlock_sgt(&sgt);
-	__free_page(page);
+	if (!kgsl_unlock_sgt(&sgt))
+		__free_page(page);
 }
 
 struct page *kgsl_alloc_secure_page(void)
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index bc8357f..3f6eac3 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.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
@@ -335,10 +335,8 @@ int kgsl_snapshot_get_object(struct kgsl_snapshot *snapshot,
 
 	entry = kgsl_sharedmem_find(process, gpuaddr);
 
-	if (entry == NULL) {
-		KGSL_CORE_ERR("Unable to find GPU buffer 0x%016llX\n", gpuaddr);
+	if (entry == NULL)
 		return -EINVAL;
-	}
 
 	/* We can't freeze external memory, because we don't own it */
 	if (entry->memdesc.flags & KGSL_MEMFLAGS_USERMEM_MASK)
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index ae8c8e6..a90967c 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -30,6 +30,7 @@
 
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/kfifo.h>
 #include <linux/sched/signal.h>
 #include <linux/export.h>
 #include <linux/slab.h>
@@ -457,7 +458,7 @@ static char *resolv_usage_page(unsigned page, struct seq_file *f) {
 	char *buf = NULL;
 
 	if (!f) {
-		buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
+		buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_ATOMIC);
 		if (!buf)
 			return ERR_PTR(-ENOMEM);
 	}
@@ -661,17 +662,12 @@ EXPORT_SYMBOL_GPL(hid_dump_device);
 /* enqueue string to 'events' ring buffer */
 void hid_debug_event(struct hid_device *hdev, char *buf)
 {
-	unsigned i;
 	struct hid_debug_list *list;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hdev->debug_list_lock, flags);
-	list_for_each_entry(list, &hdev->debug_list, node) {
-		for (i = 0; buf[i]; i++)
-			list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] =
-				buf[i];
-		list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE;
-        }
+	list_for_each_entry(list, &hdev->debug_list, node)
+		kfifo_in(&list->hid_debug_fifo, buf, strlen(buf));
 	spin_unlock_irqrestore(&hdev->debug_list_lock, flags);
 
 	wake_up_interruptible(&hdev->debug_wait);
@@ -722,8 +718,7 @@ void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 valu
 	hid_debug_event(hdev, buf);
 
 	kfree(buf);
-        wake_up_interruptible(&hdev->debug_wait);
-
+	wake_up_interruptible(&hdev->debug_wait);
 }
 EXPORT_SYMBOL_GPL(hid_dump_input);
 
@@ -1088,8 +1083,8 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
 		goto out;
 	}
 
-	if (!(list->hid_debug_buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
-		err = -ENOMEM;
+	err = kfifo_alloc(&list->hid_debug_fifo, HID_DEBUG_FIFOSIZE, GFP_KERNEL);
+	if (err) {
 		kfree(list);
 		goto out;
 	}
@@ -1109,77 +1104,57 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
 		size_t count, loff_t *ppos)
 {
 	struct hid_debug_list *list = file->private_data;
-	int ret = 0, len;
+	int ret = 0, copied;
 	DECLARE_WAITQUEUE(wait, current);
 
 	mutex_lock(&list->read_mutex);
-	while (ret == 0) {
-		if (list->head == list->tail) {
-			add_wait_queue(&list->hdev->debug_wait, &wait);
-			set_current_state(TASK_INTERRUPTIBLE);
+	if (kfifo_is_empty(&list->hid_debug_fifo)) {
+		add_wait_queue(&list->hdev->debug_wait, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
 
-			while (list->head == list->tail) {
-				if (file->f_flags & O_NONBLOCK) {
-					ret = -EAGAIN;
-					break;
-				}
-				if (signal_pending(current)) {
-					ret = -ERESTARTSYS;
-					break;
-				}
-
-				if (!list->hdev || !list->hdev->debug) {
-					ret = -EIO;
-					set_current_state(TASK_RUNNING);
-					goto out;
-				}
-
-				/* allow O_NONBLOCK from other threads */
-				mutex_unlock(&list->read_mutex);
-				schedule();
-				mutex_lock(&list->read_mutex);
-				set_current_state(TASK_INTERRUPTIBLE);
+		while (kfifo_is_empty(&list->hid_debug_fifo)) {
+			if (file->f_flags & O_NONBLOCK) {
+				ret = -EAGAIN;
+				break;
 			}
 
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&list->hdev->debug_wait, &wait);
+			if (signal_pending(current)) {
+				ret = -ERESTARTSYS;
+				break;
+			}
+
+			/* if list->hdev is NULL we cannot remove_wait_queue().
+			 * if list->hdev->debug is 0 then hid_debug_unregister()
+			 * was already called and list->hdev is being destroyed.
+			 * if we add remove_wait_queue() here we can hit a race.
+			 */
+			if (!list->hdev || !list->hdev->debug) {
+				ret = -EIO;
+				set_current_state(TASK_RUNNING);
+				goto out;
+			}
+
+			/* allow O_NONBLOCK from other threads */
+			mutex_unlock(&list->read_mutex);
+			schedule();
+			mutex_lock(&list->read_mutex);
+			set_current_state(TASK_INTERRUPTIBLE);
 		}
 
+		__set_current_state(TASK_RUNNING);
+		remove_wait_queue(&list->hdev->debug_wait, &wait);
+
 		if (ret)
 			goto out;
-
-		/* pass the ringbuffer contents to userspace */
-copy_rest:
-		if (list->tail == list->head)
-			goto out;
-		if (list->tail > list->head) {
-			len = list->tail - list->head;
-			if (len > count)
-				len = count;
-
-			if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
-				ret = -EFAULT;
-				goto out;
-			}
-			ret += len;
-			list->head += len;
-		} else {
-			len = HID_DEBUG_BUFSIZE - list->head;
-			if (len > count)
-				len = count;
-
-			if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
-				ret = -EFAULT;
-				goto out;
-			}
-			list->head = 0;
-			ret += len;
-			count -= len;
-			if (count > 0)
-				goto copy_rest;
-		}
-
 	}
+
+	/* pass the fifo content to userspace, locking is not needed with only
+	 * one concurrent reader and one concurrent writer
+	 */
+	ret = kfifo_to_user(&list->hid_debug_fifo, buffer, count, &copied);
+	if (ret)
+		goto out;
+	ret = copied;
 out:
 	mutex_unlock(&list->read_mutex);
 	return ret;
@@ -1190,7 +1165,7 @@ static unsigned int hid_debug_events_poll(struct file *file, poll_table *wait)
 	struct hid_debug_list *list = file->private_data;
 
 	poll_wait(file, &list->hdev->debug_wait, wait);
-	if (list->head != list->tail)
+	if (!kfifo_is_empty(&list->hid_debug_fifo))
 		return POLLIN | POLLRDNORM;
 	if (!list->hdev->debug)
 		return POLLERR | POLLHUP;
@@ -1205,7 +1180,7 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
 	spin_lock_irqsave(&list->hdev->debug_list_lock, flags);
 	list_del(&list->node);
 	spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags);
-	kfree(list->hid_debug_buf);
+	kfifo_free(&list->hid_debug_fifo);
 	kfree(list);
 
 	return 0;
@@ -1256,4 +1231,3 @@ void hid_debug_exit(void)
 {
 	debugfs_remove_recursive(hid_debug_root);
 }
-
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 8f649c6..d04fef0 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -17,6 +17,9 @@
 #ifndef HID_IDS_H_FILE
 #define HID_IDS_H_FILE
 
+#define USB_VENDOR_ID_258A		0x258a
+#define USB_DEVICE_ID_258A_6A88		0x6a88
+
 #define USB_VENDOR_ID_3M		0x0596
 #define USB_DEVICE_ID_3M1968		0x0500
 #define USB_DEVICE_ID_3M2256		0x0502
diff --git a/drivers/hid/hid-ite.c b/drivers/hid/hid-ite.c
index 1882a4a..98b059d 100644
--- a/drivers/hid/hid-ite.c
+++ b/drivers/hid/hid-ite.c
@@ -42,6 +42,7 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field,
 
 static const struct hid_device_id ite_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, ite_devices);
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index 643b6eb..eacc76d 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -743,7 +743,9 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
 	data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd;
 	data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd;
 	data_pointer->led_mute.dev = dev;
-	led_classdev_register(dev, &data_pointer->led_mute);
+	ret = led_classdev_register(dev, &data_pointer->led_mute);
+	if (ret < 0)
+		goto err;
 
 	data_pointer->led_micmute.name = name_micmute;
 	data_pointer->led_micmute.brightness_get =
@@ -751,7 +753,11 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
 	data_pointer->led_micmute.brightness_set =
 		lenovo_led_brightness_set_tpkbd;
 	data_pointer->led_micmute.dev = dev;
-	led_classdev_register(dev, &data_pointer->led_micmute);
+	ret = led_classdev_register(dev, &data_pointer->led_micmute);
+	if (ret < 0) {
+		led_classdev_unregister(&data_pointer->led_mute);
+		goto err;
+	}
 
 	lenovo_features_set_tpkbd(hdev);
 
diff --git a/drivers/hid/hid-qvr.c b/drivers/hid/hid-qvr.c
index 16e91f4..1f66275 100644
--- a/drivers/hid/hid-qvr.c
+++ b/drivers/hid/hid-qvr.c
@@ -35,32 +35,26 @@
 #include <linux/spinlock.h>
 #include <linux/timekeeping.h>
 #include <linux/soc/qcom/smem_state.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+#include <linux/uaccess.h>
 #include "hid-ids.h"
 #include "hid-qvr.h"
 #include "hid-trace.h"
 
-static struct dma_buf *qvr_buf;
-static void *vaddr;
-static size_t vsize;
-static uint64_t ts_base;
-static uint64_t ts_offset;
+#define QVR_START_IMU		_IO('q', 1)
+#define QVR_STOP_IMU		_IO('q', 2)
+#define QVR_READ_CALIB_DATA_LEN	_IOR('q', 3, int32_t)
+#define QVR_READ_CALIB_DATA	_IOR('q', 4, struct qvr_calib_data)
 
 struct gpio_info {
 	unsigned int smem_bit;
 	struct qcom_smem_state *smem_state;
 };
 
-
-static struct device *qvr_device;
-static struct gpio_info gpio_info_out;
-
-static struct hid_driver qvr_external_sensor_driver;
-static int fd;
-
-const static int msg_size = 368;
-const static int hid_request_report_id = 2;
-const static int hid_request_report_size = 64;
-
 struct qvr_buf_index {
 	int most_recent_index;
 	uint8_t padding[60];
@@ -82,9 +76,170 @@ struct qvr_sensor_t {
 	uint8_t padding[4];
 };
 
+struct qvr_calib_data {
+	__u64 data_ptr;
+};
 
-int qvr_send_package_wrap(u8 *message, int msize, struct hid_device *hid)
+struct qvr_external_sensor {
+	struct hid_device *hdev;
+	struct device *device;
+	struct dma_buf *qvr_buf;
+	struct class *class;
+	struct device *dev;
+	void *vaddr;
+	u8 *calib_data_pkt;
+	struct cdev cdev;
+	struct gpio_info gpio_info_out;
+	dev_t dev_no;
+	uint64_t ts_base;
+	uint64_t ts_offset;
+	size_t vsize;
+	int calib_data_len;
+	int calib_data_recv;
+	int ext_ack;
+	int fd;
+};
+
+const static int msg_size = 368;
+const static int hid_request_report_id = 2;
+const static int hid_request_report_size = 64;
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+static struct qvr_external_sensor qvr_external_sensor;
+
+static int read_calibration_len(void)
 {
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
+	__u8 *hid_buf;
+	int ret;
+
+	hid_buf = kzalloc(256, GFP_KERNEL);
+	if (hid_buf == NULL)
+		return -ENOMEM;
+
+	hid_buf[0] = 2;
+	hid_buf[1] = 20;
+
+	ret = hid_hw_raw_request(sensor->hdev, hid_buf[0],
+		hid_buf,
+		hid_request_report_size,
+		HID_FEATURE_REPORT,
+		HID_REQ_SET_REPORT);
+
+	ret = wait_event_interruptible_timeout(wq,
+		sensor->calib_data_len != -1, msecs_to_jiffies(1000));
+	if (ret == 0) {
+		kfree(hid_buf);
+		return -ETIME;
+	}
+
+	kfree(hid_buf);
+	return sensor->calib_data_len;
+}
+
+static uint8_t *read_calibration_data(void)
+{
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
+	__u8 *hid_buf;
+	int ret, total_read_len;
+	uint8_t read_len;
+	uint8_t *complete_data = NULL;
+
+	if (sensor->calib_data_len < 0) {
+		pr_err("%s: calibration data len missing", __func__);
+		return NULL;
+	}
+
+	hid_buf = kzalloc(256, GFP_KERNEL);
+	if (hid_buf == NULL)
+		return NULL;
+
+	hid_buf[0] = 2;
+	hid_buf[1] = 21;
+
+	complete_data = kzalloc(sensor->calib_data_len, GFP_KERNEL);
+	if (complete_data == NULL) {
+		kfree(hid_buf);
+		return NULL;
+	}
+	total_read_len = 0;
+	while (total_read_len < sensor->calib_data_len) {
+		sensor->calib_data_recv = 0;
+		ret = hid_hw_raw_request(sensor->hdev, hid_buf[0],
+			hid_buf,
+			hid_request_report_size,
+			HID_FEATURE_REPORT,
+			HID_REQ_SET_REPORT);
+		ret = wait_event_interruptible_timeout(wq,
+			sensor->calib_data_recv == 1, msecs_to_jiffies(1000));
+		if (ret == 0) {
+			pr_err("%s:get calibration data timeout", __func__);
+			kfree(hid_buf);
+			kfree(complete_data);
+			return NULL;
+		}
+		if (sensor->calib_data_pkt == NULL) {
+			kfree(hid_buf);
+			kfree(complete_data);
+			return NULL;
+		}
+		read_len = sensor->calib_data_pkt[2];
+		if (total_read_len > sensor->calib_data_len - read_len) {
+			kfree(hid_buf);
+			kfree(complete_data);
+			return NULL;
+		}
+		memcpy(&complete_data[total_read_len],
+			&sensor->calib_data_pkt[3], read_len);
+		total_read_len += read_len;
+	}
+
+	kfree(hid_buf);
+	return complete_data;
+}
+
+static int control_imu_stream(bool status)
+{
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
+	__u8 *hid_buf;
+	int ret;
+
+	sensor->ext_ack = 0;
+	hid_buf = kzalloc(256, GFP_KERNEL);
+	if (hid_buf == NULL)
+		return -ENOMEM;
+
+	hid_buf[0] = 2;
+	hid_buf[1] = 25;
+	hid_buf[2] = status;
+
+	ret = hid_hw_raw_request(sensor->hdev, hid_buf[0],
+		hid_buf,
+		hid_request_report_size,
+		HID_FEATURE_REPORT,
+		HID_REQ_SET_REPORT);
+	ret = wait_event_interruptible_timeout(wq, sensor->ext_ack == 1,
+		msecs_to_jiffies(1000));
+	if (ret && status) {
+		pr_debug("qvr: falling back - start IMU stream failed\n");
+		hid_buf[0] = hid_request_report_id;
+		hid_buf[1] = 7;
+		ret = hid_hw_raw_request(sensor->hdev, hid_buf[0], hid_buf,
+				hid_request_report_size,
+				HID_FEATURE_REPORT,
+				HID_REQ_SET_REPORT);
+	}
+	kfree(hid_buf);
+	if (ret > 0)
+		return 0;
+
+	return -ETIME;
+}
+
+
+static int qvr_send_package_wrap(u8 *message, int msize, struct hid_device *hid)
+{
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
 	struct qvr_sensor_t *sensor_buf;
 	struct qvr_sensor_t *data;
 	static int buf_index;
@@ -99,19 +254,22 @@ int qvr_send_package_wrap(u8 *message, int msize, struct hid_device *hid)
 	 */
 	memcpy((void *)&imuData, (void *)message + 1, msg_size);
 
-	if (!ts_base)
-		ts_base = ktime_to_ns(ktime_get_boottime());
-	if (!ts_offset)
-		ts_offset = imuData.gts0;
-	index_buf = (struct qvr_buf_index *)
-		((uintptr_t)vaddr + (vsize / 2) + (8 * sizeof(*sensor_buf)));
-	sensor_buf = (struct qvr_sensor_t *)((uintptr_t)vaddr + (vsize / 2));
+	if (!sensor->ts_base)
+		sensor->ts_base = ktime_to_ns(ktime_get_boottime());
+	if (!sensor->ts_offset)
+		sensor->ts_offset = imuData.gts0;
+	index_buf = (struct qvr_buf_index *)((uintptr_t)sensor->vaddr +
+			(sensor->vsize / 2) + (8 * sizeof(*sensor_buf)));
+	sensor_buf = (struct qvr_sensor_t *)((uintptr_t)sensor->vaddr +
+			(sensor->vsize / 2));
 
 	data = (struct qvr_sensor_t *)&(sensor_buf[buf_index]);
-	if (ts_offset > imuData.gts0)
-		data->ats = ts_base + ((ts_offset - imuData.gts0) * 100);
+	if (sensor->ts_offset > imuData.gts0)
+		data->ats = sensor->ts_base +
+				((sensor->ts_offset - imuData.gts0) * 100);
 	else
-		data->ats = ts_base + ((imuData.gts0 - ts_offset) * 100);
+		data->ats = sensor->ts_base +
+				((imuData.gts0 - sensor->ts_offset) * 100);
 	if (imuData.mts0 == 0)
 		data->mts = 0;
 	else
@@ -161,38 +319,39 @@ static int register_smp2p(struct device *dev, char *node_name,
 	}
 
 	return 0;
-
 }
-static int kernel_map_gyro_buffer(int fd)
+
+static int kernel_map_gyro_buffer(void)
 {
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
 	int ret = 0;
 
-	qvr_buf = dma_buf_get(fd);
-	if (IS_ERR_OR_NULL(qvr_buf)) {
+	sensor->qvr_buf = dma_buf_get(sensor->fd);
+	if (IS_ERR_OR_NULL(sensor->qvr_buf)) {
 		ret = -ENOMEM;
-		pr_err("dma_buf_get failed for fd: %d\n", fd);
+		pr_err("dma_buf_get failed for fd: %d\n", sensor->fd);
 		goto done;
 	}
-	ret = dma_buf_begin_cpu_access(qvr_buf, DMA_BIDIRECTIONAL);
+	ret = dma_buf_begin_cpu_access(sensor->qvr_buf, DMA_BIDIRECTIONAL);
 	if (ret) {
 		pr_err("%s: dma_buf_begin_cpu_access failed\n", __func__);
 		goto err_dma;
 	}
-	vsize = qvr_buf->size;
-	vaddr = dma_buf_kmap(qvr_buf, 0);
-	if (IS_ERR_OR_NULL(vaddr)) {
+	sensor->vsize = sensor->qvr_buf->size;
+	sensor->vaddr = dma_buf_kmap(sensor->qvr_buf, 0);
+	if (IS_ERR_OR_NULL(sensor->vaddr)) {
 		ret = -ENOMEM;
-		pr_err("dma_buf_kmap failed for fd: %d\n", fd);
+		pr_err("dma_buf_kmap failed for fd: %d\n", sensor->fd);
 		goto err_end_access;
 	}
 
 	return 0;
 
 err_end_access:
-	dma_buf_end_cpu_access(qvr_buf, DMA_BIDIRECTIONAL);
+	dma_buf_end_cpu_access(sensor->qvr_buf, DMA_BIDIRECTIONAL);
 err_dma:
-	dma_buf_put(qvr_buf);
-	qvr_buf = NULL;
+	dma_buf_put(sensor->qvr_buf);
+	sensor->qvr_buf = NULL;
 done:
 	return ret;
 
@@ -201,37 +360,40 @@ static int kernel_map_gyro_buffer(int fd)
 
 static void kernel_unmap_gyro_buffer(void)
 {
-	if (IS_ERR_OR_NULL(vaddr))
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
+
+	if (IS_ERR_OR_NULL(sensor->vaddr))
 		return;
-	dma_buf_kunmap(qvr_buf, 0, vaddr);
-	dma_buf_end_cpu_access(qvr_buf, DMA_BIDIRECTIONAL);
-	vaddr = NULL;
-	dma_buf_put(qvr_buf);
-	qvr_buf = NULL;
+	dma_buf_kunmap(sensor->qvr_buf, 0, sensor->vaddr);
+	dma_buf_end_cpu_access(sensor->qvr_buf, DMA_BIDIRECTIONAL);
+	sensor->vaddr = NULL;
+	dma_buf_put(sensor->qvr_buf);
+	sensor->qvr_buf = NULL;
 }
 
 static ssize_t fd_show(struct kobject *kobj,
 	struct kobj_attribute *attr,
 	char *buf)
 {
-	return snprintf(buf, sizeof(buf), "%d\n", fd);
+	return snprintf(buf, sizeof(buf), "%d\n", qvr_external_sensor.fd);
 }
 
 static ssize_t fd_store(struct kobject *kobj,
 	struct kobj_attribute *attr,
 	const char *buf, size_t count)
 {
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
 	int ret;
 
-	ret = kstrtoint(buf, 10, &fd);
+	ret = kstrtoint(buf, 10, &sensor->fd);
 	if (ret < 0)
 		return ret;
-	if (fd == -1)
+	if (sensor->fd == -1)
 		kernel_unmap_gyro_buffer();
 	else
-		kernel_map_gyro_buffer(fd);
-	ts_base = 0;
-	ts_offset = 0;
+		kernel_map_gyro_buffer();
+	sensor->ts_base = 0;
+	sensor->ts_offset = 0;
 
 	return count;
 }
@@ -239,7 +401,7 @@ static ssize_t fd_store(struct kobject *kobj,
 static ssize_t ts_base_show(struct kobject *kobj,
 	struct kobj_attribute *attr, char *buf)
 {
-	return  snprintf(buf, 16, "%lld\n", ts_base);
+	return snprintf(buf, 16, "%lld\n", qvr_external_sensor.ts_base);
 }
 
 static ssize_t ts_base_store(struct kobject *kobj,
@@ -252,7 +414,7 @@ static ssize_t ts_base_store(struct kobject *kobj,
 static ssize_t ts_offset_show(struct kobject *kobj,
 	struct kobj_attribute *attr, char *buf)
 {
-	return  snprintf(buf, 16, "%lld\n", ts_offset * 100);
+	return snprintf(buf, 16, "%lld\n", qvr_external_sensor.ts_offset * 100);
 }
 
 static ssize_t ts_offset_store(struct kobject *kobj,
@@ -288,11 +450,12 @@ static struct kobject *qvr_external_sensor_kobj;
 static int qvr_external_sensor_probe(struct hid_device *hdev,
 	const struct hid_device_id *id)
 {
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
 	int ret;
 	char *node_name = "qcom,smp2p-interrupt-qvrexternal-5-out";
-	__u8 *hid_buf;
+	sensor->hdev = hdev;
 
-	ret = register_smp2p(&hdev->dev, node_name, &gpio_info_out);
+	ret = register_smp2p(&hdev->dev, node_name, &sensor->gpio_info_out);
 	if (ret) {
 		pr_err("%s: register_smp2p failed", __func__);
 		goto err_free;
@@ -307,18 +470,7 @@ static int qvr_external_sensor_probe(struct hid_device *hdev,
 		pr_err("%s: hid_hw_start failed", __func__);
 		goto err_free;
 	}
-	hid_buf = kzalloc(255, GFP_ATOMIC);
-	if (hid_buf == NULL)
-		return -ENOMEM;
-	hid_buf[0] = hid_request_report_id;
-	hid_buf[1] = 7;
-	ret = hid_hw_raw_request(hdev, hid_buf[0], hid_buf,
-		hid_request_report_size,
-		HID_FEATURE_REPORT,
-		HID_REQ_SET_REPORT);
-	kfree(hid_buf);
-
-	qvr_device = &hdev->dev;
+	sensor->device = &hdev->dev;
 
 	return 0;
 
@@ -327,22 +479,96 @@ static int qvr_external_sensor_probe(struct hid_device *hdev,
 
 }
 
+static int qvr_external_sensor_fops_open(struct inode *inode,
+	struct file *file)
+{
+	return 0;
+}
+
+static int qvr_external_sensor_fops_close(struct inode *inode,
+	struct file *file)
+{
+	return 0;
+}
+static long qvr_external_sensor_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
+	struct qvr_calib_data data;
+	uint8_t *calib_data;
+	void __user *argp = (void __user *)arg;
+	int ret;
+
+	if (sensor->device == NULL) {
+		pr_err("%s: device not connected", __func__);
+		return -EINVAL;
+	}
+
+	switch (cmd) {
+	case QVR_START_IMU:
+		ret = control_imu_stream(1);
+		return ret;
+	case QVR_STOP_IMU:
+		ret = control_imu_stream(0);
+		return ret;
+	case QVR_READ_CALIB_DATA_LEN:
+		sensor->calib_data_len = -1;
+		ret = read_calibration_len();
+		if (ret < 0)
+			return ret;
+		if (copy_to_user(argp, &sensor->calib_data_len,
+					sizeof(sensor->calib_data_len)))
+			return -EFAULT;
+		return 0;
+	case QVR_READ_CALIB_DATA:
+		sensor->calib_data_recv = 0;
+		calib_data = read_calibration_data();
+		if (calib_data == NULL)
+			return -ENOMEM;
+		data.data_ptr = (__u64)arg;
+		if (copy_to_user(u64_to_user_ptr(data.data_ptr), calib_data,
+				sensor->calib_data_len)) {
+			kfree(calib_data);
+			return -EFAULT;
+		}
+		kfree(calib_data);
+		return 0;
+	default:
+		pr_err("%s: wrong command", __func__);
+		return -EINVAL;
+
+	}
+	return 0;
+}
 static int qvr_external_sensor_raw_event(struct hid_device *hid,
 	struct hid_report *report,
 	u8 *data, int size)
 {
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
 	static int val;
 	int ret = -1;
 
-	if (vaddr != NULL && report->id == 0x1) {
+	if (sensor->vaddr != NULL && report->id == 0x1) {
 		ret = qvr_send_package_wrap(data/*hid_value*/, size, hid);
 		if (ret == 0) {
 			val = 1 ^ val;
-			qcom_smem_state_update_bits(gpio_info_out.smem_state,
-				BIT(gpio_info_out.smem_bit), val);
+			qcom_smem_state_update_bits(
+				sensor->gpio_info_out.smem_state,
+				BIT(sensor->gpio_info_out.smem_bit), val);
 			ret = -1;
 		}
 	}
+	if (report->id == 0x2) {
+		if (data[0] == 2 && data[1] == 0) /*calibration data len*/
+			sensor->calib_data_len = (data[3] << 24)
+				| (data[4] << 16) | (data[5] << 8) | data[6];
+		else if (data[0] == 2 && data[1] == 1) { /*calibration data*/
+			sensor->calib_data_pkt = data;
+			sensor->calib_data_recv = 1;
+		} else if (data[0] == 2 && data[1] == 4) /*calibration ack*/
+			sensor->ext_ack = 1;
+
+	}
 	return ret;
 }
 
@@ -358,6 +584,14 @@ static struct hid_device_id qvr_external_sensor_table[] = {
 };
 MODULE_DEVICE_TABLE(hid, qvr_external_sensor_table);
 
+static const struct file_operations qvr_external_sensor_ops = {
+	.owner = THIS_MODULE,
+	.open = qvr_external_sensor_fops_open,
+	.unlocked_ioctl = qvr_external_sensor_ioctl,
+	.compat_ioctl = qvr_external_sensor_ioctl,
+	.release = qvr_external_sensor_fops_close,
+};
+
 static struct hid_driver qvr_external_sensor_driver = {
 	.name = "qvr_external_sensor",
 	.id_table = qvr_external_sensor_table,
@@ -370,6 +604,7 @@ module_hid_driver(qvr_external_sensor_driver);
 
 static int __init qvr_external_sensor_init(void)
 {
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
 	int ret = 0;
 
 	qvr_external_sensor_kobj =
@@ -384,15 +619,47 @@ static int __init qvr_external_sensor_init(void)
 		return -ENOMEM;
 	}
 
+	ret = alloc_chrdev_region(&sensor->dev_no, 0, 1, "qvr_external_sensor");
+	if (ret < 0) {
+		pr_err("%s: alloc_chrdev_region failed");
+		return ret;
+	}
+	cdev_init(&sensor->cdev, &qvr_external_sensor_ops);
+	ret = cdev_add(&sensor->cdev, sensor->dev_no, 1);
+
+	if (ret < 0) {
+		pr_err("%s: cdev_add failed");
+		return ret;
+	}
+	sensor->class = class_create(THIS_MODULE, "qvr_external_sensor");
+	if (sensor->class == NULL) {
+		cdev_del(&sensor->cdev);
+		unregister_chrdev_region(sensor->dev_no, 1);
+		return -ret;
+	}
+	sensor->dev = device_create(sensor->class, NULL,
+				MKDEV(MAJOR(sensor->dev_no), 0), NULL,
+				"qvr_external_sensor_ioctl");
+	if (sensor->dev == NULL) {
+		class_destroy(sensor->class);
+		cdev_del(&sensor->cdev);
+		unregister_chrdev_region(sensor->dev_no, 1);
+		return -ret;
+	}
 	return ret;
 }
 
 static void __exit qvr_external_sensor_exit(void)
 {
+	struct qvr_external_sensor *sensor = &qvr_external_sensor;
+
+	device_destroy(sensor->class, MKDEV(MAJOR(sensor->dev_no), 0));
+	class_destroy(sensor->class);
+	cdev_del(&sensor->cdev);
+	unregister_chrdev_region(sensor->dev_no, 1);
 	kobject_put(qvr_external_sensor_kobj);
 }
 
 module_init(qvr_external_sensor_init);
 module_exit(qvr_external_sensor_exit);
 MODULE_LICENSE("GPL v2");
-
diff --git a/drivers/hid/hid-qvr.h b/drivers/hid/hid-qvr.h
index 575c4a1..5cf1e7f6 100644
--- a/drivers/hid/hid-qvr.h
+++ b/drivers/hid/hid-qvr.h
@@ -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
@@ -156,7 +156,6 @@ struct external_imu_format {
 	s16 mz3; //368 bytes
 };
 
-int qvr_send_package_wrap(u8 *message, int msize, struct hid_device *hid);
 void qvr_clear_def_parmeter(void);
 void qvr_init(struct hid_device *hdev);
 int qvr_input_init(void);
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 50b89ea..247a6260 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -2,7 +2,7 @@
 
 config HYPERV
 	tristate "Microsoft Hyper-V client drivers"
-	depends on X86 && ACPI && PCI && X86_LOCAL_APIC && HYPERVISOR_GUEST
+	depends on X86 && ACPI && X86_LOCAL_APIC && HYPERVISOR_GUEST
 	select PARAVIRT
 	help
 	  Select this option to run Linux as a Hyper-V client operating
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index db0e665..0824405 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -846,12 +846,14 @@ static unsigned long handle_pg_range(unsigned long pg_start,
 			pfn_cnt -= pgs_ol;
 			/*
 			 * Check if the corresponding memory block is already
-			 * online by checking its last previously backed page.
-			 * In case it is we need to bring rest (which was not
-			 * backed previously) online too.
+			 * online. It is possible to observe struct pages still
+			 * being uninitialized here so check section instead.
+			 * In case the section is online we need to bring the
+			 * rest of pfns (which were not backed previously)
+			 * online too.
 			 */
 			if (start_pfn > has->start_pfn &&
-			    !PageReserved(pfn_to_page(start_pfn - 1)))
+			    online_section_nr(pfn_to_section_nr(start_pfn)))
 				hv_bring_pgs_online(has, start_pfn, pgs_ol);
 
 		}
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 3f8dde8..74c1dfb 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -141,26 +141,25 @@ static u32 hv_copyto_ringbuffer(
 }
 
 /* Get various debug metrics for the specified ring buffer. */
-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
-				 struct hv_ring_buffer_debug_info *debug_info)
+int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
+				struct hv_ring_buffer_debug_info *debug_info)
 {
 	u32 bytes_avail_towrite;
 	u32 bytes_avail_toread;
 
-	if (ring_info->ring_buffer) {
-		hv_get_ringbuffer_availbytes(ring_info,
-					&bytes_avail_toread,
-					&bytes_avail_towrite);
+	if (!ring_info->ring_buffer)
+		return -EINVAL;
 
-		debug_info->bytes_avail_toread = bytes_avail_toread;
-		debug_info->bytes_avail_towrite = bytes_avail_towrite;
-		debug_info->current_read_index =
-			ring_info->ring_buffer->read_index;
-		debug_info->current_write_index =
-			ring_info->ring_buffer->write_index;
-		debug_info->current_interrupt_mask =
-			ring_info->ring_buffer->interrupt_mask;
-	}
+	hv_get_ringbuffer_availbytes(ring_info,
+				     &bytes_avail_toread,
+				     &bytes_avail_towrite);
+	debug_info->bytes_avail_toread = bytes_avail_toread;
+	debug_info->bytes_avail_towrite = bytes_avail_towrite;
+	debug_info->current_read_index = ring_info->ring_buffer->read_index;
+	debug_info->current_write_index = ring_info->ring_buffer->write_index;
+	debug_info->current_interrupt_mask
+		= ring_info->ring_buffer->interrupt_mask;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo);
 
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 4218a61..1fd812e 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -297,12 +297,16 @@ static ssize_t out_intr_mask_show(struct device *dev,
 {
 	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_ring_buffer_debug_info outbound;
+	int ret;
 
 	if (!hv_dev->channel)
 		return -ENODEV;
-	if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-		return -EINVAL;
-	hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+	ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+					  &outbound);
+	if (ret < 0)
+		return ret;
+
 	return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
 }
 static DEVICE_ATTR_RO(out_intr_mask);
@@ -312,12 +316,15 @@ static ssize_t out_read_index_show(struct device *dev,
 {
 	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_ring_buffer_debug_info outbound;
+	int ret;
 
 	if (!hv_dev->channel)
 		return -ENODEV;
-	if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-		return -EINVAL;
-	hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+	ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+					  &outbound);
+	if (ret < 0)
+		return ret;
 	return sprintf(buf, "%d\n", outbound.current_read_index);
 }
 static DEVICE_ATTR_RO(out_read_index);
@@ -328,12 +335,15 @@ static ssize_t out_write_index_show(struct device *dev,
 {
 	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_ring_buffer_debug_info outbound;
+	int ret;
 
 	if (!hv_dev->channel)
 		return -ENODEV;
-	if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-		return -EINVAL;
-	hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+	ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+					  &outbound);
+	if (ret < 0)
+		return ret;
 	return sprintf(buf, "%d\n", outbound.current_write_index);
 }
 static DEVICE_ATTR_RO(out_write_index);
@@ -344,12 +354,15 @@ static ssize_t out_read_bytes_avail_show(struct device *dev,
 {
 	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_ring_buffer_debug_info outbound;
+	int ret;
 
 	if (!hv_dev->channel)
 		return -ENODEV;
-	if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-		return -EINVAL;
-	hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+	ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+					  &outbound);
+	if (ret < 0)
+		return ret;
 	return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
 }
 static DEVICE_ATTR_RO(out_read_bytes_avail);
@@ -360,12 +373,15 @@ static ssize_t out_write_bytes_avail_show(struct device *dev,
 {
 	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_ring_buffer_debug_info outbound;
+	int ret;
 
 	if (!hv_dev->channel)
 		return -ENODEV;
-	if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-		return -EINVAL;
-	hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+	ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+					  &outbound);
+	if (ret < 0)
+		return ret;
 	return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
 }
 static DEVICE_ATTR_RO(out_write_bytes_avail);
@@ -375,12 +391,15 @@ static ssize_t in_intr_mask_show(struct device *dev,
 {
 	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_ring_buffer_debug_info inbound;
+	int ret;
 
 	if (!hv_dev->channel)
 		return -ENODEV;
-	if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-		return -EINVAL;
-	hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+	ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+	if (ret < 0)
+		return ret;
+
 	return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
 }
 static DEVICE_ATTR_RO(in_intr_mask);
@@ -390,12 +409,15 @@ static ssize_t in_read_index_show(struct device *dev,
 {
 	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_ring_buffer_debug_info inbound;
+	int ret;
 
 	if (!hv_dev->channel)
 		return -ENODEV;
-	if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-		return -EINVAL;
-	hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+	ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+	if (ret < 0)
+		return ret;
+
 	return sprintf(buf, "%d\n", inbound.current_read_index);
 }
 static DEVICE_ATTR_RO(in_read_index);
@@ -405,12 +427,15 @@ static ssize_t in_write_index_show(struct device *dev,
 {
 	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_ring_buffer_debug_info inbound;
+	int ret;
 
 	if (!hv_dev->channel)
 		return -ENODEV;
-	if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-		return -EINVAL;
-	hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+	ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+	if (ret < 0)
+		return ret;
+
 	return sprintf(buf, "%d\n", inbound.current_write_index);
 }
 static DEVICE_ATTR_RO(in_write_index);
@@ -421,12 +446,15 @@ static ssize_t in_read_bytes_avail_show(struct device *dev,
 {
 	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_ring_buffer_debug_info inbound;
+	int ret;
 
 	if (!hv_dev->channel)
 		return -ENODEV;
-	if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-		return -EINVAL;
-	hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+	ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+	if (ret < 0)
+		return ret;
+
 	return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
 }
 static DEVICE_ATTR_RO(in_read_bytes_avail);
@@ -437,12 +465,15 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
 {
 	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_ring_buffer_debug_info inbound;
+	int ret;
 
 	if (!hv_dev->channel)
 		return -ENODEV;
-	if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-		return -EINVAL;
-	hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+	ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+	if (ret < 0)
+		return ret;
+
 	return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
 }
 static DEVICE_ATTR_RO(in_write_bytes_avail);
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 08e3945..f9b8e3e 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -360,9 +360,11 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	struct i2c_client *client = data->client;
 	unsigned long min, val;
 	u8 reg;
-	int err = kstrtoul(buf, 10, &val);
-	if (err < 0)
-		return err;
+	int rv;
+
+	rv = kstrtoul(buf, 10, &val);
+	if (rv < 0)
+		return rv;
 
 	/* Save fan_min */
 	mutex_lock(&data->update_lock);
@@ -390,8 +392,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 		return -EINVAL;
 	}
 
-	reg = (lm80_read_value(client, LM80_REG_FANDIV) &
-	       ~(3 << (2 * (nr + 1)))) | (data->fan_div[nr] << (2 * (nr + 1)));
+	rv = lm80_read_value(client, LM80_REG_FANDIV);
+	if (rv < 0) {
+		mutex_unlock(&data->update_lock);
+		return rv;
+	}
+	reg = (rv & ~(3 << (2 * (nr + 1))))
+	    | (data->fan_div[nr] << (2 * (nr + 1)));
 	lm80_write_value(client, LM80_REG_FANDIV, reg);
 
 	/* Restore fan_min */
@@ -623,6 +630,7 @@ static int lm80_probe(struct i2c_client *client,
 	struct device *dev = &client->dev;
 	struct device *hwmon_dev;
 	struct lm80_data *data;
+	int rv;
 
 	data = devm_kzalloc(dev, sizeof(struct lm80_data), GFP_KERNEL);
 	if (!data)
@@ -635,8 +643,14 @@ static int lm80_probe(struct i2c_client *client,
 	lm80_init_client(client);
 
 	/* A few vars need to be filled upon startup */
-	data->fan[f_min][0] = lm80_read_value(client, LM80_REG_FAN_MIN(1));
-	data->fan[f_min][1] = lm80_read_value(client, LM80_REG_FAN_MIN(2));
+	rv = lm80_read_value(client, LM80_REG_FAN_MIN(1));
+	if (rv < 0)
+		return rv;
+	data->fan[f_min][0] = rv;
+	rv = lm80_read_value(client, LM80_REG_FAN_MIN(2));
+	if (rv < 0)
+		return rv;
+	data->fan[f_min][1] = rv;
 
 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
 							   data, lm80_groups);
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index e363992..ceb3db6f3 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -88,7 +88,7 @@ static const struct of_device_id tmp421_of_match[] = {
 		.data = (void *)2
 	},
 	{
-		.compatible = "ti,tmp422",
+		.compatible = "ti,tmp442",
 		.data = (void *)3
 	},
 	{ },
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 85b93c1..d229fd2 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -30,4 +30,4 @@
 obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
 obj-$(CONFIG_CORESIGHT_REMOTE_ETM) += coresight-remote-etm.o
 obj-$(CONFIG_CORESIGHT_CSR) += coresight-csr.o
-obj-$(CONFIG_CORESIGHT_TGU) += coresight-tgu.o
+obj-$(CONFIG_CORESIGHT_TGU) += coresight-tgu.o apss_tgu.o
diff --git a/drivers/hwtracing/coresight/apss_tgu.c b/drivers/hwtracing/coresight/apss_tgu.c
new file mode 100644
index 0000000..0776cdd
--- /dev/null
+++ b/drivers/hwtracing/coresight/apss_tgu.c
@@ -0,0 +1,58 @@
+/* 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 <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#define CREATE_TRACE_POINTS
+#include "trace/events/tgu.h"
+#include "apss_tgu.h"
+
+static irqreturn_t tgu_irq_handler(int irq, void *data)
+{
+	trace_tgu_interrupt(irq);
+	return IRQ_HANDLED;
+}
+
+
+int register_interrupt_handler(struct device_node *node)
+{
+	int irq, ret, i, n;
+
+	n = of_irq_count(node);
+	pr_debug("number of irqs == %d\n", n);
+
+	for (i = 0; i < n; i++) {
+		irq = of_irq_get(node, i);
+		if (irq < 0) {
+			pr_err("Invalid IRQ for error fatal %u\n", irq);
+			return irq;
+		}
+
+		ret = request_irq(irq,  tgu_irq_handler,
+				IRQF_TRIGGER_RISING, "apps-tgu", NULL);
+		if (ret < 0) {
+			pr_err("Unable to register IRQ handler %d", irq);
+			continue;
+		}
+
+		ret = irq_set_irq_wake(irq, true);
+		if (ret < 0)
+			pr_err("Unable to set as wakeup irq %d\n", irq);
+
+	}
+	return 0;
+}
diff --git a/drivers/hwtracing/coresight/apss_tgu.h b/drivers/hwtracing/coresight/apss_tgu.h
new file mode 100644
index 0000000..a70bc5d
--- /dev/null
+++ b/drivers/hwtracing/coresight/apss_tgu.h
@@ -0,0 +1,17 @@
+/* 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 __QCOM_APSS_TGU_H__
+#define __QCOM_APSS_TGU_H__
+
+int register_interrupt_handler(struct device_node *node);
+#endif /* __QCOM_APSS_TGU_H__ */
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index 4e6eab5..6ac35db 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -2073,16 +2073,16 @@ static u32 etmv4_cross_read(const struct device *dev, u32 offset)
 	coresight_simple_func(struct etmv4_drvdata, etmv4_cross_read,	\
 			      name, offset)
 
-coresight_etm4x_reg(trcpdcr, TRCPDCR);
-coresight_etm4x_reg(trcpdsr, TRCPDSR);
-coresight_etm4x_reg(trclsr, TRCLSR);
-coresight_etm4x_reg(trcauthstatus, TRCAUTHSTATUS);
-coresight_etm4x_reg(trcdevid, TRCDEVID);
-coresight_etm4x_reg(trcdevtype, TRCDEVTYPE);
-coresight_etm4x_reg(trcpidr0, TRCPIDR0);
-coresight_etm4x_reg(trcpidr1, TRCPIDR1);
-coresight_etm4x_reg(trcpidr2, TRCPIDR2);
-coresight_etm4x_reg(trcpidr3, TRCPIDR3);
+coresight_etm4x_cross_read(trcpdcr, TRCPDCR);
+coresight_etm4x_cross_read(trcpdsr, TRCPDSR);
+coresight_etm4x_cross_read(trclsr, TRCLSR);
+coresight_etm4x_cross_read(trcauthstatus, TRCAUTHSTATUS);
+coresight_etm4x_cross_read(trcdevid, TRCDEVID);
+coresight_etm4x_cross_read(trcdevtype, TRCDEVTYPE);
+coresight_etm4x_cross_read(trcpidr0, TRCPIDR0);
+coresight_etm4x_cross_read(trcpidr1, TRCPIDR1);
+coresight_etm4x_cross_read(trcpidr2, TRCPIDR2);
+coresight_etm4x_cross_read(trcpidr3, TRCPIDR3);
 coresight_etm4x_cross_read(trcoslsr, TRCOSLSR);
 coresight_etm4x_cross_read(trcconfig, TRCCONFIGR);
 coresight_etm4x_cross_read(trctraceid, TRCTRACEIDR);
diff --git a/drivers/hwtracing/coresight/coresight-tgu.c b/drivers/hwtracing/coresight/coresight-tgu.c
index 607bc60..8006e0f 100644
--- a/drivers/hwtracing/coresight/coresight-tgu.c
+++ b/drivers/hwtracing/coresight/coresight-tgu.c
@@ -25,6 +25,7 @@
 #include <linux/coresight.h>
 
 #include "coresight-priv.h"
+#include "apss_tgu.h"
 
 #define tgu_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
 #define tgu_readl(drvdata, off)		__raw_readl(drvdata->base + off)
@@ -415,6 +416,7 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
 	struct coresight_platform_data *pdata;
 	struct tgu_drvdata *drvdata;
 	struct coresight_desc *desc;
+	const char *name;
 
 	pdata = of_get_coresight_platform_data(dev, adev->dev.of_node);
 	if (IS_ERR(pdata))
@@ -504,6 +506,13 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
 		goto err;
 	}
 
+	of_property_read_string(adev->dev.of_node, "coresight-name", &name);
+	if (!strcmp(name, "coresight-tgu-apss")) {
+		ret = register_interrupt_handler(adev->dev.of_node);
+		if (ret)
+			return ret;
+	}
+
 	pm_runtime_put(&adev->dev);
 	dev_dbg(dev, "TGU initialized\n");
 	return 0;
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 3aa81bc..bad7afd 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -943,18 +943,11 @@ static ssize_t reset_store(struct device *dev,
 	/* Init the default data */
 	tpdm_init_default_data(drvdata);
 
-	/* Disable tpdm if enabled */
-	if (drvdata->enable) {
-		__tpdm_disable(drvdata);
-		drvdata->enable = false;
-	}
-
 	mutex_unlock(&drvdata->lock);
 
-	if (drvdata->enable) {
-		tpdm_setup_disable(drvdata);
-		dev_info(drvdata->dev, "TPDM tracing disabled\n");
-	}
+	/* Disable tpdm if enabled */
+	if (drvdata->enable)
+		coresight_disable(drvdata->csdev);
 
 	return size;
 }
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 6118c23..b801fc6 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -25,6 +25,7 @@
 #include <linux/of_platform.h>
 #include <linux/delay.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 
 #include "coresight-priv.h"
 
@@ -116,6 +117,53 @@ static void coresight_reset_all_sink(void)
 	bus_for_each_dev(&coresight_bustype, NULL, NULL, coresight_reset_sink);
 }
 
+void coresight_enable_reg_clk(struct coresight_device *csdev)
+{
+	struct coresight_reg_clk *reg_clk = csdev->reg_clk;
+	int ret;
+	int i, j;
+
+	if (IS_ERR_OR_NULL(reg_clk))
+		return;
+
+	for (i = 0; i < reg_clk->nr_reg; i++) {
+		ret = regulator_enable(reg_clk->reg[i]);
+		if (ret)
+			goto err_regs;
+	}
+
+	for (j = 0; j < reg_clk->nr_clk; j++) {
+		ret = clk_prepare_enable(reg_clk->clk[j]);
+		if (ret)
+			goto err_clks;
+	}
+
+	return;
+
+err_clks:
+	for (j--; j >= 0; j--)
+		clk_disable_unprepare(reg_clk->clk[j]);
+err_regs:
+	for (i--; i >= 0; i--)
+		regulator_disable(reg_clk->reg[i]);
+}
+EXPORT_SYMBOL(coresight_enable_reg_clk);
+
+void coresight_disable_reg_clk(struct coresight_device *csdev)
+{
+	struct coresight_reg_clk *reg_clk = csdev->reg_clk;
+	int i;
+
+	if (IS_ERR_OR_NULL(reg_clk))
+		return;
+
+	for (i = reg_clk->nr_clk - 1; i >= 0; i--)
+		clk_disable_unprepare(reg_clk->clk[i]);
+	for (i = reg_clk->nr_reg - 1; i >= 0; i--)
+		regulator_disable(reg_clk->reg[i]);
+}
+EXPORT_SYMBOL(coresight_disable_reg_clk);
+
 static int coresight_find_link_inport(struct coresight_device *csdev,
 				      struct coresight_device *parent)
 {
@@ -158,9 +206,12 @@ static int coresight_enable_sink(struct coresight_device *csdev, u32 mode)
 
 	if (!csdev->enable) {
 		if (sink_ops(csdev)->enable) {
+			coresight_enable_reg_clk(csdev);
 			ret = sink_ops(csdev)->enable(csdev, mode);
-			if (ret)
+			if (ret) {
+				coresight_disable_reg_clk(csdev);
 				return ret;
+			}
 		}
 		csdev->enable = true;
 	}
@@ -175,6 +226,7 @@ static void coresight_disable_sink(struct coresight_device *csdev)
 	if (atomic_dec_return(csdev->refcnt) == 0) {
 		if (sink_ops(csdev)->disable) {
 			sink_ops(csdev)->disable(csdev);
+			coresight_disable_reg_clk(csdev);
 			csdev->enable = false;
 			csdev->activated = false;
 		}
@@ -208,8 +260,10 @@ static int coresight_enable_link(struct coresight_device *csdev,
 
 	if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
 		if (link_ops(csdev)->enable) {
+			coresight_enable_reg_clk(csdev);
 			ret = link_ops(csdev)->enable(csdev, inport, outport);
 			if (ret) {
+				coresight_disable_reg_clk(csdev);
 				atomic_dec(&csdev->refcnt[refport]);
 				return ret;
 			}
@@ -248,8 +302,10 @@ static void coresight_disable_link(struct coresight_device *csdev,
 	}
 
 	if (atomic_dec_return(&csdev->refcnt[refport]) == 0) {
-		if (link_ops(csdev)->disable)
+		if (link_ops(csdev)->disable) {
 			link_ops(csdev)->disable(csdev, inport, outport);
+			coresight_disable_reg_clk(csdev);
+		}
 	}
 
 	for (i = 0; i < nr_conns; i++)
@@ -271,9 +327,12 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
 
 	if (!csdev->enable) {
 		if (source_ops(csdev)->enable) {
+			coresight_enable_reg_clk(csdev);
 			ret = source_ops(csdev)->enable(csdev, NULL, mode);
-			if (ret)
+			if (ret) {
+				coresight_disable_reg_clk(csdev);
 				return ret;
+			}
 		}
 		csdev->enable = true;
 	}
@@ -294,8 +353,10 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
 static bool coresight_disable_source(struct coresight_device *csdev)
 {
 	if (atomic_dec_return(csdev->refcnt) == 0) {
-		if (source_ops(csdev)->disable)
+		if (source_ops(csdev)->disable) {
 			source_ops(csdev)->disable(csdev, NULL);
+			coresight_disable_reg_clk(csdev);
+		}
 		csdev->enable = false;
 	}
 	return !csdev->enable;
@@ -1150,6 +1211,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
 	csdev->subtype = desc->subtype;
 	csdev->ops = desc->ops;
 	csdev->orphan = false;
+	csdev->reg_clk = desc->pdata->reg_clk;
 
 	csdev->dev.type = &coresight_dev_type[desc->type];
 	csdev->dev.groups = desc->groups;
diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c
index 3f568f9..7b3d5e0 100644
--- a/drivers/hwtracing/coresight/of_coresight.c
+++ b/drivers/hwtracing/coresight/of_coresight.c
@@ -118,6 +118,59 @@ int of_coresight_get_cpu(const struct device_node *node)
 }
 EXPORT_SYMBOL_GPL(of_coresight_get_cpu);
 
+static struct coresight_reg_clk *
+of_coresight_get_reg_clk(struct device *dev, const struct device_node *node)
+{
+	struct coresight_reg_clk *reg_clk;
+	const char *clk_name, *reg_name;
+	int nr_reg, nr_clk, i, ret;
+
+	nr_reg = of_property_count_strings(node, "qcom,proxy-regs");
+	nr_clk = of_property_count_strings(node, "qcom,proxy-clks");
+	if (!nr_reg && !nr_clk)
+		return NULL;
+
+	reg_clk = devm_kzalloc(dev, sizeof(*reg_clk), GFP_KERNEL);
+	if (!reg_clk)
+		return ERR_PTR(-ENOMEM);
+
+	reg_clk->nr_reg = nr_reg;
+	reg_clk->nr_clk = nr_clk;
+	if (nr_reg > 0) {
+		reg_clk->reg = devm_kzalloc(dev, nr_reg *
+			sizeof(reg_clk->reg), GFP_KERNEL);
+		if (!reg_clk->reg)
+			return ERR_PTR(-ENOMEM);
+
+		for (i = 0; i < nr_reg; i++) {
+			ret = of_property_read_string_index(node,
+				"qcom,proxy-regs", i, &reg_name);
+			if (ret)
+				return ERR_PTR(ret);
+			reg_clk->reg[i] = devm_regulator_get(dev, reg_name);
+			if (IS_ERR(reg_clk->reg[i]))
+				return ERR_PTR(-EINVAL);
+		}
+	}
+	if (nr_clk > 0) {
+		reg_clk->clk = devm_kzalloc(dev, nr_clk *
+			sizeof(reg_clk->clk), GFP_KERNEL);
+		if (!reg_clk->clk)
+			return ERR_PTR(-ENOMEM);
+
+		for (i = 0; i < nr_clk; i++) {
+			ret = of_property_read_string_index(node,
+				"qcom,proxy-clks", i, &clk_name);
+			if (ret)
+				return ERR_PTR(ret);
+			reg_clk->clk[i] = devm_clk_get(dev, clk_name);
+			if (IS_ERR(reg_clk->clk[i]))
+				return ERR_PTR(-EINVAL);
+		}
+	}
+	return reg_clk;
+}
+
 struct coresight_platform_data *
 of_get_coresight_platform_data(struct device *dev,
 			       const struct device_node *node)
@@ -199,6 +252,10 @@ of_get_coresight_platform_data(struct device *dev,
 
 	pdata->cpu = of_coresight_get_cpu(node);
 
+	pdata->reg_clk = of_coresight_get_reg_clk(dev, node);
+	if (IS_ERR(pdata->reg_clk))
+		return (void *)(pdata->reg_clk);
+
 	return pdata;
 }
 EXPORT_SYMBOL_GPL(of_get_coresight_platform_data);
diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c
index 58ac786..82f2b70 100644
--- a/drivers/hwtracing/intel_th/msu.c
+++ b/drivers/hwtracing/intel_th/msu.c
@@ -1431,7 +1431,8 @@ nr_pages_store(struct device *dev, struct device_attribute *attr,
 		if (!end)
 			break;
 
-		len -= end - p;
+		/* consume the number and the following comma, hence +1 */
+		len -= end - p + 1;
 		p = end + 1;
 	} while (len);
 
diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
index deea138..30d80ce 100644
--- a/drivers/i2c/busses/i2c-axxia.c
+++ b/drivers/i2c/busses/i2c-axxia.c
@@ -296,22 +296,7 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
 			i2c_int_disable(idev, MST_STATUS_TFL);
 	}
 
-	if (status & MST_STATUS_SCC) {
-		/* Stop completed */
-		i2c_int_disable(idev, ~MST_STATUS_TSS);
-		complete(&idev->msg_complete);
-	} else if (status & MST_STATUS_SNS) {
-		/* Transfer done */
-		i2c_int_disable(idev, ~MST_STATUS_TSS);
-		if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
-			axxia_i2c_empty_rx_fifo(idev);
-		complete(&idev->msg_complete);
-	} else if (status & MST_STATUS_TSS) {
-		/* Transfer timeout */
-		idev->msg_err = -ETIMEDOUT;
-		i2c_int_disable(idev, ~MST_STATUS_TSS);
-		complete(&idev->msg_complete);
-	} else if (unlikely(status & MST_STATUS_ERR)) {
+	if (unlikely(status & MST_STATUS_ERR)) {
 		/* Transfer error */
 		i2c_int_disable(idev, ~0);
 		if (status & MST_STATUS_AL)
@@ -328,6 +313,21 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
 			readl(idev->base + MST_TX_BYTES_XFRD),
 			readl(idev->base + MST_TX_XFER));
 		complete(&idev->msg_complete);
+	} else if (status & MST_STATUS_SCC) {
+		/* Stop completed */
+		i2c_int_disable(idev, ~MST_STATUS_TSS);
+		complete(&idev->msg_complete);
+	} else if (status & MST_STATUS_SNS) {
+		/* Transfer done */
+		i2c_int_disable(idev, ~MST_STATUS_TSS);
+		if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
+			axxia_i2c_empty_rx_fifo(idev);
+		complete(&idev->msg_complete);
+	} else if (status & MST_STATUS_TSS) {
+		/* Transfer timeout */
+		idev->msg_err = -ETIMEDOUT;
+		i2c_int_disable(idev, ~MST_STATUS_TSS);
+		complete(&idev->msg_complete);
 	}
 
 out:
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 68f1db3..45e106fe 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -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
@@ -28,6 +28,7 @@
 #include <linux/ipc_logging.h>
 #include <linux/dmaengine.h>
 #include <linux/msm_gpi.h>
+#include <soc/qcom/boot_stats.h>
 
 #define SE_I2C_TX_TRANS_LEN		(0x26C)
 #define SE_I2C_RX_TRANS_LEN		(0x270)
@@ -327,11 +328,12 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev)
 				       SE_DMA_RX_IRQ_CLR);
 		/* Ensure all writes are done before returning from ISR. */
 		wmb();
+		if ((dm_tx_st & TX_DMA_DONE) || (dm_rx_st & RX_DMA_DONE))
+			complete(&gi2c->xfer);
+
 	}
 	/* if this is err with done-bit not set, handle that thr' timeout. */
-	if (m_stat & M_CMD_DONE_EN)
-		complete(&gi2c->xfer);
-	else if ((dm_tx_st & TX_DMA_DONE) || (dm_rx_st & RX_DMA_DONE))
+	else if (m_stat & M_CMD_DONE_EN)
 		complete(&gi2c->xfer);
 
 	return IRQ_HANDLED;
@@ -671,6 +673,7 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
 		dma_addr_t tx_dma = 0;
 		dma_addr_t rx_dma = 0;
 		enum se_xfer_mode mode = FIFO_MODE;
+		reinit_completion(&gi2c->xfer);
 
 		m_param |= (stretch ? STOP_STRETCH : 0);
 		m_param |= ((msgs[i].addr & 0x7F) << SLV_ADDR_SHFT);
@@ -730,6 +733,7 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
 						gi2c->xfer_timeout);
 		if (!timeout) {
 			geni_i2c_err(gi2c, GENI_TIMEOUT);
+			reinit_completion(&gi2c->xfer);
 			gi2c->cur = NULL;
 			geni_abort_m_cmd(gi2c->base);
 			timeout = wait_for_completion_timeout(&gi2c->xfer, HZ);
@@ -738,6 +742,7 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
 		gi2c->cur_rd = 0;
 		if (mode == SE_DMA) {
 			if (gi2c->err) {
+				reinit_completion(&gi2c->xfer);
 				if (msgs[i].flags != I2C_M_RD)
 					writel_relaxed(1, gi2c->base +
 							SE_DMA_TX_FSM_RST);
@@ -786,12 +791,16 @@ static int geni_i2c_probe(struct platform_device *pdev)
 	struct platform_device *wrapper_pdev;
 	struct device_node *wrapper_ph_node;
 	int ret;
+	char boot_marker[40];
 
 	gi2c = devm_kzalloc(&pdev->dev, sizeof(*gi2c), GFP_KERNEL);
 	if (!gi2c)
 		return -ENOMEM;
 
 	gi2c->dev = &pdev->dev;
+	snprintf(boot_marker, sizeof(boot_marker),
+				"M - DRIVER GENI_I2C Init");
+	place_marker(boot_marker);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -921,6 +930,9 @@ static int geni_i2c_probe(struct platform_device *pdev)
 	pm_runtime_enable(gi2c->dev);
 	i2c_add_adapter(&gi2c->adap);
 
+	snprintf(boot_marker, sizeof(boot_marker),
+				"M - DRIVER GENI_I2C_%d Ready", gi2c->adap.nr);
+	place_marker(boot_marker);
 	dev_dbg(gi2c->dev, "I2C probed\n");
 	return 0;
 }
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 6f2aaeb..338344e 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -836,6 +836,7 @@ static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
 	{ .compatible = "renesas,rcar-gen2-iic", .data = &fast_clock_dt_config },
 	{ .compatible = "renesas,iic-r8a7795", .data = &fast_clock_dt_config },
 	{ .compatible = "renesas,rcar-gen3-iic", .data = &fast_clock_dt_config },
+	{ .compatible = "renesas,iic-r8a77990", .data = &fast_clock_dt_config },
 	{ .compatible = "renesas,iic-sh73a0", .data = &fast_clock_dt_config },
 	{ .compatible = "renesas,rmobile-iic", .data = &default_dt_config },
 	{},
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 6f638bb..00e8e67 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -461,9 +461,15 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		return i2cdev_ioctl_smbus(client, arg);
 
 	case I2C_RETRIES:
+		if (arg > INT_MAX)
+			return -EINVAL;
+
 		client->adapter->retries = arg;
 		break;
 	case I2C_TIMEOUT:
+		if (arg > INT_MAX)
+			return -EINVAL;
+
 		/* For historical reasons, user-space sets the timeout
 		 * value in units of 10 ms.
 		 */
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
index 3f968c4..7846368 100644
--- a/drivers/iio/accel/kxcjk-1013.c
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -1393,6 +1393,7 @@ static const struct acpi_device_id kx_acpi_match[] = {
 	{"KXCJ1008", KXCJ91008},
 	{"KXCJ9000", KXCJ91008},
 	{"KIOX000A", KXCJ91008},
+	{"KIOX010A", KXCJ91008}, /* KXCJ91008 inside the display of a 2-in-1 */
 	{"KXTJ1009", KXTJ21009},
 	{"SMO8500",  KXCJ91008},
 	{ },
diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c
index 462a99c..0153df0 100644
--- a/drivers/iio/adc/axp288_adc.c
+++ b/drivers/iio/adc/axp288_adc.c
@@ -27,9 +27,18 @@
 #include <linux/iio/machine.h>
 #include <linux/iio/driver.h>
 
-#define AXP288_ADC_EN_MASK		0xF1
-#define AXP288_ADC_TS_PIN_GPADC		0xF2
-#define AXP288_ADC_TS_PIN_ON		0xF3
+/*
+ * This mask enables all ADCs except for the battery temp-sensor (TS), that is
+ * left as-is to avoid breaking charging on devices without a temp-sensor.
+ */
+#define AXP288_ADC_EN_MASK				0xF0
+#define AXP288_ADC_TS_ENABLE				0x01
+
+#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK		GENMASK(1, 0)
+#define AXP288_ADC_TS_CURRENT_OFF			(0 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING		(1 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND		(2 << 0)
+#define AXP288_ADC_TS_CURRENT_ON			(3 << 0)
 
 enum axp288_adc_id {
 	AXP288_ADC_TS,
@@ -44,6 +53,7 @@ enum axp288_adc_id {
 struct axp288_adc_info {
 	int irq;
 	struct regmap *regmap;
+	bool ts_enabled;
 };
 
 static const struct iio_chan_spec axp288_adc_channels[] = {
@@ -123,21 +133,33 @@ static int axp288_adc_read_channel(int *val, unsigned long address,
 	return IIO_VAL_INT;
 }
 
-static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode,
-				unsigned long address)
+/*
+ * The current-source used for the battery temp-sensor (TS) is shared
+ * with the GPADC. For proper fuel-gauge and charger operation the TS
+ * current-source needs to be permanently on. But to read the GPADC we
+ * need to temporary switch the TS current-source to ondemand, so that
+ * the GPADC can use it, otherwise we will always read an all 0 value.
+ */
+static int axp288_adc_set_ts(struct axp288_adc_info *info,
+			     unsigned int mode, unsigned long address)
 {
 	int ret;
 
-	/* channels other than GPADC do not need to switch TS pin */
+	/* No need to switch the current-source if the TS pin is disabled */
+	if (!info->ts_enabled)
+		return 0;
+
+	/* Channels other than GPADC do not need the current source */
 	if (address != AXP288_GP_ADC_H)
 		return 0;
 
-	ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode);
+	ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+				 AXP288_ADC_TS_CURRENT_ON_OFF_MASK, mode);
 	if (ret)
 		return ret;
 
 	/* When switching to the GPADC pin give things some time to settle */
-	if (mode == AXP288_ADC_TS_PIN_GPADC)
+	if (mode == AXP288_ADC_TS_CURRENT_ON_ONDEMAND)
 		usleep_range(6000, 10000);
 
 	return 0;
@@ -153,14 +175,14 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
 	mutex_lock(&indio_dev->mlock);
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC,
+		if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON_ONDEMAND,
 					chan->address)) {
 			dev_err(&indio_dev->dev, "GPADC mode\n");
 			ret = -EINVAL;
 			break;
 		}
 		ret = axp288_adc_read_channel(val, chan->address, info->regmap);
-		if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON,
+		if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON,
 						chan->address))
 			dev_err(&indio_dev->dev, "TS pin restore\n");
 		break;
@@ -172,13 +194,35 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
 	return ret;
 }
 
-static int axp288_adc_set_state(struct regmap *regmap)
+static int axp288_adc_initialize(struct axp288_adc_info *info)
 {
-	/* ADC should be always enabled for internal FG to function */
-	if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON))
-		return -EIO;
+	int ret, adc_enable_val;
 
-	return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK);
+	/*
+	 * Determine if the TS pin is enabled and set the TS current-source
+	 * accordingly.
+	 */
+	ret = regmap_read(info->regmap, AXP20X_ADC_EN1, &adc_enable_val);
+	if (ret)
+		return ret;
+
+	if (adc_enable_val & AXP288_ADC_TS_ENABLE) {
+		info->ts_enabled = true;
+		ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+					 AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+					 AXP288_ADC_TS_CURRENT_ON);
+	} else {
+		info->ts_enabled = false;
+		ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+					 AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+					 AXP288_ADC_TS_CURRENT_OFF);
+	}
+	if (ret)
+		return ret;
+
+	/* Turn on the ADC for all channels except TS, leave TS as is */
+	return regmap_update_bits(info->regmap, AXP20X_ADC_EN1,
+				  AXP288_ADC_EN_MASK, AXP288_ADC_EN_MASK);
 }
 
 static const struct iio_info axp288_adc_iio_info = {
@@ -209,7 +253,7 @@ static int axp288_adc_probe(struct platform_device *pdev)
 	 * Set ADC to enabled state at all time, including system suspend.
 	 * otherwise internal fuel gauge functionality may be affected.
 	 */
-	ret = axp288_adc_set_state(axp20x->regmap);
+	ret = axp288_adc_initialize(info);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to enable ADC device\n");
 		return ret;
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 11484cb3..2515bad 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -583,8 +583,11 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
 	struct clk_init_data init;
 	const char *clk_parents[1];
 
-	init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_div",
-				   indio_dev->dev.of_node);
+	init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_div",
+				   dev_name(indio_dev->dev.parent));
+	if (!init.name)
+		return -ENOMEM;
+
 	init.flags = 0;
 	init.ops = &clk_divider_ops;
 	clk_parents[0] = __clk_get_name(priv->clkin);
@@ -602,8 +605,11 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
 	if (WARN_ON(IS_ERR(priv->adc_div_clk)))
 		return PTR_ERR(priv->adc_div_clk);
 
-	init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_en",
-				   indio_dev->dev.of_node);
+	init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_en",
+				   dev_name(indio_dev->dev.parent));
+	if (!init.name)
+		return -ENOMEM;
+
 	init.flags = CLK_SET_RATE_PARENT;
 	init.ops = &clk_gate_ops;
 	clk_parents[0] = __clk_get_name(priv->adc_div_clk);
diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c
index ef761a5..dad2a8b 100644
--- a/drivers/iio/chemical/atlas-ph-sensor.c
+++ b/drivers/iio/chemical/atlas-ph-sensor.c
@@ -453,9 +453,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_TEMP:
-			*val = 1; /* 0.01 */
-			*val2 = 100;
-			break;
+			*val = 10;
+			return IIO_VAL_INT;
 		case IIO_PH:
 			*val = 1; /* 0.001 */
 			*val2 = 1000;
@@ -486,7 +485,7 @@ static int atlas_write_raw(struct iio_dev *indio_dev,
 			   int val, int val2, long mask)
 {
 	struct atlas_data *data = iio_priv(indio_dev);
-	__be32 reg = cpu_to_be32(val);
+	__be32 reg = cpu_to_be32(val / 10);
 
 	if (val2 != 0 || val < 0 || val > 20000)
 		return -EINVAL;
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 156630a..463210d 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -40,6 +40,7 @@
 
 source "drivers/iio/imu/inv_mpu6050/Kconfig"
 source "drivers/iio/imu/st_lsm6dsx/Kconfig"
+source "drivers/iio/imu/st_asm330lhh/Kconfig"
 
 endmenu
 
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 68629c68..349a7de 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -20,3 +20,4 @@
 obj-$(CONFIG_KMX61) += kmx61.o
 
 obj-y += st_lsm6dsx/
+obj-y += st_asm330lhh/
diff --git a/drivers/iio/imu/st_asm330lhh/Kconfig b/drivers/iio/imu/st_asm330lhh/Kconfig
new file mode 100644
index 0000000..092cc48
--- /dev/null
+++ b/drivers/iio/imu/st_asm330lhh/Kconfig
@@ -0,0 +1,23 @@
+
+config IIO_ST_ASM330LHH
+	tristate "STMicroelectronics ASM330LHH sensor"
+	depends on (I2C || SPI)
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
+	select IIO_ST_ASM330LHH_I2C if (I2C)
+	select IIO_ST_ASM330LHH_SPI if (SPI_MASTER)
+	help
+	  Say yes here to build support for STMicroelectronics ASM330LHH imu
+	  sensor.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called st_asm330lhh.
+
+config IIO_ST_ASM330LHH_I2C
+	tristate
+	depends on IIO_ST_ASM330LHH
+
+config IIO_ST_ASM330LHH_SPI
+	tristate
+	depends on IIO_ST_ASM330LHH
+
diff --git a/drivers/iio/imu/st_asm330lhh/Makefile b/drivers/iio/imu/st_asm330lhh/Makefile
new file mode 100644
index 0000000..7af80de
--- /dev/null
+++ b/drivers/iio/imu/st_asm330lhh/Makefile
@@ -0,0 +1,5 @@
+st_asm330lhh-y := st_asm330lhh_core.o st_asm330lhh_buffer.o
+
+obj-$(CONFIG_IIO_ST_ASM330LHH) += st_asm330lhh.o
+obj-$(CONFIG_IIO_ST_ASM330LHH_I2C) += st_asm330lhh_i2c.o
+obj-$(CONFIG_IIO_ST_ASM330LHH_SPI) += st_asm330lhh_spi.o
diff --git a/drivers/iio/imu/st_asm330lhh/README.md b/drivers/iio/imu/st_asm330lhh/README.md
new file mode 100644
index 0000000..d471530
--- /dev/null
+++ b/drivers/iio/imu/st_asm330lhh/README.md
@@ -0,0 +1,201 @@
+Index
+=======
+	* Introduction
+	* Driver Integration details
+	* Android SensorHAL integration
+	* Linux SensorHAL integration
+	* More information
+	* Copyright
+
+
+Introduction
+==============
+This repository contains asm330lhh IMU STMicroelectronics MEMS sensor linux driver support for kernel version 4.14.
+
+Data collected by asm330lhh STM sensor are pushed to userland through the kernel buffers of Linux IIO framework. User space applications can get sensor events by reading the related IIO devices created in the /dev directory (*/dev/iio{x}*). Please see [IIO][1] for more information.
+
+Asm330lhh IMU STM MEMS sensor support *I2C/SPI* digital interface. Please refer to [I2C][2] and [SPI][3] for detailed documentation.
+
+The STM Hardware Abstraction Layer (*HAL*) defines a standard interface for STM sensors allowing Android to be agnostic about low level driver implementation. The HAL library is packaged into modules (.so) file and loaded by the Android or Linux system at the appropriate time. For more information see [AOSP HAL Interface](https://source.android.com/devices/sensors/hal-interface.html) 
+
+STM Sensor HAL is leaning on [Linux IIO framework](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/iio) to gather data from sensor device drivers and to forward samples to the Android Framework
+
+Driver Integration details
+=====================
+
+In order to explain how to integrate Asm330lhh IMU STM sensor into the kernel, please consider the following example
+
+### Source code integration
+
+> * Copy driver source code into your linux kernel target directory (e.g. *drivers/iio/imu*)
+> * Edit related Kconfig (e.g. *drivers/iio/imu/Kconfig*) adding *ASM330LHH* support:
+
+>         source "drivers/iio/imu/st_asm330lhh/Kconfig"
+
+> * Edit related Makefile (e.g. *drivers/iio/imu/Makefile*) adding the following line:
+
+>         obj-y += st_asm330lhh/
+
+### Device Tree configuration
+
+> 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>;
+>			};
+
+### Kernel configuration
+
+Configure kernel with *make menuconfig* (alternatively use *make xconfig* or *make qconfig*)
+ 
+>		Device Drivers  --->
+>			<M> Industrial I/O support  --->
+>				Inertial measurement units  --->
+>				<M>   STMicroelectronics ASM330LHH sensor  --->
+
+
+Android SensorHAL integration
+==============
+
+STM Sensor HAL is written in *C++* language using object-oriented design. For each hw sensor there is a custom class file (*Accelerometer.cpp*, *Gyroscope.cpp*) which extends the common base class (*SensorBase.cpp*).
+
+Copy the HAL source code into *<AOSP_DIR\>/hardware/STMicroelectronics/SensorHAL_IIO* folder. During building process Android will include automatically the SensorHAL Android.mk.
+In *<AOSP_DIR\>/device/<vendor\>/<board\>/device.mk* add package build information:
+
+	PRODUCT_PACKAGES += sensors.{TARGET_BOARD_PLATFORM}
+
+	Note: device.mk can not read $(TARGET_BOARD_PLATFORM) variable, read and replace the value from your BoardConfig.mk (e.g. PRODUCT_PACKAGES += sensors.msm8974 for Nexus 5)
+
+To compile the SensorHAL_IIO just build AOSP source code from *$TOP* folder
+
+	$ cd <AOSP_DIR>
+	$ source build/envsetup.sh
+	$ lunch <select target platform>
+	$ make V=99
+
+The compiled library will be placed in *<AOSP_DIR\>/out/target/product/<board\>/system/vendor/lib/hw/sensor.{TARGET_BOARD_PLATFORM}.so*
+
+To configure sensor the Sensor HAL IIO use mm utility from HAL root folder
+
+    since Android 7
+	$mm sensors-defconfig (default configuration)
+	$mm sensors-menuconfig
+
+    after Android 7
+    make -f Makefile_config sensors-defconfig (default configuration)
+    make -f Makefile_config sensors-menuconfig
+    
+Linux SensorHAL integration
+==============
+
+Linux Sensor HAL share the same source code of Android Sensor HAL. Before compiling the Linux Sensor HAL IIO
+you need to follow the same procedure listed in previous chapter "Android SensorHAL integration"
+To cross compile Linux Sensor HAL must export the following shell variables 
+
+>   export AOSP_DIR=<AOSP_DIR>
+>   export ARCH=<your target architecture>
+>   export CROSS_COMPILE=<toolchain for your target>
+
+then in *<AOSP_DIR\>/hardware/STMicroelectronics/SensorHAL_IIO* folder type
+>   make
+
+it will produce a SensorHAL.so file containing the library. 
+In relative pat Documentation/LinuxHal/ there are some examples explaining how to use Linux Sensor HAL
+
+Copyright
+========
+Copyright (C) 2017 STMicroelectronics
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+More Information
+=================
+[http://st.com](http://st.com)
+
+[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/iio](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/input)
+
+[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/i2c](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/i2c)
+
+[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/spi](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/spi)
+
+[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bings/interrupt-controller/interrupts.txt](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt)
+
+
+Copyright Driver
+===========
+Copyright (C) 2017 STMicroelectronics
+
+This software is distributed under the GNU General Public License - see the accompanying COPYING file for more details.
+
+[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/iio/iio_configfs.txt "IIO"
+[2]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/i2c "I2C"
+[3]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/spi "SPI"
+[4]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt "interrupts"
+
+Copyright SensorHAL
+========
+Copyright (C) 2017 STMicroelectronics
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h b/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h
new file mode 100644
index 0000000..47f3b08
--- /dev/null
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh.h
@@ -0,0 +1,240 @@
+/*
+ * STMicroelectronics st_asm330lhh sensor driver
+ *
+ * Copyright 2018 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_ASM330LHH_H
+#define ST_ASM330LHH_H
+
+#include <linux/device.h>
+#include <linux/iio/iio.h>
+
+#define ST_ASM330LHH_REVISION		"2.0.1"
+#define ST_ASM330LHH_PATCH		"1"
+
+#define ST_ASM330LHH_VERSION		"v"	\
+	ST_ASM330LHH_REVISION			\
+	"-"					\
+	ST_ASM330LHH_PATCH
+
+#define ST_ASM330LHH_DEV_NAME		"asm330lhh"
+
+#define ST_ASM330LHH_SAMPLE_SIZE	6
+#define ST_ASM330LHH_TS_SAMPLE_SIZE	4
+#define ST_ASM330LHH_TAG_SIZE		1
+#define ST_ASM330LHH_FIFO_SAMPLE_SIZE	(ST_ASM330LHH_SAMPLE_SIZE + \
+					 ST_ASM330LHH_TAG_SIZE)
+#define ST_ASM330LHH_MAX_FIFO_DEPTH	416
+
+#define ST_ASM330LHH_REG_FIFO_BATCH_ADDR	0x09
+#define ST_ASM330LHH_REG_FIFO_CTRL4_ADDR	0x0a
+#define ST_ASM330LHH_REG_STATUS_ADDR		0x1e
+#define ST_ASM330LHH_REG_STATUS_TDA		BIT(2)
+#define ST_ASM330LHH_REG_OUT_TEMP_L_ADDR	0x20
+#define ST_ASM330LHH_REG_OUT_TEMP_H_ADDR	0x21
+
+#define ST_ASM330LHH_MAX_ODR			416
+
+/* Define Custom events for FIFO flush */
+#define CUSTOM_IIO_EV_DIR_FIFO_EMPTY (IIO_EV_DIR_NONE + 1)
+#define CUSTOM_IIO_EV_DIR_FIFO_DATA (IIO_EV_DIR_NONE + 2)
+#define CUSTOM_IIO_EV_TYPE_FIFO_FLUSH (IIO_EV_TYPE_CHANGE + 1)
+
+#define ST_ASM330LHH_CHANNEL(chan_type, addr, mod, ch2, scan_idx,	\
+			   rb, sb, sg)					\
+{									\
+	.type = chan_type,						\
+	.address = addr,						\
+	.modified = mod,						\
+	.channel2 = ch2,						\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |			\
+			      BIT(IIO_CHAN_INFO_SCALE),			\
+	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
+	.scan_index = scan_idx,						\
+	.scan_type = {							\
+		.sign = sg,						\
+		.realbits = rb,						\
+		.storagebits = sb,					\
+		.endianness = IIO_LE,					\
+	},								\
+}
+
+static const struct iio_event_spec st_asm330lhh_flush_event = {
+	.type = CUSTOM_IIO_EV_TYPE_FIFO_FLUSH,
+	.dir = IIO_EV_DIR_EITHER,
+};
+
+#define ST_ASM330LHH_FLUSH_CHANNEL(dtype)		\
+{							\
+	.type = dtype,					\
+	.modified = 0,					\
+	.scan_index = -1,				\
+	.indexed = -1,					\
+	.event_spec = &st_asm330lhh_flush_event,	\
+	.num_event_specs = 1,				\
+}
+
+#define ST_ASM330LHH_RX_MAX_LENGTH	8
+#define ST_ASM330LHH_TX_MAX_LENGTH	8
+
+struct st_asm330lhh_transfer_buffer {
+	u8 rx_buf[ST_ASM330LHH_RX_MAX_LENGTH];
+	u8 tx_buf[ST_ASM330LHH_TX_MAX_LENGTH] ____cacheline_aligned;
+};
+
+struct st_asm330lhh_transfer_function {
+	int (*read)(struct device *dev, u8 addr, int len, u8 *data);
+	int (*write)(struct device *dev, u8 addr, int len, u8 *data);
+};
+
+struct st_asm330lhh_reg {
+	u8 addr;
+	u8 mask;
+};
+
+struct st_asm330lhh_odr {
+	u16 hz;
+	u8 val;
+};
+
+#define ST_ASM330LHH_ODR_LIST_SIZE	7
+struct st_asm330lhh_odr_table_entry {
+	struct st_asm330lhh_reg reg;
+	struct st_asm330lhh_odr odr_avl[ST_ASM330LHH_ODR_LIST_SIZE];
+};
+
+struct st_asm330lhh_fs {
+	u32 gain;
+	u8 val;
+};
+
+#define ST_ASM330LHH_FS_ACC_LIST_SIZE		4
+#define ST_ASM330LHH_FS_GYRO_LIST_SIZE		6
+#define ST_ASM330LHH_FS_TEMP_LIST_SIZE		1
+#define ST_ASM330LHH_FS_LIST_SIZE		6
+struct st_asm330lhh_fs_table_entry {
+	u32 size;
+	struct st_asm330lhh_reg reg;
+	struct st_asm330lhh_fs fs_avl[ST_ASM330LHH_FS_LIST_SIZE];
+};
+
+enum st_asm330lhh_sensor_id {
+	ST_ASM330LHH_ID_ACC,
+	ST_ASM330LHH_ID_GYRO,
+	ST_ASM330LHH_ID_TEMP,
+	ST_ASM330LHH_ID_MAX,
+};
+
+enum st_asm330lhh_fifo_mode {
+	ST_ASM330LHH_FIFO_BYPASS = 0x0,
+	ST_ASM330LHH_FIFO_CONT = 0x6,
+};
+
+enum {
+	ST_ASM330LHH_HW_FLUSH,
+	ST_ASM330LHH_HW_OPERATIONAL,
+};
+
+/**
+ * struct st_asm330lhh_sensor - ST IMU sensor instance
+ * @id: Sensor identifier.
+ * @hw: Pointer to instance of struct st_asm330lhh_hw.
+ * @gain: Configured sensor sensitivity.
+ * @odr: Output data rate of the sensor [Hz].
+ * @watermark: Sensor watermark level.
+ * @batch_mask: Sensor mask for FIFO batching register
+ */
+struct st_asm330lhh_sensor {
+	enum st_asm330lhh_sensor_id id;
+	struct st_asm330lhh_hw *hw;
+
+	u32 gain;
+	u16 odr;
+	u32 offset;
+
+	__le16 old_data;
+
+	u8 std_samples;
+	u8 std_level;
+
+	u16 watermark;
+	u8 batch_mask;
+	u8 batch_addr;
+};
+
+/**
+ * struct st_asm330lhh_hw - ST IMU MEMS hw instance
+ * @dev: Pointer to instance of struct device (I2C or SPI).
+ * @irq: Device interrupt line (I2C or SPI).
+ * @lock: Mutex to protect read and write operations.
+ * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO.
+ * @fifo_mode: FIFO operating mode supported by the device.
+ * @state: hw operational state.
+ * @enable_mask: Enabled sensor bitmask.
+ * @ts_offset: Hw timestamp offset.
+ * @hw_ts: Latest hw timestamp from the sensor.
+ * @ts: Latest timestamp from irq handler.
+ * @delta_ts: Delta time between two consecutive interrupts.
+ * @iio_devs: Pointers to acc/gyro iio_dev instances.
+ * @tf: Transfer function structure used by I/O operations.
+ * @tb: Transfer buffers used by SPI I/O operations.
+ */
+struct st_asm330lhh_hw {
+	struct device *dev;
+	int irq;
+
+	struct mutex lock;
+	struct mutex fifo_lock;
+
+	enum st_asm330lhh_fifo_mode fifo_mode;
+	unsigned long state;
+	u8 enable_mask;
+
+	s64 ts_offset;
+	s64 hw_ts;
+	s64 delta_ts;
+	s64 ts;
+	s64 tsample;
+	s64 hw_ts_old;
+	s64 delta_hw_ts;
+
+	/* Timestamp sample ODR */
+	u16 odr;
+
+	struct iio_dev *iio_devs[ST_ASM330LHH_ID_MAX];
+
+	const struct st_asm330lhh_transfer_function *tf;
+	struct st_asm330lhh_transfer_buffer tb;
+	struct regulator *vdd;
+	struct regulator *vio;
+};
+
+extern const struct dev_pm_ops st_asm330lhh_pm_ops;
+
+int st_asm330lhh_probe(struct device *dev, int irq,
+		       const struct st_asm330lhh_transfer_function *tf_ops);
+int st_asm330lhh_sensor_set_enable(struct st_asm330lhh_sensor *sensor,
+				   bool enable);
+int st_asm330lhh_fifo_setup(struct st_asm330lhh_hw *hw);
+int st_asm330lhh_write_with_mask(struct st_asm330lhh_hw *hw, u8 addr, u8 mask,
+				 u8 val);
+int st_asm330lhh_get_odr_val(enum st_asm330lhh_sensor_id id, u16 odr, u8 *val);
+ssize_t st_asm330lhh_flush_fifo(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size);
+ssize_t st_asm330lhh_get_max_watermark(struct device *dev,
+				       struct device_attribute *attr, char *buf);
+ssize_t st_asm330lhh_get_watermark(struct device *dev,
+				   struct device_attribute *attr, char *buf);
+ssize_t st_asm330lhh_set_watermark(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size);
+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);
+#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
new file mode 100644
index 0000000..a2f54a8
--- /dev/null
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_buffer.c
@@ -0,0 +1,533 @@
+/*
+ * STMicroelectronics st_asm330lhh FIFO buffer library driver
+ *
+ * Copyright 2018 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
+#include <asm/unaligned.h>
+#include <linux/of.h>
+
+#include "st_asm330lhh.h"
+
+#define ST_ASM330LHH_REG_FIFO_THL_ADDR		0x07
+#define ST_ASM330LHH_REG_FIFO_LEN_MASK		GENMASK(8, 0)
+#define ST_ASM330LHH_REG_FIFO_MODE_MASK		GENMASK(2, 0)
+#define ST_ASM330LHH_REG_DEC_TS_MASK		GENMASK(7, 6)
+#define ST_ASM330LHH_REG_HLACTIVE_ADDR		0x12
+#define ST_ASM330LHH_REG_HLACTIVE_MASK		BIT(5)
+#define ST_ASM330LHH_REG_PP_OD_ADDR		0x12
+#define ST_ASM330LHH_REG_PP_OD_MASK		BIT(4)
+#define ST_ASM330LHH_REG_FIFO_DIFFL_ADDR	0x3a
+#define ST_ASM330LHH_REG_TS0_ADDR		0x40
+#define ST_ASM330LHH_REG_TS2_ADDR		0x42
+#define ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR	0x78
+#define ST_ASM330LHH_GYRO_TAG			0x01
+#define ST_ASM330LHH_ACC_TAG			0x02
+#define ST_ASM330LHH_TS_TAG			0x04
+
+#define ST_ASM330LHH_TS_DELTA_NS		25000ULL /* 25us/LSB */
+
+static inline s64 st_asm330lhh_get_time_ns(void)
+{
+	struct timespec ts;
+
+	get_monotonic_boottime(&ts);
+	return timespec_to_ns(&ts);
+}
+
+#define ST_ASM330LHH_EWMA_LEVEL			120
+#define ST_ASM330LHH_EWMA_DIV			128
+static inline s64 st_asm330lhh_ewma(s64 old, s64 new, int weight)
+{
+	s64 diff, incr;
+
+	diff = new - old;
+	incr = div_s64((ST_ASM330LHH_EWMA_DIV - weight) * diff,
+		       ST_ASM330LHH_EWMA_DIV);
+
+	return old + incr;
+}
+
+static inline int st_asm330lhh_reset_hwts(struct st_asm330lhh_hw *hw)
+{
+	u8 data = 0xaa;
+
+	hw->ts = st_asm330lhh_get_time_ns();
+	hw->ts_offset = hw->ts;
+	hw->hw_ts_old = 0ull;
+	hw->tsample = 0ull;
+
+	return hw->tf->write(hw->dev, ST_ASM330LHH_REG_TS2_ADDR, sizeof(data),
+			     &data);
+}
+
+int st_asm330lhh_set_fifo_mode(struct st_asm330lhh_hw *hw,
+			       enum st_asm330lhh_fifo_mode fifo_mode)
+{
+	int err;
+
+	err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_FIFO_CTRL4_ADDR,
+					   ST_ASM330LHH_REG_FIFO_MODE_MASK,
+					   fifo_mode);
+	if (err < 0)
+		return err;
+
+	hw->fifo_mode = fifo_mode;
+
+	return 0;
+}
+
+static int st_asm330lhh_set_sensor_batching_odr(struct st_asm330lhh_sensor *sensor,
+						bool enable)
+{
+	struct st_asm330lhh_hw *hw = sensor->hw;
+	u8 data = 0;
+	int err;
+
+	if (enable) {
+		err = st_asm330lhh_get_odr_val(sensor->id, sensor->odr, &data);
+		if (err < 0)
+			return err;
+	}
+
+	return st_asm330lhh_write_with_mask(hw,
+					    sensor->batch_addr,
+					    sensor->batch_mask, data);
+}
+
+static u16 st_asm330lhh_ts_odr(struct st_asm330lhh_hw *hw)
+{
+	struct st_asm330lhh_sensor *sensor;
+	u16 odr = 0;
+	u8 i;
+
+	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
+		if (!hw->iio_devs[i])
+			continue;
+
+		sensor = iio_priv(hw->iio_devs[i]);
+		if (hw->enable_mask & BIT(sensor->id))
+			odr = max_t(u16, odr, sensor->odr);
+	}
+
+	return odr;
+}
+
+static int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
+					 u16 watermark)
+{
+	u16 fifo_watermark = ST_ASM330LHH_MAX_FIFO_DEPTH, cur_watermark = 0;
+	struct st_asm330lhh_hw *hw = sensor->hw;
+	struct st_asm330lhh_sensor *cur_sensor;
+	__le16 wdata;
+	int i, err;
+	u8 data;
+
+	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
+		cur_sensor = iio_priv(hw->iio_devs[i]);
+
+		if (!(hw->enable_mask & BIT(cur_sensor->id)))
+			continue;
+
+		cur_watermark = (cur_sensor == sensor) ? watermark
+						       : cur_sensor->watermark;
+
+		fifo_watermark = min_t(u16, fifo_watermark, cur_watermark);
+	}
+
+	fifo_watermark = max_t(u16, fifo_watermark, 2);
+	mutex_lock(&hw->lock);
+
+	err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_FIFO_THL_ADDR + 1,
+			   sizeof(data), &data);
+	if (err < 0)
+		goto out;
+
+	fifo_watermark = ((data << 8) & ~ST_ASM330LHH_REG_FIFO_LEN_MASK) |
+			 (fifo_watermark & ST_ASM330LHH_REG_FIFO_LEN_MASK);
+	wdata = cpu_to_le16(fifo_watermark);
+	err = hw->tf->write(hw->dev, ST_ASM330LHH_REG_FIFO_THL_ADDR,
+			    sizeof(wdata), (u8 *)&wdata);
+
+out:
+	mutex_unlock(&hw->lock);
+
+	return err < 0 ? err : 0;
+}
+
+static inline void st_asm330lhh_sync_hw_ts(struct st_asm330lhh_hw *hw, s64 ts)
+{
+	s64 delta = ts - hw->hw_ts;
+
+	hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, delta,
+					  ST_ASM330LHH_EWMA_LEVEL);
+}
+
+static struct iio_dev *st_asm330lhh_get_iiodev_from_tag(struct st_asm330lhh_hw *hw,
+							u8 tag)
+{
+	struct iio_dev *iio_dev;
+
+	switch (tag) {
+	case ST_ASM330LHH_GYRO_TAG:
+		iio_dev = hw->iio_devs[ST_ASM330LHH_ID_GYRO];
+		break;
+	case ST_ASM330LHH_ACC_TAG:
+		iio_dev = hw->iio_devs[ST_ASM330LHH_ID_ACC];
+		break;
+	default:
+		iio_dev = NULL;
+		break;
+	}
+
+	return iio_dev;
+}
+
+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;
+	s64 ts_delta_hw_ts = 0, ts_irq;
+	s64 ts_delta_offs;
+	int i, err, read_len, word_len, fifo_len;
+	struct st_asm330lhh_sensor *sensor;
+	struct iio_dev *iio_dev;
+	__le16 fifo_status;
+	u16 fifo_depth;
+	u32 val;
+	int ts_processed = 0;
+	s64 hw_ts = 0ull, delta_hw_ts, cpu_timestamp;
+
+	ts_irq = hw->ts - hw->delta_ts;
+
+	do
+	{
+		err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_FIFO_DIFFL_ADDR,
+				   sizeof(fifo_status), (u8 *)&fifo_status);
+		if (err < 0)
+			return err;
+
+		fifo_depth = le16_to_cpu(fifo_status) & ST_ASM330LHH_REG_FIFO_LEN_MASK;
+		if (!fifo_depth)
+			return 0;
+
+		read_len = 0;
+		fifo_len = fifo_depth * ST_ASM330LHH_FIFO_SAMPLE_SIZE;
+		while (read_len < fifo_len) {
+			word_len = min_t(int, fifo_len - read_len, sizeof(buf));
+			err = hw->tf->read(hw->dev,
+					   ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR,
+					   word_len, buf);
+			if (err < 0)
+				return err;
+
+			for (i = 0; i < word_len; i += ST_ASM330LHH_FIFO_SAMPLE_SIZE) {
+				ptr = &buf[i + ST_ASM330LHH_TAG_SIZE];
+				tag = buf[i] >> 3;
+
+				if (tag == ST_ASM330LHH_TS_TAG) {
+					val = get_unaligned_le32(ptr);
+					hw->hw_ts = val * ST_ASM330LHH_TS_DELTA_NS;
+					ts_delta_hw_ts = hw->hw_ts - hw->hw_ts_old;
+					hw_ts += ts_delta_hw_ts;
+					ts_delta_offs =
+						div_s64(hw->delta_hw_ts * ST_ASM330LHH_MAX_ODR, hw->odr);
+
+					hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, ts_irq -
+						hw->hw_ts + ts_delta_offs, ST_ASM330LHH_EWMA_LEVEL);
+
+					ts_irq += (hw->hw_ts + ts_delta_offs);
+					hw->hw_ts_old = hw->hw_ts;
+					ts_processed++;
+
+					if (!hw->tsample)
+						hw->tsample =
+							hw->ts_offset + (hw->hw_ts + ts_delta_offs);
+					else
+						hw->tsample =
+							hw->tsample + (ts_delta_hw_ts + ts_delta_offs);
+				} else {
+					iio_dev = st_asm330lhh_get_iiodev_from_tag(hw, tag);
+					if (!iio_dev)
+						continue;
+
+					sensor = iio_priv(iio_dev);
+					if (sensor->std_samples < sensor->std_level) {
+						sensor->std_samples++;
+						continue;
+					}
+
+					sensor = iio_priv(iio_dev);
+
+					/* Check if timestamp is in the future. */
+					cpu_timestamp = st_asm330lhh_get_time_ns();
+
+					/* Avoid samples in the future. */
+					if (hw->tsample > cpu_timestamp)
+						hw->tsample = cpu_timestamp;
+
+					memcpy(iio_buf, ptr, ST_ASM330LHH_SAMPLE_SIZE);
+					iio_push_to_buffers_with_timestamp(iio_dev,
+									   iio_buf,
+									   hw->tsample);
+				}
+			}
+			read_len += word_len;
+		}
+
+		delta_hw_ts = div_s64(hw->delta_ts - hw_ts, ts_processed);
+		delta_hw_ts = div_s64(delta_hw_ts * hw->odr, ST_ASM330LHH_MAX_ODR);
+		hw->delta_hw_ts = st_asm330lhh_ewma(hw->delta_hw_ts,
+							delta_hw_ts,
+							ST_ASM330LHH_EWMA_LEVEL);
+	} while(read_len);
+
+	return read_len;
+}
+
+ssize_t st_asm330lhh_get_max_watermark(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", ST_ASM330LHH_MAX_FIFO_DEPTH);
+}
+
+ssize_t st_asm330lhh_get_watermark(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct iio_dev *iio_dev = dev_get_drvdata(dev);
+	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
+
+	return sprintf(buf, "%d\n", sensor->watermark);
+}
+
+ssize_t st_asm330lhh_set_watermark(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	struct iio_dev *iio_dev = dev_get_drvdata(dev);
+	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
+	int err, val;
+
+	mutex_lock(&iio_dev->mlock);
+	if (iio_buffer_enabled(iio_dev)) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	err = kstrtoint(buf, 10, &val);
+	if (err < 0)
+		goto out;
+
+	err = st_asm330lhh_update_watermark(sensor, val);
+	if (err < 0)
+		goto out;
+
+	sensor->watermark = val;
+
+out:
+	mutex_unlock(&iio_dev->mlock);
+
+	return err < 0 ? err : size;
+}
+
+ssize_t st_asm330lhh_flush_fifo(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct iio_dev *iio_dev = dev_get_drvdata(dev);
+	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
+	struct st_asm330lhh_hw *hw = sensor->hw;
+	s64 type, event;
+	int count;
+	s64 ts;
+
+	mutex_lock(&hw->fifo_lock);
+	ts = st_asm330lhh_get_time_ns();
+	hw->delta_ts = ts - hw->ts;
+	hw->ts = ts;
+	set_bit(ST_ASM330LHH_HW_FLUSH, &hw->state);
+
+	count = st_asm330lhh_read_fifo(hw);
+
+	mutex_unlock(&hw->fifo_lock);
+
+	type = count > 0 ? CUSTOM_IIO_EV_DIR_FIFO_DATA : CUSTOM_IIO_EV_DIR_FIFO_EMPTY;
+	event = IIO_UNMOD_EVENT_CODE(iio_dev->channels[0].type, -1,
+				     CUSTOM_IIO_EV_TYPE_FIFO_FLUSH, type);
+	iio_push_event(iio_dev, event, st_asm330lhh_get_time_ns());
+
+	return size;
+}
+
+int st_asm330lhh_suspend_fifo(struct st_asm330lhh_hw *hw)
+{
+	int err;
+
+	mutex_lock(&hw->fifo_lock);
+
+	st_asm330lhh_read_fifo(hw);
+	err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_BYPASS);
+
+	mutex_unlock(&hw->fifo_lock);
+
+	return err;
+}
+
+static 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;
+	int err;
+
+	mutex_lock(&hw->fifo_lock);
+
+	err = st_asm330lhh_sensor_set_enable(sensor, enable);
+	if (err < 0)
+		goto out;
+
+	err = st_asm330lhh_set_sensor_batching_odr(sensor, enable);
+	if (err < 0)
+		goto out;
+
+	err = st_asm330lhh_update_watermark(sensor, sensor->watermark);
+	if (err < 0)
+		goto out;
+
+	hw->odr = st_asm330lhh_ts_odr(hw);
+
+	if (enable && hw->fifo_mode == ST_ASM330LHH_FIFO_BYPASS) {
+		st_asm330lhh_reset_hwts(hw);
+		err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_CONT);
+	} else if (!hw->enable_mask) {
+		err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_BYPASS);
+	}
+
+out:
+	mutex_unlock(&hw->fifo_lock);
+
+	return err;
+}
+
+static irqreturn_t st_asm330lhh_handler_irq(int irq, void *private)
+{
+	struct st_asm330lhh_hw *hw = (struct st_asm330lhh_hw *)private;
+	s64 ts = st_asm330lhh_get_time_ns();
+
+	hw->delta_ts = ts - hw->ts;
+	hw->ts = ts;
+
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t st_asm330lhh_handler_thread(int irq, void *private)
+{
+	struct st_asm330lhh_hw *hw = (struct st_asm330lhh_hw *)private;
+
+	mutex_lock(&hw->fifo_lock);
+
+	st_asm330lhh_read_fifo(hw);
+	clear_bit(ST_ASM330LHH_HW_FLUSH, &hw->state);
+
+	mutex_unlock(&hw->fifo_lock);
+
+	return IRQ_HANDLED;
+}
+
+static int st_asm330lhh_buffer_preenable(struct iio_dev *iio_dev)
+{
+	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);
+}
+
+static const struct iio_buffer_setup_ops st_asm330lhh_buffer_ops = {
+	.preenable = st_asm330lhh_buffer_preenable,
+	.postdisable = st_asm330lhh_buffer_postdisable,
+};
+
+static int st_asm330lhh_fifo_init(struct st_asm330lhh_hw *hw)
+{
+	return st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_FIFO_CTRL4_ADDR,
+					    ST_ASM330LHH_REG_DEC_TS_MASK, 1);
+}
+
+int st_asm330lhh_fifo_setup(struct st_asm330lhh_hw *hw)
+{
+	struct device_node *np = hw->dev->of_node;
+	struct iio_buffer *buffer;
+	unsigned long irq_type;
+	bool irq_active_low;
+	int i, err;
+
+	irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
+
+	switch (irq_type) {
+	case IRQF_TRIGGER_HIGH:
+	case IRQF_TRIGGER_RISING:
+		irq_active_low = false;
+		break;
+	case IRQF_TRIGGER_LOW:
+	case IRQF_TRIGGER_FALLING:
+		irq_active_low = true;
+		break;
+	default:
+		dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
+		return -EINVAL;
+	}
+
+	err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_HLACTIVE_ADDR,
+					   ST_ASM330LHH_REG_HLACTIVE_MASK,
+					   irq_active_low);
+	if (err < 0)
+		return err;
+
+	if (np && of_property_read_bool(np, "drive-open-drain")) {
+		err = st_asm330lhh_write_with_mask(hw,
+					ST_ASM330LHH_REG_PP_OD_ADDR,
+					ST_ASM330LHH_REG_PP_OD_MASK, 1);
+		if (err < 0)
+			return err;
+
+		irq_type |= IRQF_SHARED;
+	}
+
+	err = devm_request_threaded_irq(hw->dev, hw->irq,
+					st_asm330lhh_handler_irq,
+					st_asm330lhh_handler_thread,
+					irq_type | IRQF_ONESHOT,
+					"asm330lhh", hw);
+	if (err) {
+		dev_err(hw->dev, "failed to request trigger irq %d\n",
+			hw->irq);
+		return err;
+	}
+
+	for (i = ST_ASM330LHH_ID_ACC; i < ST_ASM330LHH_ID_MAX; i++) {
+		if (!hw->iio_devs[i])
+			continue;
+
+		buffer = devm_iio_kfifo_allocate(hw->dev);
+		if (!buffer)
+			return -ENOMEM;
+
+		iio_device_attach_buffer(hw->iio_devs[i], buffer);
+		hw->iio_devs[i]->modes |= INDIO_BUFFER_SOFTWARE;
+		hw->iio_devs[i]->setup_ops = &st_asm330lhh_buffer_ops;
+	}
+
+	return st_asm330lhh_fifo_init(hw);
+}
+
diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c
new file mode 100644
index 0000000..c0bf8dc
--- /dev/null
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_core.c
@@ -0,0 +1,952 @@
+/*
+ * STMicroelectronics st_asm330lhh sensor driver
+ *
+ * Copyright 2018 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/pm.h>
+#include <linux/version.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/platform_data/st_sensors_pdata.h>
+
+#include "st_asm330lhh.h"
+
+#define ST_ASM330LHH_REG_INT1_ADDR		0x0d
+#define ST_ASM330LHH_REG_INT2_ADDR		0x0e
+#define ST_ASM330LHH_REG_FIFO_CTRL4_ADDR	0x0a
+#define ST_ASM330LHH_REG_FIFO_FTH_IRQ_MASK	BIT(3)
+#define ST_ASM330LHH_REG_WHOAMI_ADDR		0x0f
+#define ST_ASM330LHH_WHOAMI_VAL			0x6b
+#define ST_ASM330LHH_REG_CTRL1_XL_ADDR		0x10
+#define ST_ASM330LHH_REG_CTRL2_G_ADDR		0x11
+#define ST_ASM330LHH_REG_RESET_ADDR		0x12
+#define ST_ASM330LHH_REG_RESET_MASK		BIT(0)
+#define ST_ASM330LHH_REG_BDU_ADDR		0x12
+#define ST_ASM330LHH_REG_BDU_MASK		BIT(6)
+#define ST_ASM330LHH_REG_INT2_ON_INT1_ADDR	0x13
+#define ST_ASM330LHH_REG_INT2_ON_INT1_MASK	BIT(5)
+#define ST_ASM330LHH_REG_ROUNDING_ADDR		0x14
+#define ST_ASM330LHH_REG_ROUNDING_MASK		GENMASK(6, 5)
+#define ST_ASM330LHH_REG_TIMESTAMP_EN_ADDR	0x19
+#define ST_ASM330LHH_REG_TIMESTAMP_EN_MASK	BIT(5)
+
+#define ST_ASM330LHH_REG_GYRO_OUT_X_L_ADDR	0x22
+#define ST_ASM330LHH_REG_GYRO_OUT_Y_L_ADDR	0x24
+#define ST_ASM330LHH_REG_GYRO_OUT_Z_L_ADDR	0x26
+
+#define ST_ASM330LHH_REG_ACC_OUT_X_L_ADDR	0x28
+#define ST_ASM330LHH_REG_ACC_OUT_Y_L_ADDR	0x2a
+#define ST_ASM330LHH_REG_ACC_OUT_Z_L_ADDR	0x2c
+
+#define ST_ASM330LHH_REG_LIR_ADDR		0x56
+#define ST_ASM330LHH_REG_LIR_MASK		BIT(0)
+
+#define ST_ASM330LHH_ACC_FS_2G_GAIN		IIO_G_TO_M_S_2(61)
+#define ST_ASM330LHH_ACC_FS_4G_GAIN		IIO_G_TO_M_S_2(122)
+#define ST_ASM330LHH_ACC_FS_8G_GAIN		IIO_G_TO_M_S_2(244)
+#define ST_ASM330LHH_ACC_FS_16G_GAIN		IIO_G_TO_M_S_2(488)
+
+#define ST_ASM330LHH_GYRO_FS_125_GAIN		IIO_DEGREE_TO_RAD(4375)
+#define ST_ASM330LHH_GYRO_FS_250_GAIN		IIO_DEGREE_TO_RAD(8750)
+#define ST_ASM330LHH_GYRO_FS_500_GAIN		IIO_DEGREE_TO_RAD(17500)
+#define ST_ASM330LHH_GYRO_FS_1000_GAIN		IIO_DEGREE_TO_RAD(35000)
+#define ST_ASM330LHH_GYRO_FS_2000_GAIN		IIO_DEGREE_TO_RAD(70000)
+#define ST_ASM330LHH_GYRO_FS_4000_GAIN		IIO_DEGREE_TO_RAD(140000)
+
+/* Temperature in uC */
+#define ST_ASM330LHH_TEMP_GAIN			256
+#define ST_ASM330LHH_TEMP_FS_GAIN		(1000000 / ST_ASM330LHH_TEMP_GAIN)
+#define ST_ASM330LHH_OFFSET			(6400)
+
+struct st_asm330lhh_std_entry {
+	u16 odr;
+	u8 val;
+};
+
+/* Minimal number of sample to be discarded */
+struct st_asm330lhh_std_entry st_asm330lhh_std_table[] = {
+	{  13,  2 },
+	{  26,  3 },
+	{  52,  4 },
+	{ 104,  6 },
+	{ 208,  8 },
+	{ 416, 18 },
+};
+
+static const struct st_asm330lhh_odr_table_entry st_asm330lhh_odr_table[] = {
+	[ST_ASM330LHH_ID_ACC] = {
+		.reg = {
+			.addr = ST_ASM330LHH_REG_CTRL1_XL_ADDR,
+			.mask = GENMASK(7, 4),
+		},
+		.odr_avl[0] = {   0, 0x00 },
+		.odr_avl[1] = {  13, 0x01 },
+		.odr_avl[2] = {  26, 0x02 },
+		.odr_avl[3] = {  52, 0x03 },
+		.odr_avl[4] = { 104, 0x04 },
+		.odr_avl[5] = { 208, 0x05 },
+		.odr_avl[6] = { 416, 0x06 },
+	},
+	[ST_ASM330LHH_ID_GYRO] = {
+		.reg = {
+			.addr = ST_ASM330LHH_REG_CTRL2_G_ADDR,
+			.mask = GENMASK(7, 4),
+		},
+		.odr_avl[0] = {   0, 0x00 },
+		.odr_avl[1] = {  13, 0x01 },
+		.odr_avl[2] = {  26, 0x02 },
+		.odr_avl[3] = {  52, 0x03 },
+		.odr_avl[4] = { 104, 0x04 },
+		.odr_avl[5] = { 208, 0x05 },
+		.odr_avl[6] = { 416, 0x06 },
+	},
+	[ST_ASM330LHH_ID_TEMP] = {
+		.odr_avl[0] = {   0, 0x00 },
+		.odr_avl[1] = {  52, 0x01 },
+	}
+};
+
+static const struct st_asm330lhh_fs_table_entry st_asm330lhh_fs_table[] = {
+	[ST_ASM330LHH_ID_ACC] = {
+		.reg = {
+			.addr = ST_ASM330LHH_REG_CTRL1_XL_ADDR,
+			.mask = GENMASK(3, 2),
+		},
+		.size = ST_ASM330LHH_FS_ACC_LIST_SIZE,
+		.fs_avl[0] = {  ST_ASM330LHH_ACC_FS_2G_GAIN, 0x0 },
+		.fs_avl[1] = {  ST_ASM330LHH_ACC_FS_4G_GAIN, 0x2 },
+		.fs_avl[2] = {  ST_ASM330LHH_ACC_FS_8G_GAIN, 0x3 },
+		.fs_avl[3] = { ST_ASM330LHH_ACC_FS_16G_GAIN, 0x1 },
+	},
+	[ST_ASM330LHH_ID_GYRO] = {
+		.reg = {
+			.addr = ST_ASM330LHH_REG_CTRL2_G_ADDR,
+			.mask = GENMASK(3, 0),
+		},
+		.size = ST_ASM330LHH_FS_GYRO_LIST_SIZE,
+		.fs_avl[0] = {  ST_ASM330LHH_GYRO_FS_125_GAIN, 0x2 },
+		.fs_avl[1] = {  ST_ASM330LHH_GYRO_FS_250_GAIN, 0x0 },
+		.fs_avl[2] = {  ST_ASM330LHH_GYRO_FS_500_GAIN, 0x4 },
+		.fs_avl[3] = { ST_ASM330LHH_GYRO_FS_1000_GAIN, 0x8 },
+		.fs_avl[4] = { ST_ASM330LHH_GYRO_FS_2000_GAIN, 0xC },
+		.fs_avl[5] = { ST_ASM330LHH_GYRO_FS_4000_GAIN, 0x1 },
+	},
+	[ST_ASM330LHH_ID_TEMP] = {
+		.size = ST_ASM330LHH_FS_TEMP_LIST_SIZE,
+		.fs_avl[0] = {  ST_ASM330LHH_TEMP_FS_GAIN, 0x0 },
+	}
+};
+
+static const struct iio_chan_spec st_asm330lhh_acc_channels[] = {
+	ST_ASM330LHH_CHANNEL(IIO_ACCEL, ST_ASM330LHH_REG_ACC_OUT_X_L_ADDR,
+			   1, IIO_MOD_X, 0, 16, 16, 's'),
+	ST_ASM330LHH_CHANNEL(IIO_ACCEL, ST_ASM330LHH_REG_ACC_OUT_Y_L_ADDR,
+			   1, IIO_MOD_Y, 1, 16, 16, 's'),
+	ST_ASM330LHH_CHANNEL(IIO_ACCEL, ST_ASM330LHH_REG_ACC_OUT_Z_L_ADDR,
+			   1, IIO_MOD_Z, 2, 16, 16, 's'),
+	ST_ASM330LHH_FLUSH_CHANNEL(IIO_ACCEL),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const struct iio_chan_spec st_asm330lhh_gyro_channels[] = {
+	ST_ASM330LHH_CHANNEL(IIO_ANGL_VEL, ST_ASM330LHH_REG_GYRO_OUT_X_L_ADDR,
+			   1, IIO_MOD_X, 0, 16, 16, 's'),
+	ST_ASM330LHH_CHANNEL(IIO_ANGL_VEL, ST_ASM330LHH_REG_GYRO_OUT_Y_L_ADDR,
+			   1, IIO_MOD_Y, 1, 16, 16, 's'),
+	ST_ASM330LHH_CHANNEL(IIO_ANGL_VEL, ST_ASM330LHH_REG_GYRO_OUT_Z_L_ADDR,
+			   1, IIO_MOD_Z, 2, 16, 16, 's'),
+	ST_ASM330LHH_FLUSH_CHANNEL(IIO_ANGL_VEL),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const struct iio_chan_spec st_asm330lhh_temp_channels[] = {
+	{
+		.type = IIO_TEMP,
+		.address = ST_ASM330LHH_REG_OUT_TEMP_L_ADDR,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)
+				| BIT(IIO_CHAN_INFO_OFFSET)
+				| BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = -1,
+	},
+};
+
+int st_asm330lhh_write_with_mask(struct st_asm330lhh_hw *hw, u8 addr, u8 mask,
+				 u8 val)
+{
+	u8 data;
+	int err;
+
+	mutex_lock(&hw->lock);
+
+	err = hw->tf->read(hw->dev, addr, sizeof(data), &data);
+	if (err < 0) {
+		dev_err(hw->dev, "failed to read %02x register\n", addr);
+		goto out;
+	}
+
+	data = (data & ~mask) | ((val << __ffs(mask)) & mask);
+
+	err = hw->tf->write(hw->dev, addr, sizeof(data), &data);
+	if (err < 0)
+		dev_err(hw->dev, "failed to write %02x register\n", addr);
+
+out:
+	mutex_unlock(&hw->lock);
+
+	return err;
+}
+
+static int st_asm330lhh_check_whoami(struct st_asm330lhh_hw *hw)
+{
+	int err;
+	u8 data;
+
+	err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_WHOAMI_ADDR, sizeof(data),
+			   &data);
+	if (err < 0) {
+		dev_err(hw->dev, "failed to read whoami register\n");
+		return err;
+	}
+
+	if (data != ST_ASM330LHH_WHOAMI_VAL) {
+		dev_err(hw->dev, "unsupported whoami [%02x]\n", data);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int st_asm330lhh_set_full_scale(struct st_asm330lhh_sensor *sensor,
+				       u32 gain)
+{
+	enum st_asm330lhh_sensor_id id = sensor->id;
+	int i, err;
+	u8 val;
+
+	for (i = 0; i < st_asm330lhh_fs_table[id].size; i++)
+		if (st_asm330lhh_fs_table[id].fs_avl[i].gain == gain)
+			break;
+
+	if (i == st_asm330lhh_fs_table[id].size)
+		return -EINVAL;
+
+	val = st_asm330lhh_fs_table[id].fs_avl[i].val;
+	err = st_asm330lhh_write_with_mask(sensor->hw,
+					st_asm330lhh_fs_table[id].reg.addr,
+					st_asm330lhh_fs_table[id].reg.mask,
+					val);
+	if (err < 0)
+		return err;
+
+	sensor->gain = gain;
+
+	return 0;
+}
+
+int st_asm330lhh_get_odr_val(enum st_asm330lhh_sensor_id id, u16 odr, u8 *val)
+{
+	int i;
+
+	for (i = 0; i < ST_ASM330LHH_ODR_LIST_SIZE; i++)
+		if (st_asm330lhh_odr_table[id].odr_avl[i].hz >= odr)
+			break;
+
+	if (i == ST_ASM330LHH_ODR_LIST_SIZE)
+		return -EINVAL;
+
+	*val = st_asm330lhh_odr_table[id].odr_avl[i].val;
+
+	return 0;
+}
+
+static int st_asm330lhh_set_std_level(struct st_asm330lhh_sensor *sensor,
+			u16 odr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(st_asm330lhh_std_table); i++)
+		if (st_asm330lhh_std_table[i].odr == odr)
+			break;
+
+	if (i == ARRAY_SIZE(st_asm330lhh_std_table))
+		return -EINVAL;
+
+	sensor->std_level = st_asm330lhh_std_table[i].val;
+	sensor->std_samples = 0;
+
+	return 0;
+}
+
+static int st_asm330lhh_set_odr(struct st_asm330lhh_sensor *sensor, u16 odr)
+{
+	struct st_asm330lhh_hw *hw = sensor->hw;
+	u8 val;
+
+	if (st_asm330lhh_get_odr_val(sensor->id, odr, &val) < 0)
+		return -EINVAL;
+
+	return st_asm330lhh_write_with_mask(hw,
+				st_asm330lhh_odr_table[sensor->id].reg.addr,
+				st_asm330lhh_odr_table[sensor->id].reg.mask, val);
+}
+
+int st_asm330lhh_sensor_set_enable(struct st_asm330lhh_sensor *sensor,
+				   bool enable)
+{
+	u16 odr = enable ? sensor->odr : 0;
+	int err;
+
+	if (sensor->id != ST_ASM330LHH_ID_TEMP) {
+		err = st_asm330lhh_set_odr(sensor, odr);
+		if (err < 0)
+			return err;
+	}
+
+	if (enable)
+		sensor->hw->enable_mask |= BIT(sensor->id);
+	else
+		sensor->hw->enable_mask &= ~BIT(sensor->id);
+
+	return 0;
+}
+
+static int st_asm330lhh_read_oneshot(struct st_asm330lhh_sensor *sensor,
+				     u8 addr, int *val)
+{
+	int err, delay;
+	__le16 data;
+
+	if (sensor->id == ST_ASM330LHH_ID_TEMP) {
+		u8 status;
+
+		mutex_lock(&sensor->hw->fifo_lock);
+		err = sensor->hw->tf->read(sensor->hw->dev,
+					   ST_ASM330LHH_REG_STATUS_ADDR, sizeof(status), &status);
+		if (err < 0)
+			goto unlock;
+
+		if (status & ST_ASM330LHH_REG_STATUS_TDA) {
+			err = sensor->hw->tf->read(sensor->hw->dev, addr, sizeof(data),
+					   (u8 *)&data);
+			if (err < 0)
+				goto unlock;
+
+			sensor->old_data = data;
+		} else
+			data = sensor->old_data;
+unlock:
+		mutex_unlock(&sensor->hw->fifo_lock);
+
+	} else {
+		err = st_asm330lhh_sensor_set_enable(sensor, true);
+		if (err < 0)
+			return err;
+
+		delay = 1000000 / sensor->odr;
+		usleep_range(delay, 2 * delay);
+
+		err = sensor->hw->tf->read(sensor->hw->dev, addr, sizeof(data),
+					   (u8 *)&data);
+		if (err < 0)
+			return err;
+
+		st_asm330lhh_sensor_set_enable(sensor, false);
+	}
+
+	*val = (s16)data;
+
+	return IIO_VAL_INT;
+}
+
+static int st_asm330lhh_read_raw(struct iio_dev *iio_dev,
+				 struct iio_chan_spec const *ch,
+				 int *val, int *val2, long mask)
+{
+	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&iio_dev->mlock);
+		if (iio_buffer_enabled(iio_dev)) {
+			ret = -EBUSY;
+			mutex_unlock(&iio_dev->mlock);
+			break;
+		}
+		ret = st_asm330lhh_read_oneshot(sensor, ch->address, val);
+		mutex_unlock(&iio_dev->mlock);
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		switch (ch->type) {
+		case IIO_TEMP:
+			*val = sensor->offset;
+			ret = IIO_VAL_INT;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = sensor->odr;
+		ret = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		switch (ch->type) {
+		case IIO_TEMP:
+			*val = 1;
+			*val2 = ST_ASM330LHH_TEMP_GAIN;
+			ret = IIO_VAL_FRACTIONAL;
+			break;
+		case IIO_ACCEL:
+		case IIO_ANGL_VEL:
+			*val = 0;
+			*val2 = sensor->gain;
+			ret = IIO_VAL_INT_PLUS_MICRO;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int st_asm330lhh_write_raw(struct iio_dev *iio_dev,
+				  struct iio_chan_spec const *chan,
+				  int val, int val2, long mask)
+{
+	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
+	int err;
+
+	mutex_lock(&iio_dev->mlock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		err = st_asm330lhh_set_full_scale(sensor, val2);
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ: {
+		u8 data;
+
+		err = st_asm330lhh_set_std_level(sensor, val);
+		if (err < 0)
+			break;
+
+		err = st_asm330lhh_get_odr_val(sensor->id, val, &data);
+		if (!err)
+			sensor->odr = val;
+
+		err = st_asm330lhh_set_odr(sensor, sensor->odr);
+		break;
+	}
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	mutex_unlock(&iio_dev->mlock);
+
+	return err;
+}
+
+static ssize_t
+st_asm330lhh_sysfs_sampling_frequency_avail(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct st_asm330lhh_sensor *sensor = iio_priv(dev_get_drvdata(dev));
+	enum st_asm330lhh_sensor_id id = sensor->id;
+	int i, len = 0;
+
+	for (i = 1; i < ST_ASM330LHH_ODR_LIST_SIZE; i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
+				 st_asm330lhh_odr_table[id].odr_avl[i].hz);
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static ssize_t st_asm330lhh_sysfs_scale_avail(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	struct st_asm330lhh_sensor *sensor = iio_priv(dev_get_drvdata(dev));
+	enum st_asm330lhh_sensor_id id = sensor->id;
+	int i, len = 0;
+
+	for (i = 0; i < st_asm330lhh_fs_table[id].size; i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
+				 st_asm330lhh_fs_table[id].fs_avl[i].gain);
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+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);
+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,
+		       st_asm330lhh_sysfs_scale_avail, NULL, 0);
+static IIO_DEVICE_ATTR(hwfifo_watermark_max, 0444,
+		       st_asm330lhh_get_max_watermark, NULL, 0);
+static IIO_DEVICE_ATTR(hwfifo_flush, 0200, NULL, st_asm330lhh_flush_fifo, 0);
+static IIO_DEVICE_ATTR(hwfifo_watermark, 0644, st_asm330lhh_get_watermark,
+		       st_asm330lhh_set_watermark, 0);
+
+static struct attribute *st_asm330lhh_acc_attributes[] = {
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	&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,
+	&iio_dev_attr_hwfifo_flush.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group st_asm330lhh_acc_attribute_group = {
+	.attrs = st_asm330lhh_acc_attributes,
+};
+
+static const struct iio_info st_asm330lhh_acc_info = {
+	.driver_module = THIS_MODULE,
+	.attrs = &st_asm330lhh_acc_attribute_group,
+	.read_raw = st_asm330lhh_read_raw,
+	.write_raw = st_asm330lhh_write_raw,
+};
+
+static struct attribute *st_asm330lhh_gyro_attributes[] = {
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	&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,
+	&iio_dev_attr_hwfifo_flush.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group st_asm330lhh_gyro_attribute_group = {
+	.attrs = st_asm330lhh_gyro_attributes,
+};
+
+static const struct iio_info st_asm330lhh_gyro_info = {
+	.driver_module = THIS_MODULE,
+	.attrs = &st_asm330lhh_gyro_attribute_group,
+	.read_raw = st_asm330lhh_read_raw,
+	.write_raw = st_asm330lhh_write_raw,
+};
+
+static struct attribute *st_asm330lhh_temp_attributes[] = {
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	&iio_dev_attr_in_temp_scale_available.dev_attr.attr,
+	&iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
+	&iio_dev_attr_hwfifo_watermark.dev_attr.attr,
+	&iio_dev_attr_hwfifo_flush.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group st_asm330lhh_temp_attribute_group = {
+	.attrs = st_asm330lhh_temp_attributes,
+};
+
+static const struct iio_info st_asm330lhh_temp_info = {
+	.driver_module = THIS_MODULE,
+	.attrs = &st_asm330lhh_temp_attribute_group,
+	.read_raw = st_asm330lhh_read_raw,
+	.write_raw = st_asm330lhh_write_raw,
+};
+
+static const unsigned long st_asm330lhh_available_scan_masks[] = { 0x7, 0x0 };
+
+static int st_asm330lhh_of_get_drdy_pin(struct st_asm330lhh_hw *hw, int *drdy_pin)
+{
+	struct device_node *np = hw->dev->of_node;
+
+	if (!np)
+		return -EINVAL;
+
+	return of_property_read_u32(np, "st,drdy-int-pin", drdy_pin);
+}
+
+static int st_asm330lhh_get_drdy_reg(struct st_asm330lhh_hw *hw, u8 *drdy_reg)
+{
+	int err = 0, drdy_pin;
+
+	if (st_asm330lhh_of_get_drdy_pin(hw, &drdy_pin) < 0) {
+		struct st_sensors_platform_data *pdata;
+		struct device *dev = hw->dev;
+
+		pdata = (struct st_sensors_platform_data *)dev->platform_data;
+		drdy_pin = pdata ? pdata->drdy_int_pin : 1;
+	}
+
+	switch (drdy_pin) {
+	case 1:
+		*drdy_reg = ST_ASM330LHH_REG_INT1_ADDR;
+		break;
+	case 2:
+		*drdy_reg = ST_ASM330LHH_REG_INT2_ADDR;
+		break;
+	default:
+		dev_err(hw->dev, "unsupported data ready pin\n");
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+static int st_asm330lhh_init_device(struct st_asm330lhh_hw *hw)
+{
+	u8 drdy_int_reg;
+	int err;
+
+	err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_RESET_ADDR,
+					   ST_ASM330LHH_REG_RESET_MASK, 1);
+	if (err < 0)
+		return err;
+
+	msleep(200);
+
+	/* latch interrupts */
+	err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_LIR_ADDR,
+					   ST_ASM330LHH_REG_LIR_MASK, 1);
+	if (err < 0)
+		return err;
+
+	/* enable Block Data Update */
+	err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_BDU_ADDR,
+					   ST_ASM330LHH_REG_BDU_MASK, 1);
+	if (err < 0)
+		return err;
+
+	err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_ROUNDING_ADDR,
+					   ST_ASM330LHH_REG_ROUNDING_MASK, 3);
+	if (err < 0)
+		return err;
+
+	/* init timestamp engine */
+	err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_TIMESTAMP_EN_ADDR,
+					   ST_ASM330LHH_REG_TIMESTAMP_EN_MASK, 1);
+	if (err < 0)
+		return err;
+
+	/* enable FIFO watermak interrupt */
+	err = st_asm330lhh_get_drdy_reg(hw, &drdy_int_reg);
+	if (err < 0)
+		return err;
+
+	return st_asm330lhh_write_with_mask(hw, drdy_int_reg,
+					    ST_ASM330LHH_REG_FIFO_FTH_IRQ_MASK, 1);
+}
+
+static struct iio_dev *st_asm330lhh_alloc_iiodev(struct st_asm330lhh_hw *hw,
+						 enum st_asm330lhh_sensor_id id)
+{
+	struct st_asm330lhh_sensor *sensor;
+	struct iio_dev *iio_dev;
+
+	iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor));
+	if (!iio_dev)
+		return NULL;
+
+	iio_dev->modes = INDIO_DIRECT_MODE;
+	iio_dev->dev.parent = hw->dev;
+	iio_dev->available_scan_masks = st_asm330lhh_available_scan_masks;
+
+	sensor = iio_priv(iio_dev);
+	sensor->id = id;
+	sensor->hw = hw;
+	sensor->odr = st_asm330lhh_odr_table[id].odr_avl[1].hz;
+	sensor->gain = st_asm330lhh_fs_table[id].fs_avl[0].gain;
+	sensor->watermark = 1;
+	sensor->old_data = 0;
+
+	switch (id) {
+	case ST_ASM330LHH_ID_ACC:
+		iio_dev->channels = st_asm330lhh_acc_channels;
+		iio_dev->num_channels = ARRAY_SIZE(st_asm330lhh_acc_channels);
+		iio_dev->name = "asm330lhh_accel";
+		iio_dev->info = &st_asm330lhh_acc_info;
+		sensor->batch_addr = ST_ASM330LHH_REG_FIFO_BATCH_ADDR;
+		sensor->batch_mask = GENMASK(3, 0);
+		sensor->offset = 0;
+		break;
+	case ST_ASM330LHH_ID_GYRO:
+		iio_dev->channels = st_asm330lhh_gyro_channels;
+		iio_dev->num_channels = ARRAY_SIZE(st_asm330lhh_gyro_channels);
+		iio_dev->name = "asm330lhh_gyro";
+		iio_dev->info = &st_asm330lhh_gyro_info;
+		sensor->batch_addr = ST_ASM330LHH_REG_FIFO_BATCH_ADDR;
+		sensor->batch_mask = GENMASK(7, 4);
+		sensor->offset = 0;
+		break;
+	case ST_ASM330LHH_ID_TEMP:
+		iio_dev->channels = st_asm330lhh_temp_channels;
+		iio_dev->num_channels = ARRAY_SIZE(st_asm330lhh_temp_channels);
+		iio_dev->name = "asm330lhh_temp";
+		iio_dev->info = &st_asm330lhh_temp_info;
+		sensor->offset = ST_ASM330LHH_OFFSET;
+		break;
+	default:
+		return NULL;
+	}
+
+	return iio_dev;
+}
+
+static void st_asm330lhh_regulator_power_down(struct st_asm330lhh_hw *hw)
+{
+	regulator_disable(hw->vdd);
+	regulator_set_voltage(hw->vdd, 0, INT_MAX);
+	regulator_set_load(hw->vdd, 0);
+	regulator_disable(hw->vio);
+	regulator_set_voltage(hw->vio, 0, INT_MAX);
+	regulator_set_load(hw->vio, 0);
+}
+
+static int st_asm330lhh_regulator_init(struct st_asm330lhh_hw *hw)
+{
+	int err = 0;
+
+	hw->vdd  = devm_regulator_get(hw->dev, "vdd");
+	if (IS_ERR(hw->vdd)) {
+		err = PTR_ERR(hw->vdd);
+		if (err != -EPROBE_DEFER)
+			dev_err(hw->dev, "Error %d to get vdd\n", err);
+		return err;
+	}
+
+	hw->vio = devm_regulator_get(hw->dev, "vio");
+	if (IS_ERR(hw->vio)) {
+		err = PTR_ERR(hw->vio);
+		if (err != -EPROBE_DEFER)
+			dev_err(hw->dev, "Error %d to get vio\n", err);
+		return err;
+	}
+	return err;
+}
+
+static int st_asm330lhh_regulator_power_up(struct st_asm330lhh_hw *hw)
+{
+	u32 vdd_voltage[2] = {3000000, 3600000};
+	u32 vio_voltage[2] = {1620000, 3600000};
+	u32 vdd_current = 30000;
+	u32 vio_current = 30000;
+	int err = 0;
+
+	/* Enable VDD for ASM330 */
+	if (vdd_voltage[0] > 0 && vdd_voltage[0] <= vdd_voltage[1]) {
+		err = regulator_set_voltage(hw->vdd, vdd_voltage[0],
+						vdd_voltage[1]);
+		if (err) {
+			pr_err("Error %d during vdd set_voltage\n", err);
+			return err;
+		}
+	}
+
+	if (vdd_current > 0) {
+		err = regulator_set_load(hw->vdd, vdd_current);
+		if (err < 0) {
+			pr_err("vdd regulator_set_load failed,err=%d\n", err);
+			goto remove_vdd_voltage;
+		}
+	}
+
+	err = regulator_enable(hw->vdd);
+	if (err) {
+		dev_err(hw->dev, "vdd enable failed with error %d\n", err);
+		goto remove_vdd_current;
+	}
+
+	/* Enable VIO for ASM330 */
+	if (vio_voltage[0] > 0 && vio_voltage[0] <= vio_voltage[1]) {
+		err = regulator_set_voltage(hw->vio, vio_voltage[0],
+						vio_voltage[1]);
+		if (err) {
+			pr_err("Error %d during vio set_voltage\n", err);
+			goto disable_vdd;
+		}
+	}
+
+	if (vio_current > 0) {
+		err = regulator_set_load(hw->vio, vio_current);
+		if (err < 0) {
+			pr_err("vio regulator_set_load failed,err=%d\n", err);
+			goto remove_vio_voltage;
+		}
+	}
+
+	err = regulator_enable(hw->vio);
+	if (err) {
+		dev_err(hw->dev, "vio enable failed with error %d\n", err);
+		goto remove_vio_current;
+	}
+
+	return 0;
+
+remove_vio_current:
+	regulator_set_load(hw->vio, 0);
+remove_vio_voltage:
+	regulator_set_voltage(hw->vio, 0, INT_MAX);
+disable_vdd:
+	regulator_disable(hw->vdd);
+remove_vdd_current:
+	regulator_set_load(hw->vdd, 0);
+remove_vdd_voltage:
+	regulator_set_voltage(hw->vdd, 0, INT_MAX);
+
+	return err;
+}
+
+int st_asm330lhh_probe(struct device *dev, int irq,
+		       const struct st_asm330lhh_transfer_function *tf_ops)
+{
+	struct st_asm330lhh_hw *hw;
+	int i = 0, err = 0;
+
+	hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
+	if (!hw)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, (void *)hw);
+
+	mutex_init(&hw->lock);
+	mutex_init(&hw->fifo_lock);
+
+	hw->dev = dev;
+	hw->irq = irq;
+	hw->tf = tf_ops;
+
+	dev_info(hw->dev, "Ver: %s\n", ST_ASM330LHH_VERSION);
+
+	err = st_asm330lhh_regulator_init(hw);
+	if (err < 0) {
+		dev_err(hw->dev, "regulator init failed\n");
+		return err;
+	}
+
+	err = st_asm330lhh_regulator_power_up(hw);
+	if (err < 0) {
+		dev_err(hw->dev, "regulator power up failed\n");
+		return err;
+	}
+
+	/* allow time for enabling regulators */
+	usleep_range(1000, 2000);
+
+	err = st_asm330lhh_check_whoami(hw);
+	if (err < 0)
+		goto regulator_shutdown;
+
+	err = st_asm330lhh_init_device(hw);
+	if (err < 0)
+		goto regulator_shutdown;
+
+	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
+		hw->iio_devs[i] = st_asm330lhh_alloc_iiodev(hw, i);
+		if (!hw->iio_devs[i]) {
+			err = -ENOMEM;
+			goto regulator_shutdown;
+		}
+	}
+
+	if (hw->irq > 0) {
+		err = st_asm330lhh_fifo_setup(hw);
+		if (err < 0)
+			goto regulator_shutdown;
+	}
+
+	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
+		if (!hw->iio_devs[i])
+			continue;
+
+		err = devm_iio_device_register(hw->dev, hw->iio_devs[i]);
+		if (err)
+			goto regulator_shutdown;
+	}
+
+	dev_info(hw->dev, "probe ok\n");
+
+	return 0;
+
+regulator_shutdown:
+	st_asm330lhh_regulator_power_down(hw);
+
+	return err;
+}
+EXPORT_SYMBOL(st_asm330lhh_probe);
+
+static int __maybe_unused st_asm330lhh_suspend(struct device *dev)
+{
+	struct st_asm330lhh_hw *hw = dev_get_drvdata(dev);
+	struct st_asm330lhh_sensor *sensor;
+	int i, err = 0;
+
+	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
+		if (!hw->iio_devs[i])
+			continue;
+
+		sensor = iio_priv(hw->iio_devs[i]);
+
+		if (!(hw->enable_mask & BIT(sensor->id)))
+			continue;
+
+		err = st_asm330lhh_set_odr(sensor, 0);
+		if (err < 0)
+			return err;
+	}
+
+	if (hw->enable_mask)
+		err = st_asm330lhh_suspend_fifo(hw);
+
+	return err;
+}
+
+static int __maybe_unused st_asm330lhh_resume(struct device *dev)
+{
+	struct st_asm330lhh_hw *hw = dev_get_drvdata(dev);
+	struct st_asm330lhh_sensor *sensor;
+	int i, err = 0;
+
+	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
+		if (!hw->iio_devs[i])
+			continue;
+
+		sensor = iio_priv(hw->iio_devs[i]);
+		if (!(hw->enable_mask & BIT(sensor->id)))
+			continue;
+
+		err = st_asm330lhh_set_odr(sensor, sensor->odr);
+		if (err < 0)
+			return err;
+	}
+
+	if (hw->enable_mask)
+		err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_CONT);
+
+	return err;
+}
+
+const struct dev_pm_ops st_asm330lhh_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(st_asm330lhh_suspend, st_asm330lhh_resume)
+};
+EXPORT_SYMBOL(st_asm330lhh_pm_ops);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics st_asm330lhh driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(ST_ASM330LHH_VERSION);
diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_i2c.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_i2c.c
new file mode 100644
index 0000000..4875097
--- /dev/null
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_i2c.c
@@ -0,0 +1,94 @@
+/*
+ * STMicroelectronics st_asm330lhh i2c driver
+ *
+ * Copyright 2018 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include "st_asm330lhh.h"
+
+static int st_asm330lhh_i2c_read(struct device *dev, u8 addr, int len, u8 *data)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_msg msg[2];
+
+	msg[0].addr = client->addr;
+	msg[0].flags = client->flags;
+	msg[0].len = 1;
+	msg[0].buf = &addr;
+
+	msg[1].addr = client->addr;
+	msg[1].flags = client->flags | I2C_M_RD;
+	msg[1].len = len;
+	msg[1].buf = data;
+
+	return i2c_transfer(client->adapter, msg, 2);
+}
+
+static int st_asm330lhh_i2c_write(struct device *dev, u8 addr, int len, u8 *data)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_msg msg;
+	u8 send[len + 1];
+
+	send[0] = addr;
+	memcpy(&send[1], data, len * sizeof(u8));
+
+	msg.addr = client->addr;
+	msg.flags = client->flags;
+	msg.len = len + 1;
+	msg.buf = send;
+
+	return i2c_transfer(client->adapter, &msg, 1);
+}
+
+static const struct st_asm330lhh_transfer_function st_asm330lhh_transfer_fn = {
+	.read = st_asm330lhh_i2c_read,
+	.write = st_asm330lhh_i2c_write,
+};
+
+static int st_asm330lhh_i2c_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	return st_asm330lhh_probe(&client->dev, client->irq,
+				&st_asm330lhh_transfer_fn);
+}
+
+static const struct of_device_id st_asm330lhh_i2c_of_match[] = {
+	{
+		.compatible = "st,asm330lhh",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, st_asm330lhh_i2c_of_match);
+
+static const struct i2c_device_id st_asm330lhh_i2c_id_table[] = {
+	{ ST_ASM330LHH_DEV_NAME },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, st_asm330lhh_i2c_id_table);
+
+static struct i2c_driver st_asm330lhh_driver = {
+	.driver = {
+		.name = "st_asm330lhh_i2c",
+		.pm = &st_asm330lhh_pm_ops,
+		.of_match_table = of_match_ptr(st_asm330lhh_i2c_of_match),
+	},
+	.probe = st_asm330lhh_i2c_probe,
+	.id_table = st_asm330lhh_i2c_id_table,
+};
+module_i2c_driver(st_asm330lhh_driver);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics st_asm330lhh i2c driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(ST_ASM330LHH_VERSION);
diff --git a/drivers/iio/imu/st_asm330lhh/st_asm330lhh_spi.c b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_spi.c
new file mode 100644
index 0000000..07b8400
--- /dev/null
+++ b/drivers/iio/imu/st_asm330lhh/st_asm330lhh_spi.c
@@ -0,0 +1,109 @@
+/*
+ * STMicroelectronics st_asm330lhh spi driver
+ *
+ * Copyright 2018 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include "st_asm330lhh.h"
+
+#define SENSORS_SPI_READ	BIT(7)
+
+static int st_asm330lhh_spi_read(struct device *dev, u8 addr, int len,
+			       u8 *data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct st_asm330lhh_hw *hw = spi_get_drvdata(spi);
+	int err;
+
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = hw->tb.tx_buf,
+			.bits_per_word = 8,
+			.len = 1,
+		},
+		{
+			.rx_buf = hw->tb.rx_buf,
+			.bits_per_word = 8,
+			.len = len,
+		}
+	};
+
+	hw->tb.tx_buf[0] = addr | SENSORS_SPI_READ;
+
+	err = spi_sync_transfer(spi, xfers,  ARRAY_SIZE(xfers));
+	if (err < 0)
+		return err;
+
+	memcpy(data, hw->tb.rx_buf, len * sizeof(u8));
+
+	return len;
+}
+
+static int st_asm330lhh_spi_write(struct device *dev, u8 addr, int len,
+				u8 *data)
+{
+	struct st_asm330lhh_hw *hw;
+	struct spi_device *spi;
+
+	if (len >= ST_ASM330LHH_TX_MAX_LENGTH)
+		return -ENOMEM;
+
+	spi = to_spi_device(dev);
+	hw = spi_get_drvdata(spi);
+
+	hw->tb.tx_buf[0] = addr;
+	memcpy(&hw->tb.tx_buf[1], data, len);
+
+	return spi_write(spi, hw->tb.tx_buf, len + 1);
+}
+
+static const struct st_asm330lhh_transfer_function st_asm330lhh_transfer_fn = {
+	.read = st_asm330lhh_spi_read,
+	.write = st_asm330lhh_spi_write,
+};
+
+static int st_asm330lhh_spi_probe(struct spi_device *spi)
+{
+	return st_asm330lhh_probe(&spi->dev, spi->irq,
+				&st_asm330lhh_transfer_fn);
+}
+
+static const struct of_device_id st_asm330lhh_spi_of_match[] = {
+	{
+		.compatible = "st,asm330lhh",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, st_asm330lhh_spi_of_match);
+
+static const struct spi_device_id st_asm330lhh_spi_id_table[] = {
+	{ ST_ASM330LHH_DEV_NAME },
+	{},
+};
+MODULE_DEVICE_TABLE(spi, st_asm330lhh_spi_id_table);
+
+static struct spi_driver st_asm330lhh_driver = {
+	.driver = {
+		.name = "st_asm330lhh_spi",
+		.pm = &st_asm330lhh_pm_ops,
+		.of_match_table = of_match_ptr(st_asm330lhh_spi_of_match),
+	},
+	.probe = st_asm330lhh_spi_probe,
+	.id_table = st_asm330lhh_spi_id_table,
+};
+module_spi_driver(st_asm330lhh_driver);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics st_asm330lhh spi driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(ST_ASM330LHH_VERSION);
diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c
index 9abc5a9..76861a8 100644
--- a/drivers/infiniband/hw/hfi1/file_ops.c
+++ b/drivers/infiniband/hw/hfi1/file_ops.c
@@ -605,7 +605,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
 		vmf = 1;
 		break;
 	case STATUS:
-		if (flags & (unsigned long)(VM_WRITE | VM_EXEC)) {
+		if (flags & VM_WRITE) {
 			ret = -EPERM;
 			goto done;
 		}
diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c
index 818bac1..d3b8cb9 100644
--- a/drivers/infiniband/hw/hfi1/rc.c
+++ b/drivers/infiniband/hw/hfi1/rc.c
@@ -1162,6 +1162,7 @@ void hfi1_rc_send_complete(struct rvt_qp *qp, struct hfi1_opa_header *opah)
 		if (cmp_psn(wqe->lpsn, qp->s_sending_psn) >= 0 &&
 		    cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)
 			break;
+		rvt_qp_wqe_unreserve(qp, wqe);
 		s_last = qp->s_last;
 		trace_hfi1_qp_send_completion(qp, wqe, s_last);
 		if (++s_last >= qp->s_size)
@@ -1214,6 +1215,7 @@ static struct rvt_swqe *do_rc_completion(struct rvt_qp *qp,
 		u32 s_last;
 
 		rvt_put_swqe(wqe);
+		rvt_qp_wqe_unreserve(qp, wqe);
 		s_last = qp->s_last;
 		trace_hfi1_qp_send_completion(qp, wqe, s_last);
 		if (++s_last >= qp->s_size)
diff --git a/drivers/infiniband/hw/hfi1/ruc.c b/drivers/infiniband/hw/hfi1/ruc.c
index 5866ccc..e8aaae4 100644
--- a/drivers/infiniband/hw/hfi1/ruc.c
+++ b/drivers/infiniband/hw/hfi1/ruc.c
@@ -440,6 +440,8 @@ static void ruc_loopback(struct rvt_qp *sqp)
 			goto op_err;
 		if (!ret)
 			goto rnr_nak;
+		if (wqe->length > qp->r_len)
+			goto inv_err;
 		break;
 
 	case IB_WR_RDMA_WRITE_WITH_IMM:
@@ -607,7 +609,10 @@ static void ruc_loopback(struct rvt_qp *sqp)
 	goto err;
 
 inv_err:
-	send_status = IB_WC_REM_INV_REQ_ERR;
+	send_status =
+		sqp->ibqp.qp_type == IB_QPT_RC ?
+			IB_WC_REM_INV_REQ_ERR :
+			IB_WC_SUCCESS;
 	wc.status = IB_WC_LOC_QP_OP_ERR;
 	goto err;
 
diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c
index 53efbb0..dd812ad 100644
--- a/drivers/infiniband/hw/qib/qib_ruc.c
+++ b/drivers/infiniband/hw/qib/qib_ruc.c
@@ -425,6 +425,8 @@ static void qib_ruc_loopback(struct rvt_qp *sqp)
 			goto op_err;
 		if (!ret)
 			goto rnr_nak;
+		if (wqe->length > qp->r_len)
+			goto inv_err;
 		break;
 
 	case IB_WR_RDMA_WRITE_WITH_IMM:
@@ -585,7 +587,10 @@ static void qib_ruc_loopback(struct rvt_qp *sqp)
 	goto err;
 
 inv_err:
-	send_status = IB_WC_REM_INV_REQ_ERR;
+	send_status =
+		sqp->ibqp.qp_type == IB_QPT_RC ?
+			IB_WC_REM_INV_REQ_ERR :
+			IB_WC_SUCCESS;
 	wc.status = IB_WC_LOC_QP_OP_ERR;
 	goto err;
 
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 3c3453d..fdfa250 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -310,13 +310,16 @@ int usnic_ib_query_port(struct ib_device *ibdev, u8 port,
 
 	usnic_dbg("\n");
 
-	mutex_lock(&us_ibdev->usdev_lock);
 	if (ib_get_eth_speed(ibdev, port, &props->active_speed,
-			     &props->active_width)) {
-		mutex_unlock(&us_ibdev->usdev_lock);
+			     &props->active_width))
 		return -EINVAL;
-	}
 
+	/*
+	 * usdev_lock is acquired after (and not before) ib_get_eth_speed call
+	 * because acquiring rtnl_lock in ib_get_eth_speed, while holding
+	 * usdev_lock could lead to a deadlock.
+	 */
+	mutex_lock(&us_ibdev->usdev_lock);
 	/* props being zeroed by the caller, avoid zeroing it here */
 
 	props->lid = 0;
diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
index de853bc..08ae4f3 100644
--- a/drivers/infiniband/sw/rxe/rxe_req.c
+++ b/drivers/infiniband/sw/rxe/rxe_req.c
@@ -640,6 +640,7 @@ int rxe_requester(void *arg)
 			rmr->access = wqe->wr.wr.reg.access;
 			rmr->lkey = wqe->wr.wr.reg.key;
 			rmr->rkey = wqe->wr.wr.reg.key;
+			rmr->iova = wqe->wr.wr.reg.mr->iova;
 			wqe->state = wqe_state_done;
 			wqe->status = IB_WC_SUCCESS;
 		} else {
diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
index 4d84b01..7432856 100644
--- a/drivers/infiniband/sw/rxe/rxe_resp.c
+++ b/drivers/infiniband/sw/rxe/rxe_resp.c
@@ -845,11 +845,16 @@ static enum resp_states do_complete(struct rxe_qp *qp,
 
 	memset(&cqe, 0, sizeof(cqe));
 
-	wc->wr_id		= wqe->wr_id;
-	wc->status		= qp->resp.status;
-	wc->qp			= &qp->ibqp;
+	if (qp->rcq->is_user) {
+		uwc->status             = qp->resp.status;
+		uwc->qp_num             = qp->ibqp.qp_num;
+		uwc->wr_id              = wqe->wr_id;
+	} else {
+		wc->status              = qp->resp.status;
+		wc->qp                  = &qp->ibqp;
+		wc->wr_id               = wqe->wr_id;
+	}
 
-	/* fields after status are not required for errors */
 	if (wc->status == IB_WC_SUCCESS) {
 		wc->opcode = (pkt->mask & RXE_IMMDT_MASK &&
 				pkt->mask & RXE_WRITE_MASK) ?
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index ade98c23..3f5b589 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -2669,7 +2669,6 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
 {
 	struct srp_target_port *target = host_to_target(scmnd->device->host);
 	struct srp_rdma_ch *ch;
-	int i, j;
 	u8 status;
 
 	shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
@@ -2681,15 +2680,6 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
 	if (status)
 		return FAILED;
 
-	for (i = 0; i < target->ch_count; i++) {
-		ch = &target->ch[i];
-		for (j = 0; j < target->req_ring_size; ++j) {
-			struct srp_request *req = &ch->req_ring[j];
-
-			srp_finish_req(ch, req, scmnd->device, DID_RESET << 16);
-		}
-	}
-
 	return SUCCESS;
 }
 
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index f55dcdf..26476a6 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -255,6 +255,8 @@ static const struct xpad_device {
 	{ 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
 	{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
 	{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
+	{ 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
+	{ 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
 	{ 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
 	{ 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
@@ -431,6 +433,7 @@ static const struct usb_device_id xpad_table[] = {
 	XPAD_XBOXONE_VENDOR(0x0e6f),		/* 0x0e6f X-Box One controllers */
 	XPAD_XBOX360_VENDOR(0x0f0d),		/* Hori Controllers */
 	XPAD_XBOXONE_VENDOR(0x0f0d),		/* Hori Controllers */
+	XPAD_XBOX360_VENDOR(0x1038),		/* SteelSeries Controllers */
 	XPAD_XBOX360_VENDOR(0x11c9),		/* Nacon GC100XF */
 	XPAD_XBOX360_VENDOR(0x12ab),		/* X-Box 360 dance pads */
 	XPAD_XBOX360_VENDOR(0x1430),		/* RedOctane X-Box 360 controllers */
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index ce8e2ba..616fdd9 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -126,12 +126,8 @@ static irqreturn_t omap4_keypad_irq_handler(int irq, void *dev_id)
 {
 	struct omap4_keypad *keypad_data = dev_id;
 
-	if (kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)) {
-		/* Disable interrupts */
-		kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
-				 OMAP4_VAL_IRQDISABLE);
+	if (kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS))
 		return IRQ_WAKE_THREAD;
-	}
 
 	return IRQ_NONE;
 }
@@ -173,11 +169,6 @@ static irqreturn_t omap4_keypad_irq_thread_fn(int irq, void *dev_id)
 	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
 			 kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
 
-	/* enable interrupts */
-	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
-		OMAP4_DEF_IRQENABLE_EVENTEN |
-				OMAP4_DEF_IRQENABLE_LONGKEY);
-
 	return IRQ_HANDLED;
 }
 
@@ -214,9 +205,10 @@ static void omap4_keypad_close(struct input_dev *input)
 
 	disable_irq(keypad_data->irq);
 
-	/* Disable interrupts */
+	/* Disable interrupts and wake-up events */
 	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
 			 OMAP4_VAL_IRQDISABLE);
+	kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, 0);
 
 	/* clear pending interrupts */
 	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
@@ -364,7 +356,7 @@ static int omap4_keypad_probe(struct platform_device *pdev)
 	}
 
 	error = request_threaded_irq(keypad_data->irq, omap4_keypad_irq_handler,
-				     omap4_keypad_irq_thread_fn, 0,
+				     omap4_keypad_irq_thread_fn, IRQF_ONESHOT,
 				     "omap4-keypad", keypad_data);
 	if (error) {
 		dev_err(&pdev->dev, "failed to register interrupt\n");
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
index 1efcfdf..dd9dd4e 100644
--- a/drivers/input/misc/bma150.c
+++ b/drivers/input/misc/bma150.c
@@ -481,13 +481,14 @@ static int bma150_register_input_device(struct bma150_data *bma150)
 	idev->close = bma150_irq_close;
 	input_set_drvdata(idev, bma150);
 
+	bma150->input = idev;
+
 	error = input_register_device(idev);
 	if (error) {
 		input_free_device(idev);
 		return error;
 	}
 
-	bma150->input = idev;
 	return 0;
 }
 
@@ -510,15 +511,15 @@ static int bma150_register_polled_device(struct bma150_data *bma150)
 
 	bma150_init_input_device(bma150, ipoll_dev->input);
 
+	bma150->input_polled = ipoll_dev;
+	bma150->input = ipoll_dev->input;
+
 	error = input_register_polled_device(ipoll_dev);
 	if (error) {
 		input_free_polled_device(ipoll_dev);
 		return error;
 	}
 
-	bma150->input_polled = ipoll_dev;
-	bma150->input = ipoll_dev->input;
-
 	return 0;
 }
 
diff --git a/drivers/input/misc/qti-haptics.c b/drivers/input/misc/qti-haptics.c
index 7bbfa31..d495beb 100644
--- a/drivers/input/misc/qti-haptics.c
+++ b/drivers/input/misc/qti-haptics.c
@@ -1103,8 +1103,11 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip)
 	 * Skip configurations below for ERM actuator
 	 * as they're only for LRA actuators
 	 */
-	if (config->act_type == ACT_ERM)
-		return 0;
+	if (config->act_type == ACT_ERM) {
+		/* Disable AUTO_RES for ERM */
+		rc = qti_haptics_lra_auto_res_enable(chip, false);
+		return rc;
+	}
 
 	addr = REG_HAP_CFG2;
 	val = config->lra_shape;
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 443151d..8c95d3f7 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -39,6 +39,7 @@
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/uinput.h>
+#include <linux/overflow.h>
 #include <linux/input/mt.h>
 #include "../input-compat.h"
 
@@ -356,7 +357,7 @@ static int uinput_open(struct inode *inode, struct file *file)
 static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
 				   const struct input_absinfo *abs)
 {
-	int min, max;
+	int min, max, range;
 
 	min = abs->minimum;
 	max = abs->maximum;
@@ -368,7 +369,7 @@ static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
 		return -EINVAL;
 	}
 
-	if (abs->flat > max - min) {
+	if (!check_sub_overflow(max, min, &range) && abs->flat > range) {
 		printk(KERN_DEBUG
 		       "%s: abs_flat #%02x out of range: %d (min:%d/max:%d)\n",
 		       UINPUT_NAME, code, abs->flat, min, max);
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index f2bf8fa..fce70f4 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -1251,7 +1251,6 @@ MODULE_DEVICE_TABLE(i2c, elan_id);
 static const struct acpi_device_id elan_acpi_id[] = {
 	{ "ELAN0000", 0 },
 	{ "ELAN0100", 0 },
-	{ "ELAN0501", 0 },
 	{ "ELAN0600", 0 },
 	{ "ELAN0602", 0 },
 	{ "ELAN0605", 0 },
@@ -1262,6 +1261,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
 	{ "ELAN060C", 0 },
 	{ "ELAN0611", 0 },
 	{ "ELAN0612", 0 },
+	{ "ELAN0617", 0 },
 	{ "ELAN0618", 0 },
 	{ "ELAN061C", 0 },
 	{ "ELAN061D", 0 },
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 84c69e9..fda33fc 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1121,6 +1121,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Asus UX31               0x361f00        20, 15, 0e      clickpad
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
+ * Fujitsu CELSIUS H760    0x570f02        40, 14, 0c      3 hw buttons (**)
+ * Fujitsu CELSIUS H780    0x5d0f02        41, 16, 0d      3 hw buttons (**)
  * Fujitsu LIFEBOOK E544   0x470f00        d0, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E546   0x470f00        50, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E547   0x470f00        50, 12, 09      2 hw buttons
@@ -1173,6 +1175,13 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"),
 		},
 	},
+	{
+		/* Fujitsu H780 also has a middle button */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H780"),
+		},
+	},
 #endif
 	{ }
 };
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 54f0d03..e9ec5d1 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -171,6 +171,7 @@ static const char * const smbus_pnp_ids[] = {
 	"LEN0046", /* X250 */
 	"LEN004a", /* W541 */
 	"LEN005b", /* P50 */
+	"LEN005e", /* T560 */
 	"LEN0071", /* T480 */
 	"LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */
 	"LEN0073", /* X1 Carbon G5 (Elantech) */
@@ -178,6 +179,7 @@ static const char * const smbus_pnp_ids[] = {
 	"LEN0096", /* X280 */
 	"LEN0097", /* X280 -> ALPS trackpoint */
 	"LEN200f", /* T450s */
+	"SYN3052", /* HP EliteBook 840 G4 */
 	"SYN3221", /* HP 15-ay000 */
 	NULL
 };
diff --git a/drivers/input/touchscreen/st/fts.c b/drivers/input/touchscreen/st/fts.c
index b53169c..f6f2efab 100644
--- a/drivers/input/touchscreen/st/fts.c
+++ b/drivers/input/touchscreen/st/fts.c
@@ -2772,7 +2772,7 @@ static void fts_enter_pointer_event_handler(struct fts_ts_info *info,
 			unsigned char *event)
 {
 	unsigned char touchId, touchcount;
-	int x, y, z;
+	int x, y;
 	int minor;
 	int major, distance;
 	u8 touchsize;
@@ -2791,9 +2791,6 @@ static void fts_enter_pointer_event_handler(struct fts_ts_info *info,
 
 	x = (event[2] << 4) | (event[4] & 0xF0) >> 4;
 	y = (event[3] << 4) | (event[4] & 0x0F);
-	z = (event[5] & 0x3F);
-	if (z == 0)
-		z = 10;
 
 	if (info->bdata->x_flip)
 		x = X_AXIS_MAX - x;
@@ -2820,7 +2817,6 @@ static void fts_enter_pointer_event_handler(struct fts_ts_info *info,
 	input_report_abs(info->input_dev, ABS_MT_POSITION_Y, y);
 	input_report_abs(info->input_dev, ABS_MT_TOUCH_MAJOR, major);
 	input_report_abs(info->input_dev, ABS_MT_TOUCH_MINOR, minor);
-	input_report_abs(info->input_dev, ABS_MT_PRESSURE, z);
 	input_report_abs(info->input_dev, ABS_MT_DISTANCE, distance);
 no_report:
 	return;
@@ -4599,8 +4595,6 @@ static int fts_probe(struct i2c_client *client,
 			AREA_MIN, AREA_MAX, 0, 0);
 	input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MINOR,
 			AREA_MIN, AREA_MAX, 0, 0);
-	input_set_abs_params(info->input_dev, ABS_MT_PRESSURE,
-			PRESSURE_MIN, PRESSURE_MAX, 0, 0);
 
 #ifdef PHONE_GESTURE
 	input_set_capability(info->input_dev, EV_KEY, KEY_WAKEUP);
diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.c b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.c
index 39c6d98..41af427 100644
--- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.c
+++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.c
@@ -40,7 +40,7 @@
 
 /* #define RESUME_EARLY_UNBLANK */
 
-#define RESET_ON_RESUME_DELAY_MS 20
+#define RESET_ON_RESUME_DELAY_MS 50
 
 #define PREDICTIVE_READING
 
@@ -48,7 +48,7 @@
 
 #define KEEP_DRIVER_ON_ERROR
 
-#define FORCE_RUN_APPLICATION_FIRMWARE
+/* #define FORCE_RUN_APPLICATION_FIRMWARE */
 
 #define NOTIFIER_PRIORITY 2
 
@@ -68,7 +68,7 @@
 
 #define WATCHDOG_TRIGGER_COUNT 2
 
-#define WATCHDOG_DELAY_MS 1000
+#define WATCHDOG_DELAY_MS 5000
 
 #define MODE_SWITCH_DELAY_MS 100
 
@@ -518,6 +518,7 @@ static void syna_tcm_module_work(struct work_struct *work)
 	struct syna_tcm_hcd *tcm_hcd = mod_pool.tcm_hcd;
 
 	mutex_lock(&mod_pool.mutex);
+	mod_pool.reconstructing = true;
 
 	if (!list_empty(&mod_pool.list)) {
 		list_for_each_entry_safe(mod_handler,
@@ -538,6 +539,7 @@ static void syna_tcm_module_work(struct work_struct *work)
 		}
 	}
 
+	mod_pool.reconstructing = false;
 	mutex_unlock(&mod_pool.mutex);
 }
 
@@ -568,6 +570,7 @@ static int syna_tcm_report_notifier(void *data)
 		set_current_state(TASK_RUNNING);
 
 		mutex_lock(&mod_pool.mutex);
+		mod_pool.reconstructing = true;
 
 		if (!list_empty(&mod_pool.list)) {
 			list_for_each_entry(mod_handler, &mod_pool.list, link) {
@@ -578,6 +581,7 @@ static int syna_tcm_report_notifier(void *data)
 			}
 		}
 
+		mod_pool.reconstructing = false;
 		mutex_unlock(&mod_pool.mutex);
 
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -623,7 +627,6 @@ static void syna_tcm_dispatch_report(struct syna_tcm_hcd *tcm_hcd)
 		}
 	}
 
-
 	tcm_hcd->async_report_id = tcm_hcd->status_report_code;
 
 	mutex_unlock(&mod_pool.mutex);
@@ -738,7 +741,7 @@ static void syna_tcm_dispatch_message(struct syna_tcm_hcd *tcm_hcd)
 		if (tcm_hcd->wr_chunk_size == 0)
 			tcm_hcd->wr_chunk_size = max_write_size;
 
-		LOGN(tcm_hcd->pdev->dev.parent,
+		LOGD(tcm_hcd->pdev->dev.parent,
 			"Received identify report (firmware mode = 0x%02x)\n",
 			tcm_hcd->id_info.mode);
 
@@ -780,10 +783,15 @@ static void syna_tcm_dispatch_message(struct syna_tcm_hcd *tcm_hcd)
 #endif
 	}
 
-	if (tcm_hcd->status_report_code >= REPORT_IDENTIFY)
+	if (tcm_hcd->status_report_code >= REPORT_IDENTIFY) {
+		if ((mod_pool.reconstructing)
+			&& (tcm_hcd->status_report_code == REPORT_TOUCH))
+			return;
 		syna_tcm_dispatch_report(tcm_hcd);
-	else
+
+	} else
 		syna_tcm_dispatch_response(tcm_hcd);
+
 }
 
 /**
@@ -1291,10 +1299,14 @@ static int syna_tcm_read_message(struct syna_tcm_hcd *tcm_hcd,
 		tcm_hcd->read_length = total_length;
 #endif
 
+	mutex_unlock(&tcm_hcd->rw_ctrl_mutex);
+
 	syna_tcm_dispatch_message(tcm_hcd);
 
 	retval = 0;
 
+	return retval;
+
 exit:
 	if (retval < 0) {
 		if (atomic_read(&tcm_hcd->command_status) == CMD_BUSY) {
@@ -1603,7 +1615,6 @@ static void syna_tcm_update_watchdog(struct syna_tcm_hcd *tcm_hcd, bool en)
 static void syna_tcm_watchdog_work(struct work_struct *work)
 {
 	int retval;
-	unsigned char marker;
 	struct delayed_work *delayed_work =
 			container_of(work, struct delayed_work, work);
 	struct syna_tcm_watchdog *watchdog =
@@ -1618,12 +1629,12 @@ static void syna_tcm_watchdog_work(struct work_struct *work)
 	mutex_lock(&tcm_hcd->rw_ctrl_mutex);
 
 	retval = syna_tcm_read(tcm_hcd,
-			&marker,
+			&tcm_hcd->marker,
 			1);
 
 	mutex_unlock(&tcm_hcd->rw_ctrl_mutex);
 
-	if (retval < 0 || marker != MESSAGE_MARKER) {
+	if (retval < 0 || tcm_hcd->marker != MESSAGE_MARKER) {
 		LOGE(tcm_hcd->pdev->dev.parent,
 				"Failed to read from device\n");
 
@@ -2660,7 +2671,7 @@ static int syna_tcm_reset(struct syna_tcm_hcd *tcm_hcd, bool hw, bool update_wd)
 	}
 
 get_features:
-	LOGN(tcm_hcd->pdev->dev.parent,
+	LOGD(tcm_hcd->pdev->dev.parent,
 			"Firmware mode = 0x%02x\n",
 			tcm_hcd->id_info.mode);
 
@@ -2704,6 +2715,7 @@ static int syna_tcm_reset(struct syna_tcm_hcd *tcm_hcd, bool hw, bool update_wd)
 
 dispatch_reset:
 	mutex_lock(&mod_pool.mutex);
+	mod_pool.reconstructing = true;
 
 	if (!list_empty(&mod_pool.list)) {
 		list_for_each_entry(mod_handler, &mod_pool.list, link) {
@@ -2714,6 +2726,7 @@ static int syna_tcm_reset(struct syna_tcm_hcd *tcm_hcd, bool hw, bool update_wd)
 		}
 	}
 
+	mod_pool.reconstructing = false;
 	mutex_unlock(&mod_pool.mutex);
 
 	retval = 0;
@@ -2827,6 +2840,13 @@ static int syna_tcm_resume(struct device *dev)
 
 	if (!tcm_hcd->init_okay)
 		syna_tcm_deferred_probe(dev);
+	else {
+		if (tcm_hcd->irq_enabled) {
+			tcm_hcd->watchdog.run = false;
+			tcm_hcd->update_watchdog(tcm_hcd, false);
+			tcm_hcd->enable_irq(tcm_hcd, false, false);
+		}
+	}
 
 	if (!tcm_hcd->in_suspend)
 		return 0;
@@ -2933,10 +2953,6 @@ static int syna_tcm_suspend(struct device *dev)
 
 	mutex_unlock(&mod_pool.mutex);
 
-#ifndef WAKEUP_GESTURE
-	tcm_hcd->enable_irq(tcm_hcd, false, true);
-#endif
-
 	tcm_hcd->in_suspend = true;
 
 	return 0;
@@ -2990,6 +3006,10 @@ static int syna_tcm_early_suspend(struct device *dev)
 
 	mutex_unlock(&mod_pool.mutex);
 
+#ifndef WAKEUP_GESTURE
+	tcm_hcd->enable_irq(tcm_hcd, false, true);
+#endif
+
 	return 0;
 }
 
@@ -3005,30 +3025,46 @@ static int syna_tcm_fb_notifier_cb(struct notifier_block *nb,
 	if (!evdata || (evdata->id != 0))
 		return 0;
 
-	if (evdata && evdata->data && tcm_hcd) {
-		transition = (int *) evdata->data;
-		if (action == MSM_DRM_EARLY_EVENT_BLANK &&
-				*transition == MSM_DRM_BLANK_POWERDOWN)
-			retval = syna_tcm_early_suspend(&tcm_hcd->pdev->dev);
-		else if (action == MSM_DRM_EVENT_BLANK) {
-			if (*transition == MSM_DRM_BLANK_POWERDOWN) {
-				retval = syna_tcm_suspend(&tcm_hcd->pdev->dev);
-				tcm_hcd->fb_ready = 0;
-			} else if (*transition == MSM_DRM_BLANK_UNBLANK) {
+	if (!evdata->data || !tcm_hcd)
+		return 0;
+
+	transition = (int *) evdata->data;
+
+	if (atomic_read(&tcm_hcd->firmware_flashing)
+		&& *transition == MSM_DRM_BLANK_POWERDOWN) {
+		retval = wait_event_interruptible_timeout(tcm_hcd->reflash_wq,
+				!atomic_read(&tcm_hcd->firmware_flashing),
+				msecs_to_jiffies(RESPONSE_TIMEOUT_MS));
+		if (retval == 0) {
+			LOGE(tcm_hcd->pdev->dev.parent,
+				"Timed out waiting for flashing firmware\n");
+			atomic_set(&tcm_hcd->firmware_flashing, 0);
+			return -EIO;
+		}
+	}
+
+	if (action == MSM_DRM_EARLY_EVENT_BLANK &&
+			*transition == MSM_DRM_BLANK_POWERDOWN)
+		retval = syna_tcm_early_suspend(&tcm_hcd->pdev->dev);
+	else if (action == MSM_DRM_EVENT_BLANK) {
+		if (*transition == MSM_DRM_BLANK_POWERDOWN) {
+			retval = syna_tcm_suspend(&tcm_hcd->pdev->dev);
+			tcm_hcd->fb_ready = 0;
+		} else if (*transition == MSM_DRM_BLANK_UNBLANK) {
 #ifndef RESUME_EARLY_UNBLANK
-				retval = syna_tcm_resume(&tcm_hcd->pdev->dev);
-				tcm_hcd->fb_ready++;
-#endif
-			}
-		} else if (action == MSM_DRM_EARLY_EVENT_BLANK &&
-				*transition == MSM_DRM_BLANK_UNBLANK) {
-#ifdef RESUME_EARLY_UNBLANK
 			retval = syna_tcm_resume(&tcm_hcd->pdev->dev);
 			tcm_hcd->fb_ready++;
 #endif
 		}
+	} else if (action == MSM_DRM_EARLY_EVENT_BLANK &&
+			*transition == MSM_DRM_BLANK_UNBLANK) {
+#ifdef RESUME_EARLY_UNBLANK
+		retval = syna_tcm_resume(&tcm_hcd->pdev->dev);
+		tcm_hcd->fb_ready++;
+#endif
 	}
 
+
 	return 0;
 }
 
@@ -3083,36 +3119,49 @@ static int syna_tcm_early_suspend(struct device *dev)
 static int syna_tcm_fb_notifier_cb(struct notifier_block *nb,
 		unsigned long action, void *data)
 {
-	int retval;
+	int retval = 0;
 	int *transition;
 	struct fb_event *evdata = data;
 	struct syna_tcm_hcd *tcm_hcd =
 			container_of(nb, struct syna_tcm_hcd, fb_notifier);
 
-	retval = 0;
+	if (!evdata || !evdata->data || !tcm_hcd)
+		return 0;
 
-	if (evdata && evdata->data && tcm_hcd) {
-		transition = (int *)evdata->data;
-		if (action == FB_EARLY_EVENT_BLANK &&
-				*transition == FB_BLANK_POWERDOWN)
-			retval = syna_tcm_early_suspend(&tcm_hcd->pdev->dev);
-		else if (action == FB_EVENT_BLANK) {
-			if (*transition == FB_BLANK_POWERDOWN) {
-				retval = syna_tcm_suspend(&tcm_hcd->pdev->dev);
-				tcm_hcd->fb_ready = 0;
-			} else if (*transition == FB_BLANK_UNBLANK) {
+	transition = (int *)evdata->data;
+
+	if (atomic_read(&tcm_hcd->firmware_flashing)
+		&& *transition == FB_BLANK_POWERDOWN) {
+		retval = wait_event_interruptible_timeout(tcm_hcd->reflash_wq,
+				!atomic_read(&tcm_hcd->firmware_flashing),
+				msecs_to_jiffies(RESPONSE_TIMEOUT_MS));
+		if (retval == 0) {
+			LOGE(tcm_hcd->pdev->dev.parent,
+				"Timed out waiting for flashing firmware\n");
+			atomic_set(&tcm_hcd->firmware_flashing, 0);
+			return -EIO;
+		}
+	}
+
+	if (action == FB_EARLY_EVENT_BLANK &&
+			*transition == FB_BLANK_POWERDOWN)
+		retval = syna_tcm_early_suspend(&tcm_hcd->pdev->dev);
+	else if (action == FB_EVENT_BLANK) {
+		if (*transition == FB_BLANK_POWERDOWN) {
+			retval = syna_tcm_suspend(&tcm_hcd->pdev->dev);
+			tcm_hcd->fb_ready = 0;
+		} else if (*transition == FB_BLANK_UNBLANK) {
 #ifndef RESUME_EARLY_UNBLANK
-				retval = syna_tcm_resume(&tcm_hcd->pdev->dev);
-				tcm_hcd->fb_ready++;
-#endif
-			}
-		} else if (action == FB_EARLY_EVENT_BLANK &&
-				*transition == FB_BLANK_UNBLANK) {
-#ifdef RESUME_EARLY_UNBLANK
 			retval = syna_tcm_resume(&tcm_hcd->pdev->dev);
 			tcm_hcd->fb_ready++;
 #endif
 		}
+	} else if (action == FB_EARLY_EVENT_BLANK &&
+			*transition == FB_BLANK_UNBLANK) {
+#ifdef RESUME_EARLY_UNBLANK
+		retval = syna_tcm_resume(&tcm_hcd->pdev->dev);
+		tcm_hcd->fb_ready++;
+#endif
 	}
 
 	return 0;
@@ -3217,6 +3266,9 @@ static int syna_tcm_probe(struct platform_device *pdev)
 
 	init_waitqueue_head(&tcm_hcd->hdl_wq);
 
+	init_waitqueue_head(&tcm_hcd->reflash_wq);
+	atomic_set(&tcm_hcd->firmware_flashing, 0);
+
 	if (!mod_pool.initialized) {
 		mutex_init(&mod_pool.mutex);
 		INIT_LIST_HEAD(&mod_pool.list);
@@ -3327,6 +3379,7 @@ static int syna_tcm_probe(struct platform_device *pdev)
 	INIT_WORK(&mod_pool.work, syna_tcm_module_work);
 	mod_pool.tcm_hcd = tcm_hcd;
 	mod_pool.queue_work = true;
+	mod_pool.reconstructing = false;
 
 	return 0;
 
@@ -3429,13 +3482,15 @@ static int syna_tcm_remove(struct platform_device *pdev)
 {
 	int idx;
 	struct syna_tcm_module_handler *mod_handler;
+	struct syna_tcm_module_handler *tmp_handler;
 	struct syna_tcm_hcd *tcm_hcd = platform_get_drvdata(pdev);
 	const struct syna_tcm_board_data *bdata = tcm_hcd->hw_if->bdata;
 
 	mutex_lock(&mod_pool.mutex);
 
 	if (!list_empty(&mod_pool.list)) {
-		list_for_each_entry(mod_handler, &mod_pool.list, link) {
+		list_for_each_entry_safe(mod_handler, tmp_handler,
+				&mod_pool.list, link) {
 			if (mod_handler->mod_cb->remove)
 				mod_handler->mod_cb->remove(tcm_hcd);
 			list_del(&mod_handler->link);
@@ -3514,6 +3569,11 @@ static int syna_tcm_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static void syna_tcm_shutdown(struct platform_device *pdev)
+{
+	syna_tcm_remove(pdev);
+}
+
 #ifdef CONFIG_PM
 static const struct dev_pm_ops syna_tcm_dev_pm_ops = {
 #if !defined(CONFIG_DRM) && !defined(CONFIG_FB)
@@ -3533,6 +3593,7 @@ static struct platform_driver syna_tcm_driver = {
 	},
 	.probe = syna_tcm_probe,
 	.remove = syna_tcm_remove,
+	.shutdown = syna_tcm_shutdown,
 };
 
 static int __init syna_tcm_module_init(void)
diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.h b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.h
index 79c5e76..30e741e 100644
--- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.h
+++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.h
@@ -387,13 +387,16 @@ struct syna_tcm_hcd {
 	pid_t isr_pid;
 	atomic_t command_status;
 	atomic_t host_downloading;
+	atomic_t firmware_flashing;
 	wait_queue_head_t hdl_wq;
+	wait_queue_head_t reflash_wq;
 	int irq;
 	bool init_okay;
 	bool do_polling;
 	bool in_suspend;
 	bool irq_enabled;
 	bool host_download_mode;
+	unsigned char marker;
 	unsigned char fb_ready;
 	unsigned char command;
 	unsigned char async_report_id;
@@ -486,6 +489,7 @@ struct syna_tcm_module_handler {
 struct syna_tcm_module_pool {
 	bool initialized;
 	bool queue_work;
+	bool reconstructing;
 	struct mutex mutex;
 	struct list_head list;
 	struct work_struct work;
diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_device.c b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_device.c
index 97de087..963e299 100644
--- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_device.c
+++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_device.c
@@ -257,10 +257,13 @@ static int device_ioctl(struct inode *inp, struct file *filp, unsigned int cmd,
 			retval = tcm_hcd->enable_irq(tcm_hcd, true, NULL);
 		break;
 	case DEVICE_IOC_RAW:
-		if (arg == 0)
+		if (arg == 0) {
 			device_hcd->raw_mode = false;
-		else if (arg == 1)
+			tcm_hcd->update_watchdog(tcm_hcd, true);
+		} else if (arg == 1) {
 			device_hcd->raw_mode = true;
+			tcm_hcd->update_watchdog(tcm_hcd, false);
+		}
 		break;
 	case DEVICE_IOC_CONCURRENT:
 		if (arg == 0)
diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_i2c.c b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_i2c.c
index 913ef8b..604f721 100644
--- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_i2c.c
+++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_i2c.c
@@ -33,6 +33,7 @@
 #include <linux/i2c.h>
 #include <linux/of_gpio.h>
 #include "synaptics_tcm_core.h"
+#include "linux/moduleparam.h"
 
 #define XFER_ATTEMPTS 10
 
@@ -46,6 +47,8 @@ static struct syna_tcm_hw_interface hw_if;
 
 static struct platform_device *syna_tcm_i2c_device;
 
+active_tp_setup(synaptics_tcm);
+
 #ifdef CONFIG_OF
 static int parse_dt(struct device *dev, struct syna_tcm_board_data *bdata)
 {
@@ -239,11 +242,11 @@ static int syna_tcm_i2c_rmi_read(struct syna_tcm_hcd *tcm_hcd,
 			retval = length;
 			goto exit;
 		}
-		LOGE(&i2c->dev,
-				"Transfer attempt %d failed\n",
-				attempt + 1);
+
+		LOGD(&i2c->dev, "Transfer attempt %d times\n", attempt + 1);
 
 		if (attempt + 1 == XFER_ATTEMPTS) {
+			LOGE(&i2c->dev, "Transfer failed\n");
 			retval = -EIO;
 			goto exit;
 		}
@@ -300,11 +303,11 @@ static int syna_tcm_i2c_rmi_write(struct syna_tcm_hcd *tcm_hcd,
 			retval = length;
 			goto exit;
 		}
-		LOGE(&i2c->dev,
-				"Transfer attempt %d failed\n",
-				attempt + 1);
+
+		LOGD(&i2c->dev, "Transfer attempt %d times\n", attempt + 1);
 
 		if (attempt + 1 == XFER_ATTEMPTS) {
+			LOGE(&i2c->dev, "Transfer failed\n");
 			retval = -EIO;
 			goto exit;
 		}
@@ -338,11 +341,11 @@ static int syna_tcm_i2c_read(struct syna_tcm_hcd *tcm_hcd, unsigned char *data,
 			retval = length;
 			goto exit;
 		}
-		LOGE(&i2c->dev,
-				"Transfer attempt %d failed\n",
-				attempt + 1);
+
+		LOGD(&i2c->dev, "Transfer attempt %d times\n", attempt + 1);
 
 		if (attempt + 1 == XFER_ATTEMPTS) {
+			LOGE(&i2c->dev, "Transfer failed\n");
 			retval = -EIO;
 			goto exit;
 		}
@@ -376,11 +379,11 @@ static int syna_tcm_i2c_write(struct syna_tcm_hcd *tcm_hcd, unsigned char *data,
 			retval = length;
 			goto exit;
 		}
-		LOGE(&i2c->dev,
-				"Transfer attempt %d failed\n",
-				attempt + 1);
+
+		LOGD(&i2c->dev, "Transfer attempt %d times\n", attempt + 1);
 
 		if (attempt + 1 == XFER_ATTEMPTS) {
+			LOGE(&i2c->dev, "Transfer failed\n");
 			retval = -EIO;
 			goto exit;
 		}
@@ -398,6 +401,11 @@ static int syna_tcm_i2c_probe(struct i2c_client *i2c,
 		const struct i2c_device_id *dev_id)
 {
 	int retval;
+	struct device_node *dt = i2c->dev.of_node;
+
+	if (synaptics_tcm_check_assigned_tp(dt, "compatible",
+				"qcom,i2c-touch-active") < 0)
+		return -ENODEV;
 
 	syna_tcm_i2c_device = platform_device_alloc(PLATFORM_DRIVER_NAME, 0);
 	if (!syna_tcm_i2c_device) {
diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_reflash.c b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_reflash.c
index 3217b58..bb6bef6f 100644
--- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_reflash.c
+++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_reflash.c
@@ -448,7 +448,7 @@ static ssize_t reflash_sysfs_reflash_store(struct device *dev,
 
 	retval = reflash_get_fw_image();
 	if (retval < 0) {
-		LOGE(tcm_hcd->pdev->dev.parent,
+		LOGD(tcm_hcd->pdev->dev.parent,
 				"Failed to get firmware image\n");
 		goto exit;
 	}
@@ -932,7 +932,7 @@ static int reflash_get_fw_image(void)
 		retval = request_firmware(&reflash_hcd->fw_entry, FW_IMAGE_NAME,
 				tcm_hcd->pdev->dev.parent);
 		if (retval < 0) {
-			LOGE(tcm_hcd->pdev->dev.parent,
+			LOGD(tcm_hcd->pdev->dev.parent,
 					"Failed to request %s\n",
 					FW_IMAGE_NAME);
 			return retval;
@@ -1024,16 +1024,14 @@ static enum update_area reflash_compare_id_info(void)
 	update_area = NONE;
 
 exit:
-	if (update_area == NONE) {
-		LOGN(tcm_hcd->pdev->dev.parent,
-				"No need to do reflash\n");
-	} else {
-		LOGN(tcm_hcd->pdev->dev.parent,
+	if (update_area == NONE)
+		LOGD(tcm_hcd->pdev->dev.parent, "No need to do reflash\n");
+	else
+		LOGD(tcm_hcd->pdev->dev.parent,
 				"Updating %s\n",
 				update_area == FIRMWARE_CONFIG ?
 				"firmware and config" :
 				"config only");
-	}
 
 	return update_area;
 }
@@ -1869,14 +1867,16 @@ static int reflash_do_reflash(void)
 
 	retval = reflash_get_fw_image();
 	if (retval < 0) {
-		LOGE(tcm_hcd->pdev->dev.parent,
+		LOGD(tcm_hcd->pdev->dev.parent,
 				"Failed to get firmware image\n");
 		goto exit;
 	}
 
-	LOGN(tcm_hcd->pdev->dev.parent,
+	LOGD(tcm_hcd->pdev->dev.parent,
 			"Start of reflash\n");
 
+	atomic_set(&tcm_hcd->firmware_flashing, 1);
+
 	update_area = reflash_compare_id_info();
 
 	switch (update_area) {
@@ -1917,7 +1917,7 @@ static int reflash_do_reflash(void)
 		break;
 	}
 
-	LOGN(tcm_hcd->pdev->dev.parent,
+	LOGD(tcm_hcd->pdev->dev.parent,
 			"End of reflash\n");
 
 	retval = 0;
@@ -1930,6 +1930,8 @@ static int reflash_do_reflash(void)
 		reflash_hcd->image_size = 0;
 	}
 
+	atomic_set(&tcm_hcd->firmware_flashing, 0);
+	wake_up_interruptible(&tcm_hcd->reflash_wq);
 	return retval;
 }
 
diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_touch.c b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_touch.c
index c354ecd..82b758ce 100644
--- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_touch.c
+++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_touch.c
@@ -996,7 +996,7 @@ static int touch_set_input_reporting(void)
 				"Failed to check input parameters\n");
 		goto exit;
 	} else if (retval == 0) {
-		LOGN(tcm_hcd->pdev->dev.parent,
+		LOGD(tcm_hcd->pdev->dev.parent,
 				"Input parameters unchanged\n");
 		goto exit;
 	}
@@ -1070,7 +1070,8 @@ static int touch_remove(struct syna_tcm_hcd *tcm_hcd)
 
 	tcm_hcd->report_touch = NULL;
 
-	input_unregister_device(touch_hcd->input_dev);
+	if (touch_hcd->input_dev)
+		input_unregister_device(touch_hcd->input_dev);
 
 	kfree(touch_hcd->touch_data.object_data);
 	kfree(touch_hcd->prev_status);
@@ -1164,7 +1165,11 @@ static int touch_early_suspend(struct syna_tcm_hcd *tcm_hcd)
 	if (!touch_hcd)
 		return 0;
 
+#ifdef WAKEUP_GESTURE
+	touch_hcd->suspend_touch = false;
+#else
 	touch_hcd->suspend_touch = true;
+#endif
 
 	touch_free_objects();
 
@@ -1190,6 +1195,8 @@ static int touch_suspend(struct syna_tcm_hcd *tcm_hcd)
 		touch_hcd->irq_wake = true;
 	}
 
+	touch_hcd->suspend_touch = false;
+
 	retval = tcm_hcd->set_dynamic_config(tcm_hcd,
 			DC_IN_WAKEUP_GESTURE_MODE,
 			1);
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index efa6cd2..766103e 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -442,7 +442,14 @@ static int iommu_init_device(struct device *dev)
 
 	dev_data->alias = get_alias(dev);
 
-	if (dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
+	/*
+	 * By default we use passthrough mode for IOMMUv2 capable device.
+	 * But if amd_iommu=force_isolation is set (e.g. to debug DMA to
+	 * invalid address), we ignore the capability for the device so
+	 * it'll be forced to go into translation mode.
+	 */
+	if ((iommu_pass_through || !amd_iommu_force_isolation) &&
+	    dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
 		struct amd_iommu *iommu;
 
 		iommu = amd_iommu_rlookup_table[dev_data->devid];
diff --git a/drivers/iommu/arm-smmu-regs.h b/drivers/iommu/arm-smmu-regs.h
index 3613fdc..6b75f81 100644
--- a/drivers/iommu/arm-smmu-regs.h
+++ b/drivers/iommu/arm-smmu-regs.h
@@ -193,6 +193,7 @@ enum arm_smmu_s2cr_privcfg {
 #define ARM_SMMU_CB_ATSR		0x8f0
 #define ARM_SMMU_STATS_SYNC_INV_TBU_ACK 0x25dc
 #define ARM_SMMU_TBU_PWR_STATUS         0x2204
+#define ARM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR 0x2670
 
 #define SCTLR_SHCFG_SHIFT		22
 #define SCTLR_SHCFG_MASK		0x3
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 56135f4..cabacbb 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -730,7 +730,13 @@ static void queue_inc_cons(struct arm_smmu_queue *q)
 	u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
 
 	q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
-	writel(q->cons, q->cons_reg);
+
+	/*
+	 * Ensure that all CPU accesses (reads and writes) to the queue
+	 * are complete before we update the cons pointer.
+	 */
+	mb();
+	writel_relaxed(q->cons, q->cons_reg);
 }
 
 static int queue_sync_prod(struct arm_smmu_queue *q)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 541bb9f..cb3ac4f 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -258,6 +258,7 @@ struct arm_smmu_device {
 #define ARM_SMMU_OPT_STATIC_CB		(1 << 6)
 #define ARM_SMMU_OPT_DISABLE_ATOS	(1 << 7)
 #define ARM_SMMU_OPT_MIN_IOVA_ALIGN	(1 << 8)
+#define ARM_SMMU_OPT_NO_DYNAMIC_ASID	(1 << 9)
 	u32				options;
 	enum arm_smmu_arch_version	version;
 	enum arm_smmu_implementation	model;
@@ -398,6 +399,7 @@ static struct arm_smmu_option_prop arm_smmu_options[] = {
 	{ ARM_SMMU_OPT_STATIC_CB, "qcom,enable-static-cb"},
 	{ ARM_SMMU_OPT_DISABLE_ATOS, "qcom,disable-atos" },
 	{ ARM_SMMU_OPT_MIN_IOVA_ALIGN, "qcom,min-iova-align" },
+	{ ARM_SMMU_OPT_NO_DYNAMIC_ASID, "qcom,no-dynamic-asid" },
 	{ 0, NULL},
 };
 
@@ -1103,7 +1105,7 @@ static int __arm_smmu_tlb_sync(struct arm_smmu_device *smmu,
 				void __iomem *sync, void __iomem *status)
 {
 	unsigned int spin_cnt, delay;
-	u32 sync_inv_ack, tbu_pwr_status;
+	u32 sync_inv_ack, tbu_pwr_status, sync_inv_progress;
 
 	writel_relaxed(0, sync);
 	for (delay = 1; delay < TLB_LOOP_TIMEOUT; delay *= 2) {
@@ -1118,10 +1120,12 @@ static int __arm_smmu_tlb_sync(struct arm_smmu_device *smmu,
 				     ARM_SMMU_STATS_SYNC_INV_TBU_ACK));
 	tbu_pwr_status = scm_io_read((unsigned long)(smmu->phys_addr +
 				     ARM_SMMU_TBU_PWR_STATUS));
+	sync_inv_progress = scm_io_read((unsigned long)(smmu->phys_addr +
+					ARM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR));
 	trace_tlbsync_timeout(smmu->dev, 0);
 	dev_err_ratelimited(smmu->dev,
-			    "TLB sync timed out -- SMMU may be deadlocked ack 0x%x pwr 0x%x\n",
-			    sync_inv_ack, tbu_pwr_status);
+			    "TLB sync timed out -- SMMU may be deadlocked ack 0x%x pwr 0x%x sync and invalidation progress 0x%x\n",
+			    sync_inv_ack, tbu_pwr_status, sync_inv_progress);
 	BUG_ON(IS_ENABLED(CONFIG_IOMMU_TLBSYNC_DEBUG));
 	return -EINVAL;
 }
@@ -1406,6 +1410,62 @@ static struct iommu_gather_ops msm_smmu_gather_ops = {
 	.free_pages_exact = arm_smmu_free_pages_exact,
 };
 
+static void print_ctx_regs(struct arm_smmu_device *smmu, struct arm_smmu_cfg
+			   *cfg, unsigned int fsr)
+{
+	u32 fsynr0;
+	void __iomem *cb_base = ARM_SMMU_CB(smmu, cfg->cbndx);
+	void __iomem *gr1_base = ARM_SMMU_GR1(smmu);
+	bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
+
+	fsynr0 = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0);
+
+	dev_err(smmu->dev, "FAR    = 0x%016llx\n",
+		readq_relaxed(cb_base + ARM_SMMU_CB_FAR));
+	dev_err(smmu->dev, "PAR    = 0x%pK\n",
+		readq_relaxed(cb_base + ARM_SMMU_CB_PAR));
+
+	dev_err(smmu->dev,
+		"FSR    = 0x%08x [%s%s%s%s%s%s%s%s%s%s]\n",
+		fsr,
+		(fsr & 0x02) ?  (fsynr0 & 0x10 ?
+				 "TF W " : "TF R ") : "",
+		(fsr & 0x04) ? "AFF " : "",
+		(fsr & 0x08) ? (fsynr0 & 0x10 ?
+				"PF W " : "PF R ") : "",
+		(fsr & 0x10) ? "EF " : "",
+		(fsr & 0x20) ? "TLBMCF " : "",
+		(fsr & 0x40) ? "TLBLKF " : "",
+		(fsr & 0x80) ? "MHF " : "",
+		(fsr & 0x100) ? "UUT " : "",
+		(fsr & 0x40000000) ? "SS " : "",
+		(fsr & 0x80000000) ? "MULTI " : "");
+
+	if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
+		dev_err(smmu->dev, "TTBR0  = 0x%pK\n",
+			readl_relaxed(cb_base + ARM_SMMU_CB_TTBR0));
+		dev_err(smmu->dev, "TTBR1  = 0x%pK\n",
+			readl_relaxed(cb_base + ARM_SMMU_CB_TTBR1));
+	} else {
+		dev_err(smmu->dev, "TTBR0  = 0x%pK\n",
+			readq_relaxed(cb_base + ARM_SMMU_CB_TTBR0));
+		if (stage1)
+			dev_err(smmu->dev, "TTBR1  = 0x%pK\n",
+				readq_relaxed(cb_base + ARM_SMMU_CB_TTBR1));
+	}
+
+
+	dev_err(smmu->dev, "SCTLR  = 0x%08x ACTLR  = 0x%08x\n",
+	       readl_relaxed(cb_base + ARM_SMMU_CB_SCTLR),
+	       readl_relaxed(cb_base + ARM_SMMU_CB_ACTLR));
+	dev_err(smmu->dev, "CBAR  = 0x%08x\n",
+	       readl_relaxed(gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx)));
+	dev_err(smmu->dev, "MAIR0   = 0x%08x MAIR1   = 0x%08x\n",
+	       readl_relaxed(cb_base + ARM_SMMU_CB_S1_MAIR0),
+	       readl_relaxed(cb_base + ARM_SMMU_CB_S1_MAIR1));
+
+}
+
 static phys_addr_t arm_smmu_verify_fault(struct iommu_domain *domain,
 					 dma_addr_t iova, u32 fsr)
 {
@@ -1493,29 +1553,16 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
 		ret = IRQ_HANDLED;
 		resume = RESUME_TERMINATE;
 	} else {
-		phys_addr_t phys_atos = arm_smmu_verify_fault(domain, iova,
-							      fsr);
 		if (__ratelimit(&_rs)) {
+			phys_addr_t phys_atos;
+
+			print_ctx_regs(smmu, cfg, fsr);
+			phys_atos = arm_smmu_verify_fault(domain, iova, fsr);
 			dev_err(smmu->dev,
 				"Unhandled context fault: iova=0x%08lx, cb=%d, fsr=0x%x, fsynr0=0x%x, fsynr1=0x%x\n",
 				iova, cfg->cbndx, fsr, fsynr0, fsynr1);
-			dev_err(smmu->dev, "FAR    = %016lx\n",
-				(unsigned long)iova);
-			dev_err(smmu->dev,
-				"FSR    = %08x [%s%s%s%s%s%s%s%s%s%s]\n",
-				fsr,
-				(fsr & 0x02) ?  (fsynr0 & 0x10 ?
-						"TF W " : "TF R ") : "",
-				(fsr & 0x04) ? "AFF " : "",
-				(fsr & 0x08) ? (fsynr0 & 0x10 ?
-						"PF W " : "PF R ") : "",
-				(fsr & 0x10) ? "EF " : "",
-				(fsr & 0x20) ? "TLBMCF " : "",
-				(fsr & 0x40) ? "TLBLKF " : "",
-				(fsr & 0x80) ? "MHF " : "",
-				(fsr & 0x100) ? "UUT " : "",
-				(fsr & 0x40000000) ? "SS " : "",
-				(fsr & 0x80000000) ? "MULTI " : "");
+
+
 			dev_err(smmu->dev,
 				"soft iova-to-phys=%pa\n", &phys_soft);
 			if (!phys_soft)
@@ -1800,7 +1847,7 @@ static int arm_smmu_init_asid(struct iommu_domain *domain,
 	bool dynamic = is_dynamic_domain(domain);
 	int ret;
 
-	if (!dynamic) {
+	if (!dynamic || (smmu->options & ARM_SMMU_OPT_NO_DYNAMIC_ASID)) {
 		cfg->asid = cfg->cbndx + 1;
 	} else {
 		mutex_lock(&smmu->idr_mutex);
@@ -2789,7 +2836,7 @@ static uint64_t arm_smmu_iova_to_pte(struct iommu_domain *domain,
 	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 	struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops;
 
-	if (!ops)
+	if (!ops || !ops->iova_to_pte)
 		return 0;
 
 	spin_lock_irqsave(&smmu_domain->cb_lock, flags);
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index e86c1c8..802ba7b 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2093,7 +2093,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
 	 * than default.  Unnecessary for PT mode.
 	 */
 	if (translation != CONTEXT_TT_PASS_THROUGH) {
-		for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
+		for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
 			ret = -ENOMEM;
 			pgd = phys_to_virt(dma_pte_addr(pgd));
 			if (!dma_pte_present(pgd))
@@ -2107,7 +2107,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
 			translation = CONTEXT_TT_MULTI_LEVEL;
 
 		context_set_address_root(context, virt_to_phys(pgd));
-		context_set_address_width(context, iommu->agaw);
+		context_set_address_width(context, agaw);
 	} else {
 		/*
 		 * In pass through mode, AW must be programmed to
@@ -5210,7 +5210,7 @@ static void intel_iommu_put_resv_regions(struct device *dev,
 	struct iommu_resv_region *entry, *next;
 
 	list_for_each_entry_safe(entry, next, head, list) {
-		if (entry->type == IOMMU_RESV_RESERVED)
+		if (entry->type == IOMMU_RESV_MSI)
 			kfree(entry);
 	}
 }
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 51514f5..8ee9115 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -289,7 +289,6 @@ static void iopte_tblcnt_add(arm_lpae_iopte *table_ptep, int cnt)
 }
 
 static bool selftest_running = false;
-static bool suppress_map_failures;
 
 static dma_addr_t __arm_lpae_dma_addr(void *pages)
 {
@@ -404,7 +403,7 @@ static int arm_lpae_init_pte(struct arm_lpae_io_pgtable *data,
 
 	/* We require an unmap first */
 	if (pte & ARM_LPAE_PTE_VALID) {
-		BUG_ON(!suppress_map_failures);
+		WARN_RATELIMIT(1, "map without unmap\n");
 		return -EEXIST;
 	}
 
@@ -1416,7 +1415,6 @@ static void __init arm_lpae_dump_ops(struct io_pgtable_ops *ops)
 #define __FAIL(ops, i)	({						\
 		WARN(1, "selftest: test failed for fmt idx %d\n", (i));	\
 		arm_lpae_dump_ops(ops);					\
-		suppress_map_failures = false;				\
 		selftest_running = false;				\
 		-EFAULT;						\
 })
@@ -1503,12 +1501,10 @@ static int __init arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
 							    IOMMU_CACHE))
 				return __FAIL(ops, i);
 
-			suppress_map_failures = true;
 			/* Overlapping mappings */
 			if (!ops->map(ops, iova, iova + size, size,
 				      IOMMU_READ | IOMMU_NOEXEC))
 				return __FAIL(ops, i);
-			suppress_map_failures = false;
 
 			if (!arm_lpae_range_has_specific_mapping(ops, iova,
 								 iova, size))
@@ -1657,7 +1653,6 @@ static int __init arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
 	}
 
 	selftest_running = false;
-	suppress_map_failures = false;
 	return 0;
 }
 
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index de6f714..a4b35c3 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -1495,7 +1495,7 @@ static ssize_t iommu_debug_test_virt_addr_read(struct file *file,
 	else
 		snprintf(buf, buf_len, "0x%pK\n", test_virt_addr);
 
-	buflen = min(count, strlen(buf)+1);
+	buflen = min(count, strlen(buf));
 	if (copy_to_user(ubuf, buf, buflen)) {
 		pr_err_ratelimited("Couldn't copy_to_user\n");
 		retval = -EFAULT;
@@ -1624,7 +1624,7 @@ static ssize_t iommu_debug_pte_read(struct file *file, char __user *ubuf,
 	else
 		snprintf(buf, sizeof(buf), "pte=%016llx\n", pte);
 
-	buflen = min(count, strlen(buf)+1);
+	buflen = min(count, strlen(buf));
 	if (copy_to_user(ubuf, buf, buflen)) {
 		pr_err_ratelimited("Couldn't copy_to_user\n");
 		retval = -EFAULT;
@@ -1698,7 +1698,7 @@ static ssize_t iommu_debug_atos_read(struct file *file, char __user *ubuf,
 		snprintf(buf, 100, "%pa\n", &phys);
 	}
 
-	buflen = min(count, strlen(buf)+1);
+	buflen = min(count, strlen(buf));
 	if (copy_to_user(ubuf, buf, buflen)) {
 		pr_err_ratelimited("Couldn't copy_to_user\n");
 		retval = -EFAULT;
@@ -1757,7 +1757,7 @@ static ssize_t iommu_debug_dma_atos_read(struct file *file, char __user *ubuf,
 	else
 		snprintf(buf, sizeof(buf), "%pa\n", &phys);
 
-	buflen = min(count, strlen(buf)+1);
+	buflen = min(count, strlen(buf));
 	if (copy_to_user(ubuf, buf, buflen)) {
 		pr_err_ratelimited("Couldn't copy_to_user\n");
 		retval = -EFAULT;
@@ -1999,7 +1999,7 @@ static ssize_t iommu_debug_dma_map_read(struct file *file, char __user *ubuf,
 	iova = ddev->iova;
 	snprintf(buf, sizeof(buf), "%pa\n", &iova);
 
-	buflen = min(count, strlen(buf)+1);
+	buflen = min(count, strlen(buf));
 	if (copy_to_user(ubuf, buf, buflen)) {
 		pr_err_ratelimited("Couldn't copy_to_user\n");
 		retval = -EFAULT;
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 2ea39a8..d8ecc90 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -87,9 +87,14 @@ struct its_baser {
  * The ITS structure - contains most of the infrastructure, with the
  * top-level MSI domain, the command queue, the collections, and the
  * list of devices writing to it.
+ *
+ * dev_alloc_lock has to be taken for device allocations, while the
+ * spinlock must be taken to parse data structures such as the device
+ * list.
  */
 struct its_node {
 	raw_spinlock_t		lock;
+	struct mutex		dev_alloc_lock;
 	struct list_head	entry;
 	void __iomem		*base;
 	phys_addr_t		phys_base;
@@ -138,6 +143,7 @@ struct its_device {
 	void			*itt;
 	u32			nr_ites;
 	u32			device_id;
+	bool			shared;
 };
 
 static struct {
@@ -2086,13 +2092,14 @@ static void its_free_device(struct its_device *its_dev)
 	kfree(its_dev);
 }
 
-static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
+static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number_t *hwirq)
 {
 	int idx;
 
-	idx = find_first_zero_bit(dev->event_map.lpi_map,
-				  dev->event_map.nr_lpis);
-	if (idx == dev->event_map.nr_lpis)
+	idx = bitmap_find_free_region(dev->event_map.lpi_map,
+				      dev->event_map.nr_lpis,
+				      get_count_order(nvecs));
+	if (idx < 0)
 		return -ENOSPC;
 
 	*hwirq = dev->event_map.lpi_base + idx;
@@ -2108,6 +2115,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
 	struct its_device *its_dev;
 	struct msi_domain_info *msi_info;
 	u32 dev_id;
+	int err = 0;
 
 	/*
 	 * We ignore "dev" entierely, and rely on the dev_id that has
@@ -2130,6 +2138,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
 		return -EINVAL;
 	}
 
+	mutex_lock(&its->dev_alloc_lock);
 	its_dev = its_find_device(its, dev_id);
 	if (its_dev) {
 		/*
@@ -2137,18 +2146,22 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
 		 * another alias (PCI bridge of some sort). No need to
 		 * create the device.
 		 */
+		its_dev->shared = true;
 		pr_debug("Reusing ITT for devID %x\n", dev_id);
 		goto out;
 	}
 
 	its_dev = its_create_device(its, dev_id, nvec, true);
-	if (!its_dev)
-		return -ENOMEM;
+	if (!its_dev) {
+		err = -ENOMEM;
+		goto out;
+	}
 
 	pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec));
 out:
+	mutex_unlock(&its->dev_alloc_lock);
 	info->scratchpad[0].ptr = its_dev;
-	return 0;
+	return err;
 }
 
 static struct msi_domain_ops its_msi_domain_ops = {
@@ -2188,21 +2201,21 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	int err;
 	int i;
 
-	for (i = 0; i < nr_irqs; i++) {
-		err = its_alloc_device_irq(its_dev, &hwirq);
-		if (err)
-			return err;
+	err = its_alloc_device_irq(its_dev, nr_irqs, &hwirq);
+	if (err)
+		return err;
 
-		err = its_irq_gic_domain_alloc(domain, virq + i, hwirq);
+	for (i = 0; i < nr_irqs; i++) {
+		err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
 		if (err)
 			return err;
 
 		irq_domain_set_hwirq_and_chip(domain, virq + i,
-					      hwirq, &its_irq_chip, its_dev);
+					      hwirq + i, &its_irq_chip, its_dev);
 		irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i)));
 		pr_debug("ID:%d pID:%d vID:%d\n",
-			 (int)(hwirq - its_dev->event_map.lpi_base),
-			 (int) hwirq, virq + i);
+			 (int)(hwirq + i - its_dev->event_map.lpi_base),
+			 (int)(hwirq + i), virq + i);
 	}
 
 	return 0;
@@ -2251,6 +2264,7 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 {
 	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+	struct its_node *its = its_dev->its;
 	int i;
 
 	for (i = 0; i < nr_irqs; i++) {
@@ -2265,8 +2279,14 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 		irq_domain_reset_irq_data(data);
 	}
 
-	/* If all interrupts have been freed, start mopping the floor */
-	if (bitmap_empty(its_dev->event_map.lpi_map,
+	mutex_lock(&its->dev_alloc_lock);
+
+	/*
+	 * If all interrupts have been freed, start mopping the
+	 * floor. This is conditionned on the device not being shared.
+	 */
+	if (!its_dev->shared &&
+	    bitmap_empty(its_dev->event_map.lpi_map,
 			 its_dev->event_map.nr_lpis)) {
 		its_lpi_free_chunks(its_dev->event_map.lpi_map,
 				    its_dev->event_map.lpi_base,
@@ -2278,6 +2298,8 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 		its_free_device(its_dev);
 	}
 
+	mutex_unlock(&its->dev_alloc_lock);
+
 	irq_domain_free_irqs_parent(domain, virq, nr_irqs);
 }
 
@@ -2965,6 +2987,7 @@ static int __init its_probe_one(struct resource *res,
 	}
 
 	raw_spin_lock_init(&its->lock);
+	mutex_init(&its->dev_alloc_lock);
 	INIT_LIST_HEAD(&its->entry);
 	INIT_LIST_HEAD(&its->its_device_list);
 	typer = gic_read_typer(its_base + GITS_TYPER);
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index d557e46..7a32be2 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -41,6 +41,7 @@
 #include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/msm_rtb.h>
 
 #include <asm/cputype.h>
 #include <asm/irq.h>
@@ -365,6 +366,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 				writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
 			isb();
 			handle_domain_irq(gic->domain, irqnr, regs);
+			uncached_logk(LOGK_IRQ, (void *)(uintptr_t)irqnr);
 			continue;
 		}
 		if (irqnr < 16) {
@@ -382,6 +384,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 			smp_rmb();
 			handle_IPI(irqnr, regs);
 #endif
+			uncached_logk(LOGK_IRQ, (void *)(uintptr_t)irqnr);
 			continue;
 		}
 		break;
diff --git a/drivers/irqchip/qcom/mpm-trinket.c b/drivers/irqchip/qcom/mpm-trinket.c
index 0789d9b..ae496d6 100644
--- a/drivers/irqchip/qcom/mpm-trinket.c
+++ b/drivers/irqchip/qcom/mpm-trinket.c
@@ -17,8 +17,8 @@ const struct mpm_pin mpm_trinket_gic_chip_data[] = {
 	{2, 222},
 	{12, 454}, /* b3_lfps_rxterm_irq */
 	{86, 215}, /* mpm_wake,spmi_m */
-	{90, 286}, /* eud_p0_dpse_int_mx */
-	{91, 286}, /* eud_p0_dmse_int_mx */
+	{90, 292}, /* eud_p0_dpse_int_mx */
+	{91, 292}, /* eud_p0_dmse_int_mx */
 	{-1},
 };
 
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index b1833d0..40a099f 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -423,7 +423,7 @@ void b1_parse_version(avmctrl_info *cinfo)
 	int i, j;
 
 	for (j = 0; j < AVM_MAXVERSION; j++)
-		cinfo->version[j] = "\0\0" + 1;
+		cinfo->version[j] = "";
 	for (i = 0, j = 0;
 	     j < AVM_MAXVERSION && i < cinfo->versionlen;
 	     j++, i += cinfo->versionbuf[i] + 1)
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index f9ca35c..b42d27a 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -1169,11 +1169,13 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
 		if (cs->debug & L1_DEB_LAPD)
 			debugl1(cs, "-> PH_REQUEST_PULL");
 #endif
+		spin_lock_irqsave(&cs->lock, flags);
 		if (!cs->tx_skb) {
 			test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 		} else
 			test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+		spin_unlock_irqrestore(&cs->lock, flags);
 		break;
 	case (HW_RESET | REQUEST):
 		spin_lock_irqsave(&cs->lock, flags);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index d30130c..b107452 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1456,15 +1456,19 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
 	modem_info *info = (modem_info *) tty->driver_data;
 
+	mutex_lock(&modem_info_mutex);
 	if (!old_termios)
 		isdn_tty_change_speed(info);
 	else {
 		if (tty->termios.c_cflag == old_termios->c_cflag &&
 		    tty->termios.c_ispeed == old_termios->c_ispeed &&
-		    tty->termios.c_ospeed == old_termios->c_ospeed)
+		    tty->termios.c_ospeed == old_termios->c_ospeed) {
+			mutex_unlock(&modem_info_mutex);
 			return;
+		}
 		isdn_tty_change_speed(info);
 	}
+	mutex_unlock(&modem_info_mutex);
 }
 
 /*
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c
index b1e135f..7f42fb6 100644
--- a/drivers/isdn/mISDN/timerdev.c
+++ b/drivers/isdn/mISDN/timerdev.c
@@ -170,8 +170,8 @@ dev_expire_timer(unsigned long data)
 	spin_lock_irqsave(&timer->dev->lock, flags);
 	if (timer->id >= 0)
 		list_move_tail(&timer->list, &timer->dev->expired);
-	spin_unlock_irqrestore(&timer->dev->lock, flags);
 	wake_up_interruptible(&timer->dev->wait);
+	spin_unlock_irqrestore(&timer->dev->lock, flags);
 }
 
 static int
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 924e50a..13838d7 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -318,7 +318,9 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
 
 	/* Let the programs run for couple of ms and check the engine status */
 	usleep_range(3000, 6000);
-	lp55xx_read(chip, LP5523_REG_STATUS, &status);
+	ret = lp55xx_read(chip, LP5523_REG_STATUS, &status);
+	if (ret)
+		return ret;
 	status &= LP5523_ENG_STATUS_MASK;
 
 	if (status != LP5523_ENG_STATUS_MASK) {
diff --git a/drivers/leds/leds-qti-tri-led.c b/drivers/leds/leds-qti-tri-led.c
index 8090b62..b1d9319 100644
--- a/drivers/leds/leds-qti-tri-led.c
+++ b/drivers/leds/leds-qti-tri-led.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
@@ -378,6 +378,8 @@ static ssize_t breath_store(struct device *dev, struct device_attribute *attr,
 	if (rc < 0)
 		return rc;
 
+	cancel_work_sync(&led_cdev->set_brightness_work);
+
 	mutex_lock(&led->lock);
 	if (led->breathing == breath)
 		goto unlock;
diff --git a/drivers/mailbox/qcom-rpmh-mailbox.c b/drivers/mailbox/qcom-rpmh-mailbox.c
index 98d92f3..3c11aa9 100644
--- a/drivers/mailbox/qcom-rpmh-mailbox.c
+++ b/drivers/mailbox/qcom-rpmh-mailbox.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
@@ -404,7 +404,7 @@ static inline void send_tcs_response(struct tcs_response *resp)
 	list_add_tail(&resp->list, &drv->response_pending);
 	spin_unlock_irqrestore(&drv->drv_lock, flags);
 
-	tasklet_schedule(&drv->tasklet);
+	tasklet_hi_schedule(&drv->tasklet);
 }
 
 static inline void enable_tcs_irq(struct rsc_drv *drv, int m, bool enable)
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index eedbb31..0ba0a5b 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -49,7 +49,7 @@ struct convert_context {
 	struct bio *bio_out;
 	struct bvec_iter iter_in;
 	struct bvec_iter iter_out;
-	sector_t cc_sector;
+	u64 cc_sector;
 	atomic_t cc_pending;
 	union {
 		struct skcipher_request *req;
@@ -81,7 +81,7 @@ struct dm_crypt_request {
 	struct convert_context *ctx;
 	struct scatterlist sg_in[4];
 	struct scatterlist sg_out[4];
-	sector_t iv_sector;
+	u64 iv_sector;
 };
 
 struct crypt_config;
@@ -173,7 +173,7 @@ struct crypt_config {
 		struct iv_lmk_private lmk;
 		struct iv_tcw_private tcw;
 	} iv_gen_private;
-	sector_t iv_offset;
+	u64 iv_offset;
 	unsigned int iv_size;
 	unsigned short int sector_size;
 	unsigned char sector_shift;
@@ -936,7 +936,7 @@ static int dm_crypt_integrity_io_alloc(struct dm_crypt_io *io, struct bio *bio)
 	if (IS_ERR(bip))
 		return PTR_ERR(bip);
 
-	tag_len = io->cc->on_disk_tag_size * bio_sectors(bio);
+	tag_len = io->cc->on_disk_tag_size * (bio_sectors(bio) >> io->cc->sector_shift);
 
 	bip->bip_iter.bi_size = tag_len;
 	bip->bip_iter.bi_sector = io->cc->start + io->sector;
@@ -2414,9 +2414,21 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key
 	 * capi:cipher_api_spec-iv:ivopts
 	 */
 	tmp = &cipher_in[strlen("capi:")];
-	cipher_api = strsep(&tmp, "-");
-	*ivmode = strsep(&tmp, ":");
-	*ivopts = tmp;
+
+	/* Separate IV options if present, it can contain another '-' in hash name */
+	*ivopts = strrchr(tmp, ':');
+	if (*ivopts) {
+		**ivopts = '\0';
+		(*ivopts)++;
+	}
+	/* Parse IV mode */
+	*ivmode = strrchr(tmp, '-');
+	if (*ivmode) {
+		**ivmode = '\0';
+		(*ivmode)++;
+	}
+	/* The rest is crypto API spec */
+	cipher_api = tmp;
 
 	if (*ivmode && !strcmp(*ivmode, "lmk"))
 		cc->tfms_count = 64;
@@ -2486,11 +2498,8 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key
 		goto bad_mem;
 
 	chainmode = strsep(&tmp, "-");
-	*ivopts = strsep(&tmp, "-");
-	*ivmode = strsep(&*ivopts, ":");
-
-	if (tmp)
-		DMWARN("Ignoring unexpected additional cipher options");
+	*ivmode = strsep(&tmp, ":");
+	*ivopts = tmp;
 
 	/*
 	 * For compatibility with the original dm-crypt mapping format, if
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index d4b3269..b9d1897 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -55,15 +55,17 @@ struct dm_kcopyd_client {
 	struct dm_kcopyd_throttle *throttle;
 
 /*
- * We maintain three lists of jobs:
+ * We maintain four lists of jobs:
  *
  * i)   jobs waiting for pages
  * ii)  jobs that have pages, and are waiting for the io to be issued.
- * iii) jobs that have completed.
+ * iii) jobs that don't need to do any IO and just run a callback
+ * iv) jobs that have completed.
  *
- * All three of these are protected by job_lock.
+ * All four of these are protected by job_lock.
  */
 	spinlock_t job_lock;
+	struct list_head callback_jobs;
 	struct list_head complete_jobs;
 	struct list_head io_jobs;
 	struct list_head pages_jobs;
@@ -622,6 +624,7 @@ static void do_work(struct work_struct *work)
 	struct dm_kcopyd_client *kc = container_of(work,
 					struct dm_kcopyd_client, kcopyd_work);
 	struct blk_plug plug;
+	unsigned long flags;
 
 	/*
 	 * The order that these are called is *very* important.
@@ -630,6 +633,10 @@ static void do_work(struct work_struct *work)
 	 * list.  io jobs call wake when they complete and it all
 	 * starts again.
 	 */
+	spin_lock_irqsave(&kc->job_lock, flags);
+	list_splice_tail_init(&kc->callback_jobs, &kc->complete_jobs);
+	spin_unlock_irqrestore(&kc->job_lock, flags);
+
 	blk_start_plug(&plug);
 	process_jobs(&kc->complete_jobs, kc, run_complete_job);
 	process_jobs(&kc->pages_jobs, kc, run_pages_job);
@@ -647,7 +654,7 @@ static void dispatch_job(struct kcopyd_job *job)
 	struct dm_kcopyd_client *kc = job->kc;
 	atomic_inc(&kc->nr_jobs);
 	if (unlikely(!job->source.count))
-		push(&kc->complete_jobs, job);
+		push(&kc->callback_jobs, job);
 	else if (job->pages == &zero_page_list)
 		push(&kc->io_jobs, job);
 	else
@@ -857,7 +864,7 @@ void dm_kcopyd_do_callback(void *j, int read_err, unsigned long write_err)
 	job->read_err = read_err;
 	job->write_err = write_err;
 
-	push(&kc->complete_jobs, job);
+	push(&kc->callback_jobs, job);
 	wake(kc);
 }
 EXPORT_SYMBOL(dm_kcopyd_do_callback);
@@ -887,6 +894,7 @@ struct dm_kcopyd_client *dm_kcopyd_client_create(struct dm_kcopyd_throttle *thro
 		return ERR_PTR(-ENOMEM);
 
 	spin_lock_init(&kc->job_lock);
+	INIT_LIST_HEAD(&kc->callback_jobs);
 	INIT_LIST_HEAD(&kc->complete_jobs);
 	INIT_LIST_HEAD(&kc->io_jobs);
 	INIT_LIST_HEAD(&kc->pages_jobs);
@@ -936,6 +944,7 @@ void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc)
 	/* Wait for completion of all jobs submitted by this client. */
 	wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
 
+	BUG_ON(!list_empty(&kc->callback_jobs));
 	BUG_ON(!list_empty(&kc->complete_jobs));
 	BUG_ON(!list_empty(&kc->io_jobs));
 	BUG_ON(!list_empty(&kc->pages_jobs));
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index a0613bd..b502deb 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -19,6 +19,7 @@
 #include <linux/vmalloc.h>
 #include <linux/log2.h>
 #include <linux/dm-kcopyd.h>
+#include <linux/semaphore.h>
 
 #include "dm.h"
 
@@ -105,6 +106,9 @@ struct dm_snapshot {
 	/* The on disk metadata handler */
 	struct dm_exception_store *store;
 
+	/* Maximum number of in-flight COW jobs. */
+	struct semaphore cow_count;
+
 	struct dm_kcopyd_client *kcopyd_client;
 
 	/* Wait for events based on state_bits */
@@ -145,6 +149,19 @@ struct dm_snapshot {
 #define RUNNING_MERGE          0
 #define SHUTDOWN_MERGE         1
 
+/*
+ * Maximum number of chunks being copied on write.
+ *
+ * The value was decided experimentally as a trade-off between memory
+ * consumption, stalling the kernel's workqueues and maintaining a high enough
+ * throughput.
+ */
+#define DEFAULT_COW_THRESHOLD 2048
+
+static int cow_threshold = DEFAULT_COW_THRESHOLD;
+module_param_named(snapshot_cow_threshold, cow_threshold, int, 0644);
+MODULE_PARM_DESC(snapshot_cow_threshold, "Maximum number of chunks being copied on write");
+
 DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle,
 		"A percentage of time allocated for copy on write");
 
@@ -1189,6 +1206,8 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 		goto bad_hash_tables;
 	}
 
+	sema_init(&s->cow_count, (cow_threshold > 0) ? cow_threshold : INT_MAX);
+
 	s->kcopyd_client = dm_kcopyd_client_create(&dm_kcopyd_throttle);
 	if (IS_ERR(s->kcopyd_client)) {
 		r = PTR_ERR(s->kcopyd_client);
@@ -1560,6 +1579,7 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
 		}
 		list_add(&pe->out_of_order_entry, lh);
 	}
+	up(&s->cow_count);
 }
 
 /*
@@ -1583,6 +1603,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
 	dest.count = src.count;
 
 	/* Hand over to kcopyd */
+	down(&s->cow_count);
 	dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, copy_callback, pe);
 }
 
@@ -1602,6 +1623,7 @@ static void start_full_bio(struct dm_snap_pending_exception *pe,
 	pe->full_bio = bio;
 	pe->full_bio_end_io = bio->bi_end_io;
 
+	down(&s->cow_count);
 	callback_data = dm_kcopyd_prepare_callback(s->kcopyd_client,
 						   copy_callback, pe);
 
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 45ff8fd..b85a66f 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1687,7 +1687,7 @@ int dm_thin_remove_range(struct dm_thin_device *td,
 	return r;
 }
 
-int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
+int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
 {
 	int r;
 	uint32_t ref_count;
@@ -1695,7 +1695,7 @@ int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *resu
 	down_read(&pmd->root_lock);
 	r = dm_sm_get_count(pmd->data_sm, b, &ref_count);
 	if (!r)
-		*result = (ref_count != 0);
+		*result = (ref_count > 1);
 	up_read(&pmd->root_lock);
 
 	return r;
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
index 35e954e..f6be0d7 100644
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -195,7 +195,7 @@ int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
 
 int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
 
-int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
+int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
 
 int dm_pool_inc_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e);
 int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e);
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index da98fc7..18d6a8a 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -257,6 +257,7 @@ struct pool {
 
 	spinlock_t lock;
 	struct bio_list deferred_flush_bios;
+	struct bio_list deferred_flush_completions;
 	struct list_head prepared_mappings;
 	struct list_head prepared_discards;
 	struct list_head prepared_discards_pt2;
@@ -950,6 +951,39 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
 	mempool_free(m, m->tc->pool->mapping_pool);
 }
 
+static void complete_overwrite_bio(struct thin_c *tc, struct bio *bio)
+{
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	/*
+	 * If the bio has the REQ_FUA flag set we must commit the metadata
+	 * before signaling its completion.
+	 */
+	if (!bio_triggers_commit(tc, bio)) {
+		bio_endio(bio);
+		return;
+	}
+
+	/*
+	 * Complete bio with an error if earlier I/O caused changes to the
+	 * metadata that can't be committed, e.g, due to I/O errors on the
+	 * metadata device.
+	 */
+	if (dm_thin_aborted_changes(tc->td)) {
+		bio_io_error(bio);
+		return;
+	}
+
+	/*
+	 * Batch together any bios that trigger commits and then issue a
+	 * single commit for them in process_deferred_bios().
+	 */
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_add(&pool->deferred_flush_completions, bio);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
 static void process_prepared_mapping(struct dm_thin_new_mapping *m)
 {
 	struct thin_c *tc = m->tc;
@@ -982,7 +1016,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
 	 */
 	if (bio) {
 		inc_remap_and_issue_cell(tc, m->cell, m->data_block);
-		bio_endio(bio);
+		complete_overwrite_bio(tc, bio);
 	} else {
 		inc_all_io_entry(tc->pool, m->cell->holder);
 		remap_and_issue(tc, m->cell->holder, m->data_block);
@@ -1042,7 +1076,7 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
 	 * passdown we have to check that these blocks are now unused.
 	 */
 	int r = 0;
-	bool used = true;
+	bool shared = true;
 	struct thin_c *tc = m->tc;
 	struct pool *pool = tc->pool;
 	dm_block_t b = m->data_block, e, end = m->data_block + m->virt_end - m->virt_begin;
@@ -1052,11 +1086,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
 	while (b != end) {
 		/* find start of unmapped run */
 		for (; b < end; b++) {
-			r = dm_pool_block_is_used(pool->pmd, b, &used);
+			r = dm_pool_block_is_shared(pool->pmd, b, &shared);
 			if (r)
 				goto out;
 
-			if (!used)
+			if (!shared)
 				break;
 		}
 
@@ -1065,11 +1099,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
 
 		/* find end of run */
 		for (e = b + 1; e != end; e++) {
-			r = dm_pool_block_is_used(pool->pmd, e, &used);
+			r = dm_pool_block_is_shared(pool->pmd, e, &shared);
 			if (r)
 				goto out;
 
-			if (used)
+			if (shared)
 				break;
 		}
 
@@ -2328,7 +2362,7 @@ static void process_deferred_bios(struct pool *pool)
 {
 	unsigned long flags;
 	struct bio *bio;
-	struct bio_list bios;
+	struct bio_list bios, bio_completions;
 	struct thin_c *tc;
 
 	tc = get_first_thin(pool);
@@ -2339,26 +2373,36 @@ static void process_deferred_bios(struct pool *pool)
 	}
 
 	/*
-	 * If there are any deferred flush bios, we must commit
-	 * the metadata before issuing them.
+	 * If there are any deferred flush bios, we must commit the metadata
+	 * before issuing them or signaling their completion.
 	 */
 	bio_list_init(&bios);
+	bio_list_init(&bio_completions);
+
 	spin_lock_irqsave(&pool->lock, flags);
 	bio_list_merge(&bios, &pool->deferred_flush_bios);
 	bio_list_init(&pool->deferred_flush_bios);
+
+	bio_list_merge(&bio_completions, &pool->deferred_flush_completions);
+	bio_list_init(&pool->deferred_flush_completions);
 	spin_unlock_irqrestore(&pool->lock, flags);
 
-	if (bio_list_empty(&bios) &&
+	if (bio_list_empty(&bios) && bio_list_empty(&bio_completions) &&
 	    !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool)))
 		return;
 
 	if (commit(pool)) {
+		bio_list_merge(&bios, &bio_completions);
+
 		while ((bio = bio_list_pop(&bios)))
 			bio_io_error(bio);
 		return;
 	}
 	pool->last_commit_jiffies = jiffies;
 
+	while ((bio = bio_list_pop(&bio_completions)))
+		bio_endio(bio);
+
 	while ((bio = bio_list_pop(&bios)))
 		generic_make_request(bio);
 }
@@ -2965,6 +3009,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
 	INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout);
 	spin_lock_init(&pool->lock);
 	bio_list_init(&pool->deferred_flush_bios);
+	bio_list_init(&pool->deferred_flush_completions);
 	INIT_LIST_HEAD(&pool->prepared_mappings);
 	INIT_LIST_HEAD(&pool->prepared_discards);
 	INIT_LIST_HEAD(&pool->prepared_discards_pt2);
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index 0227c46..1943395 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -140,10 +140,26 @@ static int verity_hash_update(struct dm_verity *v, struct ahash_request *req,
 {
 	struct scatterlist sg;
 
-	sg_init_one(&sg, data, len);
-	ahash_request_set_crypt(req, &sg, NULL, len);
-
-	return verity_complete_op(res, crypto_ahash_update(req));
+	if (likely(!is_vmalloc_addr(data))) {
+		sg_init_one(&sg, data, len);
+		ahash_request_set_crypt(req, &sg, NULL, len);
+		return verity_complete_op(res, crypto_ahash_update(req));
+	} else {
+		do {
+			int r;
+			size_t this_step = min_t(size_t, len, PAGE_SIZE - offset_in_page(data));
+			flush_kernel_vmap_range((void *)data, this_step);
+			sg_init_table(&sg, 1);
+			sg_set_page(&sg, vmalloc_to_page(data), this_step, offset_in_page(data));
+			ahash_request_set_crypt(req, &sg, NULL, this_step);
+			r = verity_complete_op(res, crypto_ahash_update(req));
+			if (unlikely(r))
+				return r;
+			data += this_step;
+			len -= this_step;
+		} while (len);
+		return 0;
+	}
 }
 
 /*
diff --git a/drivers/md/dm-zoned-target.c b/drivers/md/dm-zoned-target.c
index ba6b0a9..532bfce 100644
--- a/drivers/md/dm-zoned-target.c
+++ b/drivers/md/dm-zoned-target.c
@@ -20,7 +20,6 @@ struct dmz_bioctx {
 	struct dm_zone		*zone;
 	struct bio		*bio;
 	atomic_t		ref;
-	blk_status_t		status;
 };
 
 /*
@@ -78,65 +77,66 @@ static inline void dmz_bio_endio(struct bio *bio, blk_status_t status)
 {
 	struct dmz_bioctx *bioctx = dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
 
-	if (bioctx->status == BLK_STS_OK && status != BLK_STS_OK)
-		bioctx->status = status;
-	bio_endio(bio);
+	if (status != BLK_STS_OK && bio->bi_status == BLK_STS_OK)
+		bio->bi_status = status;
+
+	if (atomic_dec_and_test(&bioctx->ref)) {
+		struct dm_zone *zone = bioctx->zone;
+
+		if (zone) {
+			if (bio->bi_status != BLK_STS_OK &&
+			    bio_op(bio) == REQ_OP_WRITE &&
+			    dmz_is_seq(zone))
+				set_bit(DMZ_SEQ_WRITE_ERR, &zone->flags);
+			dmz_deactivate_zone(zone);
+		}
+		bio_endio(bio);
+	}
 }
 
 /*
- * Partial clone read BIO completion callback. This terminates the
+ * Completion callback for an internally cloned target BIO. This terminates the
  * target BIO when there are no more references to its context.
  */
-static void dmz_read_bio_end_io(struct bio *bio)
+static void dmz_clone_endio(struct bio *clone)
 {
-	struct dmz_bioctx *bioctx = bio->bi_private;
-	blk_status_t status = bio->bi_status;
+	struct dmz_bioctx *bioctx = clone->bi_private;
+	blk_status_t status = clone->bi_status;
 
-	bio_put(bio);
+	bio_put(clone);
 	dmz_bio_endio(bioctx->bio, status);
 }
 
 /*
- * Issue a BIO to a zone. The BIO may only partially process the
+ * Issue a clone of a target BIO. The clone may only partially process the
  * original target BIO.
  */
-static int dmz_submit_read_bio(struct dmz_target *dmz, struct dm_zone *zone,
-			       struct bio *bio, sector_t chunk_block,
-			       unsigned int nr_blocks)
+static int dmz_submit_bio(struct dmz_target *dmz, struct dm_zone *zone,
+			  struct bio *bio, sector_t chunk_block,
+			  unsigned int nr_blocks)
 {
 	struct dmz_bioctx *bioctx = dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
-	sector_t sector;
 	struct bio *clone;
 
-	/* BIO remap sector */
-	sector = dmz_start_sect(dmz->metadata, zone) + dmz_blk2sect(chunk_block);
-
-	/* If the read is not partial, there is no need to clone the BIO */
-	if (nr_blocks == dmz_bio_blocks(bio)) {
-		/* Setup and submit the BIO */
-		bio->bi_iter.bi_sector = sector;
-		atomic_inc(&bioctx->ref);
-		generic_make_request(bio);
-		return 0;
-	}
-
-	/* Partial BIO: we need to clone the BIO */
 	clone = bio_clone_fast(bio, GFP_NOIO, dmz->bio_set);
 	if (!clone)
 		return -ENOMEM;
 
-	/* Setup the clone */
-	clone->bi_iter.bi_sector = sector;
+	bio_set_dev(clone, dmz->dev->bdev);
+	clone->bi_iter.bi_sector =
+		dmz_start_sect(dmz->metadata, zone) + dmz_blk2sect(chunk_block);
 	clone->bi_iter.bi_size = dmz_blk2sect(nr_blocks) << SECTOR_SHIFT;
-	clone->bi_end_io = dmz_read_bio_end_io;
+	clone->bi_end_io = dmz_clone_endio;
 	clone->bi_private = bioctx;
 
 	bio_advance(bio, clone->bi_iter.bi_size);
 
-	/* Submit the clone */
 	atomic_inc(&bioctx->ref);
 	generic_make_request(clone);
 
+	if (bio_op(bio) == REQ_OP_WRITE && dmz_is_seq(zone))
+		zone->wp_block += nr_blocks;
+
 	return 0;
 }
 
@@ -214,7 +214,7 @@ static int dmz_handle_read(struct dmz_target *dmz, struct dm_zone *zone,
 		if (nr_blocks) {
 			/* Valid blocks found: read them */
 			nr_blocks = min_t(unsigned int, nr_blocks, end_block - chunk_block);
-			ret = dmz_submit_read_bio(dmz, rzone, bio, chunk_block, nr_blocks);
+			ret = dmz_submit_bio(dmz, rzone, bio, chunk_block, nr_blocks);
 			if (ret)
 				return ret;
 			chunk_block += nr_blocks;
@@ -229,25 +229,6 @@ static int dmz_handle_read(struct dmz_target *dmz, struct dm_zone *zone,
 }
 
 /*
- * Issue a write BIO to a zone.
- */
-static void dmz_submit_write_bio(struct dmz_target *dmz, struct dm_zone *zone,
-				 struct bio *bio, sector_t chunk_block,
-				 unsigned int nr_blocks)
-{
-	struct dmz_bioctx *bioctx = dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
-
-	/* Setup and submit the BIO */
-	bio_set_dev(bio, dmz->dev->bdev);
-	bio->bi_iter.bi_sector = dmz_start_sect(dmz->metadata, zone) + dmz_blk2sect(chunk_block);
-	atomic_inc(&bioctx->ref);
-	generic_make_request(bio);
-
-	if (dmz_is_seq(zone))
-		zone->wp_block += nr_blocks;
-}
-
-/*
  * Write blocks directly in a data zone, at the write pointer.
  * If a buffer zone is assigned, invalidate the blocks written
  * in place.
@@ -265,7 +246,9 @@ static int dmz_handle_direct_write(struct dmz_target *dmz,
 		return -EROFS;
 
 	/* Submit write */
-	dmz_submit_write_bio(dmz, zone, bio, chunk_block, nr_blocks);
+	ret = dmz_submit_bio(dmz, zone, bio, chunk_block, nr_blocks);
+	if (ret)
+		return ret;
 
 	/*
 	 * Validate the blocks in the data zone and invalidate
@@ -301,7 +284,9 @@ static int dmz_handle_buffered_write(struct dmz_target *dmz,
 		return -EROFS;
 
 	/* Submit write */
-	dmz_submit_write_bio(dmz, bzone, bio, chunk_block, nr_blocks);
+	ret = dmz_submit_bio(dmz, bzone, bio, chunk_block, nr_blocks);
+	if (ret)
+		return ret;
 
 	/*
 	 * Validate the blocks in the buffer zone
@@ -600,7 +585,6 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
 	bioctx->zone = NULL;
 	bioctx->bio = bio;
 	atomic_set(&bioctx->ref, 1);
-	bioctx->status = BLK_STS_OK;
 
 	/* Set the BIO pending in the flush list */
 	if (!nr_sectors && bio_op(bio) == REQ_OP_WRITE) {
@@ -624,35 +608,6 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
 }
 
 /*
- * Completed target BIO processing.
- */
-static int dmz_end_io(struct dm_target *ti, struct bio *bio, blk_status_t *error)
-{
-	struct dmz_bioctx *bioctx = dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
-
-	if (bioctx->status == BLK_STS_OK && *error)
-		bioctx->status = *error;
-
-	if (!atomic_dec_and_test(&bioctx->ref))
-		return DM_ENDIO_INCOMPLETE;
-
-	/* Done */
-	bio->bi_status = bioctx->status;
-
-	if (bioctx->zone) {
-		struct dm_zone *zone = bioctx->zone;
-
-		if (*error && bio_op(bio) == REQ_OP_WRITE) {
-			if (dmz_is_seq(zone))
-				set_bit(DMZ_SEQ_WRITE_ERR, &zone->flags);
-		}
-		dmz_deactivate_zone(zone);
-	}
-
-	return DM_ENDIO_DONE;
-}
-
-/*
  * Get zoned device information.
  */
 static int dmz_get_zoned_device(struct dm_target *ti, char *path)
@@ -946,7 +901,6 @@ static struct target_type dmz_type = {
 	.ctr		 = dmz_ctr,
 	.dtr		 = dmz_dtr,
 	.map		 = dmz_map,
-	.end_io		 = dmz_end_io,
 	.io_hints	 = dmz_io_hints,
 	.prepare_ioctl	 = dmz_prepare_ioctl,
 	.postsuspend	 = dmz_suspend,
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 205f86f..31c4391 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1854,6 +1854,20 @@ static void end_sync_read(struct bio *bio)
 		reschedule_retry(r1_bio);
 }
 
+static void abort_sync_write(struct mddev *mddev, struct r1bio *r1_bio)
+{
+	sector_t sync_blocks = 0;
+	sector_t s = r1_bio->sector;
+	long sectors_to_go = r1_bio->sectors;
+
+	/* make sure these bits don't get cleared. */
+	do {
+		bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
+		s += sync_blocks;
+		sectors_to_go -= sync_blocks;
+	} while (sectors_to_go > 0);
+}
+
 static void end_sync_write(struct bio *bio)
 {
 	int uptodate = !bio->bi_status;
@@ -1865,16 +1879,7 @@ static void end_sync_write(struct bio *bio)
 	struct md_rdev *rdev = conf->mirrors[find_bio_disk(r1_bio, bio)].rdev;
 
 	if (!uptodate) {
-		sector_t sync_blocks = 0;
-		sector_t s = r1_bio->sector;
-		long sectors_to_go = r1_bio->sectors;
-		/* make sure these bits doesn't get cleared. */
-		do {
-			bitmap_end_sync(mddev->bitmap, s,
-					&sync_blocks, 1);
-			s += sync_blocks;
-			sectors_to_go -= sync_blocks;
-		} while (sectors_to_go > 0);
+		abort_sync_write(mddev, r1_bio);
 		set_bit(WriteErrorSeen, &rdev->flags);
 		if (!test_and_set_bit(WantReplacement, &rdev->flags))
 			set_bit(MD_RECOVERY_NEEDED, &
@@ -2164,8 +2169,10 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
 		     (i == r1_bio->read_disk ||
 		      !test_bit(MD_RECOVERY_SYNC, &mddev->recovery))))
 			continue;
-		if (test_bit(Faulty, &conf->mirrors[i].rdev->flags))
+		if (test_bit(Faulty, &conf->mirrors[i].rdev->flags)) {
+			abort_sync_write(mddev, r1_bio);
 			continue;
+		}
 
 		bio_set_op_attrs(wbio, REQ_OP_WRITE, 0);
 		if (test_bit(FailFast, &conf->mirrors[i].rdev->flags))
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index e786546..2ce079a 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1190,7 +1190,9 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
 		struct bio *split = bio_split(bio, max_sectors,
 					      gfp, conf->bio_split);
 		bio_chain(split, bio);
+		allow_barrier(conf);
 		generic_make_request(bio);
+		wait_barrier(conf);
 		bio = split;
 		r10_bio->master_bio = bio;
 		r10_bio->sectors = max_sectors;
@@ -1479,7 +1481,9 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
 		struct bio *split = bio_split(bio, r10_bio->sectors,
 					      GFP_NOIO, conf->bio_split);
 		bio_chain(split, bio);
+		allow_barrier(conf);
 		generic_make_request(bio);
+		wait_barrier(conf);
 		bio = split;
 		r10_bio->master_bio = bio;
 	}
@@ -4591,15 +4595,18 @@ static int handle_reshape_read_error(struct mddev *mddev,
 	/* Use sync reads to get the blocks from somewhere else */
 	int sectors = r10_bio->sectors;
 	struct r10conf *conf = mddev->private;
-	struct {
-		struct r10bio r10_bio;
-		struct r10dev devs[conf->copies];
-	} on_stack;
-	struct r10bio *r10b = &on_stack.r10_bio;
+	struct r10bio *r10b;
 	int slot = 0;
 	int idx = 0;
 	struct page **pages;
 
+	r10b = kmalloc(sizeof(*r10b) +
+	       sizeof(struct r10dev) * conf->copies, GFP_NOIO);
+	if (!r10b) {
+		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+		return -ENOMEM;
+	}
+
 	/* reshape IOs share pages from .devs[0].bio */
 	pages = get_resync_pages(r10_bio->devs[0].bio)->pages;
 
@@ -4648,11 +4655,13 @@ static int handle_reshape_read_error(struct mddev *mddev,
 			/* couldn't read this block, must give up */
 			set_bit(MD_RECOVERY_INTR,
 				&mddev->recovery);
+			kfree(r10b);
 			return -EIO;
 		}
 		sectors -= s;
 		idx++;
 	}
+	kfree(r10b);
 	return 0;
 }
 
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index 0d535b4..dcef761 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -1942,12 +1942,14 @@ r5l_recovery_replay_one_stripe(struct r5conf *conf,
 }
 
 static struct stripe_head *
-r5c_recovery_alloc_stripe(struct r5conf *conf,
-			  sector_t stripe_sect)
+r5c_recovery_alloc_stripe(
+		struct r5conf *conf,
+		sector_t stripe_sect,
+		int noblock)
 {
 	struct stripe_head *sh;
 
-	sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0);
+	sh = raid5_get_active_stripe(conf, stripe_sect, 0, noblock, 0);
 	if (!sh)
 		return NULL;  /* no more stripe available */
 
@@ -2157,7 +2159,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
 						stripe_sect);
 
 		if (!sh) {
-			sh = r5c_recovery_alloc_stripe(conf, stripe_sect);
+			sh = r5c_recovery_alloc_stripe(conf, stripe_sect, 1);
 			/*
 			 * cannot get stripe from raid5_get_active_stripe
 			 * try replay some stripes
@@ -2166,20 +2168,29 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
 				r5c_recovery_replay_stripes(
 					cached_stripe_list, ctx);
 				sh = r5c_recovery_alloc_stripe(
-					conf, stripe_sect);
+					conf, stripe_sect, 1);
 			}
 			if (!sh) {
+				int new_size = conf->min_nr_stripes * 2;
 				pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n",
 					mdname(mddev),
-					conf->min_nr_stripes * 2);
-				raid5_set_cache_size(mddev,
-						     conf->min_nr_stripes * 2);
-				sh = r5c_recovery_alloc_stripe(conf,
-							       stripe_sect);
+					new_size);
+				ret = raid5_set_cache_size(mddev, new_size);
+				if (conf->min_nr_stripes <= new_size / 2) {
+					pr_err("md/raid:%s: Cannot increase cache size, ret=%d, new_size=%d, min_nr_stripes=%d, max_nr_stripes=%d\n",
+						mdname(mddev),
+						ret,
+						new_size,
+						conf->min_nr_stripes,
+						conf->max_nr_stripes);
+					return -ENOMEM;
+				}
+				sh = r5c_recovery_alloc_stripe(
+					conf, stripe_sect, 0);
 			}
 			if (!sh) {
 				pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
-				       mdname(mddev));
+					mdname(mddev));
 				return -ENOMEM;
 			}
 			list_add_tail(&sh->lru, cached_stripe_list);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index dbf51b4..7dbb74c 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -6336,6 +6336,7 @@ raid5_show_stripe_cache_size(struct mddev *mddev, char *page)
 int
 raid5_set_cache_size(struct mddev *mddev, int size)
 {
+	int result = 0;
 	struct r5conf *conf = mddev->private;
 
 	if (size <= 16 || size > 32768)
@@ -6352,11 +6353,14 @@ raid5_set_cache_size(struct mddev *mddev, int size)
 
 	mutex_lock(&conf->cache_size_mutex);
 	while (size > conf->max_nr_stripes)
-		if (!grow_one_stripe(conf, GFP_KERNEL))
+		if (!grow_one_stripe(conf, GFP_KERNEL)) {
+			conf->min_nr_stripes = conf->max_nr_stripes;
+			result = -ENOMEM;
 			break;
+		}
 	mutex_unlock(&conf->cache_size_mutex);
 
-	return 0;
+	return result;
 }
 EXPORT_SYMBOL(raid5_set_cache_size);
 
diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c
index 5bde6c2..b243e4a 100644
--- a/drivers/media/firewire/firedtv-avc.c
+++ b/drivers/media/firewire/firedtv-avc.c
@@ -968,7 +968,8 @@ static int get_ca_object_length(struct avc_response_frame *r)
 	return r->operand[7];
 }
 
-int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
+int avc_ca_app_info(struct firedtv *fdtv, unsigned char *app_info,
+		    unsigned int *len)
 {
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 	struct avc_response_frame *r = (void *)fdtv->avc_data;
@@ -1009,7 +1010,8 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
 	return ret;
 }
 
-int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
+int avc_ca_info(struct firedtv *fdtv, unsigned char *app_info,
+		unsigned int *len)
 {
 	struct avc_command_frame *c = (void *)fdtv->avc_data;
 	struct avc_response_frame *r = (void *)fdtv->avc_data;
diff --git a/drivers/media/firewire/firedtv.h b/drivers/media/firewire/firedtv.h
index 345d1eda..5b18a08 100644
--- a/drivers/media/firewire/firedtv.h
+++ b/drivers/media/firewire/firedtv.h
@@ -124,8 +124,10 @@ int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
 		    struct dvb_diseqc_master_cmd *diseqcmd);
 void avc_remote_ctrl_work(struct work_struct *work);
 int avc_register_remote_control(struct firedtv *fdtv);
-int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
-int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
+int avc_ca_app_info(struct firedtv *fdtv, unsigned char *app_info,
+		    unsigned int *len);
+int avc_ca_info(struct firedtv *fdtv, unsigned char *app_info,
+		unsigned int *len);
 int avc_ca_reset(struct firedtv *fdtv);
 int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
 int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
index a056d6c..f0b200a 100644
--- a/drivers/media/i2c/ad9389b.c
+++ b/drivers/media/i2c/ad9389b.c
@@ -590,7 +590,7 @@ static const struct v4l2_dv_timings_cap ad9389b_timings_cap = {
 	.type = V4L2_DV_BT_656_1120,
 	/* keep this initialization for compatibility with GCC < 4.4.6 */
 	.reserved = { 0 },
-	V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000,
+	V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1200, 25000000, 170000000,
 		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
 		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index 2817baf..80c2040 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -142,7 +142,7 @@ static const struct v4l2_dv_timings_cap adv7511_timings_cap = {
 	.type = V4L2_DV_BT_656_1120,
 	/* keep this initialization for compatibility with GCC < 4.4.6 */
 	.reserved = { 0 },
-	V4L2_INIT_BT_TIMINGS(0, ADV7511_MAX_WIDTH, 0, ADV7511_MAX_HEIGHT,
+	V4L2_INIT_BT_TIMINGS(640, ADV7511_MAX_WIDTH, 350, ADV7511_MAX_HEIGHT,
 		ADV7511_MIN_PIXELCLOCK, ADV7511_MAX_PIXELCLOCK,
 		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index f289b8a..d2108aa 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -778,7 +778,7 @@ static const struct v4l2_dv_timings_cap adv7604_timings_cap_analog = {
 	.type = V4L2_DV_BT_656_1120,
 	/* keep this initialization for compatibility with GCC < 4.4.6 */
 	.reserved = { 0 },
-	V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000,
+	V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1200, 25000000, 170000000,
 		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
 		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
@@ -789,7 +789,7 @@ static const struct v4l2_dv_timings_cap adv76xx_timings_cap_digital = {
 	.type = V4L2_DV_BT_656_1120,
 	/* keep this initialization for compatibility with GCC < 4.4.6 */
 	.reserved = { 0 },
-	V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 225000000,
+	V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1200, 25000000, 225000000,
 		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
 		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 65f34e7..f9c2317 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -676,7 +676,7 @@ static const struct v4l2_dv_timings_cap adv7842_timings_cap_analog = {
 	.type = V4L2_DV_BT_656_1120,
 	/* keep this initialization for compatibility with GCC < 4.4.6 */
 	.reserved = { 0 },
-	V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000,
+	V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1200, 25000000, 170000000,
 		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
 		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
@@ -687,7 +687,7 @@ static const struct v4l2_dv_timings_cap adv7842_timings_cap_digital = {
 	.type = V4L2_DV_BT_656_1120,
 	/* keep this initialization for compatibility with GCC < 4.4.6 */
 	.reserved = { 0 },
-	V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 225000000,
+	V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1200, 25000000, 225000000,
 		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
 		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
index e6f5c36..c9647e2 100644
--- a/drivers/media/i2c/tc358743.c
+++ b/drivers/media/i2c/tc358743.c
@@ -70,7 +70,7 @@ static const struct v4l2_dv_timings_cap tc358743_timings_cap = {
 	/* keep this initialization for compatibility with GCC < 4.4.6 */
 	.reserved = { 0 },
 	/* Pixel clock from REF_01 p. 20. Min/max height/width are unknown */
-	V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 165000000,
+	V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1200, 13000000, 165000000,
 			V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
 			V4L2_DV_BT_CAP_PROGRESSIVE |
diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c
index 498ad23..f5ee280 100644
--- a/drivers/media/i2c/ths8200.c
+++ b/drivers/media/i2c/ths8200.c
@@ -49,7 +49,7 @@ static const struct v4l2_dv_timings_cap ths8200_timings_cap = {
 	.type = V4L2_DV_BT_656_1120,
 	/* keep this initialization for compatibility with GCC < 4.4.6 */
 	.reserved = { 0 },
-	V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1080, 25000000, 148500000,
+	V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1080, 25000000, 148500000,
 		V4L2_DV_BT_STD_CEA861, V4L2_DV_BT_CAP_PROGRESSIVE)
 };
 
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index 291c409..3457a5f 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -953,16 +953,15 @@ static int coda_start_encoding(struct coda_ctx *ctx)
 		else
 			coda_write(dev, CODA_STD_H264,
 				   CODA_CMD_ENC_SEQ_COD_STD);
-		if (ctx->params.h264_deblk_enabled) {
-			value = ((ctx->params.h264_deblk_alpha &
-				  CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) <<
-				 CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) |
-				((ctx->params.h264_deblk_beta &
-				  CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) <<
-				 CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET);
-		} else {
-			value = 1 << CODA_264PARAM_DISABLEDEBLK_OFFSET;
-		}
+		value = ((ctx->params.h264_disable_deblocking_filter_idc &
+			  CODA_264PARAM_DISABLEDEBLK_MASK) <<
+			 CODA_264PARAM_DISABLEDEBLK_OFFSET) |
+			((ctx->params.h264_slice_alpha_c0_offset_div2 &
+			  CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) <<
+			 CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) |
+			((ctx->params.h264_slice_beta_offset_div2 &
+			  CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) <<
+			 CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET);
 		coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA);
 		break;
 	case V4L2_PIX_FMT_JPEG:
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 99d138d..2e1472f 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -1675,14 +1675,13 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
 		ctx->params.h264_max_qp = ctrl->val;
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
-		ctx->params.h264_deblk_alpha = ctrl->val;
+		ctx->params.h264_slice_alpha_c0_offset_div2 = ctrl->val;
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
-		ctx->params.h264_deblk_beta = ctrl->val;
+		ctx->params.h264_slice_beta_offset_div2 = ctrl->val;
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
-		ctx->params.h264_deblk_enabled = (ctrl->val ==
-				V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
+		ctx->params.h264_disable_deblocking_filter_idc = ctrl->val;
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
 		/* TODO: switch between baseline and constrained baseline */
@@ -1764,13 +1763,13 @@ static void coda_encode_ctrls(struct coda_ctx *ctx)
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
 		V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 0, 51, 1, 51);
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, 0, 15, 1, 0);
+		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, -6, 6, 1, 0);
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, 0, 15, 1, 0);
+		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, -6, 6, 1, 0);
 	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
 		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
-		V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED, 0x0,
-		V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
+		V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY,
+		0x0, V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
 	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
 		V4L2_CID_MPEG_VIDEO_H264_PROFILE,
 		V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, 0x0,
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index c5f504d..389a882 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -114,9 +114,9 @@ struct coda_params {
 	u8			h264_inter_qp;
 	u8			h264_min_qp;
 	u8			h264_max_qp;
-	u8			h264_deblk_enabled;
-	u8			h264_deblk_alpha;
-	u8			h264_deblk_beta;
+	u8			h264_disable_deblocking_filter_idc;
+	s8			h264_slice_alpha_c0_offset_div2;
+	s8			h264_slice_beta_offset_div2;
 	u8			h264_profile_idc;
 	u8			h264_level_idc;
 	u8			mpeg4_intra_qp;
diff --git a/drivers/media/platform/coda/coda_regs.h b/drivers/media/platform/coda/coda_regs.h
index 38df5fd..546f576 100644
--- a/drivers/media/platform/coda/coda_regs.h
+++ b/drivers/media/platform/coda/coda_regs.h
@@ -292,7 +292,7 @@
 #define		CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET	8
 #define		CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK	0x0f
 #define		CODA_264PARAM_DISABLEDEBLK_OFFSET		6
-#define		CODA_264PARAM_DISABLEDEBLK_MASK		0x01
+#define		CODA_264PARAM_DISABLEDEBLK_MASK		0x03
 #define		CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET	5
 #define		CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_MASK	0x01
 #define		CODA_264PARAM_CHROMAQPOFFSET_OFFSET		0
diff --git a/drivers/media/platform/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c
index 7f64625..1d3c13e 100644
--- a/drivers/media/platform/davinci/vpbe.c
+++ b/drivers/media/platform/davinci/vpbe.c
@@ -739,7 +739,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
 	if (ret) {
 		v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default output %s",
 			 def_output);
-		return ret;
+		goto fail_kfree_amp;
 	}
 
 	printk(KERN_NOTICE "Setting default mode to %s\n", def_mode);
@@ -747,12 +747,15 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
 	if (ret) {
 		v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default mode %s",
 			 def_mode);
-		return ret;
+		goto fail_kfree_amp;
 	}
 	vpbe_dev->initialized = 1;
 	/* TBD handling of bootargs for default output and mode */
 	return 0;
 
+fail_kfree_amp:
+	mutex_lock(&vpbe_dev->lock);
+	kfree(vpbe_dev->amp);
 fail_kfree_encoders:
 	kfree(vpbe_dev->encoders);
 fail_dev_unregister:
diff --git a/drivers/media/platform/msm/ais/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/ais/cam_cdm/cam_cdm_hw_core.c
index 13a653a..e1809a1 100644
--- a/drivers/media/platform/msm/ais/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/ais/cam_cdm/cam_cdm_hw_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
@@ -509,8 +509,8 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw,
 
 		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 @@ static void cam_hw_cdm_work(struct work_struct *work)
 		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 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data)
 			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/ais/cam_core/cam_node.c b/drivers/media/platform/msm/ais/cam_core/cam_node.c
index 397f19b..c2aa06a 100644
--- a/drivers/media/platform/msm/ais/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/ais/cam_core/cam_node.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
@@ -111,6 +111,7 @@ static int __cam_node_handle_acquire_dev(struct cam_node *node,
 		goto err;
 	}
 
+	ctx->last_flush_req = 0;
 	rc = cam_context_handle_acquire_dev(ctx, acquire);
 	if (rc) {
 		CAM_ERR(CAM_CORE, "Acquire device failed for node %s",
diff --git a/drivers/media/platform/msm/ais/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/ais/cam_cpas/cam_cpas_hw.c
index 13417bd..7cc8af9 100644
--- a/drivers/media/platform/msm/ais/cam_cpas/cam_cpas_hw.c
+++ b/drivers/media/platform/msm/ais/cam_cpas/cam_cpas_hw.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
@@ -934,7 +934,7 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args,
 	}
 
 	if (sizeof(struct cam_cpas_hw_cmd_start) != arg_size) {
-		CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d",
+		CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d",
 			sizeof(struct cam_cpas_hw_cmd_start), arg_size);
 		return -EINVAL;
 	}
@@ -1066,7 +1066,7 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args,
 	}
 
 	if (sizeof(struct cam_cpas_hw_cmd_stop) != arg_size) {
-		CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d",
+		CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d",
 			sizeof(struct cam_cpas_hw_cmd_stop), arg_size);
 		return -EINVAL;
 	}
@@ -1169,7 +1169,7 @@ static int cam_cpas_hw_init(void *hw_priv, void *init_hw_args,
 	}
 
 	if (sizeof(struct cam_cpas_hw_caps) != arg_size) {
-		CAM_ERR(CAM_CPAS, "INIT HW size mismatch %ld %d",
+		CAM_ERR(CAM_CPAS, "INIT HW size mismatch %zd %d",
 			sizeof(struct cam_cpas_hw_caps), arg_size);
 		return -EINVAL;
 	}
@@ -1326,7 +1326,7 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv,
 	}
 
 	if (sizeof(struct cam_cpas_hw_caps) != arg_size) {
-		CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %ld %d",
+		CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d",
 			sizeof(struct cam_cpas_hw_caps), arg_size);
 		return -EINVAL;
 	}
diff --git a/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cam_cpastop_hw.c
index ee72171..f2a2c6a 100644
--- a/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cam_cpastop_hw.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
@@ -505,8 +505,6 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw)
 {
 	int i;
 
-	cam_cpastop_reset_irq(cpas_hw);
-
 	for (i = 0; i < camnoc_info->specific_size; i++) {
 		if (camnoc_info->specific[i].enable) {
 			cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC,
diff --git a/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cpastop_v175_120.h b/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cpastop_v175_120.h
index 072361a..bcd9547 100644
--- a/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cpastop_v175_120.h
+++ b/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cpastop_v175_120.h
@@ -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
@@ -388,7 +388,7 @@ static struct cam_camnoc_specific
 			.enable = true,
 			.access_type = CAM_REG_TYPE_READ_WRITE,
 			.offset = 0x3240, /* SPECIFIC_IFE1_DANGERLUT_LOW */
-			.value = 0xFFFFFF00,
+			.value = 0x00000000,
 		},
 		.safe_lut = {
 			.enable = true,
@@ -535,7 +535,7 @@ static struct cam_camnoc_specific
 			.enable = true,
 			.access_type = CAM_REG_TYPE_READ_WRITE,
 			.masked_value = 1,
-			.offset = 0x2E38, /* SPECIFIC_IBL_WR_URGENCY_LOW */
+			.offset = 0x2A38, /* SPECIFIC_IBL_WR_URGENCY_LOW */
 			/* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_MASK */
 			.mask = 0x70,
 			/* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_SHIFT */
@@ -578,7 +578,7 @@ static struct cam_camnoc_specific
 			.masked_value = 0,
 			/* SPECIFIC_IPE_VID_DISP_PRIORITYLUT_LOW */
 			.offset = 0x5E30,
-			.value = 0x33330000,
+			.value = 0x33333333,
 		},
 		.priority_lut_high = {
 			.enable = true,
@@ -674,7 +674,46 @@ static struct cam_camnoc_specific
 	},
 	{
 		.port_type = CAM_CAMNOC_FD,
-		.enable = false,
+		.enable = true,
+		.priority_lut_low = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x3E30, /* SPECIFIC_FD_PRIORITYLUT_LOW */
+			.value = 0x44444444,
+		},
+		.priority_lut_high = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x3E34, /* SPECIFIC_FD_PRIORITYLUT_HIGH */
+			.value = 0x44444444,
+		},
+		.urgency = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x3E38, /* SPECIFIC_FD_URGENCY_LOW */
+			.value = 0x44,
+		},
+		.danger_lut = {
+			.enable = false,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x3E40, /* SPECIFIC_FD_DANGERLUT_LOW */
+			.value = 0x0,
+		},
+		.safe_lut = {
+			.enable = false,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0x3E48, /* SPECIFIC_FD_SAFELUT_LOW */
+			.value = 0x0,
+		},
+		.ubwc_ctl = {
+			.enable = false,
+		},
+
 	},
 	{
 		/*SidebandManager_main_SidebandManager_FlagOutSet0_Low*/
diff --git a/drivers/media/platform/msm/ais/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h b/drivers/media/platform/msm/ais/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h
index a842b82..4431b92 100644
--- a/drivers/media/platform/msm/ais/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h
+++ b/drivers/media/platform/msm/ais/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.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
@@ -111,7 +111,7 @@ struct cam_fd_hw_io_buffer {
 	struct cam_buf_io_cfg *io_cfg;
 	uint32_t               num_buf;
 	uint64_t               io_addr[CAM_PACKET_MAX_PLANES];
-	uint64_t               cpu_addr[CAM_PACKET_MAX_PLANES];
+	uintptr_t              cpu_addr[CAM_PACKET_MAX_PLANES];
 };
 
 /**
diff --git a/drivers/media/platform/msm/ais/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/ais/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 901f54e..e5ee853 100644
--- a/drivers/media/platform/msm/ais/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/ais/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.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
@@ -3813,8 +3813,8 @@ static int cam_icp_mgr_update_hfi_frame_process(
 		hfi_cmd = (struct hfi_cmd_ipebps_async *)
 		&ctx_data->hfi_frame_process.frame_info[index].hfi_cfg_io_cmd;
 		rc = cam_icp_mgr_process_cfg_io_cmd(ctx_data, hfi_cmd,
-		packet->header.request_id,
-		ctx_data->hfi_frame_process.frame_info[index].io_config);
+		     packet->header.request_id,
+		     ctx_data->hfi_frame_process.frame_info[index].io_config);
 	}
 	*idx = index;
 
diff --git a/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c
index bb321078..f8f380b 100644
--- a/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.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
@@ -488,6 +488,7 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
 		req_isp->bubble_detected = false;
 		list_del_init(&req->list);
 		list_add(&req->list, &ctx->pending_req_list);
+		atomic_set(&ctx_isp->process_bubble, 0);
 
 		CAM_DBG(CAM_REQ,
 			"Move active request %lld to pending list(cnt = %d) [bubble recovery]",
@@ -805,6 +806,7 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
 		notify.req_id = req->request_id;
 		notify.error = CRM_KMD_ERR_BUBBLE;
 		ctx->ctx_crm_intf->notify_err(&notify);
+		atomic_set(&ctx_isp->process_bubble, 1);
 		CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
 			ctx_isp->frame_id);
 	} else {
@@ -1302,6 +1304,14 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
 	 */
 	ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
 
+	if (atomic_read(&ctx_isp->process_bubble)) {
+		CAM_DBG(CAM_ISP,
+			"Processing bubble cannot apply Request Id %llu",
+			apply->request_id);
+		rc = -EAGAIN;
+		goto end;
+	}
+
 	spin_lock_bh(&ctx->lock);
 	req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
 		list);
diff --git a/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.h
index 5ebd82e..4954f20 100644
--- a/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.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
@@ -144,6 +144,8 @@ struct cam_isp_context_state_monitor {
  * @base:                      Common context object pointer
  * @frame_id:                  Frame id tracking for the isp context
  * @substate_actiavted:        Current substate for the activated state.
+ * @process_bubble:            Atomic variable to check if ctx is still
+ *                             processing bubble.
  * @substate_machine:          ISP substate machine for external interface
  * @substate_machine_irq:      ISP substate machine for irq handling
  * @req_base:                  Common request object storage
@@ -170,6 +172,7 @@ struct cam_isp_context {
 
 	int64_t                          frame_id;
 	uint32_t                         substate_activated;
+	atomic_t                         process_bubble;
 	struct cam_ctx_ops              *substate_machine;
 	struct cam_isp_ctx_irq_ops      *substate_machine_irq;
 
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 2cd34b6..81ff44f 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.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
@@ -43,7 +43,7 @@
 	(CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON + 1)
 
 #define CAM_ISP_GENERIC_BLOB_TYPE_MAX               \
-	(CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG + 1)
+	(CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG + 1)
 
 static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
 	CAM_ISP_HW_CMD_GET_HFR_UPDATE,
@@ -51,6 +51,7 @@ static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
 	CAM_ISP_HW_CMD_BW_UPDATE,
 	CAM_ISP_HW_CMD_UBWC_UPDATE,
 	CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE,
+	CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG,
 };
 
 static struct cam_ife_hw_mgr g_ife_hw_mgr;
@@ -288,65 +289,6 @@ static void cam_ife_hw_mgr_deinit_hw_res(
 	}
 }
 
-static int cam_ife_hw_mgr_init_hw(
-	struct cam_ife_hw_mgr_ctx *ctx)
-{
-	struct cam_ife_hw_mgr_res *hw_mgr_res;
-	int rc = 0, i;
-
-	CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d",
-		ctx->ctx_index);
-	/* INIT IFE CID */
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
-		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)",
-				 hw_mgr_res->res_id);
-			return rc;
-		}
-	}
-
-	CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d",
-		ctx->ctx_index);
-
-	/* INIT IFE csid */
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
-		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)",
-				 hw_mgr_res->res_id);
-			return rc;
-		}
-	}
-
-	/* INIT IFE SRC */
-	CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d",
-		ctx->ctx_index);
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
-		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)",
-				 hw_mgr_res->res_id);
-			return rc;
-		}
-	}
-
-	/* INIT IFE OUT */
-	CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d",
-		ctx->ctx_index);
-
-	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
-		rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)",
-				 ctx->res_list_ife_out[i].res_id);
-			return rc;
-		}
-	}
-
-	return rc;
-}
-
 static void cam_ife_hw_mgr_deinit_hw(
 	struct cam_ife_hw_mgr_ctx *ctx)
 {
@@ -375,6 +317,11 @@ static void cam_ife_hw_mgr_deinit_hw(
 		cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
 	}
 
+	/* Deint IFE RD */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+		cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
+	}
+
 	/* Deinit IFE OUT */
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
 		cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]);
@@ -382,6 +329,81 @@ static void cam_ife_hw_mgr_deinit_hw(
 	ctx->init_done = false;
 }
 
+static int cam_ife_hw_mgr_init_hw(
+	struct cam_ife_hw_mgr_ctx *ctx)
+{
+	struct cam_ife_hw_mgr_res *hw_mgr_res;
+	int rc = 0, i;
+
+	CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d",
+		ctx->ctx_index);
+	/* INIT IFE CID */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
+		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)",
+				 hw_mgr_res->res_id);
+			goto deinit;
+		}
+	}
+
+	CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d",
+		ctx->ctx_index);
+
+	/* INIT IFE csid */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
+		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)",
+				 hw_mgr_res->res_id);
+			goto deinit;
+		}
+	}
+
+	/* INIT IFE SRC */
+	CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d",
+		ctx->ctx_index);
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)",
+				 hw_mgr_res->res_id);
+			goto deinit;
+		}
+	}
+
+	/* INIT IFE BUS RD */
+	CAM_DBG(CAM_ISP, "INIT IFE BUS RD in ctx id:%d",
+		ctx->ctx_index);
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not IFE BUS RD (%d)",
+				 hw_mgr_res->res_id);
+			return rc;
+		}
+	}
+
+	/* INIT IFE OUT */
+	CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d",
+		ctx->ctx_index);
+
+	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
+		rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)",
+				 ctx->res_list_ife_out[i].res_id);
+			goto deinit;
+		}
+	}
+
+	return rc;
+deinit:
+	ctx->init_done = true;
+	cam_ife_hw_mgr_deinit_hw(ctx);
+	return rc;
+}
+
 static int cam_ife_hw_mgr_put_res(
 	struct list_head                *src_list,
 	struct cam_ife_hw_mgr_res      **res)
@@ -496,6 +518,13 @@ static int cam_ife_hw_mgr_release_hw_for_ctx(
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
 		cam_ife_hw_mgr_free_hw_res(&ife_ctx->res_list_ife_out[i]);
 
+	/* ife bus rd resource */
+	list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp,
+		&ife_ctx->res_list_ife_in_rd, list) {
+		cam_ife_hw_mgr_free_hw_res(hw_mgr_res);
+		cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &hw_mgr_res);
+	}
+
 	/* ife source resource */
 	list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp,
 		&ife_ctx->res_list_ife_src, list) {
@@ -641,6 +670,91 @@ static int cam_ife_mgr_process_base_info(
 	return 0;
 }
 
+static int cam_ife_hw_mgr_acquire_res_bus_rd(
+	struct cam_ife_hw_mgr_ctx       *ife_ctx,
+	struct cam_isp_in_port_info     *in_port)
+{
+	int rc = -EINVAL;
+	struct cam_vfe_acquire_args               vfe_acquire;
+	struct cam_ife_hw_mgr_res                *ife_in_rd_res;
+	struct cam_hw_intf                       *hw_intf;
+	struct cam_ife_hw_mgr_res                *ife_src_res;
+	int i;
+
+	CAM_DBG(CAM_ISP, "Enter");
+
+	list_for_each_entry(ife_src_res, &ife_ctx->res_list_ife_src, list) {
+		if (ife_src_res->res_id != CAM_ISP_HW_VFE_IN_RD)
+			continue;
+
+		rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
+			&ife_in_rd_res);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "No more free hw mgr resource");
+			goto err;
+		}
+		cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_in_rd,
+			&ife_in_rd_res);
+
+		vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
+		vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
+		vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops;
+		vfe_acquire.vfe_out.ctx = ife_ctx;
+		vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index;
+		vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_vfe;
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (!ife_src_res->hw_res[i])
+				continue;
+
+			hw_intf = ife_src_res->hw_res[i]->hw_intf;
+			if (i == CAM_ISP_HW_SPLIT_LEFT) {
+				vfe_acquire.vfe_out.split_id  =
+					CAM_ISP_HW_SPLIT_LEFT;
+				if (ife_src_res->is_dual_vfe) {
+					/*TBD */
+					vfe_acquire.vfe_out.is_master     = 1;
+					vfe_acquire.vfe_out.dual_slave_core =
+						(hw_intf->hw_idx == 0) ? 1 : 0;
+				} else {
+					vfe_acquire.vfe_out.is_master   = 0;
+					vfe_acquire.vfe_out.dual_slave_core =
+						0;
+				}
+			} else {
+				vfe_acquire.vfe_out.split_id  =
+					CAM_ISP_HW_SPLIT_RIGHT;
+				vfe_acquire.vfe_out.is_master       = 0;
+				vfe_acquire.vfe_out.dual_slave_core =
+					(hw_intf->hw_idx == 0) ? 1 : 0;
+			}
+			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+				&vfe_acquire,
+				sizeof(struct cam_vfe_acquire_args));
+			if (rc) {
+				CAM_ERR(CAM_ISP,
+					"Can not acquire out resource 0x%x",
+					vfe_acquire.rsrc_type);
+				goto err;
+			}
+
+			ife_in_rd_res->hw_res[i] =
+				vfe_acquire.vfe_out.rsrc_node;
+			CAM_DBG(CAM_ISP, "resource type :0x%x res id:0x%x",
+				ife_in_rd_res->hw_res[i]->res_type,
+				ife_in_rd_res->hw_res[i]->res_id);
+
+		}
+		ife_in_rd_res->is_dual_vfe = in_port->usage_type;
+		ife_in_rd_res->res_type = (enum cam_ife_hw_mgr_res_type)
+			CAM_ISP_RESOURCE_VFE_BUS_RD;
+	}
+
+	return 0;
+err:
+	CAM_DBG(CAM_ISP, "Exit rc(0x%x)", rc);
+	return rc;
+}
+
 static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
 	struct cam_ife_hw_mgr_ctx       *ife_ctx,
 	struct cam_ife_hw_mgr_res       *ife_src_res,
@@ -720,6 +834,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
 	ife_out_res->res_type = (enum cam_ife_hw_mgr_res_type)
 		CAM_ISP_RESOURCE_VFE_OUT;
 	ife_src_res->child[ife_src_res->num_children++] = ife_out_res;
+	CAM_DBG(CAM_ISP, "IFE SRC num_children = %d",
+		ife_src_res->num_children);
 
 	return 0;
 err:
@@ -813,6 +929,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel(
 		ife_out_res->res_id = out_port->res_type;
 		ife_out_res->parent = ife_src_res;
 		ife_src_res->child[ife_src_res->num_children++] = ife_out_res;
+		CAM_DBG(CAM_ISP, "IFE SRC num_children = %d",
+			ife_src_res->num_children);
 	}
 
 	return 0;
@@ -835,6 +953,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_out(
 		switch (ife_src_res->res_id) {
 		case CAM_ISP_HW_VFE_IN_CAMIF:
 		case CAM_ISP_HW_VFE_IN_CAMIF_LITE:
+		case CAM_ISP_HW_VFE_IN_RD:
 			rc = cam_ife_hw_mgr_acquire_res_ife_out_pixel(ife_ctx,
 				ife_src_res, in_port);
 			break;
@@ -860,6 +979,132 @@ static int cam_ife_hw_mgr_acquire_res_ife_out(
 	return rc;
 }
 
+static int cam_ife_hw_mgr_acquire_res_ife_rd_src(
+	struct cam_ife_hw_mgr_ctx     *ife_ctx,
+	struct cam_isp_in_port_info   *in_port)
+{
+	int rc                = -1;
+	struct cam_ife_hw_mgr_res                  *csid_res;
+	struct cam_ife_hw_mgr_res                  *ife_src_res;
+	struct cam_vfe_acquire_args                 vfe_acquire;
+	struct cam_hw_intf                         *hw_intf;
+	struct cam_ife_hw_mgr                      *ife_hw_mgr;
+	int vfe_idx = -1, i = 0;
+
+	ife_hw_mgr = ife_ctx->hw_mgr;
+
+	CAM_DBG(CAM_ISP, "Enter");
+	list_for_each_entry(csid_res, &ife_ctx->res_list_ife_csid, list) {
+		if (csid_res->res_id != CAM_IFE_PIX_PATH_RES_RDI_0) {
+			CAM_DBG(CAM_ISP, "not RDI0: %d", csid_res->res_id);
+			continue;
+		}
+
+		rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
+			&ife_src_res);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "No more free hw mgr resource");
+			goto err;
+		}
+		cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_src,
+			&ife_src_res);
+
+		CAM_DBG(CAM_ISP, "csid_res_id %d", csid_res->res_id);
+		vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_IN;
+		vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
+		vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops;
+		vfe_acquire.vfe_in.in_port = in_port;
+		vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_RD;
+		vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE;
+
+		ife_src_res->res_type =
+			(enum cam_ife_hw_mgr_res_type)vfe_acquire.rsrc_type;
+		ife_src_res->res_id = vfe_acquire.vfe_in.res_id;
+		ife_src_res->is_dual_vfe = csid_res->is_dual_vfe;
+
+		hw_intf =
+			ife_hw_mgr->ife_devices[csid_res->hw_res[
+			CAM_ISP_HW_SPLIT_LEFT]->hw_intf->hw_idx];
+
+		vfe_idx = csid_res->hw_res[
+			CAM_ISP_HW_SPLIT_LEFT]->hw_intf->hw_idx;
+
+		/*
+		 * fill in more acquire information as needed
+		 */
+		if (ife_src_res->is_dual_vfe)
+			vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_MASTER;
+
+		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+				&vfe_acquire,
+				sizeof(struct cam_vfe_acquire_args));
+		if (rc) {
+			CAM_ERR(CAM_ISP,
+				"Can not acquire IFE HW res %d",
+				csid_res->res_id);
+			goto err;
+		}
+		ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT] =
+			vfe_acquire.vfe_in.rsrc_node;
+		CAM_DBG(CAM_ISP,
+			"acquire success IFE:%d  res type :0x%x res id:0x%x",
+			hw_intf->hw_idx,
+			ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->res_type,
+			ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->res_id);
+
+		if (!ife_src_res->is_dual_vfe)
+			goto acq;
+
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (i == CAM_ISP_HW_SPLIT_LEFT) {
+				CAM_DBG(CAM_ISP, "vfe_idx %d is acquired",
+					vfe_idx);
+				continue;
+			}
+
+			hw_intf = ife_hw_mgr->ife_devices[i];
+
+			/* fill in more acquire information as needed */
+			if (i == CAM_ISP_HW_SPLIT_RIGHT)
+				vfe_acquire.vfe_in.sync_mode =
+					CAM_ISP_HW_SYNC_SLAVE;
+
+			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+					&vfe_acquire,
+					sizeof(struct cam_vfe_acquire_args));
+			if (rc) {
+				CAM_ERR(CAM_ISP,
+					"Can not acquire IFE HW res %d",
+					csid_res->res_id);
+				goto err;
+			}
+			ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
+			CAM_DBG(CAM_ISP,
+				"acquire success IFE:%d  res type :0x%x res id:0x%x",
+				hw_intf->hw_idx,
+				ife_src_res->hw_res[i]->res_type,
+				ife_src_res->hw_res[i]->res_id);
+		}
+acq:
+		/*
+		 * It should be one to one mapping between
+		 * csid resource and ife source resource
+		 */
+		csid_res->child[0] = ife_src_res;
+		ife_src_res->parent = csid_res;
+		csid_res->child[csid_res->num_children++] = ife_src_res;
+		CAM_DBG(CAM_ISP,
+			"csid_res=%d  CSID num_children=%d ife_src_res=%d",
+			csid_res->res_id, csid_res->num_children,
+			ife_src_res->res_id);
+	}
+
+err:
+	/* release resource at the entry function */
+	CAM_DBG(CAM_ISP, "Exit rc(0x%x)", rc);
+	return rc;
+}
+
 static int cam_ife_hw_mgr_acquire_res_ife_src(
 	struct cam_ife_hw_mgr_ctx     *ife_ctx,
 	struct cam_isp_in_port_info   *in_port)
@@ -972,7 +1217,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_src(
 		csid_res->child[0] = ife_src_res;
 		ife_src_res->parent = csid_res;
 		csid_res->child[csid_res->num_children++] = ife_src_res;
-		CAM_DBG(CAM_ISP, "csid_res=%d  num_children=%d ife_src_res=%d",
+		CAM_DBG(CAM_ISP,
+			"csid_res=%d  CSID num_children=%d ife_src_res=%d",
 			csid_res->res_id, csid_res->num_children,
 			ife_src_res->res_id);
 	}
@@ -987,7 +1233,7 @@ static int cam_ife_mgr_acquire_cid_res(
 	struct cam_ife_hw_mgr_ctx          *ife_ctx,
 	struct cam_isp_in_port_info        *in_port,
 	struct cam_ife_hw_mgr_res         **cid_res,
-	enum cam_ife_pix_path_res_id        csid_path)
+	enum cam_ife_pix_path_res_id        path_res_id)
 {
 	int rc = -1;
 	int i, j;
@@ -1011,8 +1257,8 @@ static int cam_ife_mgr_acquire_cid_res(
 
 	csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
 	csid_acquire.in_port = in_port;
-	csid_acquire.res_id =  csid_path;
-	CAM_DBG(CAM_ISP, "path %d", csid_path);
+	csid_acquire.res_id =  path_res_id;
+	CAM_DBG(CAM_ISP, "path_res_id %d", path_res_id);
 
 	if (in_port->num_out_res)
 		out_port = &(in_port->data[0]);
@@ -1045,12 +1291,12 @@ static int cam_ife_mgr_acquire_cid_res(
 				csid_acquire.node_res;
 
 			CAM_DBG(CAM_ISP,
-				"acquired csid(%s)=%d CID rsrc successfully",
+				"acquired from old csid(%s)=%d CID rsrc successfully",
 				(i == 0) ? "left" : "right",
 				hw_intf->hw_idx);
 
 			if (in_port->usage_type && acquired_cnt == 1 &&
-				csid_path == CAM_IFE_PIX_PATH_RES_IPP)
+				path_res_id == CAM_IFE_PIX_PATH_RES_IPP)
 				/*
 				 * Continue to acquire Right for IPP.
 				 * Dual IFE for RDI and PPP is not currently
@@ -1070,27 +1316,52 @@ static int cam_ife_mgr_acquire_cid_res(
 	}
 
 	/* Acquire Left if not already acquired */
-	for (i = CAM_IFE_CSID_HW_NUM_MAX - 1; i >= 0; i--) {
-		if (!ife_hw_mgr->csid_devices[i])
-			continue;
+	if (ife_ctx->is_fe_enable) {
+		for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
+			if (!ife_hw_mgr->csid_devices[i])
+				continue;
 
-		hw_intf = ife_hw_mgr->csid_devices[i];
-		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &csid_acquire,
-			sizeof(csid_acquire));
-		if (rc)
-			continue;
-		else {
-			cid_res_temp->hw_res[acquired_cnt++] =
-				csid_acquire.node_res;
-			break;
+			hw_intf = ife_hw_mgr->csid_devices[i];
+			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+				&csid_acquire, sizeof(csid_acquire));
+			if (rc)
+				continue;
+			else {
+				cid_res_temp->hw_res[acquired_cnt++] =
+					csid_acquire.node_res;
+				break;
+			}
+		}
+		if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) {
+			CAM_ERR(CAM_ISP,
+				"Can not acquire ife cid resource for path %d",
+				path_res_id);
+			goto put_res;
+		}
+	} else {
+		for (i = CAM_IFE_CSID_HW_NUM_MAX - 1; i >= 0; i--) {
+			if (!ife_hw_mgr->csid_devices[i])
+				continue;
+
+			hw_intf = ife_hw_mgr->csid_devices[i];
+			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+				&csid_acquire, sizeof(csid_acquire));
+			if (rc)
+				continue;
+			else {
+				cid_res_temp->hw_res[acquired_cnt++] =
+					csid_acquire.node_res;
+				break;
+			}
+		}
+		if (i == -1 || !csid_acquire.node_res) {
+			CAM_ERR(CAM_ISP,
+				"Can not acquire ife cid resource for path %d",
+				path_res_id);
+			goto put_res;
 		}
 	}
 
-	if (i == -1 || !csid_acquire.node_res) {
-		CAM_ERR(CAM_ISP, "Can not acquire ife cid resource for path %d",
-			csid_path);
-		goto put_res;
-	}
 
 acquire_successful:
 	CAM_DBG(CAM_ISP, "CID left acquired success is_dual %d",
@@ -1110,7 +1381,7 @@ static int cam_ife_mgr_acquire_cid_res(
 	 * Acquire Right if not already acquired.
 	 * Dual IFE for RDI and PPP is not currently supported.
 	 */
-	if (cid_res_temp->is_dual_vfe && csid_path
+	if (cid_res_temp->is_dual_vfe && path_res_id
 		== CAM_IFE_PIX_PATH_RES_IPP && acquired_cnt == 1) {
 		csid_acquire.node_res = NULL;
 		csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
@@ -1143,6 +1414,8 @@ static int cam_ife_mgr_acquire_cid_res(
 	cid_res_temp->parent = &ife_ctx->res_list_ife_in;
 	ife_ctx->res_list_ife_in.child[
 		ife_ctx->res_list_ife_in.num_children++] = cid_res_temp;
+	CAM_DBG(CAM_ISP, "IFE IN num_children = %d",
+		ife_ctx->res_list_ife_in.num_children);
 
 	return 0;
 put_res:
@@ -1201,6 +1474,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl(
 		csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE;
 	}
 
+	CAM_DBG(CAM_ISP, "CSID Acq: E");
 	/* IPP resource needs to be from same HW as CID resource */
 	for (i = 0; i <= csid_res->is_dual_vfe; i++) {
 		CAM_DBG(CAM_ISP, "i %d is_dual %d", i, csid_res->is_dual_vfe);
@@ -1251,8 +1525,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl(
 	csid_res->parent = cid_res;
 	cid_res->child[cid_res->num_children++] = csid_res;
 
-	CAM_DBG(CAM_ISP, "acquire res %d", csid_acquire.res_id);
-
+	CAM_DBG(CAM_ISP, "acquire res %d CID children = %d",
+		csid_acquire.res_id, cid_res->num_children);
 	return 0;
 put_res:
 	cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res);
@@ -1265,6 +1539,7 @@ static enum cam_ife_pix_path_res_id
 	uint32_t                 out_port_type)
 {
 	enum cam_ife_pix_path_res_id path_id;
+	CAM_DBG(CAM_ISP, "out_port_type %x", out_port_type);
 
 	switch (out_port_type) {
 	case CAM_ISP_IFE_OUT_RES_RDI_0:
@@ -1285,7 +1560,7 @@ static enum cam_ife_pix_path_res_id
 		break;
 	}
 
-	CAM_DBG(CAM_ISP, "out_port %d path_id %d", out_port_type, path_id);
+	CAM_DBG(CAM_ISP, "out_port %x path_id %d", out_port_type, path_id);
 
 	return path_id;
 }
@@ -1303,20 +1578,20 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
 	struct cam_hw_intf                  *hw_intf;
 	struct cam_isp_out_port_info        *out_port;
 	struct cam_csid_hw_reserve_resource_args  csid_acquire;
-	enum cam_ife_pix_path_res_id         path_type;
+	enum cam_ife_pix_path_res_id         path_res_id;
 
 	ife_hw_mgr = ife_ctx->hw_mgr;
 
 	for (i = 0; i < in_port->num_out_res; i++) {
 		out_port = &in_port->data[i];
-		path_type = cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
+		path_res_id = cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
 			out_port->res_type);
-		if (path_type == CAM_IFE_PIX_PATH_RES_MAX)
+		if (path_res_id == CAM_IFE_PIX_PATH_RES_MAX)
 			continue;
 
 		/* get cid resource */
 		rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res,
-			path_type);
+			path_res_id);
 		if (rc) {
 			CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
 			goto end;
@@ -1331,8 +1606,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
 		}
 
 		memset(&csid_acquire, 0, sizeof(csid_acquire));
-		csid_acquire.res_id = path_type;
-
+		csid_acquire.res_id = path_res_id;
 		csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH;
 		csid_acquire.cid = cid_res->hw_res[0]->res_id;
 		csid_acquire.in_port = in_port;
@@ -1364,11 +1638,11 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
 		csid_res->is_dual_vfe = 0;
 		csid_res->hw_res[0] = csid_acquire.node_res;
 		csid_res->hw_res[1] = NULL;
-		CAM_DBG(CAM_ISP, "acquire res %d",
-			csid_acquire.res_id);
 		csid_res->parent = cid_res;
 		cid_res->child[cid_res->num_children++] =
 			csid_res;
+		CAM_DBG(CAM_ISP, "acquire res %d CID children = %d",
+			csid_acquire.res_id, cid_res->num_children);
 		cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
 
 	}
@@ -1391,7 +1665,8 @@ static int cam_ife_hw_mgr_acquire_res_root(
 		ife_ctx->res_list_ife_in.res_type = CAM_IFE_HW_MGR_RES_ROOT;
 		ife_ctx->res_list_ife_in.res_id = in_port->res_type;
 		ife_ctx->res_list_ife_in.is_dual_vfe = in_port->usage_type;
-	} else if (ife_ctx->res_list_ife_in.res_id != in_port->res_type) {
+	} else if ((ife_ctx->res_list_ife_in.res_id !=
+		in_port->res_type) && (!ife_ctx->is_fe_enable))  {
 		CAM_ERR(CAM_ISP, "No Free resource for this context");
 		goto err;
 	} else {
@@ -1403,35 +1678,85 @@ static int cam_ife_hw_mgr_acquire_res_root(
 	return rc;
 }
 
-static int cam_ife_hw_mgr_preprocess_out_port(
+static int cam_ife_mgr_check_and_update_fe(
+	struct cam_ife_hw_mgr_ctx         *ife_ctx,
+	struct cam_isp_acquire_hw_info    *acquire_hw_info)
+{
+	int i;
+	struct cam_isp_in_port_info       *in_port = NULL;
+	uint32_t                           in_port_length = 0;
+	uint32_t                           total_in_port_length = 0;
+
+	in_port = (struct cam_isp_in_port_info *)
+		((uint8_t *)&acquire_hw_info->data +
+		 acquire_hw_info->input_info_offset);
+	for (i = 0; i < acquire_hw_info->num_inputs; i++) {
+		in_port_length = sizeof(struct cam_isp_in_port_info) +
+			(in_port->num_out_res - 1) *
+			sizeof(struct cam_isp_out_port_info);
+		total_in_port_length += in_port_length;
+
+		if (total_in_port_length > acquire_hw_info->input_info_size) {
+			CAM_ERR(CAM_ISP, "buffer size is not enough");
+			return -EINVAL;
+		}
+		CAM_DBG(CAM_ISP, "in_port%d res_type %d", i,
+			in_port->res_type);
+		if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
+			ife_ctx->is_fe_enable = true;
+			break;
+		}
+
+		in_port = (struct cam_isp_in_port_info *)((uint8_t *)in_port +
+			in_port_length);
+	}
+	CAM_DBG(CAM_ISP, "is_fe_enable %d", ife_ctx->is_fe_enable);
+
+	return 0;
+}
+
+static int cam_ife_hw_mgr_preprocess_port(
 	struct cam_ife_hw_mgr_ctx   *ife_ctx,
 	struct cam_isp_in_port_info *in_port,
 	int                         *ipp_count,
 	int                         *rdi_count,
-	int                         *ppp_count)
+	int                         *ppp_count,
+	int                         *ife_rd_count)
 {
 	int ipp_num        = 0;
 	int rdi_num        = 0;
 	int ppp_num        = 0;
+	int ife_rd_num     = 0;
 	uint32_t i;
 	struct cam_isp_out_port_info      *out_port;
 	struct cam_ife_hw_mgr             *ife_hw_mgr;
 
 	ife_hw_mgr = ife_ctx->hw_mgr;
 
-	for (i = 0; i < in_port->num_out_res; i++) {
-		out_port = &in_port->data[i];
-		if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
-			rdi_num++;
-		else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
-			ppp_num++;
-		else
-			ipp_num++;
+	if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
+		ife_rd_num++;
+	} else {
+		for (i = 0; i < in_port->num_out_res; i++) {
+			out_port = &in_port->data[i];
+			if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
+				rdi_num++;
+			else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
+				ppp_num++;
+			else {
+				CAM_DBG(CAM_ISP, "out_res_type %d",
+				out_port->res_type);
+				ipp_num++;
+			}
+		}
 	}
 
 	*ipp_count = ipp_num;
 	*rdi_count = rdi_num;
 	*ppp_count = ppp_num;
+	*ife_rd_count = ife_rd_num;
+
+	CAM_DBG(CAM_ISP, "rdi: %d ipp: %d ppp: %d ife_rd: %d",
+		rdi_num, ipp_num, ppp_num, ife_rd_num);
 
 	return 0;
 }
@@ -1446,6 +1771,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
 	int ipp_count                             = 0;
 	int rdi_count                             = 0;
 	int ppp_count                             = 0;
+	int ife_rd_count                          = 0;
 
 	is_dual_vfe = in_port->usage_type;
 
@@ -1456,11 +1782,11 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
 		goto err;
 	}
 
-	cam_ife_hw_mgr_preprocess_out_port(ife_ctx, in_port,
-		&ipp_count, &rdi_count, &ppp_count);
+	cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port,
+		&ipp_count, &rdi_count, &ppp_count, &ife_rd_count);
 
-	if (!ipp_count && !rdi_count && !ppp_count) {
-		CAM_ERR(CAM_ISP, "No PIX or RDI or PPP resource");
+	if (!ipp_count && !rdi_count && !ppp_count && !ife_rd_count) {
+		CAM_ERR(CAM_ISP, "No PIX or RDI or PPP or IFE RD resource");
 		return -EINVAL;
 	}
 
@@ -1498,19 +1824,26 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
 
 
 	/* get ife src resource */
-	rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port);
+	if (ife_rd_count) {
+		rc = cam_ife_hw_mgr_acquire_res_ife_rd_src(ife_ctx, in_port);
+		rc = cam_ife_hw_mgr_acquire_res_bus_rd(ife_ctx, in_port);
+	} else {
+		rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port);
+	}
+
 	if (rc) {
 		CAM_ERR(CAM_ISP, "Acquire IFE SRC resource Failed");
 		goto err;
 	}
 
+	CAM_DBG(CAM_ISP, "Acquiring IFE OUT resource...");
 	rc = cam_ife_hw_mgr_acquire_res_ife_out(ife_ctx, in_port);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "Acquire IFE OUT resource Failed");
 		goto err;
 	}
 
-	*num_pix_port += ipp_count + ppp_count;
+	*num_pix_port += ipp_count + ppp_count + ife_rd_count;
 	*num_rdi_port += rdi_count;
 
 	return 0;
@@ -1534,8 +1867,8 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
 	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",
@@ -1614,8 +1947,22 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 		((uint8_t *)&acquire_hw_info->data +
 		 acquire_hw_info->input_info_offset);
 
+	rc = cam_ife_mgr_check_and_update_fe(ife_ctx, acquire_hw_info);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "buffer size is not enough");
+		goto free_ctx;
+	}
+
 	/* acquire HW resources */
 	for (i = 0; i < acquire_hw_info->num_inputs; i++) {
+
+		if (in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) {
+			CAM_ERR(CAM_ISP, "too many output res %d",
+				in_port->num_out_res);
+			rc = -EINVAL;
+			goto free_res;
+		}
+
 		in_port_length = sizeof(struct cam_isp_in_port_info) +
 			(in_port->num_out_res - 1) *
 			sizeof(struct cam_isp_out_port_info);
@@ -1626,6 +1973,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 			rc = -EINVAL;
 			goto free_res;
 		}
+		CAM_DBG(CAM_ISP, "in_res_type %x", in_port->res_type);
 		rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
 			&num_pix_port_per_in, &num_rdi_port_per_in);
 		total_pix_port += num_pix_port_per_in;
@@ -1741,6 +2089,8 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args)
 		if (isp_resource[i].resource_id != CAM_ISP_RES_ID_PORT)
 			continue;
 
+		CAM_DBG(CAM_ISP, "acquire no = %d total = %d", i,
+			acquire_args->num_acq);
 		CAM_DBG(CAM_ISP,
 			"start copy from user handle %lld with len = %d",
 			isp_resource[i].res_hdl,
@@ -2009,8 +2359,8 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
 			}
 	}
 
-	CAM_DBG(CAM_ISP, "Enter ctx id:%d num_hw_upd_entries %d",
-		ctx->ctx_index, cfg->num_hw_update_entries);
+	CAM_DBG(CAM_ISP, "Enter ctx id:%d req_id:%lld num_hw_upd_entries %d",
+		ctx->ctx_index, cfg->request_id, cfg->num_hw_update_entries);
 
 	if (cfg->num_hw_update_entries > 0) {
 		cdm_cmd = ctx->cdm_cmd;
@@ -2043,15 +2393,15 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
 				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 {
@@ -2130,6 +2480,11 @@ static int cam_ife_mgr_stop_hw_in_overflow(void *stop_hw_args)
 		cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
 	}
 
+	/* IFE bus rd resources */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+		cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
+	}
+
 	/* IFE out resources */
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
 		cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]);
@@ -2232,6 +2587,18 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
 
 	CAM_DBG(CAM_ISP, "Halting CSIDs");
 
+	CAM_DBG(CAM_ISP, "Going to stop IFE Mux");
+
+	/* IFE mux in resources */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+		cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
+	}
+
+	/* IFE bus rd resources */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+		cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
+	}
+
 	CAM_DBG(CAM_ISP, "Going to stop IFE Out");
 
 	/* IFE out resources */
@@ -2382,6 +2749,17 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args)
 	}
 
 	CAM_DBG(CAM_ISP, "START IFE SRC ... in ctx id:%d", ctx->ctx_index);
+
+	/* Start IFE BUS RD device */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not start IFE BUS RD (%d)",
+				 hw_mgr_res->res_id);
+			goto err;
+		}
+	}
+
 	/* Start the IFE mux in devices */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
 		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
@@ -2532,6 +2910,18 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
 		}
 	}
 
+	CAM_DBG(CAM_ISP, "START IFE BUS RD ... in ctx id:%d",
+		ctx->ctx_index);
+	/* Start the IFE mux in devices */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+		rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not start IFE BUS RD (%d)",
+				 hw_mgr_res->res_id);
+			goto err;
+		}
+	}
+
 	CAM_DBG(CAM_ISP, "START IFE SRC ... in ctx id:%d",
 		ctx->ctx_index);
 	/* Start the IFE mux in devices */
@@ -2663,6 +3053,78 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv,
 	return rc;
 }
 
+static int cam_isp_blob_fe_update(
+	uint32_t                               blob_type,
+	struct cam_isp_generic_blob_info      *blob_info,
+	struct cam_fe_config                  *fe_config,
+	struct cam_hw_prepare_update_args     *prepare)
+{
+	struct cam_ife_hw_mgr_ctx             *ctx = NULL;
+	struct cam_ife_hw_mgr_res             *hw_mgr_res;
+	struct cam_hw_intf                    *hw_intf;
+	int                                    rc = -EINVAL;
+	uint32_t                               i;
+	struct cam_vfe_fe_update_args          fe_upd_args;
+
+	ctx = prepare->ctxt_to_hw_map;
+
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (!hw_mgr_res->hw_res[i])
+				continue;
+
+			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+			if (hw_intf && hw_intf->hw_ops.process_cmd) {
+				fe_upd_args.node_res =
+					hw_mgr_res->hw_res[i];
+
+			memcpy(&fe_upd_args.fe_config, fe_config,
+				sizeof(struct cam_fe_config));
+
+				rc = hw_intf->hw_ops.process_cmd(
+					hw_intf->hw_priv,
+					CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD,
+					&fe_upd_args,
+					sizeof(
+					struct cam_fe_config));
+				if (rc)
+					CAM_ERR(CAM_ISP, "fs Update failed");
+			} else
+				CAM_WARN(CAM_ISP, "NULL hw_intf!");
+		}
+	}
+
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (!hw_mgr_res->hw_res[i])
+				continue;
+
+			if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_RD)
+				continue;
+
+			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+			if (hw_intf && hw_intf->hw_ops.process_cmd) {
+				fe_upd_args.node_res =
+					hw_mgr_res->hw_res[i];
+
+				memcpy(&fe_upd_args.fe_config, fe_config,
+					sizeof(struct cam_fe_config));
+
+				rc = hw_intf->hw_ops.process_cmd(
+					hw_intf->hw_priv,
+					CAM_ISP_HW_CMD_FE_UPDATE_IN_RD,
+					&fe_upd_args,
+					sizeof(
+					struct cam_vfe_fe_update_args));
+				if (rc)
+					CAM_ERR(CAM_ISP, "fe Update failed");
+			} else
+				CAM_WARN(CAM_ISP, "NULL hw_intf!");
+		}
+	}
+	return rc;
+}
+
 static int cam_isp_blob_ubwc_update(
 	uint32_t                               blob_type,
 	struct cam_isp_generic_blob_info      *blob_info,
@@ -3000,7 +3462,7 @@ static int cam_isp_blob_clock_update(
 					camif_r_clk_updated = true;
 				}
 			} else if ((hw_mgr_res->res_id >=
-				CAM_ISP_HW_VFE_IN_RDI0) && (hw_mgr_res->res_id
+				CAM_ISP_HW_VFE_IN_RD) && (hw_mgr_res->res_id
 				<= CAM_ISP_HW_VFE_IN_RDI3))
 				for (j = 0; j < clock_config->num_rdi; j++)
 					clk_rate = max(clock_config->rdi_hz[j],
@@ -3065,6 +3527,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 		return -EINVAL;
 	}
 
+	CAM_DBG(CAM_ISP, "FS2: BLOB Type: %d", blob_type);
 	switch (blob_type) {
 	case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG: {
 		struct cam_isp_resource_hfr_config    *hfr_config =
@@ -3127,6 +3590,15 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 			CAM_ERR(CAM_ISP, "Clock Update Failed");
 	}
 		break;
+	case CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG: {
+		struct cam_fe_config *fe_config =
+			(struct cam_fe_config *)blob_data;
+		rc = cam_isp_blob_fe_update(blob_type, blob_info,
+			fe_config, prepare);
+		if (rc)
+			CAM_ERR(CAM_ISP, "FS Update Failed rc: %d", rc);
+	}
+		break;
 	default:
 		CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type);
 		break;
@@ -3223,6 +3695,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
 			hw_mgr->mgr_common.img_iommu_hdl_secure,
 			prepare, ctx->base[i].idx,
 			&kmd_buf, ctx->res_list_ife_out,
+			&ctx->res_list_ife_in_rd,
 			CAM_IFE_HW_OUT_RES_MAX, fill_fence);
 
 		if (rc) {
@@ -3944,6 +4417,7 @@ static int cam_ife_hw_mgr_handle_reg_update(
 		case CAM_ISP_HW_VFE_IN_CAMIF_LITE:
 			break;
 		case CAM_ISP_HW_VFE_IN_CAMIF:
+		case CAM_ISP_HW_VFE_IN_RD:
 			if (ife_src_res->is_dual_vfe)
 				/* It checks for slave core RUP ACK*/
 				hw_res = ife_src_res->hw_res[1];
@@ -4104,9 +4578,10 @@ static int cam_ife_hw_mgr_handle_epoch_for_camif_hw_res(
 	list_for_each_entry(isp_ife_camif_res,
 		&ife_hwr_mgr_ctx->res_list_ife_src, list) {
 		if ((isp_ife_camif_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT)
-			|| (isp_ife_camif_res->res_id !=
-			CAM_ISP_HW_VFE_IN_CAMIF))
+			|| (isp_ife_camif_res->res_id >
+			CAM_ISP_HW_VFE_IN_RD)) {
 			continue;
+		}
 
 		hw_res_l = isp_ife_camif_res->hw_res[0];
 		hw_res_r = isp_ife_camif_res->hw_res[1];
@@ -4360,6 +4835,7 @@ static int cam_ife_hw_mgr_handle_sof(
 			break;
 
 		case CAM_ISP_HW_VFE_IN_CAMIF:
+		case CAM_ISP_HW_VFE_IN_RD:
 			sof_status = cam_ife_hw_mgr_process_camif_sof(
 				ife_src_res, ife_hw_mgr_ctx, evt_payload);
 			if (!sof_status && !sof_sent) {
@@ -4973,6 +5449,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
 		INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_cid);
 		INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_csid);
 		INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_src);
+		INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_in_rd);
 		ctx_pool = &g_ife_hw_mgr.ctx_pool[i];
 		for (j = 0; j < CAM_IFE_HW_OUT_RES_MAX; j++) {
 			res_list_ife_out = &ctx_pool->res_list_ife_out[j];
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index cf1e425..639c7ba 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.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
@@ -26,6 +26,7 @@ enum cam_ife_hw_mgr_res_type {
 	CAM_IFE_HW_MGR_RES_CID,
 	CAM_IFE_HW_MGR_RES_CSID,
 	CAM_IFE_HW_MGR_RES_IFE_SRC,
+	CAM_IFE_HW_MGR_RES_IFE_IN_RD,
 	CAM_IFE_HW_MGR_RES_IFE_OUT,
 };
 
@@ -108,6 +109,7 @@ struct cam_ife_hw_mgr_debug {
  *                          one.
  * @res_list_csid:          CSID resource list
  * @res_list_ife_src:       IFE input resource list
+ * @res_list_ife_in_rd      IFE input resource list for read path
  * @res_list_ife_out:       IFE output resoruces array
  * @free_res_list:          Free resources list for the branch node
  * @res_pool:               memory storage for the free resource list
@@ -128,6 +130,7 @@ struct cam_ife_hw_mgr_debug {
  * @is_rdi_only_context     flag to specify the context has only rdi resource
  * @config_done_complete    indicator for configuration complete
  * @init_done               indicate whether init hw is done
+ * @is_fe_enable            indicate whether fetch engine\read path is enabled
  */
 struct cam_ife_hw_mgr_ctx {
 	struct list_head                list;
@@ -141,6 +144,7 @@ struct cam_ife_hw_mgr_ctx {
 	struct list_head                res_list_ife_cid;
 	struct list_head                res_list_ife_csid;
 	struct list_head                res_list_ife_src;
+	struct list_head                res_list_ife_in_rd;
 	struct cam_ife_hw_mgr_res       res_list_ife_out[
 						CAM_IFE_HW_OUT_RES_MAX];
 
@@ -162,6 +166,7 @@ struct cam_ife_hw_mgr_ctx {
 	uint32_t                        is_rdi_only_context;
 	struct completion               config_done_complete;
 	bool                            init_done;
+	bool                            is_fe_enable;
 };
 
 /**
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
index f352144..73aae7c 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.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
@@ -436,6 +436,7 @@ int cam_isp_add_io_buffers(
 	uint32_t                              base_idx,
 	struct cam_kmd_buf_info              *kmd_buf_info,
 	struct cam_ife_hw_mgr_res            *res_list_isp_out,
+	struct list_head                     *res_list_ife_in_rd,
 	uint32_t                              size_isp_out,
 	bool                                  fill_fence)
 {
@@ -446,6 +447,7 @@ int cam_isp_add_io_buffers(
 	struct cam_ife_hw_mgr_res          *hw_mgr_res;
 	struct cam_isp_hw_get_cmd_update    update_buf;
 	struct cam_isp_hw_get_wm_update     wm_update;
+	struct cam_isp_hw_get_wm_update     bus_rd_update;
 	struct cam_hw_fence_map_entry      *out_map_entries;
 	struct cam_hw_fence_map_entry      *in_map_entries;
 	uint32_t                            kmd_buf_remain_size;
@@ -523,6 +525,15 @@ int cam_isp_add_io_buffers(
 			CAM_DBG(CAM_ISP,
 				"configure input io with fill fence %d",
 				fill_fence);
+			if (!list_empty(res_list_ife_in_rd)) {
+				hw_mgr_res =
+					list_first_entry(res_list_ife_in_rd,
+					struct cam_ife_hw_mgr_res, list);
+			} else {
+				CAM_ERR(CAM_ISP,
+					"No IFE in Read resource");
+				return -EINVAL;
+			}
 			in_map_entries =
 				&prepare->in_map_entries[num_in_buf];
 			if (fill_fence) {
@@ -539,7 +550,6 @@ int cam_isp_add_io_buffers(
 					return -EINVAL;
 				}
 			}
-			continue;
 		} else {
 			CAM_ERR(CAM_ISP, "Invalid io config direction :%d",
 				io_cfg[i].direction);
@@ -547,7 +557,8 @@ int cam_isp_add_io_buffers(
 		}
 
 		CAM_DBG(CAM_ISP, "setup mem io");
-		for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
+		for (j = 0; j < CAM_ISP_HW_SPLIT_MAX &&
+			io_cfg[i].direction == CAM_BUF_OUTPUT; j++) {
 			if (!hw_mgr_res->hw_res[j])
 				continue;
 
@@ -662,6 +673,116 @@ int cam_isp_add_io_buffers(
 			}
 			io_cfg_used_bytes += update_buf.cmd.used_bytes;
 		}
+		for (j = 0; j < CAM_ISP_HW_SPLIT_MAX &&
+			io_cfg[i].direction == CAM_BUF_INPUT; j++) {
+			if (!hw_mgr_res->hw_res[j])
+				continue;
+
+			if (hw_mgr_res->hw_res[j]->hw_intf->hw_idx != base_idx)
+				continue;
+
+			res = hw_mgr_res->hw_res[j];
+
+			memset(io_addr, 0, sizeof(io_addr));
+
+			for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES;
+						plane_id++) {
+				if (!io_cfg[i].mem_handle[plane_id])
+					break;
+
+				hdl = io_cfg[i].mem_handle[plane_id];
+				if (res->process_cmd(res,
+						CAM_ISP_HW_CMD_GET_SECURE_MODE,
+						&mode,
+						sizeof(bool)))
+					return -EINVAL;
+
+				is_buf_secure = cam_mem_is_secure_buf(hdl);
+				if ((mode == CAM_SECURE_MODE_SECURE) &&
+					is_buf_secure) {
+					mmu_hdl = sec_iommu_hdl;
+				} else if (
+					(mode == CAM_SECURE_MODE_NON_SECURE) &&
+					(!is_buf_secure)) {
+					mmu_hdl = iommu_hdl;
+				} else {
+					CAM_ERR_RATE_LIMIT(CAM_ISP,
+						"Invalid hdl: port mode[%u], buf mode[%u]",
+						mode, is_buf_secure);
+					return -EINVAL;
+				}
+
+				rc = cam_mem_get_io_buf(
+					io_cfg[i].mem_handle[plane_id],
+					mmu_hdl, &io_addr[plane_id], &size);
+				if (rc) {
+					CAM_ERR(CAM_ISP,
+						"no io addr for plane%d",
+						plane_id);
+					rc = -ENOMEM;
+					return rc;
+				}
+
+				/* need to update with offset */
+				io_addr[plane_id] +=
+						io_cfg[i].offsets[plane_id];
+				CAM_DBG(CAM_ISP,
+					"get io_addr for plane %d: 0x%llx, mem_hdl=0x%x",
+					plane_id, io_addr[plane_id],
+					io_cfg[i].mem_handle[plane_id]);
+
+				CAM_DBG(CAM_ISP,
+					"mmu_hdl=0x%x, size=%d, end=0x%x",
+					mmu_hdl, (int)size,
+					io_addr[plane_id]+size);
+
+			}
+			if (!plane_id) {
+				CAM_ERR(CAM_ISP, "No valid planes for res%d",
+					res->res_id);
+				rc = -ENOMEM;
+				return rc;
+			}
+
+			if ((kmd_buf_info->used_bytes + io_cfg_used_bytes) <
+				kmd_buf_info->size) {
+				kmd_buf_remain_size = kmd_buf_info->size -
+					(kmd_buf_info->used_bytes +
+					io_cfg_used_bytes);
+			} else {
+				CAM_ERR(CAM_ISP,
+					"no free kmd memory for base %d",
+					base_idx);
+				rc = -ENOMEM;
+				return rc;
+			}
+			update_buf.res = res;
+			update_buf.cmd_type = CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM;
+			update_buf.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr +
+				kmd_buf_info->used_bytes/4 +
+					io_cfg_used_bytes/4;
+			bus_rd_update.image_buf = io_addr;
+			bus_rd_update.num_buf   = plane_id;
+			bus_rd_update.io_cfg    = &io_cfg[i];
+			update_buf.cmd.size = kmd_buf_remain_size;
+			update_buf.rm_update = &bus_rd_update;
+
+			CAM_DBG(CAM_ISP, "cmd buffer 0x%pK, size %d",
+				update_buf.cmd.cmd_buf_addr,
+				update_buf.cmd.size);
+			rc = res->hw_intf->hw_ops.process_cmd(
+				res->hw_intf->hw_priv,
+				CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM, &update_buf,
+				sizeof(struct cam_isp_hw_get_cmd_update));
+
+			if (rc) {
+				CAM_ERR(CAM_ISP, "get buf cmd error:%d",
+					res->res_id);
+				rc = -ENOMEM;
+				return rc;
+			}
+			io_cfg_used_bytes += update_buf.cmd.used_bytes;
+		}
 	}
 
 	CAM_DBG(CAM_ISP, "io_cfg_used_bytes %d, fill_fence %d",
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
index 9c1caa0..2db8e45 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.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
@@ -123,6 +123,7 @@ int cam_isp_add_command_buffers(
  * @base_idx:              Base or dev index of the IFE/VFE HW instance
  * @kmd_buf_info:          Kmd buffer to store the change base command
  * @res_list_isp_out:      IFE /VFE out resource list
+ * @res_list_ife_in_rd:    IFE /VFE in rd resource list
  * @size_isp_out:          Size of the res_list_isp_out array
  * @fill_fence:            If true, Fence map table will be filled
  *
@@ -136,6 +137,7 @@ int cam_isp_add_io_buffers(
 	uint32_t                              base_idx,
 	struct cam_kmd_buf_info              *kmd_buf_info,
 	struct cam_ife_hw_mgr_res            *res_list_isp_out,
+	struct list_head                     *res_list_ife_in_rd,
 	uint32_t                              size_isp_out,
 	bool                                  fill_fence);
 
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
index 85fec0f1..bea99eb 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.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
@@ -222,6 +222,7 @@ static struct cam_ife_csid_csi2_rx_reg_offset
 	.csi2_capture_short_pkt_vc_shift              = 15,
 	.csi2_capture_cphy_pkt_dt_shift               = 20,
 	.csi2_capture_cphy_pkt_vc_shift               = 26,
+	.csi2_rx_phy_num_mask                         = 0x3,
 };
 
 static struct cam_ife_csid_csi2_tpg_reg_offset
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h
index 4b0040f..cf36039 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h
@@ -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
@@ -263,6 +263,7 @@ static struct cam_ife_csid_csi2_rx_reg_offset
 	.csi2_capture_short_pkt_vc_shift              = 15,
 	.csi2_capture_cphy_pkt_dt_shift               = 20,
 	.csi2_capture_cphy_pkt_vc_shift               = 26,
+	.csi2_rx_phy_num_mask                         = 0x3,
 };
 
 static struct cam_ife_csid_csi2_tpg_reg_offset
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h
new file mode 100644
index 0000000..d34f62d
--- /dev/null
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h
@@ -0,0 +1,368 @@
+/* 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_IFE_CSID_175_200_H_
+#define _CAM_IFE_CSID_175_200_H_
+
+#include "cam_ife_csid_core.h"
+
+static struct cam_ife_csid_pxl_reg_offset
+	cam_ife_csid_175_200_ipp_reg_offset = {
+	.csid_pxl_irq_status_addr            = 0x30,
+	.csid_pxl_irq_mask_addr              = 0x34,
+	.csid_pxl_irq_clear_addr             = 0x38,
+	.csid_pxl_irq_set_addr               = 0x3c,
+
+	.csid_pxl_cfg0_addr                  = 0x200,
+	.csid_pxl_cfg1_addr                  = 0x204,
+	.csid_pxl_ctrl_addr                  = 0x208,
+	.csid_pxl_frm_drop_pattern_addr      = 0x20c,
+	.csid_pxl_frm_drop_period_addr       = 0x210,
+	.csid_pxl_irq_subsample_pattern_addr = 0x214,
+	.csid_pxl_irq_subsample_period_addr  = 0x218,
+	.csid_pxl_hcrop_addr                 = 0x21c,
+	.csid_pxl_vcrop_addr                 = 0x220,
+	.csid_pxl_pix_drop_pattern_addr      = 0x224,
+	.csid_pxl_pix_drop_period_addr       = 0x228,
+	.csid_pxl_line_drop_pattern_addr     = 0x22c,
+	.csid_pxl_line_drop_period_addr      = 0x230,
+	.csid_pxl_rst_strobes_addr           = 0x240,
+	.csid_pxl_status_addr                = 0x254,
+	.csid_pxl_misr_val_addr              = 0x258,
+	.csid_pxl_format_measure_cfg0_addr   = 0x270,
+	.csid_pxl_format_measure_cfg1_addr   = 0x274,
+	.csid_pxl_format_measure0_addr       = 0x278,
+	.csid_pxl_format_measure1_addr       = 0x27c,
+	.csid_pxl_format_measure2_addr       = 0x280,
+	.csid_pxl_timestamp_curr0_sof_addr   = 0x290,
+	.csid_pxl_timestamp_curr1_sof_addr   = 0x294,
+	.csid_pxl_timestamp_perv0_sof_addr   = 0x298,
+	.csid_pxl_timestamp_perv1_sof_addr   = 0x29c,
+	.csid_pxl_timestamp_curr0_eof_addr   = 0x2a0,
+	.csid_pxl_timestamp_curr1_eof_addr   = 0x2a4,
+	.csid_pxl_timestamp_perv0_eof_addr   = 0x2a8,
+	.csid_pxl_timestamp_perv1_eof_addr   = 0x2ac,
+	/* configurations */
+	.pix_store_en_shift_val              = 7,
+	.early_eof_en_shift_val              = 29,
+	.ccif_violation_en                   = 1,
+};
+
+static struct cam_ife_csid_pxl_reg_offset
+	cam_ife_csid_175_200_ppp_reg_offset = {
+	.csid_pxl_irq_status_addr            = 0xa0,
+	.csid_pxl_irq_mask_addr              = 0xa4,
+	.csid_pxl_irq_clear_addr             = 0xa8,
+	.csid_pxl_irq_set_addr               = 0xac,
+
+	.csid_pxl_cfg0_addr                  = 0x700,
+	.csid_pxl_cfg1_addr                  = 0x704,
+	.csid_pxl_ctrl_addr                  = 0x708,
+	.csid_pxl_frm_drop_pattern_addr      = 0x70c,
+	.csid_pxl_frm_drop_period_addr       = 0x710,
+	.csid_pxl_irq_subsample_pattern_addr = 0x714,
+	.csid_pxl_irq_subsample_period_addr  = 0x718,
+	.csid_pxl_hcrop_addr                 = 0x71c,
+	.csid_pxl_vcrop_addr                 = 0x720,
+	.csid_pxl_pix_drop_pattern_addr      = 0x724,
+	.csid_pxl_pix_drop_period_addr       = 0x728,
+	.csid_pxl_line_drop_pattern_addr     = 0x72c,
+	.csid_pxl_line_drop_period_addr      = 0x730,
+	.csid_pxl_rst_strobes_addr           = 0x740,
+	.csid_pxl_status_addr                = 0x754,
+	.csid_pxl_misr_val_addr              = 0x758,
+	.csid_pxl_format_measure_cfg0_addr   = 0x770,
+	.csid_pxl_format_measure_cfg1_addr   = 0x774,
+	.csid_pxl_format_measure0_addr       = 0x778,
+	.csid_pxl_format_measure1_addr       = 0x77c,
+	.csid_pxl_format_measure2_addr       = 0x780,
+	.csid_pxl_timestamp_curr0_sof_addr   = 0x790,
+	.csid_pxl_timestamp_curr1_sof_addr   = 0x794,
+	.csid_pxl_timestamp_perv0_sof_addr   = 0x798,
+	.csid_pxl_timestamp_perv1_sof_addr   = 0x79c,
+	.csid_pxl_timestamp_curr0_eof_addr   = 0x7a0,
+	.csid_pxl_timestamp_curr1_eof_addr   = 0x7a4,
+	.csid_pxl_timestamp_perv0_eof_addr   = 0x7a8,
+	.csid_pxl_timestamp_perv1_eof_addr   = 0x7ac,
+	/* configurations */
+	.pix_store_en_shift_val              = 7,
+	.early_eof_en_shift_val              = 29,
+	.ccif_violation_en                   = 1,
+};
+
+
+static struct cam_ife_csid_rdi_reg_offset
+	cam_ife_csid_175_200_rdi_0_reg_offset = {
+	.csid_rdi_irq_status_addr                 = 0x40,
+	.csid_rdi_irq_mask_addr                   = 0x44,
+	.csid_rdi_irq_clear_addr                  = 0x48,
+	.csid_rdi_irq_set_addr                    = 0x4c,
+	.csid_rdi_cfg0_addr                       = 0x300,
+	.csid_rdi_cfg1_addr                       = 0x304,
+	.csid_rdi_ctrl_addr                       = 0x308,
+	.csid_rdi_frm_drop_pattern_addr           = 0x30c,
+	.csid_rdi_frm_drop_period_addr            = 0x310,
+	.csid_rdi_irq_subsample_pattern_addr      = 0x314,
+	.csid_rdi_irq_subsample_period_addr       = 0x318,
+	.csid_rdi_rpp_hcrop_addr                  = 0x31c,
+	.csid_rdi_rpp_vcrop_addr                  = 0x320,
+	.csid_rdi_rpp_pix_drop_pattern_addr       = 0x324,
+	.csid_rdi_rpp_pix_drop_period_addr        = 0x328,
+	.csid_rdi_rpp_line_drop_pattern_addr      = 0x32c,
+	.csid_rdi_rpp_line_drop_period_addr       = 0x330,
+	.csid_rdi_rst_strobes_addr                = 0x340,
+	.csid_rdi_status_addr                     = 0x350,
+	.csid_rdi_misr_val0_addr                  = 0x354,
+	.csid_rdi_misr_val1_addr                  = 0x358,
+	.csid_rdi_misr_val2_addr                  = 0x35c,
+	.csid_rdi_misr_val3_addr                  = 0x360,
+	.csid_rdi_format_measure_cfg0_addr        = 0x370,
+	.csid_rdi_format_measure_cfg1_addr        = 0x374,
+	.csid_rdi_format_measure0_addr            = 0x378,
+	.csid_rdi_format_measure1_addr            = 0x37c,
+	.csid_rdi_format_measure2_addr            = 0x380,
+	.csid_rdi_timestamp_curr0_sof_addr        = 0x390,
+	.csid_rdi_timestamp_curr1_sof_addr        = 0x394,
+	.csid_rdi_timestamp_prev0_sof_addr        = 0x398,
+	.csid_rdi_timestamp_prev1_sof_addr        = 0x39c,
+	.csid_rdi_timestamp_curr0_eof_addr        = 0x3a0,
+	.csid_rdi_timestamp_curr1_eof_addr        = 0x3a4,
+	.csid_rdi_timestamp_prev0_eof_addr        = 0x3a8,
+	.csid_rdi_timestamp_prev1_eof_addr        = 0x3ac,
+	.csid_rdi_byte_cntr_ping_addr             = 0x3e0,
+	.csid_rdi_byte_cntr_pong_addr             = 0x3e4,
+	.ccif_violation_en                        = 1,
+};
+
+static struct cam_ife_csid_rdi_reg_offset
+	cam_ife_csid_175_200_rdi_1_reg_offset = {
+	.csid_rdi_irq_status_addr                 = 0x50,
+	.csid_rdi_irq_mask_addr                   = 0x54,
+	.csid_rdi_irq_clear_addr                  = 0x58,
+	.csid_rdi_irq_set_addr                    = 0x5c,
+	.csid_rdi_cfg0_addr                       = 0x400,
+	.csid_rdi_cfg1_addr                       = 0x404,
+	.csid_rdi_ctrl_addr                       = 0x408,
+	.csid_rdi_frm_drop_pattern_addr           = 0x40c,
+	.csid_rdi_frm_drop_period_addr            = 0x410,
+	.csid_rdi_irq_subsample_pattern_addr      = 0x414,
+	.csid_rdi_irq_subsample_period_addr       = 0x418,
+	.csid_rdi_rpp_hcrop_addr                  = 0x41c,
+	.csid_rdi_rpp_vcrop_addr                  = 0x420,
+	.csid_rdi_rpp_pix_drop_pattern_addr       = 0x424,
+	.csid_rdi_rpp_pix_drop_period_addr        = 0x428,
+	.csid_rdi_rpp_line_drop_pattern_addr      = 0x42c,
+	.csid_rdi_rpp_line_drop_period_addr       = 0x430,
+	.csid_rdi_rst_strobes_addr                = 0x440,
+	.csid_rdi_status_addr                     = 0x450,
+	.csid_rdi_misr_val0_addr                  = 0x454,
+	.csid_rdi_misr_val1_addr                  = 0x458,
+	.csid_rdi_misr_val2_addr                  = 0x45c,
+	.csid_rdi_misr_val3_addr                  = 0x460,
+	.csid_rdi_format_measure_cfg0_addr        = 0x470,
+	.csid_rdi_format_measure_cfg1_addr        = 0x474,
+	.csid_rdi_format_measure0_addr            = 0x478,
+	.csid_rdi_format_measure1_addr            = 0x47c,
+	.csid_rdi_format_measure2_addr            = 0x480,
+	.csid_rdi_timestamp_curr0_sof_addr        = 0x490,
+	.csid_rdi_timestamp_curr1_sof_addr        = 0x494,
+	.csid_rdi_timestamp_prev0_sof_addr        = 0x498,
+	.csid_rdi_timestamp_prev1_sof_addr        = 0x49c,
+	.csid_rdi_timestamp_curr0_eof_addr        = 0x4a0,
+	.csid_rdi_timestamp_curr1_eof_addr        = 0x4a4,
+	.csid_rdi_timestamp_prev0_eof_addr        = 0x4a8,
+	.csid_rdi_timestamp_prev1_eof_addr        = 0x4ac,
+	.csid_rdi_byte_cntr_ping_addr             = 0x4e0,
+	.csid_rdi_byte_cntr_pong_addr             = 0x4e4,
+	.ccif_violation_en                        = 1,
+};
+
+static struct cam_ife_csid_rdi_reg_offset
+	cam_ife_csid_175_200_rdi_2_reg_offset = {
+	.csid_rdi_irq_status_addr                 = 0x60,
+	.csid_rdi_irq_mask_addr                   = 0x64,
+	.csid_rdi_irq_clear_addr                  = 0x68,
+	.csid_rdi_irq_set_addr                    = 0x6c,
+	.csid_rdi_cfg0_addr                       = 0x500,
+	.csid_rdi_cfg1_addr                       = 0x504,
+	.csid_rdi_ctrl_addr                       = 0x508,
+	.csid_rdi_frm_drop_pattern_addr           = 0x50c,
+	.csid_rdi_frm_drop_period_addr            = 0x510,
+	.csid_rdi_irq_subsample_pattern_addr      = 0x514,
+	.csid_rdi_irq_subsample_period_addr       = 0x518,
+	.csid_rdi_rpp_hcrop_addr                  = 0x51c,
+	.csid_rdi_rpp_vcrop_addr                  = 0x520,
+	.csid_rdi_rpp_pix_drop_pattern_addr       = 0x524,
+	.csid_rdi_rpp_pix_drop_period_addr        = 0x528,
+	.csid_rdi_rpp_line_drop_pattern_addr      = 0x52c,
+	.csid_rdi_rpp_line_drop_period_addr       = 0x530,
+	.csid_rdi_yuv_chroma_conversion_addr      = 0x534,
+	.csid_rdi_rst_strobes_addr                = 0x540,
+	.csid_rdi_status_addr                     = 0x550,
+	.csid_rdi_misr_val0_addr                  = 0x554,
+	.csid_rdi_misr_val1_addr                  = 0x558,
+	.csid_rdi_misr_val2_addr                  = 0x55c,
+	.csid_rdi_misr_val3_addr                  = 0x560,
+	.csid_rdi_format_measure_cfg0_addr        = 0x570,
+	.csid_rdi_format_measure_cfg1_addr        = 0x574,
+	.csid_rdi_format_measure0_addr            = 0x578,
+	.csid_rdi_format_measure1_addr            = 0x57c,
+	.csid_rdi_format_measure2_addr            = 0x580,
+	.csid_rdi_timestamp_curr0_sof_addr        = 0x590,
+	.csid_rdi_timestamp_curr1_sof_addr        = 0x594,
+	.csid_rdi_timestamp_prev0_sof_addr        = 0x598,
+	.csid_rdi_timestamp_prev1_sof_addr        = 0x59c,
+	.csid_rdi_timestamp_curr0_eof_addr        = 0x5a0,
+	.csid_rdi_timestamp_curr1_eof_addr        = 0x5a4,
+	.csid_rdi_timestamp_prev0_eof_addr        = 0x5a8,
+	.csid_rdi_timestamp_prev1_eof_addr        = 0x5ac,
+	.csid_rdi_byte_cntr_ping_addr             = 0x5e0,
+	.csid_rdi_byte_cntr_pong_addr             = 0x5e4,
+	.ccif_violation_en                        = 1,
+};
+
+static struct cam_ife_csid_csi2_rx_reg_offset
+			cam_ife_csid_175_200_csi2_reg_offset = {
+	.csid_csi2_rx_irq_status_addr                 = 0x20,
+	.csid_csi2_rx_irq_mask_addr                   = 0x24,
+	.csid_csi2_rx_irq_clear_addr                  = 0x28,
+	.csid_csi2_rx_irq_set_addr                    = 0x2c,
+
+	/*CSI2 rx control */
+	.csid_csi2_rx_cfg0_addr                       = 0x100,
+	.csid_csi2_rx_cfg1_addr                       = 0x104,
+	.csid_csi2_rx_capture_ctrl_addr               = 0x108,
+	.csid_csi2_rx_rst_strobes_addr                = 0x110,
+	.csid_csi2_rx_cap_unmap_long_pkt_hdr_0_addr   = 0x120,
+	.csid_csi2_rx_cap_unmap_long_pkt_hdr_1_addr   = 0x124,
+	.csid_csi2_rx_captured_short_pkt_0_addr       = 0x128,
+	.csid_csi2_rx_captured_short_pkt_1_addr       = 0x12c,
+	.csid_csi2_rx_captured_long_pkt_0_addr        = 0x130,
+	.csid_csi2_rx_captured_long_pkt_1_addr        = 0x134,
+	.csid_csi2_rx_captured_long_pkt_ftr_addr      = 0x138,
+	.csid_csi2_rx_captured_cphy_pkt_hdr_addr      = 0x13c,
+	.csid_csi2_rx_lane0_misr_addr                 = 0x150,
+	.csid_csi2_rx_lane1_misr_addr                 = 0x154,
+	.csid_csi2_rx_lane2_misr_addr                 = 0x158,
+	.csid_csi2_rx_lane3_misr_addr                 = 0x15c,
+	.csid_csi2_rx_total_pkts_rcvd_addr            = 0x160,
+	.csid_csi2_rx_stats_ecc_addr                  = 0x164,
+	.csid_csi2_rx_total_crc_err_addr              = 0x168,
+	.csid_csi2_rx_de_scramble_type3_cfg0_addr     = 0x170,
+	.csid_csi2_rx_de_scramble_type3_cfg1_addr     = 0x174,
+	.csid_csi2_rx_de_scramble_type2_cfg0_addr     = 0x178,
+	.csid_csi2_rx_de_scramble_type2_cfg1_addr     = 0x17c,
+	.csid_csi2_rx_de_scramble_type1_cfg0_addr     = 0x180,
+	.csid_csi2_rx_de_scramble_type1_cfg1_addr     = 0x184,
+	.csid_csi2_rx_de_scramble_type0_cfg0_addr     = 0x188,
+	.csid_csi2_rx_de_scramble_type0_cfg1_addr     = 0x18c,
+
+	.csi2_rst_srb_all                             = 0x3FFF,
+	.csi2_rst_done_shift_val                      = 27,
+	.csi2_irq_mask_all                            = 0xFFFFFFF,
+	.csi2_misr_enable_shift_val                   = 6,
+	.csi2_vc_mode_shift_val                       = 2,
+	.csi2_capture_long_pkt_en_shift               = 0,
+	.csi2_capture_short_pkt_en_shift              = 1,
+	.csi2_capture_cphy_pkt_en_shift               = 2,
+	.csi2_capture_long_pkt_dt_shift               = 4,
+	.csi2_capture_long_pkt_vc_shift               = 10,
+	.csi2_capture_short_pkt_vc_shift              = 15,
+	.csi2_capture_cphy_pkt_dt_shift               = 20,
+	.csi2_capture_cphy_pkt_vc_shift               = 26,
+	.csi2_rx_phy_num_mask                         = 0x7,
+};
+
+static struct cam_ife_csid_csi2_tpg_reg_offset
+			cam_ife_csid_175_200_tpg_reg_offset = {
+	/*CSID TPG control */
+	.csid_tpg_ctrl_addr                           = 0x600,
+	.csid_tpg_vc_cfg0_addr                        = 0x604,
+	.csid_tpg_vc_cfg1_addr                        = 0x608,
+	.csid_tpg_lfsr_seed_addr                      = 0x60c,
+	.csid_tpg_dt_n_cfg_0_addr                     = 0x610,
+	.csid_tpg_dt_n_cfg_1_addr                     = 0x614,
+	.csid_tpg_dt_n_cfg_2_addr                     = 0x618,
+	.csid_tpg_color_bars_cfg_addr                 = 0x640,
+	.csid_tpg_color_box_cfg_addr                  = 0x644,
+	.csid_tpg_common_gen_cfg_addr                 = 0x648,
+	.csid_tpg_cgen_n_cfg_addr                     = 0x650,
+	.csid_tpg_cgen_n_x0_addr                      = 0x654,
+	.csid_tpg_cgen_n_x1_addr                      = 0x658,
+	.csid_tpg_cgen_n_x2_addr                      = 0x65c,
+	.csid_tpg_cgen_n_xy_addr                      = 0x660,
+	.csid_tpg_cgen_n_y1_addr                      = 0x664,
+	.csid_tpg_cgen_n_y2_addr                      = 0x668,
+
+	/* configurations */
+	.tpg_dtn_cfg_offset                           = 0xc,
+	.tpg_cgen_cfg_offset                          = 0x20,
+	.tpg_cpas_ife_reg_offset                      = 0x28,
+};
+
+static struct cam_ife_csid_common_reg_offset
+			cam_ife_csid_175_200_cmn_reg_offset = {
+	.csid_hw_version_addr                         = 0x0,
+	.csid_cfg0_addr                               = 0x4,
+	.csid_ctrl_addr                               = 0x8,
+	.csid_reset_addr                              = 0xc,
+	.csid_rst_strobes_addr                        = 0x10,
+
+	.csid_test_bus_ctrl_addr                      = 0x14,
+	.csid_top_irq_status_addr                     = 0x70,
+	.csid_top_irq_mask_addr                       = 0x74,
+	.csid_top_irq_clear_addr                      = 0x78,
+	.csid_top_irq_set_addr                        = 0x7c,
+	.csid_irq_cmd_addr                            = 0x80,
+
+	/*configurations */
+	.major_version                                = 1,
+	.minor_version                                = 7,
+	.version_incr                                 = 5,
+	.num_rdis                                     = 3,
+	.num_pix                                      = 1,
+	.num_ppp                                      = 1,
+	.csid_rst_stb                                 = 0x1e,
+	.csid_rst_stb_sw_all                          = 0x1f,
+	.path_rst_stb_all                             = 0x7f,
+	.path_rst_done_shift_val                      = 1,
+	.path_en_shift_val                            = 31,
+	.dt_id_shift_val                              = 27,
+	.vc_shift_val                                 = 22,
+	.dt_shift_val                                 = 16,
+	.fmt_shift_val                                = 12,
+	.plain_fmt_shit_val                           = 10,
+	.crop_v_en_shift_val                          = 6,
+	.crop_h_en_shift_val                          = 5,
+	.crop_shift                                   = 16,
+	.ipp_irq_mask_all                             = 0xFFFF,
+	.rdi_irq_mask_all                             = 0xFFFF,
+	.ppp_irq_mask_all                             = 0xFFFF,
+	.measure_en_hbi_vbi_cnt_mask                  = 0xC,
+	.format_measure_en_val                        = 1,
+};
+
+static struct cam_ife_csid_reg_offset cam_ife_csid_175_200_reg_offset = {
+	.cmn_reg          = &cam_ife_csid_175_200_cmn_reg_offset,
+	.csi2_reg         = &cam_ife_csid_175_200_csi2_reg_offset,
+	.ipp_reg          = &cam_ife_csid_175_200_ipp_reg_offset,
+	.ppp_reg          = &cam_ife_csid_175_200_ppp_reg_offset,
+	.rdi_reg = {
+		&cam_ife_csid_175_200_rdi_0_reg_offset,
+		&cam_ife_csid_175_200_rdi_1_reg_offset,
+		&cam_ife_csid_175_200_rdi_2_reg_offset,
+		NULL,
+		},
+	.tpg_reg = &cam_ife_csid_175_200_tpg_reg_offset,
+};
+
+#endif /*_CAM_IFE_CSID_175_200_H_ */
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c
index 0df2fdd..80701bf 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.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
@@ -15,6 +15,7 @@
 #include "cam_ife_csid_core.h"
 #include "cam_ife_csid170.h"
 #include "cam_ife_csid175.h"
+#include "cam_ife_csid175_200.h"
 #include "cam_ife_csid_dev.h"
 
 #define CAM_CSID_DRV_NAME                    "csid_17x"
@@ -31,6 +32,11 @@ static struct cam_ife_csid_hw_info cam_ife_csid175_hw_info = {
 	.hw_dts_version = CAM_CSID_VERSION_V175,
 };
 
+static struct cam_ife_csid_hw_info cam_ife_csid175_200_hw_info = {
+	.csid_reg = &cam_ife_csid_175_200_reg_offset,
+	.hw_dts_version = CAM_CSID_VERSION_V175,
+};
+
 static const struct of_device_id cam_ife_csid17x_dt_match[] = {
 	{
 		.compatible = "qcom,csid170",
@@ -40,6 +46,10 @@ static const struct of_device_id cam_ife_csid17x_dt_match[] = {
 		.compatible = "qcom,csid175",
 		.data = &cam_ife_csid175_hw_info,
 	},
+	{
+		.compatible = "qcom,csid175_200",
+		.data = &cam_ife_csid175_200_hw_info,
+	},
 	{}
 };
 
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index 3cca3c7..e15186d 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.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
@@ -67,6 +67,7 @@ static int cam_ife_csid_is_ipp_ppp_format_supported(
 	case CAM_FORMAT_DPCM_12_8_12:
 	case CAM_FORMAT_DPCM_14_8_14:
 	case CAM_FORMAT_DPCM_14_10_14:
+	case CAM_FORMAT_DPCM_12_10_12:
 		rc = 0;
 		break;
 	default:
@@ -206,6 +207,10 @@ static int cam_ife_csid_get_format_rdi(
 		*decode_fmt  = 0xC;
 		*plain_fmt = 0x1;
 		break;
+	case CAM_FORMAT_DPCM_12_10_12:
+		*decode_fmt  = 0xD;
+		*plain_fmt = 0x1;
+		break;
 	default:
 		rc = -EINVAL;
 		break;
@@ -280,6 +285,10 @@ static int cam_ife_csid_get_format_ipp_ppp(
 		*decode_fmt  = 0xC;
 		*plain_fmt = 0x1;
 		break;
+	case CAM_FORMAT_DPCM_12_10_12:
+		*decode_fmt  = 0xD;
+		*plain_fmt = 0x1;
+		break;
 	default:
 		CAM_ERR(CAM_ISP, "Unsupported format %d",
 			in_format);
@@ -309,6 +318,9 @@ static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
 			if (cid_data->vc == vc && cid_data->dt == dt) {
 				cid_data->cnt++;
 				*res = &csid_hw->cid_res[i];
+				CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated",
+					csid_hw->hw_intf->hw_idx,
+					csid_hw->cid_res[i].res_id);
 				return 0;
 			}
 		}
@@ -647,12 +659,12 @@ static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
 		CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc);
 		goto end;
 	}
-	CAM_DBG(CAM_ISP, "HW version: %d", camera_hw_version);
+	CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version);
 
 	switch (camera_hw_version) {
 	case CAM_CPAS_TITAN_NONE:
 	case CAM_CPAS_TITAN_MAX:
-		CAM_ERR(CAM_ISP, "Invalid HW version: %d", camera_hw_version);
+		CAM_ERR(CAM_ISP, "Invalid HW version: %x", camera_hw_version);
 		break;
 	case CAM_CPAS_TITAN_170_V100:
 	case CAM_CPAS_TITAN_170_V110:
@@ -1327,10 +1339,11 @@ static int cam_ife_csid_enable_csi2(
 		return rc;
 
 	/* rx cfg0 */
-	val = (csid_hw->csi2_rx_cfg.lane_num - 1)  |
-		(csid_hw->csi2_rx_cfg.lane_cfg << 4) |
-		(csid_hw->csi2_rx_cfg.lane_type << 24);
-	val |= (csid_hw->csi2_rx_cfg.phy_sel & 0x3) << 20;
+	val = ((csid_hw->csi2_rx_cfg.lane_num - 1) & 0x3)  |
+		((csid_hw->csi2_rx_cfg.lane_cfg & 0xFFFF) << 4) |
+		((csid_hw->csi2_rx_cfg.lane_type & 0x1) << 24);
+	val |= (csid_hw->csi2_rx_cfg.phy_sel &
+		csid_reg->csi2_reg->csi2_rx_phy_num_mask) << 20;
 	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
 		csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr);
 
@@ -1753,6 +1766,9 @@ static int cam_ife_csid_enable_pxl_path(
 	/* Enable the required pxl path interrupts */
 	val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
 
+	if (pxl_reg->ccif_violation_en)
+		val |= CSID_PATH_ERROR_CCIF_VIOLATION;
+
 	if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)
 		val |= CSID_PATH_INFO_INPUT_SOF;
 	if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)
@@ -1814,7 +1830,7 @@ static int cam_ife_csid_disable_pxl_path(
 	}
 
 	if (!pxl_reg) {
-		CAM_ERR(CAM_ISP, "CSID:%d &s %d is not supported on HW",
+		CAM_ERR(CAM_ISP, "CSID:%d %s %d is not supported on HW",
 			csid_hw->hw_intf->hw_idx, (is_ipp) ? "IPP" : "PPP",
 			res->res_id);
 		return -EINVAL;
@@ -2063,6 +2079,9 @@ static int cam_ife_csid_enable_rdi_path(
 	/* Enable the required RDI interrupts */
 	val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
 
+	if (csid_reg->rdi_reg[id]->ccif_violation_en)
+		val |= CSID_PATH_ERROR_CCIF_VIOLATION;
+
 	if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)
 		val |= CSID_PATH_INFO_INPUT_SOF;
 	if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)
@@ -3039,10 +3058,12 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
 	if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
 		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_STREAM_UNDERFLOW",
 			 csid_hw->hw_intf->hw_idx);
+		csid_hw->error_irq_count++;
 	}
 	if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
 		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME",
 			 csid_hw->hw_intf->hw_idx);
+		csid_hw->error_irq_count++;
 	}
 
 	if (csid_hw->error_irq_count >
@@ -3170,6 +3191,11 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
 			CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP EOF received",
 				csid_hw->hw_intf->hw_idx);
 
+		if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION))
+			CAM_INFO_RATE_LIMIT(CAM_ISP,
+				"CSID:%d IPP CCIF violation",
+				csid_hw->hw_intf->hw_idx);
+
 		if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
 			CAM_ERR_RATE_LIMIT(CAM_ISP,
 				"CSID:%d IPP fifo over flow",
@@ -3203,6 +3229,11 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
 			CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP EOF received",
 				csid_hw->hw_intf->hw_idx);
 
+		if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION))
+			CAM_INFO_RATE_LIMIT(CAM_ISP,
+				"CSID:%d PPP CCIF violation",
+				csid_hw->hw_intf->hw_idx);
+
 		if (irq_status_ppp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
 			CAM_ERR_RATE_LIMIT(CAM_ISP,
 				"CSID:%d PPP fifo over flow",
@@ -3234,6 +3265,10 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
 			CAM_INFO_RATE_LIMIT(CAM_ISP,
 				"CSID RDI:%d EOF received", i);
 
+		if ((irq_status_rdi[i] & CSID_PATH_ERROR_CCIF_VIOLATION))
+			CAM_INFO_RATE_LIMIT(CAM_ISP,
+			"CSIDi RDI :%d CCIF violation", i);
+
 		if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
 			CAM_ERR_RATE_LIMIT(CAM_ISP,
 				"CSID:%d RDI fifo over flow",
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
index 43fd9b0..3a98fc0 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.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
@@ -64,6 +64,7 @@
 #define CSID_PATH_INFO_INPUT_SOF                  BIT(12)
 #define CSID_PATH_ERROR_PIX_COUNT                 BIT(13)
 #define CSID_PATH_ERROR_LINE_COUNT                BIT(14)
+#define CSID_PATH_ERROR_CCIF_VIOLATION            BIT(15)
 
 /*
  * Debug values enable the corresponding interrupts and debug logs provide
@@ -138,6 +139,8 @@ struct cam_ife_csid_pxl_reg_offset {
 	/* configuration */
 	uint32_t  pix_store_en_shift_val;
 	uint32_t  early_eof_en_shift_val;
+	uint32_t  quad_cfa_bin_en_shift_val;
+	uint32_t  ccif_violation_en;
 };
 
 struct cam_ife_csid_rdi_reg_offset {
@@ -182,6 +185,10 @@ struct cam_ife_csid_rdi_reg_offset {
 	uint32_t csid_rdi_timestamp_prev1_eof_addr;
 	uint32_t csid_rdi_byte_cntr_ping_addr;
 	uint32_t csid_rdi_byte_cntr_pong_addr;
+
+	/* configuration */
+	uint32_t packing_format;
+	uint32_t ccif_violation_en;
 };
 
 struct cam_ife_csid_csi2_rx_reg_offset {
@@ -194,7 +201,7 @@ struct cam_ife_csid_csi2_rx_reg_offset {
 	uint32_t csid_csi2_rx_capture_ctrl_addr;
 	uint32_t csid_csi2_rx_rst_strobes_addr;
 	uint32_t csid_csi2_rx_de_scramble_cfg0_addr;
-	uint32_t csid_csi2_rx_de_scramble_cfg1_addr; /* */
+	uint32_t csid_csi2_rx_de_scramble_cfg1_addr;
 	uint32_t csid_csi2_rx_cap_unmap_long_pkt_hdr_0_addr;
 	uint32_t csid_csi2_rx_cap_unmap_long_pkt_hdr_1_addr;
 	uint32_t csid_csi2_rx_captured_short_pkt_0_addr;
@@ -210,6 +217,14 @@ struct cam_ife_csid_csi2_rx_reg_offset {
 	uint32_t csid_csi2_rx_total_pkts_rcvd_addr;
 	uint32_t csid_csi2_rx_stats_ecc_addr;
 	uint32_t csid_csi2_rx_total_crc_err_addr;
+	uint32_t csid_csi2_rx_de_scramble_type3_cfg0_addr;
+	uint32_t csid_csi2_rx_de_scramble_type3_cfg1_addr;
+	uint32_t csid_csi2_rx_de_scramble_type2_cfg0_addr;
+	uint32_t csid_csi2_rx_de_scramble_type2_cfg1_addr;
+	uint32_t csid_csi2_rx_de_scramble_type1_cfg0_addr;
+	uint32_t csid_csi2_rx_de_scramble_type1_cfg1_addr;
+	uint32_t csid_csi2_rx_de_scramble_type0_cfg0_addr;
+	uint32_t csid_csi2_rx_de_scramble_type0_cfg1_addr;
 
 	/*configurations */
 	uint32_t csi2_rst_srb_all;
@@ -225,6 +240,7 @@ struct cam_ife_csid_csi2_rx_reg_offset {
 	uint32_t csi2_capture_short_pkt_vc_shift;
 	uint32_t csi2_capture_cphy_pkt_dt_shift;
 	uint32_t csi2_capture_cphy_pkt_vc_shift;
+	uint32_t csi2_rx_phy_num_mask;
 };
 
 struct cam_ife_csid_csi2_tpg_reg_offset {
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h
index d4e0511..8fe2ecf 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.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
@@ -232,6 +232,7 @@ static const struct cam_ife_csid_csi2_rx_reg_offset
 	.csi2_capture_short_pkt_vc_shift              = 15,
 	.csi2_capture_cphy_pkt_dt_shift               = 20,
 	.csi2_capture_cphy_pkt_vc_shift               = 26,
+	.csi2_rx_phy_num_mask                         = 0x3,
 };
 
 
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index b317f92..0a250df 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.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
@@ -80,14 +80,17 @@ enum cam_isp_resource_type {
 	CAM_ISP_RESOURCE_PIX_PATH,
 	CAM_ISP_RESOURCE_VFE_IN,
 	CAM_ISP_RESOURCE_VFE_OUT,
+	CAM_ISP_RESOURCE_VFE_BUS_RD,
 	CAM_ISP_RESOURCE_MAX,
 };
 
 enum cam_isp_hw_cmd_type {
 	CAM_ISP_HW_CMD_GET_CHANGE_BASE,
 	CAM_ISP_HW_CMD_GET_BUF_UPDATE,
+	CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM,
 	CAM_ISP_HW_CMD_GET_REG_UPDATE,
 	CAM_ISP_HW_CMD_GET_HFR_UPDATE,
+	CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM,
 	CAM_ISP_HW_CMD_GET_SECURE_MODE,
 	CAM_ISP_HW_CMD_STRIPE_UPDATE,
 	CAM_ISP_HW_CMD_CLOCK_UPDATE,
@@ -99,6 +102,8 @@ enum cam_isp_hw_cmd_type {
 	CAM_ISP_HW_CMD_SOF_IRQ_DEBUG,
 	CAM_ISP_HW_CMD_SET_CAMIF_DEBUG,
 	CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE,
+	CAM_ISP_HW_CMD_FE_UPDATE_IN_RD,
+	CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD,
 	CAM_ISP_HW_CMD_MAX,
 };
 
@@ -202,10 +207,12 @@ struct cam_isp_hw_get_cmd_update {
 	union {
 		void                                 *data;
 		struct cam_isp_hw_get_wm_update      *wm_update;
+		struct cam_isp_hw_get_wm_update      *rm_update;
 		struct cam_isp_port_hfr_config       *hfr_update;
 		struct cam_isp_clock_config          *clock_update;
 		struct cam_isp_bw_config             *bw_update;
 		struct cam_ubwc_plane_cfg_v1         *ubwc_update;
+		struct cam_fe_config                 *fe_update;
 	};
 };
 
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
index b957d69..e403ee7 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.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
@@ -28,7 +28,7 @@
 enum cam_isp_hw_vfe_in_mux {
 	CAM_ISP_HW_VFE_IN_CAMIF       = 0,
 	CAM_ISP_HW_VFE_IN_TESTGEN     = 1,
-	CAM_ISP_HW_VFE_IN_BUS_RD      = 2,
+	CAM_ISP_HW_VFE_IN_RD          = 2,
 	CAM_ISP_HW_VFE_IN_RDI0        = 3,
 	CAM_ISP_HW_VFE_IN_RDI1        = 4,
 	CAM_ISP_HW_VFE_IN_RDI2        = 5,
@@ -153,6 +153,7 @@ struct cam_vfe_hw_vfe_in_acquire_args {
  *                           used to schedule bottom of IRQ events associated
  *                           with this resource.
  * @vfe_out:                 Acquire args for VFE_OUT
+ * @vfe_bus_rd               Acquire args for VFE_BUS_READ
  * @vfe_in:                  Acquire args for VFE_IN
  */
 struct cam_vfe_acquire_args {
@@ -160,6 +161,7 @@ struct cam_vfe_acquire_args {
 	void                                *tasklet;
 	union {
 		struct cam_vfe_hw_vfe_out_acquire_args  vfe_out;
+		struct cam_vfe_hw_vfe_out_acquire_args  vfe_bus_rd;
 		struct cam_vfe_hw_vfe_in_acquire_args   vfe_in;
 	};
 };
@@ -178,7 +180,7 @@ struct cam_vfe_clock_update_args {
 /*
  * struct cam_vfe_bw_update_args:
  *
- * @node_res:             Resource to get the time stamp
+ * @node_res:             Resource to get the BW
  * @camnoc_bw_bytes:      Bandwidth vote request for CAMNOC
  * @external_bw_bytes:    Bandwidth vote request from CAMNOC
  *                        out to the rest of the path-to-DDR
@@ -189,6 +191,18 @@ struct cam_vfe_bw_update_args {
 	uint64_t                           external_bw_bytes;
 };
 
+/*
+ * struct cam_vfe_fe_update_args:
+ *
+ * @node_res:             Resource to get fetch configuration
+ * @fe_config:            fetch engine configuration
+ *
+ */
+struct cam_vfe_fe_update_args {
+	struct cam_isp_resource_node      *node_res;
+	struct cam_fe_config               fe_config;
+};
+
 enum cam_vfe_bw_control_action {
 	CAM_VFE_BW_CONTROL_EXCLUDE       = 0,
 	CAM_VFE_BW_CONTROL_INCLUDE       = 1
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index 5e6bb20..1b7a915 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_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
@@ -286,6 +286,16 @@ int cam_vfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size)
 		goto deinint_vfe_res;
 	}
 
+	if (core_info->vfe_rd_bus) {
+		rc = core_info->vfe_rd_bus->hw_ops.init(
+			core_info->vfe_rd_bus->bus_priv,
+			NULL, 0);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Bus RD HW init Failed rc=%d", rc);
+			goto deinint_vfe_res;
+		}
+	}
+
 	vfe_hw->hw_state = CAM_HW_STATE_POWER_UP;
 	return rc;
 
@@ -339,6 +349,14 @@ int cam_vfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size)
 	if (rc)
 		CAM_ERR(CAM_ISP, "Bus HW deinit Failed rc=%d", rc);
 
+	if (core_info->vfe_rd_bus) {
+		rc = core_info->vfe_rd_bus->hw_ops.deinit(
+			core_info->vfe_rd_bus->bus_priv,
+			NULL, 0);
+		if (rc)
+			CAM_ERR(CAM_ISP, "Bus HW deinit Failed rc=%d", rc);
+	}
+
 	isp_res   = (struct cam_isp_resource_node *)deinit_hw_args;
 	if (isp_res && isp_res->deinit) {
 		rc = isp_res->deinit(isp_res, NULL, 0);
@@ -485,18 +503,25 @@ int cam_vfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size)
 	core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info;
 	acquire = (struct cam_vfe_acquire_args   *)reserve_args;
 
+	CAM_DBG(CAM_ISP, "acq res type: %d", acquire->rsrc_type);
 	mutex_lock(&vfe_hw->hw_mutex);
-	if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_IN)
+	if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_IN) {
 		rc = core_info->vfe_top->hw_ops.reserve(
 			core_info->vfe_top->top_priv,
 			acquire,
 			sizeof(*acquire));
-	else if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_OUT)
+	} else if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_OUT) {
 		rc = core_info->vfe_bus->hw_ops.reserve(
 			core_info->vfe_bus->bus_priv, acquire,
 			sizeof(*acquire));
-	else
+	} else if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+		if (core_info->vfe_rd_bus)
+			rc = core_info->vfe_rd_bus->hw_ops.reserve(
+				core_info->vfe_rd_bus->bus_priv, acquire,
+				sizeof(*acquire));
+	} else {
 		CAM_ERR(CAM_ISP, "Invalid res type:%d", acquire->rsrc_type);
+	}
 
 	mutex_unlock(&vfe_hw->hw_mutex);
 
@@ -529,8 +554,14 @@ int cam_vfe_release(void *hw_priv, void *release_args, uint32_t arg_size)
 		rc = core_info->vfe_bus->hw_ops.release(
 			core_info->vfe_bus->bus_priv, isp_res,
 			sizeof(*isp_res));
-	else
+	else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+		if (core_info->vfe_rd_bus)
+			rc = core_info->vfe_rd_bus->hw_ops.release(
+				core_info->vfe_rd_bus->bus_priv, isp_res,
+				sizeof(*isp_res));
+	} else {
 		CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
+	}
 
 	mutex_unlock(&vfe_hw->hw_mutex);
 
@@ -570,6 +601,19 @@ int cam_vfe_start(void *hw_priv, void *start_args, uint32_t arg_size)
 					&tasklet_bh_api);
 			if (isp_res->irq_handle < 1)
 				rc = -ENOMEM;
+		} else if (isp_res->res_id == CAM_ISP_HW_VFE_IN_RD) {
+			isp_res->irq_handle =
+				cam_irq_controller_subscribe_irq(
+					core_info->vfe_irq_controller,
+					CAM_IRQ_PRIORITY_1,
+					camif_irq_reg_mask,
+					&core_info->irq_payload,
+					cam_vfe_irq_top_half,
+					cam_ife_mgr_do_tasklet,
+					isp_res->tasklet_info,
+					&tasklet_bh_api);
+			if (isp_res->irq_handle < 1)
+				rc = -ENOMEM;
 		} else if (isp_res->rdi_only_ctx) {
 			isp_res->irq_handle =
 				cam_irq_controller_subscribe_irq(
@@ -598,6 +642,10 @@ int cam_vfe_start(void *hw_priv, void *start_args, uint32_t arg_size)
 		}
 	} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
 		rc = core_info->vfe_bus->hw_ops.start(isp_res, NULL, 0);
+	} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+		if (core_info->vfe_rd_bus)
+			rc = core_info->vfe_rd_bus->hw_ops.start(isp_res,
+				NULL, 0);
 	} else {
 		CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
 		rc = -EFAULT;
@@ -653,6 +701,10 @@ int cam_vfe_stop(void *hw_priv, void *stop_args, uint32_t arg_size)
 			sizeof(struct cam_isp_resource_node));
 	} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
 		rc = core_info->vfe_bus->hw_ops.stop(isp_res, NULL, 0);
+	} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+		if (core_info->vfe_rd_bus)
+			rc = core_info->vfe_rd_bus->hw_ops.stop(isp_res,
+				NULL, 0);
 	} else {
 		CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
 	}
@@ -716,7 +768,26 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
 			core_info->vfe_bus->bus_priv, cmd_type, cmd_args,
 			arg_size);
 		break;
+	case CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM:
+	case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
+		if (core_info->vfe_rd_bus)
+			rc = core_info->vfe_rd_bus->hw_ops.process_cmd(
+				core_info->vfe_rd_bus->bus_priv, cmd_type,
+				cmd_args, arg_size);
+		break;
 
+	case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
+		rc = core_info->vfe_top->hw_ops.process_cmd(
+			core_info->vfe_top->top_priv, cmd_type, cmd_args,
+			arg_size);
+		break;
+	case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
+		if (core_info->vfe_rd_bus) {
+			rc = core_info->vfe_rd_bus->hw_ops.process_cmd(
+				core_info->vfe_rd_bus->bus_priv, cmd_type,
+				cmd_args, arg_size);
+		}
+		break;
 	default:
 		CAM_ERR(CAM_ISP, "Invalid cmd type:%d", cmd_type);
 		rc = -EINVAL;
@@ -766,7 +837,8 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info  *core_info,
 		goto deinit_controller;
 	}
 
-	rc = cam_vfe_bus_init(vfe_hw_info->bus_version, soc_info, hw_intf,
+	rc = cam_vfe_bus_init(vfe_hw_info->bus_version, BUS_TYPE_WR,
+		soc_info, hw_intf,
 		vfe_hw_info->bus_hw_info, core_info->vfe_irq_controller,
 		&core_info->vfe_bus);
 	if (rc) {
@@ -774,6 +846,19 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info  *core_info,
 		goto deinit_top;
 	}
 
+	/* Read Bus is not valid for vfe-lite */
+	if ((hw_intf->hw_idx == 0) || (hw_intf->hw_idx == 1)) {
+		rc = cam_vfe_bus_init(vfe_hw_info->bus_rd_version, BUS_TYPE_RD,
+			soc_info, hw_intf, vfe_hw_info->bus_rd_hw_info,
+			core_info->vfe_irq_controller, &core_info->vfe_rd_bus);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Error! RD cam_vfe_bus_init failed");
+			rc = 0;
+		}
+		CAM_DBG(CAM_ISP, "vfe_bus_rd %pK hw_idx %d",
+			core_info->vfe_rd_bus, hw_intf->hw_idx);
+	}
+
 	INIT_LIST_HEAD(&core_info->free_payload_list);
 	for (i = 0; i < CAM_VFE_EVT_MAX; i++) {
 		INIT_LIST_HEAD(&core_info->evt_payload[i].list);
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
index 9cec56a..dd078f2 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.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
@@ -25,6 +25,9 @@ struct cam_vfe_hw_info {
 	uint32_t                          bus_version;
 	void                             *bus_hw_info;
 
+	uint32_t                          bus_rd_version;
+	void                             *bus_rd_hw_info;
+
 	uint32_t                          top_version;
 	void                             *top_hw_info;
 	uint32_t                          camif_version;
@@ -53,6 +56,7 @@ struct cam_vfe_hw_core_info {
 	void                               *vfe_irq_controller;
 	struct cam_vfe_top                 *vfe_top;
 	struct cam_vfe_bus                 *vfe_bus;
+	struct cam_vfe_bus                 *vfe_rd_bus;
 	void                               *tasklet_info;
 	struct cam_vfe_top_irq_evt_payload  evt_payload[CAM_VFE_EVT_MAX];
 	struct list_head                    free_payload_list;
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
index ba48491..5490cb3 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_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
@@ -117,20 +117,56 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
 	}
 
 	memset(&cpas_register_param, 0, sizeof(cpas_register_param));
-	strlcpy(cpas_register_param.identifier, "ife",
-		CAM_HW_IDENTIFIER_LENGTH);
+
 	cpas_register_param.cell_index = soc_info->index;
 	cpas_register_param.dev = soc_info->dev;
 	cpas_register_param.cam_cpas_client_cb = cam_vfe_cpas_cb;
 	cpas_register_param.userdata = soc_info;
-	rc = cam_cpas_register_client(&cpas_register_param);
+
+	rc = cam_cpas_get_cpas_hw_version(&soc_private->cpas_version);
 	if (rc) {
-		CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
-		goto release_soc;
-	} else {
-		soc_private->cpas_handle = cpas_register_param.client_handle;
+		CAM_ERR(CAM_ISP, "Error! Invalid cpas version rc=%d", rc);
+		goto free_soc_private;
 	}
 
+	switch (soc_private->cpas_version) {
+	case CAM_CPAS_TITAN_175_V120:
+		strlcpy(cpas_register_param.identifier, "iferdi",
+			CAM_HW_IDENTIFIER_LENGTH);
+		rc = cam_cpas_register_client(&cpas_register_param);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "rdi CPAS registration failed rc=%d",
+				rc);
+			goto release_soc;
+		} else {
+			soc_private->cpas_handle[0] =
+				cpas_register_param.client_handle;
+		}
+
+		strlcpy(cpas_register_param.identifier, "ifenrdi",
+			CAM_HW_IDENTIFIER_LENGTH);
+		rc = cam_cpas_register_client(&cpas_register_param);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "nrdi CPAS registration failed rc=%d",
+				rc);
+			goto release_soc;
+		} else {
+			soc_private->cpas_handle[1] =
+				cpas_register_param.client_handle;
+		}
+		break;
+	default:
+		strlcpy(cpas_register_param.identifier, "ife",
+			CAM_HW_IDENTIFIER_LENGTH);
+		rc = cam_cpas_register_client(&cpas_register_param);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
+			goto release_soc;
+		} else {
+			soc_private->cpas_handle[0] =
+				cpas_register_param.client_handle;
+		}
+	}
 	return rc;
 
 release_soc:
@@ -156,10 +192,15 @@ int cam_vfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info)
 		CAM_ERR(CAM_ISP, "Error! soc_private NULL");
 		return -ENODEV;
 	}
-
-	rc = cam_cpas_unregister_client(soc_private->cpas_handle);
+	rc = cam_cpas_unregister_client(soc_private->cpas_handle[0]);
 	if (rc)
-		CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc);
+		CAM_ERR(CAM_ISP, "CPAS0 unregistration failed rc=%d", rc);
+
+	if (!rc && soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+		rc = cam_cpas_unregister_client(soc_private->cpas_handle[1]);
+		if (rc)
+			CAM_ERR(CAM_ISP, "CPAS1 unregistration failed rc=%d",
+				rc);
 
 	rc = cam_vfe_release_platform_resource(soc_info);
 	if (rc < 0)
@@ -196,13 +237,22 @@ int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 	axi_vote.compressed_bw   = 10640000000L;
 	axi_vote.uncompressed_bw = 10640000000L;
 
-	rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
+	rc = cam_cpas_start(soc_private->cpas_handle[0], &ahb_vote, &axi_vote);
 	if (rc) {
-		CAM_ERR(CAM_ISP, "Error! CPAS start failed rc=%d", rc);
+		CAM_ERR(CAM_ISP, "Error! CPAS0 start failed rc=%d", rc);
 		rc = -EFAULT;
 		goto end;
 	}
 
+	if (!rc && soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+		rc = cam_cpas_start(soc_private->cpas_handle[1], &ahb_vote,
+			&axi_vote);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Error! CPAS1 start failed rc=%d", rc);
+			rc = -EFAULT;
+			goto end;
+		}
+
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		CAM_TURBO_VOTE, true);
 	if (rc) {
@@ -213,7 +263,9 @@ int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 	return rc;
 
 stop_cpas:
-	cam_cpas_stop(soc_private->cpas_handle);
+	cam_cpas_stop(soc_private->cpas_handle[0]);
+	if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+		cam_cpas_stop(soc_private->cpas_handle[1]);
 end:
 	return rc;
 }
@@ -285,11 +337,18 @@ int cam_vfe_disable_soc_resources(struct cam_hw_soc_info *soc_info)
 		return rc;
 	}
 
-	rc = cam_cpas_stop(soc_private->cpas_handle);
+	rc = cam_cpas_stop(soc_private->cpas_handle[0]);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "Error! CPAS stop failed rc=%d", rc);
 		return rc;
 	}
 
+	if (!rc && soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+		rc = cam_cpas_stop(soc_private->cpas_handle[1]);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Error! CPAS stop failed rc=%d", rc);
+			return rc;
+		}
+
 	return rc;
 }
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
index 3f862e9..780bd34 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.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
@@ -18,6 +18,12 @@
 
 #define CAM_VFE_DSP_CLK_NAME "ife_dsp_clk"
 
+enum cam_cpas_handle_id {
+	CAM_CPAS_HANDLE_CAMIF,
+	CAM_CPAS_HANDLE_RAW,
+	CAM_CPAS_HANDLE_MAX,
+};
+
 /*
  * struct cam_vfe_soc_private:
  *
@@ -26,9 +32,11 @@
  * @cpas_handle:             Handle returned on registering with CPAS driver.
  *                           This handle is used for all further interface
  *                           with CPAS.
+ * @cpas_version:            Has cpas version read from Hardware
  */
 struct cam_vfe_soc_private {
-	uint32_t    cpas_handle;
+	uint32_t    cpas_handle[CAM_CPAS_HANDLE_MAX];
+	uint32_t    cpas_version;
 	struct clk *dsp_clk;
 	int32_t     dsp_clk_index;
 	int32_t     dsp_clk_rate;
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
new file mode 100644
index 0000000..3cf01cc
--- /dev/null
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
@@ -0,0 +1,1117 @@
+/* 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_VFE175_130_H_
+#define _CAM_VFE175_130_H_
+
+#include "cam_vfe_camif_ver2.h"
+#include "cam_vfe_camif_lite_ver2.h"
+#include "cam_vfe_bus_ver2.h"
+#include "cam_vfe_bus_rd_ver1.h"
+#include "cam_irq_controller.h"
+#include "cam_vfe_top_ver2.h"
+#include "cam_vfe_core.h"
+
+static struct cam_irq_register_set vfe175_130_top_irq_reg_set[2] = {
+	{
+		.mask_reg_offset   = 0x0000005C,
+		.clear_reg_offset  = 0x00000064,
+		.status_reg_offset = 0x0000006C,
+	},
+	{
+		.mask_reg_offset   = 0x00000060,
+		.clear_reg_offset  = 0x00000068,
+		.status_reg_offset = 0x00000070,
+	},
+};
+
+static struct cam_irq_controller_reg_info vfe175_130_top_irq_reg_info = {
+	.num_registers = 2,
+	.irq_reg_set = vfe175_130_top_irq_reg_set,
+	.global_clear_offset  = 0x00000058,
+	.global_clear_bitmask = 0x00000001,
+};
+
+static struct cam_vfe_camif_ver2_reg vfe175_130_camif_reg = {
+	.camif_cmd                = 0x00000478,
+	.camif_config             = 0x0000047C,
+	.line_skip_pattern        = 0x00000488,
+	.pixel_skip_pattern       = 0x0000048C,
+	.skip_period              = 0x00000490,
+	.irq_subsample_pattern    = 0x0000049C,
+	.epoch_irq                = 0x000004A0,
+	.raw_crop_width_cfg       = 0x00000CE4,
+	.raw_crop_height_cfg      = 0x00000CE8,
+	.reg_update_cmd           = 0x000004AC,
+	.vfe_diag_config          = 0x00000C48,
+	.vfe_diag_sensor_status   = 0x00000C4C,
+};
+
+static struct cam_vfe_camif_reg_data vfe_175_130_camif_reg_data = {
+	.raw_crop_first_pixel_shift      = 16,
+	.raw_crop_first_pixel_mask       = 0xFFFF,
+	.raw_crop_last_pixel_shift       = 0x0,
+	.raw_crop_last_pixel_mask        = 0x3FFF,
+	.raw_crop_first_line_shift       = 16,
+	.raw_crop_first_line_mask        = 0xFFFF,
+	.raw_crop_last_line_shift        = 0,
+	.raw_crop_last_line_mask         = 0x3FFF,
+	.input_mux_sel_shift             = 5,
+	.input_mux_sel_mask              = 0x3,
+	.extern_reg_update_shift         = 4,
+	.extern_reg_update_mask          = 1,
+	.pixel_pattern_shift             = 0,
+	.pixel_pattern_mask              = 0x7,
+	.dsp_mode_shift                  = 23,
+	.dsp_mode_mask                   = 0x1,
+	.dsp_en_shift                    = 3,
+	.dsp_en_mask                     = 0x1,
+	.reg_update_cmd_data             = 0x1,
+	.epoch_line_cfg                  = 0x00140014,
+	.sof_irq_mask                    = 0x00000001,
+	.epoch0_irq_mask                 = 0x00000004,
+	.reg_update_irq_mask             = 0x00000010,
+	.eof_irq_mask                    = 0x00000002,
+	.error_irq_mask0                 = 0x0003FC00,
+	.error_irq_mask1                 = 0xEFFF7E80,
+	.enable_diagnostic_hw            = 0x1,
+};
+
+static struct cam_vfe_fe_ver1_reg vfe175_130_fe_reg = {
+	.camif_cmd                = 0x00000478,
+	.camif_config             = 0x0000047C,
+	.line_skip_pattern        = 0x00000488,
+	.pixel_skip_pattern       = 0x0000048C,
+	.skip_period              = 0x00000490,
+	.irq_subsample_pattern    = 0x0000049C,
+	.epoch_irq                = 0x000004A0,
+	.raw_crop_width_cfg       = 0x00000CE4,
+	.raw_crop_height_cfg      = 0x00000CE8,
+	.reg_update_cmd           = 0x000004AC,
+	.vfe_diag_config          = 0x00000C48,
+	.vfe_diag_sensor_status   = 0x00000C4C,
+	.fe_cfg                = 0x00000084,
+};
+
+static struct cam_vfe_fe_reg_data vfe_175_130_fe_reg_data = {
+	.raw_crop_first_pixel_shift      = 16,
+	.raw_crop_first_pixel_mask       = 0xFFFF,
+	.raw_crop_last_pixel_shift       = 0x0,
+	.raw_crop_last_pixel_mask        = 0x3FFF,
+	.raw_crop_first_line_shift       = 16,
+	.raw_crop_first_line_mask        = 0xFFFF,
+	.raw_crop_last_line_shift        = 0,
+	.raw_crop_last_line_mask         = 0x3FFF,
+	.input_mux_sel_shift             = 5,
+	.input_mux_sel_mask              = 0x3,
+	.extern_reg_update_shift         = 4,
+	.extern_reg_update_mask          = 1,
+	.pixel_pattern_shift             = 0,
+	.pixel_pattern_mask              = 0x7,
+	.dsp_mode_shift                  = 23,
+	.dsp_mode_mask                   = 0x1,
+	.dsp_en_shift                    = 3,
+	.dsp_en_mask                     = 0x1,
+	.reg_update_cmd_data             = 0x1,
+	.epoch_line_cfg                  = 0x00140014,
+	.sof_irq_mask                    = 0x00000001,
+	.epoch0_irq_mask                 = 0x00000004,
+	.reg_update_irq_mask             = 0x00000010,
+	.eof_irq_mask                    = 0x00000002,
+	.error_irq_mask0                 = 0x0003FC00,
+	.error_irq_mask1                 = 0xEFFF7E80,
+	.enable_diagnostic_hw            = 0x1,
+	.fe_mux_data                  = 0x2,
+	.hbi_cnt_shift                   = 0x8,
+};
+
+static struct cam_vfe_camif_lite_ver2_reg vfe175_130_camif_lite_reg = {
+	.camif_lite_cmd                = 0x00000FC0,
+	.camif_lite_config             = 0x00000FC4,
+	.lite_skip_period              = 0x00000FC8,
+	.lite_irq_subsample_pattern    = 0x00000FCC,
+	.lite_epoch_irq                = 0x00000FD0,
+	.reg_update_cmd                = 0x000004AC,
+};
+
+static struct cam_vfe_camif_lite_ver2_reg_data
+	vfe175_130_camif_lite_reg_data = {
+	.dual_pd_reg_update_cmd_data     = 0x20,
+	.lite_epoch_line_cfg             = 0x00140014,
+	.lite_sof_irq_mask               = 0x00040000,
+	.lite_epoch0_irq_mask            = 0x00100000,
+	.dual_pd_reg_upd_irq_mask        = 0x04000000,
+	.lite_eof_irq_mask               = 0x00080000,
+	.lite_error_irq_mask0            = 0x00400000,
+	.lite_error_irq_mask1            = 0x00004100,
+	.extern_reg_update_shift         = 4,
+	.dual_pd_path_sel_shift          = 24,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_175_130_reg = {
+	.reset    = 0x0000001C,
+	.cgc_ovd  = 0x0000002C,
+	.enable   = 0x00000040,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_175_130_reg = {
+	.reset    = 0x00000020,
+	.cgc_ovd  = 0x00000030,
+	.enable   = 0x00000044,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl color_175_130_reg = {
+	.reset    = 0x00000024,
+	.cgc_ovd  = 0x00000034,
+	.enable   = 0x00000048,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_175_130_reg = {
+	.reset    = 0x00000028,
+	.cgc_ovd  = 0x00000038,
+	.enable   = 0x0000004C,
+};
+
+static struct cam_vfe_top_ver2_reg_offset_common vfe175_130_top_common_reg = {
+	.hw_version               = 0x00000000,
+	.hw_capability            = 0x00000004,
+	.lens_feature             = 0x00000008,
+	.stats_feature            = 0x0000000C,
+	.color_feature            = 0x00000010,
+	.zoom_feature             = 0x00000014,
+	.global_reset_cmd         = 0x00000018,
+	.module_ctrl              = {
+		&lens_175_130_reg,
+		&stats_175_130_reg,
+		&color_175_130_reg,
+		&zoom_175_130_reg,
+	},
+	.bus_cgc_ovd              = 0x0000003C,
+	.core_cfg                 = 0x00000050,
+	.three_D_cfg              = 0x00000054,
+	.violation_status         = 0x0000007C,
+	.reg_update_cmd           = 0x000004AC,
+};
+
+static struct cam_vfe_rdi_ver2_reg vfe175_130_rdi_reg = {
+	.reg_update_cmd           = 0x000004AC,
+};
+
+static struct cam_vfe_rdi_reg_data  vfe_175_130_rdi_0_data = {
+	.reg_update_cmd_data      = 0x2,
+	.sof_irq_mask             = 0x8000000,
+	.reg_update_irq_mask      = 0x20,
+};
+
+static struct cam_vfe_rdi_reg_data  vfe_175_130_rdi_1_data = {
+	.reg_update_cmd_data      = 0x4,
+	.sof_irq_mask             = 0x10000000,
+	.reg_update_irq_mask      = 0x40,
+};
+
+static struct cam_vfe_rdi_reg_data  vfe_175_130_rdi_2_data = {
+	.reg_update_cmd_data      = 0x8,
+	.sof_irq_mask             = 0x20000000,
+	.reg_update_irq_mask      = 0x80,
+};
+
+static struct cam_vfe_top_ver2_hw_info vfe175_130_top_hw_info = {
+	.common_reg = &vfe175_130_top_common_reg,
+	.camif_hw_info = {
+		.common_reg     = &vfe175_130_top_common_reg,
+		.camif_reg      = &vfe175_130_camif_reg,
+		.reg_data       = &vfe_175_130_camif_reg_data,
+		},
+	.camif_lite_hw_info = {
+		.common_reg     = &vfe175_130_top_common_reg,
+		.camif_lite_reg = &vfe175_130_camif_lite_reg,
+		.reg_data       = &vfe175_130_camif_lite_reg_data,
+		},
+	.rdi_hw_info = {
+		.common_reg = &vfe175_130_top_common_reg,
+		.rdi_reg    = &vfe175_130_rdi_reg,
+		.reg_data = {
+			&vfe_175_130_rdi_0_data,
+			&vfe_175_130_rdi_1_data,
+			&vfe_175_130_rdi_2_data,
+			NULL,
+			},
+		},
+	.fe_hw_info = {
+		.common_reg     = &vfe175_130_top_common_reg,
+		.fe_reg     = &vfe175_130_fe_reg,
+		.reg_data       = &vfe_175_130_fe_reg_data,
+		},
+	.mux_type = {
+		CAM_VFE_CAMIF_VER_2_0,
+		CAM_VFE_RDI_VER_1_0,
+		CAM_VFE_RDI_VER_1_0,
+		CAM_VFE_RDI_VER_1_0,
+		CAM_VFE_CAMIF_LITE_VER_2_0,
+		CAM_VFE_IN_RD_VER_1_0,
+	},
+};
+
+static struct cam_irq_register_set vfe175_130_bus_rd_irq_reg[1] = {
+		{
+			.mask_reg_offset   = 0x00005010,
+			.clear_reg_offset  = 0x00005014,
+			.status_reg_offset = 0x0000501C,
+		},
+};
+
+static struct cam_irq_register_set vfe175_130_bus_irq_reg[3] = {
+		{
+			.mask_reg_offset   = 0x00002044,
+			.clear_reg_offset  = 0x00002050,
+			.status_reg_offset = 0x0000205C,
+		},
+		{
+			.mask_reg_offset   = 0x00002048,
+			.clear_reg_offset  = 0x00002054,
+			.status_reg_offset = 0x00002060,
+		},
+		{
+			.mask_reg_offset   = 0x0000204C,
+			.clear_reg_offset  = 0x00002058,
+			.status_reg_offset = 0x00002064,
+		},
+};
+
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+	vfe175_130_ubwc_regs_client_3 = {
+	.tile_cfg         = 0x0000252C,
+	.h_init           = 0x00002530,
+	.v_init           = 0x00002534,
+	.meta_addr        = 0x00002538,
+	.meta_offset      = 0x0000253C,
+	.meta_stride      = 0x00002540,
+	.mode_cfg_0       = 0x00002544,
+	.mode_cfg_1       = 0x000025A4,
+	.bw_limit         = 0x000025A0,
+};
+
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+	vfe175_130_ubwc_regs_client_4 = {
+	.tile_cfg         = 0x0000262C,
+	.h_init           = 0x00002630,
+	.v_init           = 0x00002634,
+	.meta_addr        = 0x00002638,
+	.meta_offset      = 0x0000263C,
+	.meta_stride      = 0x00002640,
+	.mode_cfg_0       = 0x00002644,
+	.mode_cfg_1       = 0x000026A4,
+	.bw_limit         = 0x000026A0,
+};
+
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+	vfe175_130_ubwc_regs_client_20 = {
+	.tile_cfg         = 0x0000362C,
+	.h_init           = 0x00003630,
+	.v_init           = 0x00003634,
+	.meta_addr        = 0x00003638,
+	.meta_offset      = 0x0000363C,
+	.meta_stride      = 0x00003640,
+	.mode_cfg_0       = 0x00003644,
+	.mode_cfg_1       = 0x000036A4,
+	.bw_limit         = 0x000036A0,
+};
+
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+	vfe175_130_ubwc_regs_client_21 = {
+	.tile_cfg         = 0x0000372C,
+	.h_init           = 0x00003730,
+	.v_init           = 0x00003734,
+	.meta_addr        = 0x00003738,
+	.meta_offset      = 0x0000373C,
+	.meta_stride      = 0x00003740,
+	.mode_cfg_0       = 0x00003744,
+	.mode_cfg_1       = 0x000037A4,
+	.bw_limit         = 0x000037A0,
+};
+
+static struct cam_vfe_bus_rd_ver1_hw_info vfe175_130_bus_rd_hw_info = {
+	.common_reg = {
+		.hw_version                   = 0x00005000,
+		.hw_capability                = 0x00005004,
+		.sw_reset                     = 0x00005008,
+		.cgc_ovd                      = 0x0000500C,
+		.pwr_iso_cfg                  = 0x000050CC,
+		.input_if_cmd                 = 0x00005020,
+		.test_bus_ctrl                = 0x00005048,
+		.irq_reg_info = {
+			.num_registers        = 1,
+			.irq_reg_set          = vfe175_130_bus_rd_irq_reg,
+			.global_clear_offset  = 0x00005018,
+			.global_clear_bitmask = 0x00000001,
+		},
+	},
+	.num_client = 1,
+	.bus_client_reg = {
+		/* BUS Client 0 */
+		{
+			.cfg                      = 0x00005050,
+			.image_addr               = 0x00005058,
+			.buffer_width_cfg         = 0x0000505C,
+			.unpacker_cfg             = 0x00005064,
+			.stride                   = 0x00005060,
+			.burst_limit              = 0x00005080,
+			.latency_buf_allocation   = 0x00005078,
+			.ubwc_regs                = NULL,
+		},
+	},
+	.num_bus_rd_resc = 1,
+	.vfe_bus_rd_hw_info = {
+		{
+			.vfe_bus_rd_type = CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+	},
+};
+
+static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = {
+	.common_reg = {
+		.hw_version                   = 0x00002000,
+		.hw_capability                = 0x00002004,
+		.sw_reset                     = 0x00002008,
+		.cgc_ovd                      = 0x0000200C,
+		.pwr_iso_cfg                  = 0x000020CC,
+		.dual_master_comp_cfg         = 0x00002028,
+		.irq_reg_info = {
+			.num_registers        = 3,
+			.irq_reg_set          = vfe175_130_bus_irq_reg,
+			.global_clear_offset  = 0x00002068,
+			.global_clear_bitmask = 0x00000001,
+		},
+		.comp_error_status            = 0x0000206C,
+		.comp_ovrwr_status            = 0x00002070,
+		.dual_comp_error_status       = 0x00002074,
+		.dual_comp_ovrwr_status       = 0x00002078,
+		.addr_sync_cfg                = 0x0000207C,
+		.addr_sync_frame_hdr          = 0x00002080,
+		.addr_sync_no_sync            = 0x00002084,
+	},
+	.num_client = 24,
+	.bus_client_reg = {
+		/* BUS Client 0 */
+		{
+			.status0                  = 0x00002200,
+			.status1                  = 0x00002204,
+			.cfg                      = 0x00002208,
+			.header_addr              = 0x0000220C,
+			.header_cfg               = 0x00002210,
+			.image_addr               = 0x00002214,
+			.image_addr_offset        = 0x00002218,
+			.buffer_width_cfg         = 0x0000221C,
+			.buffer_height_cfg        = 0x00002220,
+			.packer_cfg               = 0x00002224,
+			.stride                   = 0x00002228,
+			.irq_subsample_period     = 0x00002248,
+			.irq_subsample_pattern    = 0x0000224C,
+			.framedrop_period         = 0x00002250,
+			.framedrop_pattern        = 0x00002254,
+			.frame_inc                = 0x00002258,
+			.burst_limit              = 0x0000225C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 1 */
+		{
+			.status0                  = 0x00002300,
+			.status1                  = 0x00002304,
+			.cfg                      = 0x00002308,
+			.header_addr              = 0x0000230C,
+			.header_cfg               = 0x00002310,
+			.image_addr               = 0x00002314,
+			.image_addr_offset        = 0x00002318,
+			.buffer_width_cfg         = 0x0000231C,
+			.buffer_height_cfg        = 0x00002320,
+			.packer_cfg               = 0x00002324,
+			.stride                   = 0x00002328,
+			.irq_subsample_period     = 0x00002348,
+			.irq_subsample_pattern    = 0x0000234C,
+			.framedrop_period         = 0x00002350,
+			.framedrop_pattern        = 0x00002354,
+			.frame_inc                = 0x00002358,
+			.burst_limit              = 0x0000235C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 2 */
+		{
+			.status0                  = 0x00002400,
+			.status1                  = 0x00002404,
+			.cfg                      = 0x00002408,
+			.header_addr              = 0x0000240C,
+			.header_cfg               = 0x00002410,
+			.image_addr               = 0x00002414,
+			.image_addr_offset        = 0x00002418,
+			.buffer_width_cfg         = 0x0000241C,
+			.buffer_height_cfg        = 0x00002420,
+			.packer_cfg               = 0x00002424,
+			.stride                   = 0x00002428,
+			.irq_subsample_period     = 0x00002448,
+			.irq_subsample_pattern    = 0x0000244C,
+			.framedrop_period         = 0x00002450,
+			.framedrop_pattern        = 0x00002454,
+			.frame_inc                = 0x00002458,
+			.burst_limit              = 0x0000245C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 3 */
+		{
+			.status0                  = 0x00002500,
+			.status1                  = 0x00002504,
+			.cfg                      = 0x00002508,
+			.header_addr              = 0x0000250C,
+			.header_cfg               = 0x00002510,
+			.image_addr               = 0x00002514,
+			.image_addr_offset        = 0x00002518,
+			.buffer_width_cfg         = 0x0000251C,
+			.buffer_height_cfg        = 0x00002520,
+			.packer_cfg               = 0x00002524,
+			.stride                   = 0x00002528,
+			.irq_subsample_period     = 0x00002548,
+			.irq_subsample_pattern    = 0x0000254C,
+			.framedrop_period         = 0x00002550,
+			.framedrop_pattern        = 0x00002554,
+			.frame_inc                = 0x00002558,
+			.burst_limit              = 0x0000255C,
+			.ubwc_regs                =
+				&vfe175_130_ubwc_regs_client_3,
+		},
+		/* BUS Client 4 */
+		{
+			.status0                  = 0x00002600,
+			.status1                  = 0x00002604,
+			.cfg                      = 0x00002608,
+			.header_addr              = 0x0000260C,
+			.header_cfg               = 0x00002610,
+			.image_addr               = 0x00002614,
+			.image_addr_offset        = 0x00002618,
+			.buffer_width_cfg         = 0x0000261C,
+			.buffer_height_cfg        = 0x00002620,
+			.packer_cfg               = 0x00002624,
+			.stride                   = 0x00002628,
+			.irq_subsample_period     = 0x00002648,
+			.irq_subsample_pattern    = 0x0000264C,
+			.framedrop_period         = 0x00002650,
+			.framedrop_pattern        = 0x00002654,
+			.frame_inc                = 0x00002658,
+			.burst_limit              = 0x0000265C,
+			.ubwc_regs                =
+				&vfe175_130_ubwc_regs_client_4,
+		},
+		/* BUS Client 5 */
+		{
+			.status0                  = 0x00002700,
+			.status1                  = 0x00002704,
+			.cfg                      = 0x00002708,
+			.header_addr              = 0x0000270C,
+			.header_cfg               = 0x00002710,
+			.image_addr               = 0x00002714,
+			.image_addr_offset        = 0x00002718,
+			.buffer_width_cfg         = 0x0000271C,
+			.buffer_height_cfg        = 0x00002720,
+			.packer_cfg               = 0x00002724,
+			.stride                   = 0x00002728,
+			.irq_subsample_period     = 0x00002748,
+			.irq_subsample_pattern    = 0x0000274C,
+			.framedrop_period         = 0x00002750,
+			.framedrop_pattern        = 0x00002754,
+			.frame_inc                = 0x00002758,
+			.burst_limit              = 0x0000275C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 6 */
+		{
+			.status0                  = 0x00002800,
+			.status1                  = 0x00002804,
+			.cfg                      = 0x00002808,
+			.header_addr              = 0x0000280C,
+			.header_cfg               = 0x00002810,
+			.image_addr               = 0x00002814,
+			.image_addr_offset        = 0x00002818,
+			.buffer_width_cfg         = 0x0000281C,
+			.buffer_height_cfg        = 0x00002820,
+			.packer_cfg               = 0x00002824,
+			.stride                   = 0x00002828,
+			.irq_subsample_period     = 0x00002848,
+			.irq_subsample_pattern    = 0x0000284C,
+			.framedrop_period         = 0x00002850,
+			.framedrop_pattern        = 0x00002854,
+			.frame_inc                = 0x00002858,
+			.burst_limit              = 0x0000285C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 7 */
+		{
+			.status0                  = 0x00002900,
+			.status1                  = 0x00002904,
+			.cfg                      = 0x00002908,
+			.header_addr              = 0x0000290C,
+			.header_cfg               = 0x00002910,
+			.image_addr               = 0x00002914,
+			.image_addr_offset        = 0x00002918,
+			.buffer_width_cfg         = 0x0000291C,
+			.buffer_height_cfg        = 0x00002920,
+			.packer_cfg               = 0x00002924,
+			.stride                   = 0x00002928,
+			.irq_subsample_period     = 0x00002948,
+			.irq_subsample_pattern    = 0x0000294C,
+			.framedrop_period         = 0x00002950,
+			.framedrop_pattern        = 0x00002954,
+			.frame_inc                = 0x00002958,
+			.burst_limit              = 0x0000295C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 8 */
+		{
+			.status0                  = 0x00002A00,
+			.status1                  = 0x00002A04,
+			.cfg                      = 0x00002A08,
+			.header_addr              = 0x00002A0C,
+			.header_cfg               = 0x00002A10,
+			.image_addr               = 0x00002A14,
+			.image_addr_offset        = 0x00002A18,
+			.buffer_width_cfg         = 0x00002A1C,
+			.buffer_height_cfg        = 0x00002A20,
+			.packer_cfg               = 0x00002A24,
+			.stride                   = 0x00002A28,
+			.irq_subsample_period     = 0x00002A48,
+			.irq_subsample_pattern    = 0x00002A4C,
+			.framedrop_period         = 0x00002A50,
+			.framedrop_pattern        = 0x00002A54,
+			.frame_inc                = 0x00002A58,
+			.burst_limit              = 0x00002A5C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 9 */
+		{
+			.status0                  = 0x00002B00,
+			.status1                  = 0x00002B04,
+			.cfg                      = 0x00002B08,
+			.header_addr              = 0x00002B0C,
+			.header_cfg               = 0x00002B10,
+			.image_addr               = 0x00002B14,
+			.image_addr_offset        = 0x00002B18,
+			.buffer_width_cfg         = 0x00002B1C,
+			.buffer_height_cfg        = 0x00002B20,
+			.packer_cfg               = 0x00002B24,
+			.stride                   = 0x00002B28,
+			.irq_subsample_period     = 0x00002B48,
+			.irq_subsample_pattern    = 0x00002B4C,
+			.framedrop_period         = 0x00002B50,
+			.framedrop_pattern        = 0x00002B54,
+			.frame_inc                = 0x00002B58,
+			.burst_limit              = 0x00002B5C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 10 */
+		{
+			.status0                  = 0x00002C00,
+			.status1                  = 0x00002C04,
+			.cfg                      = 0x00002C08,
+			.header_addr              = 0x00002C0C,
+			.header_cfg               = 0x00002C10,
+			.image_addr               = 0x00002C14,
+			.image_addr_offset        = 0x00002C18,
+			.buffer_width_cfg         = 0x00002C1C,
+			.buffer_height_cfg        = 0x00002C20,
+			.packer_cfg               = 0x00002C24,
+			.stride                   = 0x00002C28,
+			.irq_subsample_period     = 0x00002C48,
+			.irq_subsample_pattern    = 0x00002C4C,
+			.framedrop_period         = 0x00002C50,
+			.framedrop_pattern        = 0x00002C54,
+			.frame_inc                = 0x00002C58,
+			.burst_limit              = 0x00002C5C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 11 */
+		{
+			.status0                  = 0x00002D00,
+			.status1                  = 0x00002D04,
+			.cfg                      = 0x00002D08,
+			.header_addr              = 0x00002D0C,
+			.header_cfg               = 0x00002D10,
+			.image_addr               = 0x00002D14,
+			.image_addr_offset        = 0x00002D18,
+			.buffer_width_cfg         = 0x00002D1C,
+			.buffer_height_cfg        = 0x00002D20,
+			.packer_cfg               = 0x00002D24,
+			.stride                   = 0x00002D28,
+			.irq_subsample_period     = 0x00002D48,
+			.irq_subsample_pattern    = 0x00002D4C,
+			.framedrop_period         = 0x00002D50,
+			.framedrop_pattern        = 0x00002D54,
+			.frame_inc                = 0x00002D58,
+			.burst_limit              = 0x00002D5C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 12 */
+		{
+			.status0                  = 0x00002E00,
+			.status1                  = 0x00002E04,
+			.cfg                      = 0x00002E08,
+			.header_addr              = 0x00002E0C,
+			.header_cfg               = 0x00002E10,
+			.image_addr               = 0x00002E14,
+			.image_addr_offset        = 0x00002E18,
+			.buffer_width_cfg         = 0x00002E1C,
+			.buffer_height_cfg        = 0x00002E20,
+			.packer_cfg               = 0x00002E24,
+			.stride                   = 0x00002E28,
+			.irq_subsample_period     = 0x00002E48,
+			.irq_subsample_pattern    = 0x00002E4C,
+			.framedrop_period         = 0x00002E50,
+			.framedrop_pattern        = 0x00002E54,
+			.frame_inc                = 0x00002E58,
+			.burst_limit              = 0x00002E5C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 13 */
+		{
+			.status0                  = 0x00002F00,
+			.status1                  = 0x00002F04,
+			.cfg                      = 0x00002F08,
+			.header_addr              = 0x00002F0C,
+			.header_cfg               = 0x00002F10,
+			.image_addr               = 0x00002F14,
+			.image_addr_offset        = 0x00002F18,
+			.buffer_width_cfg         = 0x00002F1C,
+			.buffer_height_cfg        = 0x00002F20,
+			.packer_cfg               = 0x00002F24,
+			.stride                   = 0x00002F28,
+			.irq_subsample_period     = 0x00002F48,
+			.irq_subsample_pattern    = 0x00002F4C,
+			.framedrop_period         = 0x00002F50,
+			.framedrop_pattern        = 0x00002F54,
+			.frame_inc                = 0x00002F58,
+			.burst_limit              = 0x00002F5C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 14 */
+		{
+			.status0                  = 0x00003000,
+			.status1                  = 0x00003004,
+			.cfg                      = 0x00003008,
+			.header_addr              = 0x0000300C,
+			.header_cfg               = 0x00003010,
+			.image_addr               = 0x00003014,
+			.image_addr_offset        = 0x00003018,
+			.buffer_width_cfg         = 0x0000301C,
+			.buffer_height_cfg        = 0x00003020,
+			.packer_cfg               = 0x00003024,
+			.stride                   = 0x00003028,
+			.irq_subsample_period     = 0x00003048,
+			.irq_subsample_pattern    = 0x0000304C,
+			.framedrop_period         = 0x00003050,
+			.framedrop_pattern        = 0x00003054,
+			.frame_inc                = 0x00003058,
+			.burst_limit              = 0x0000305C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 15 */
+		{
+			.status0                  = 0x00003100,
+			.status1                  = 0x00003104,
+			.cfg                      = 0x00003108,
+			.header_addr              = 0x0000310C,
+			.header_cfg               = 0x00003110,
+			.image_addr               = 0x00003114,
+			.image_addr_offset        = 0x00003118,
+			.buffer_width_cfg         = 0x0000311C,
+			.buffer_height_cfg        = 0x00003120,
+			.packer_cfg               = 0x00003124,
+			.stride                   = 0x00003128,
+			.irq_subsample_period     = 0x00003148,
+			.irq_subsample_pattern    = 0x0000314C,
+			.framedrop_period         = 0x00003150,
+			.framedrop_pattern        = 0x00003154,
+			.frame_inc                = 0x00003158,
+			.burst_limit              = 0x0000315C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 16 */
+		{
+			.status0                  = 0x00003200,
+			.status1                  = 0x00003204,
+			.cfg                      = 0x00003208,
+			.header_addr              = 0x0000320C,
+			.header_cfg               = 0x00003210,
+			.image_addr               = 0x00003214,
+			.image_addr_offset        = 0x00003218,
+			.buffer_width_cfg         = 0x0000321C,
+			.buffer_height_cfg        = 0x00003220,
+			.packer_cfg               = 0x00003224,
+			.stride                   = 0x00003228,
+			.irq_subsample_period     = 0x00003248,
+			.irq_subsample_pattern    = 0x0000324C,
+			.framedrop_period         = 0x00003250,
+			.framedrop_pattern        = 0x00003254,
+			.frame_inc                = 0x00003258,
+			.burst_limit              = 0x0000325C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 17 */
+		{
+			.status0                  = 0x00003300,
+			.status1                  = 0x00003304,
+			.cfg                      = 0x00003308,
+			.header_addr              = 0x0000330C,
+			.header_cfg               = 0x00003310,
+			.image_addr               = 0x00003314,
+			.image_addr_offset        = 0x00003318,
+			.buffer_width_cfg         = 0x0000331C,
+			.buffer_height_cfg        = 0x00003320,
+			.packer_cfg               = 0x00003324,
+			.stride                   = 0x00003328,
+			.irq_subsample_period     = 0x00003348,
+			.irq_subsample_pattern    = 0x0000334C,
+			.framedrop_period         = 0x00003350,
+			.framedrop_pattern        = 0x00003354,
+			.frame_inc                = 0x00003358,
+			.burst_limit              = 0x0000335C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 18 */
+		{
+			.status0                  = 0x00003400,
+			.status1                  = 0x00003404,
+			.cfg                      = 0x00003408,
+			.header_addr              = 0x0000340C,
+			.header_cfg               = 0x00003410,
+			.image_addr               = 0x00003414,
+			.image_addr_offset        = 0x00003418,
+			.buffer_width_cfg         = 0x0000341C,
+			.buffer_height_cfg        = 0x00003420,
+			.packer_cfg               = 0x00003424,
+			.stride                   = 0x00003428,
+			.irq_subsample_period     = 0x00003448,
+			.irq_subsample_pattern    = 0x0000344C,
+			.framedrop_period         = 0x00003450,
+			.framedrop_pattern        = 0x00003454,
+			.frame_inc                = 0x00003458,
+			.burst_limit              = 0x0000345C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 19 */
+		{
+			.status0                  = 0x00003500,
+			.status1                  = 0x00003504,
+			.cfg                      = 0x00003508,
+			.header_addr              = 0x0000350C,
+			.header_cfg               = 0x00003510,
+			.image_addr               = 0x00003514,
+			.image_addr_offset        = 0x00003518,
+			.buffer_width_cfg         = 0x0000351C,
+			.buffer_height_cfg        = 0x00003520,
+			.packer_cfg               = 0x00003524,
+			.stride                   = 0x00003528,
+			.irq_subsample_period     = 0x00003548,
+			.irq_subsample_pattern    = 0x0000354C,
+			.framedrop_period         = 0x00003550,
+			.framedrop_pattern        = 0x00003554,
+			.frame_inc                = 0x00003558,
+			.burst_limit              = 0x0000355C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 20 */
+		{
+			.status0                  = 0x00003600,
+			.status1                  = 0x00003604,
+			.cfg                      = 0x00003608,
+			.header_addr              = 0x0000360C,
+			.header_cfg               = 0x00003610,
+			.image_addr               = 0x00003614,
+			.image_addr_offset        = 0x00003618,
+			.buffer_width_cfg         = 0x0000361C,
+			.buffer_height_cfg        = 0x00003620,
+			.packer_cfg               = 0x00003624,
+			.stride                   = 0x00003628,
+			.irq_subsample_period     = 0x00003648,
+			.irq_subsample_pattern    = 0x0000364C,
+			.framedrop_period         = 0x00003650,
+			.framedrop_pattern        = 0x00003654,
+			.frame_inc                = 0x00003658,
+			.burst_limit              = 0x0000365C,
+			.ubwc_regs                =
+				&vfe175_130_ubwc_regs_client_20,
+		},
+		/* BUS Client 21 */
+		{
+			.status0                  = 0x00003700,
+			.status1                  = 0x00003704,
+			.cfg                      = 0x00003708,
+			.header_addr              = 0x0000370C,
+			.header_cfg               = 0x00003710,
+			.image_addr               = 0x00003714,
+			.image_addr_offset        = 0x00003718,
+			.buffer_width_cfg         = 0x0000371C,
+			.buffer_height_cfg        = 0x00003720,
+			.packer_cfg               = 0x00003724,
+			.stride                   = 0x00003728,
+			.irq_subsample_period     = 0x00003748,
+			.irq_subsample_pattern    = 0x0000374C,
+			.framedrop_period         = 0x00003750,
+			.framedrop_pattern        = 0x00003754,
+			.frame_inc                = 0x00003758,
+			.burst_limit              = 0x0000375C,
+			.ubwc_regs                =
+				&vfe175_130_ubwc_regs_client_21,
+		},
+		/* BUS Client 22 */
+		{
+			.status0                  = 0x00003800,
+			.status1                  = 0x00003804,
+			.cfg                      = 0x00003808,
+			.header_addr              = 0x0000380C,
+			.header_cfg               = 0x00003810,
+			.image_addr               = 0x00003814,
+			.image_addr_offset        = 0x00003818,
+			.buffer_width_cfg         = 0x0000381C,
+			.buffer_height_cfg        = 0x00003820,
+			.packer_cfg               = 0x00003824,
+			.stride                   = 0x00003828,
+			.irq_subsample_period     = 0x00003848,
+			.irq_subsample_pattern    = 0x0000384C,
+			.framedrop_period         = 0x00003850,
+			.framedrop_pattern        = 0x00003854,
+			.frame_inc                = 0x00003858,
+			.burst_limit              = 0x0000385C,
+			.ubwc_regs                = NULL,
+		},
+		/* BUS Client 23 */
+		{
+			.status0                  = 0x00003900,
+			.status1                  = 0x00003904,
+			.cfg                      = 0x00003908,
+			.header_addr              = 0x0000390C,
+			.header_cfg               = 0x00003910,
+			.image_addr               = 0x00003914,
+			.image_addr_offset        = 0x00003918,
+			.buffer_width_cfg         = 0x0000391C,
+			.buffer_height_cfg        = 0x00003920,
+			.packer_cfg               = 0x00003924,
+			.stride                   = 0x00003928,
+			.irq_subsample_period     = 0x00003948,
+			.irq_subsample_pattern    = 0x0000394C,
+			.framedrop_period         = 0x00003950,
+			.framedrop_pattern        = 0x00003954,
+			.frame_inc                = 0x00003958,
+			.burst_limit              = 0x0000395C,
+			.ubwc_regs                = NULL,
+		},
+	},
+	.comp_grp_reg = {
+		/* CAM_VFE_BUS_VER2_COMP_GRP_0 */
+		{
+			.comp_mask                    = 0x00002010,
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_1 */
+		{
+			.comp_mask                    = 0x00002014,
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_2 */
+		{
+			.comp_mask                    = 0x00002018,
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_3 */
+		{
+			.comp_mask                    = 0x0000201C,
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_4 */
+		{
+			.comp_mask                    = 0x00002020,
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_5 */
+		{
+			.comp_mask                    = 0x00002024,
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 */
+		{
+			.comp_mask                    = 0x0000202C,
+			.addr_sync_mask               = 0x00002088,
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1 */
+		{
+			.comp_mask                    = 0x00002030,
+			.addr_sync_mask               = 0x0000208C,
+
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2 */
+		{
+			.comp_mask                    = 0x00002034,
+			.addr_sync_mask               = 0x00002090,
+
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3 */
+		{
+			.comp_mask                    = 0x00002038,
+			.addr_sync_mask               = 0x00002094,
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4 */
+		{
+			.comp_mask                    = 0x0000203C,
+			.addr_sync_mask               = 0x00002098,
+		},
+		/* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 */
+		{
+			.comp_mask                    = 0x00002040,
+			.addr_sync_mask               = 0x0000209C,
+		},
+	},
+	.num_out = 22,
+	.vfe_out_hw_info = {
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_RDI0,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_RDI1,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_RDI2,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_FULL,
+			.max_width     = 4096,
+			.max_height    = 4096,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_DS4,
+			.max_width     = 1920,
+			.max_height    = 1080,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_DS16,
+			.max_width     = 1920,
+			.max_height    = 1080,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_FD,
+			.max_width     = 1920,
+			.max_height    = 1080,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_PDAF,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  =
+				CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  =
+				CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST,
+			.max_width     = 1920,
+			.max_height    = 1080,
+		},
+		{
+			.vfe_out_type  =
+				CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  =
+				CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  =
+				CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  =
+				CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  =
+				CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  =
+				CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  =
+				CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST,
+			.max_width     = -1,
+			.max_height    = -1,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP,
+			.max_width     = 4096,
+			.max_height    = 4096,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP,
+			.max_width     = 1920,
+			.max_height    = 1080,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP,
+			.max_width     = 1920,
+			.max_height    = 1080,
+		},
+		{
+			.vfe_out_type  = CAM_VFE_BUS_VER2_VFE_OUT_2PD,
+			.max_width     = 1920,
+			.max_height    = 1080,
+		},
+	},
+};
+
+struct cam_vfe_hw_info cam_vfe175_130_hw_info = {
+	.irq_reg_info                  = &vfe175_130_top_irq_reg_info,
+
+	.bus_version                   = CAM_VFE_BUS_VER_2_0,
+	.bus_hw_info                   = &vfe175_130_bus_hw_info,
+
+	.bus_rd_version                = CAM_VFE_BUS_VER_2_0,
+	.bus_rd_hw_info                = &vfe175_130_bus_rd_hw_info,
+
+	.top_version                   = CAM_VFE_TOP_VER_2_0,
+	.top_hw_info                   = &vfe175_130_top_hw_info,
+
+	.camif_version                 = CAM_VFE_CAMIF_VER_2_0,
+	.camif_reg                     = &vfe175_130_camif_reg,
+
+	.camif_lite_version            = CAM_VFE_CAMIF_LITE_VER_2_0,
+	.camif_lite_reg                = &vfe175_130_camif_lite_reg,
+
+};
+
+#endif /* _CAM_VFE175_130_H_ */
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c
index c94b64e..2e11dc4 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.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
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include "cam_vfe170.h"
 #include "cam_vfe175.h"
+#include "cam_vfe175_130.h"
 #include "cam_vfe_lite17x.h"
 #include "cam_vfe_hw_intf.h"
 #include "cam_vfe_core.h"
@@ -28,6 +29,10 @@ static const struct of_device_id cam_vfe_dt_match[] = {
 		.data = &cam_vfe175_hw_info,
 	},
 	{
+		.compatible = "qcom,vfe175_130",
+		.data = &cam_vfe175_130_hw_info,
+	},
+	{
 		.compatible = "qcom,vfe-lite170",
 		.data = &cam_vfe_lite17x_hw_info,
 	},
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
index feb6188..bead63f 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
@@ -11,4 +11,4 @@
 ccflags-y += -Idrivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include
 ccflags-y += -Idrivers/media/platform/msm/ais/cam_cpas/include
 
-obj-$(CONFIG_MSM_AIS) += cam_vfe_bus.o cam_vfe_bus_ver2.o
+obj-$(CONFIG_MSM_AIS) += cam_vfe_bus.o cam_vfe_bus_ver2.o cam_vfe_bus_rd_ver1.o
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
index a70d8b8..d6c3670 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.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
@@ -13,9 +13,11 @@
 #include "cam_vfe_bus.h"
 #include "cam_vfe_bus_ver1.h"
 #include "cam_vfe_bus_ver2.h"
+#include "cam_vfe_bus_rd_ver1.h"
 #include "cam_debug_util.h"
 
 int cam_vfe_bus_init(uint32_t          bus_version,
+	int                            bus_type,
 	struct cam_hw_soc_info        *soc_info,
 	struct cam_hw_intf            *hw_intf,
 	void                          *bus_hw_info,
@@ -24,10 +26,16 @@ int cam_vfe_bus_init(uint32_t          bus_version,
 {
 	int rc = -ENODEV;
 
-	switch (bus_version) {
-	case CAM_VFE_BUS_VER_2_0:
-		rc = cam_vfe_bus_ver2_init(soc_info, hw_intf, bus_hw_info,
-			vfe_irq_controller, vfe_bus);
+	switch (bus_type) {
+	case BUS_TYPE_WR:
+		if (CAM_VFE_BUS_VER_2_0)
+			rc = cam_vfe_bus_ver2_init(soc_info, hw_intf,
+				bus_hw_info, vfe_irq_controller, vfe_bus);
+		break;
+	case BUS_TYPE_RD:
+		/* Call vfe bus rd init function */
+		rc = cam_vfe_bus_rd_ver1_init(soc_info, hw_intf,
+			bus_hw_info, vfe_irq_controller, vfe_bus);
 		break;
 	default:
 		CAM_ERR(CAM_ISP, "Unsupported Bus Version %x", bus_version);
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c
new file mode 100644
index 0000000..c0d662c
--- /dev/null
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c
@@ -0,0 +1,1239 @@
+/* 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/ratelimit.h>
+#include <linux/slab.h>
+#include <uapi/media/cam_isp.h>
+#include "cam_io_util.h"
+#include "cam_debug_util.h"
+#include "cam_cdm_util.h"
+#include "cam_hw_intf.h"
+#include "cam_ife_hw_mgr.h"
+#include "cam_vfe_hw_intf.h"
+#include "cam_irq_controller.h"
+#include "cam_tasklet_util.h"
+#include "cam_vfe_bus.h"
+#include "cam_vfe_bus_rd_ver1.h"
+#include "cam_vfe_core.h"
+#include "cam_debug_util.h"
+#include "cam_cpas_api.h"
+
+static const char drv_name[] = "vfe_bus_rd";
+
+#define ALIGNUP(value, alignment) \
+	((value + alignment - 1) / alignment * alignment)
+
+#define MAX_BUF_UPDATE_REG_NUM   \
+	(sizeof(struct cam_vfe_bus_rd_ver1_reg_offset_bus_client)/4)
+
+#define MAX_REG_VAL_PAIR_SIZE    \
+	(MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
+
+#define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val)    \
+	do {                                               \
+		buf_array[(index)++] = offset;             \
+		buf_array[(index)++] = val;                \
+	} while (0)
+
+enum cam_vfe_bus_rd_ver1_unpacker_format {
+	BUS_RD_VER1_PACKER_FMT_PLAIN_128                   = 0x0,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_8                     = 0x1,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_16_10BPP              = 0x2,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_16_12BPP              = 0x3,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_16_14BPP              = 0x4,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_16_16BPP              = 0x5,
+	BUS_RD_VER1_PACKER_FMT_ARGB_10                     = 0x6,
+	BUS_RD_VER1_PACKER_FMT_ARGB_12                     = 0x7,
+	BUS_RD_VER1_PACKER_FMT_ARGB_14                     = 0x8,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_32_20BPP              = 0x9,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_64                    = 0xA,
+	BUS_RD_VER1_PACKER_FMT_TP_10                       = 0xB,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_32_32BPP              = 0xC,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_8_ODD_EVEN            = 0xD,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_8_LSB_MSB_10          = 0xE,
+	BUS_RD_VER1_PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0xF,
+	BUS_RD_VER1_PACKER_FMT_MAX                         = 0xF,
+};
+
+struct cam_vfe_bus_rd_ver1_common_data {
+	uint32_t                                    core_index;
+	void __iomem                               *mem_base;
+	struct cam_hw_intf                         *hw_intf;
+	void                                       *bus_irq_controller;
+	void                                       *vfe_irq_controller;
+	struct cam_vfe_bus_rd_ver1_reg_offset_common  *common_reg;
+	uint32_t                                    io_buf_update[
+		MAX_REG_VAL_PAIR_SIZE];
+
+	struct list_head                            free_payload_list;
+	spinlock_t                                  spin_lock;
+	struct mutex                                bus_mutex;
+	uint32_t                                    secure_mode;
+	uint32_t                                    num_sec_out;
+	uint32_t                                    fs_sync_enable;
+	uint32_t                                    go_cmd_sel;
+};
+
+struct cam_vfe_bus_rd_ver1_rm_resource_data {
+	uint32_t             index;
+	struct cam_vfe_bus_rd_ver1_common_data            *common_data;
+	struct cam_vfe_bus_rd_ver1_reg_offset_bus_client  *hw_regs;
+	void                *ctx;
+
+	uint32_t             irq_enabled;
+	bool                 init_cfg_done;
+	bool                 hfr_cfg_done;
+
+	uint32_t             offset;
+
+	uint32_t             min_vbi;
+	uint32_t             fs_mode;
+	uint32_t             hbi_count;
+	uint32_t             width;
+	uint32_t             height;
+	uint32_t             stride;
+	uint32_t             format;
+	uint32_t             latency_buf_allocation;
+	uint32_t             unpacker_cfg;
+	uint32_t             burst_len;
+
+	uint32_t             go_cmd_sel;
+	uint32_t             fs_sync_enable;
+	uint32_t             fs_line_sync_en;
+
+	uint32_t             en_cfg;
+	uint32_t             is_dual;
+	uint32_t             img_addr;
+	uint32_t             input_if_cmd;
+};
+
+struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data {
+	uint32_t                              bus_rd_type;
+	struct cam_vfe_bus_rd_ver1_common_data  *common_data;
+
+	uint32_t                         num_rm;
+	struct cam_isp_resource_node    *rm_res[PLANE_MAX];
+
+	struct cam_isp_resource_node    *comp_grp;
+	enum cam_isp_hw_sync_mode        dual_comp_sync_mode;
+	uint32_t                         dual_hw_alternate_vfe_id;
+	struct list_head                 vfe_bus_rd_list;
+
+	uint32_t                         format;
+	uint32_t                         max_width;
+	uint32_t                         max_height;
+	struct cam_cdm_utils_ops        *cdm_util_ops;
+	uint32_t                         secure_mode;
+};
+
+struct cam_vfe_bus_rd_ver1_priv {
+	struct cam_vfe_bus_rd_ver1_common_data common_data;
+	uint32_t                            num_client;
+	uint32_t                            num_bus_rd_resc;
+
+	struct cam_isp_resource_node  bus_client[
+		CAM_VFE_BUS_RD_VER1_MAX_CLIENTS];
+	struct cam_isp_resource_node  vfe_bus_rd[
+		CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX];
+
+	uint32_t                            irq_handle;
+	uint32_t                            error_irq_handle;
+};
+
+static int cam_vfe_bus_process_cmd(
+	struct cam_isp_resource_node *priv,
+	uint32_t cmd_type, void *cmd_args, uint32_t arg_size);
+
+static enum cam_vfe_bus_rd_ver1_unpacker_format
+	cam_vfe_bus_get_unpacker_fmt(uint32_t unpack_fmt)
+{
+	switch (unpack_fmt) {
+	case CAM_FORMAT_MIPI_RAW_10:
+		return BUS_RD_VER1_PACKER_FMT_PLAIN_8_ODD_EVEN;
+	default:
+		return BUS_RD_VER1_PACKER_FMT_MAX;
+	}
+}
+
+static bool cam_vfe_bus_can_be_secure(uint32_t out_type)
+{
+	switch (out_type) {
+	case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0:
+		return false;
+
+	default:
+		return false;
+	}
+}
+
+static enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type
+	cam_vfe_bus_get_bus_rd_res_id(uint32_t res_type)
+{
+	switch (res_type) {
+	case CAM_ISP_RESOURCE_VFE_BUS_RD:
+		return CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0;
+	default:
+		return CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX;
+	}
+}
+
+static int cam_vfe_bus_get_num_rm(
+	enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type res_type)
+{
+	switch (res_type) {
+	case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0:
+		return 1;
+	default:
+		break;
+	}
+
+	CAM_ERR(CAM_ISP, "Unsupported resource_type %u",
+		res_type);
+	return -EINVAL;
+}
+
+static int cam_vfe_bus_get_rm_idx(
+	enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type vfe_bus_rd_res_id,
+	enum cam_vfe_bus_plane_type plane)
+{
+	int rm_idx = -1;
+
+	switch (vfe_bus_rd_res_id) {
+	case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0:
+		switch (plane) {
+		case PLANE_Y:
+			rm_idx = 0;
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return rm_idx;
+}
+
+static int cam_vfe_bus_acquire_rm(
+	struct cam_vfe_bus_rd_ver1_priv          *ver1_bus_rd_priv,
+	struct cam_isp_out_port_info             *out_port_info,
+	void                                     *tasklet,
+	void                                     *ctx,
+	enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type  vfe_bus_rd_res_id,
+	enum cam_vfe_bus_plane_type               plane,
+	uint32_t                                  subscribe_irq,
+	struct cam_isp_resource_node            **rm_res,
+	uint32_t                                 *client_done_mask,
+	uint32_t                                  is_dual)
+{
+	uint32_t rm_idx = 0;
+	struct cam_isp_resource_node              *rm_res_local = NULL;
+	struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data = NULL;
+
+	*rm_res = NULL;
+	*client_done_mask = 0;
+
+	/* No need to allocate for BUS VER2. VFE OUT to RM is fixed. */
+	rm_idx = cam_vfe_bus_get_rm_idx(vfe_bus_rd_res_id, plane);
+	if (rm_idx < 0 || rm_idx >= ver1_bus_rd_priv->num_client) {
+		CAM_ERR(CAM_ISP, "Unsupported VFE out %d plane %d",
+			vfe_bus_rd_res_id, plane);
+		return -EINVAL;
+	}
+
+	rm_res_local = &ver1_bus_rd_priv->bus_client[rm_idx];
+	if (rm_res_local->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+		CAM_ERR(CAM_ISP, "RM res not available state:%d",
+			rm_res_local->res_state);
+		return -EALREADY;
+	}
+	rm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+	rm_res_local->tasklet_info = tasklet;
+
+	rsrc_data = rm_res_local->res_priv;
+	rsrc_data->irq_enabled = subscribe_irq;
+	rsrc_data->ctx = ctx;
+	rsrc_data->is_dual = is_dual;
+	/* Set RM offset value to default */
+	rsrc_data->offset  = 0;
+
+	*client_done_mask = (1 << rm_idx);
+	*rm_res = rm_res_local;
+
+	CAM_DBG(CAM_ISP, "RM %d: Acquired");
+	return 0;
+}
+
+static int cam_vfe_bus_release_rm(void   *bus_priv,
+	struct cam_isp_resource_node     *rm_res)
+{
+	struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data =
+		rm_res->res_priv;
+
+	rsrc_data->irq_enabled = 0;
+	rsrc_data->offset = 0;
+	rsrc_data->width = 0;
+	rsrc_data->height = 0;
+	rsrc_data->stride = 0;
+	rsrc_data->format = 0;
+	rsrc_data->unpacker_cfg = 0;
+	rsrc_data->burst_len = 0;
+	rsrc_data->init_cfg_done = false;
+	rsrc_data->hfr_cfg_done = false;
+	rsrc_data->en_cfg = 0;
+	rsrc_data->is_dual = 0;
+
+	rm_res->tasklet_info = NULL;
+	rm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+
+	return 0;
+}
+
+static int cam_vfe_bus_start_rm(struct cam_isp_resource_node *rm_res)
+{
+	int rc = 0;
+	struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data =
+		rm_res->res_priv;
+	struct cam_vfe_bus_rd_ver1_common_data        *common_data =
+		rm_data->common_data;
+	uint32_t buf_size;
+	uint32_t val;
+	uint32_t offset;
+
+	CAM_DBG(CAM_ISP, "w: 0x%x", rm_data->width);
+	CAM_DBG(CAM_ISP, "h: 0x%x", rm_data->height);
+	CAM_DBG(CAM_ISP, "format: 0x%x", rm_data->format);
+	CAM_DBG(CAM_ISP, "unpacker_cfg: 0x%x", rm_data->unpacker_cfg);
+	CAM_DBG(CAM_ISP, "latency_buf_allocation: 0x%x",
+		rm_data->latency_buf_allocation);
+	CAM_DBG(CAM_ISP, "stride: 0x%x", rm_data->stride);
+	CAM_DBG(CAM_ISP, "go_cmd_sel: 0x%x", rm_data->go_cmd_sel);
+	CAM_DBG(CAM_ISP, "fs_sync_enable: 0x%x", rm_data->fs_sync_enable);
+	CAM_DBG(CAM_ISP, "hbi_count: 0x%x", rm_data->hbi_count);
+	CAM_DBG(CAM_ISP, "fs_line_sync_en: 0x%x", rm_data->fs_line_sync_en);
+	CAM_DBG(CAM_ISP, "fs_mode: 0x%x", rm_data->fs_mode);
+	CAM_DBG(CAM_ISP, "min_vbi: 0x%x", rm_data->min_vbi);
+
+	/* Write All the values*/
+	offset = rm_data->hw_regs->buffer_width_cfg;
+	buf_size = ((rm_data->width)&(0x0000FFFF)) |
+		((rm_data->height<<16)&(0xFFFF0000));
+	cam_io_w_mb(buf_size, common_data->mem_base + offset);
+	CAM_DBG(CAM_ISP, "buf_size: 0x%x", buf_size);
+
+	val = rm_data->width;
+	offset = rm_data->hw_regs->stride;
+	CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val);
+	cam_io_w_mb(val, common_data->mem_base + offset);
+
+	CAM_DBG(CAM_ISP, "rm_data->unpacker_cfg:0x%x", rm_data->unpacker_cfg);
+	val = cam_vfe_bus_get_unpacker_fmt(rm_data->unpacker_cfg);
+	CAM_DBG(CAM_ISP, " value:0x%x", val);
+	offset = rm_data->hw_regs->unpacker_cfg;
+	CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val);
+	cam_io_w_mb(val, common_data->mem_base + offset);
+
+	val = rm_data->latency_buf_allocation;
+	offset = rm_data->hw_regs->latency_buf_allocation;
+	CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val);
+	cam_io_w_mb(val, common_data->mem_base + offset);
+
+	cam_io_w_mb(0x1, common_data->mem_base +
+		rm_data->hw_regs->cfg);
+	return rc;
+}
+
+static int cam_vfe_bus_stop_rm(struct cam_isp_resource_node *rm_res)
+{
+	int rc = 0;
+	struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data =
+		rm_res->res_priv;
+	struct cam_vfe_bus_rd_ver1_common_data        *common_data =
+		rsrc_data->common_data;
+
+	/* Disable RM */
+	cam_io_w_mb(0x0,
+		common_data->mem_base + rsrc_data->hw_regs->cfg);
+
+	rm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+	rsrc_data->init_cfg_done = false;
+	rsrc_data->hfr_cfg_done = false;
+
+	return rc;
+}
+
+static int cam_vfe_bus_init_rm_resource(uint32_t index,
+	struct cam_vfe_bus_rd_ver1_priv   *ver1_bus_rd_priv,
+	struct cam_vfe_bus_rd_ver1_hw_info *bus_rd_hw_info,
+	struct cam_isp_resource_node    *rm_res)
+{
+	struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data;
+
+	rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_rd_ver1_rm_resource_data),
+		GFP_KERNEL);
+	if (!rsrc_data) {
+		CAM_DBG(CAM_ISP, "Failed to alloc for RM res priv");
+		return -ENOMEM;
+	}
+	rm_res->res_priv = rsrc_data;
+
+	rsrc_data->index = index;
+	rsrc_data->hw_regs = &bus_rd_hw_info->bus_client_reg[index];
+	rsrc_data->common_data = &ver1_bus_rd_priv->common_data;
+
+	rm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+	INIT_LIST_HEAD(&rm_res->list);
+
+	rm_res->start = cam_vfe_bus_start_rm;
+	rm_res->stop = cam_vfe_bus_stop_rm;
+	rm_res->hw_intf = ver1_bus_rd_priv->common_data.hw_intf;
+
+
+	return 0;
+}
+
+static int cam_vfe_bus_deinit_rm_resource(
+	struct cam_isp_resource_node    *rm_res)
+{
+	struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data;
+
+	rm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+	INIT_LIST_HEAD(&rm_res->list);
+
+	rm_res->start = NULL;
+	rm_res->stop = NULL;
+	rm_res->top_half_handler = NULL;
+	rm_res->bottom_half_handler = NULL;
+	rm_res->hw_intf = NULL;
+
+	rsrc_data = rm_res->res_priv;
+	rm_res->res_priv = NULL;
+	if (!rsrc_data)
+		return -ENOMEM;
+	kfree(rsrc_data);
+
+	return 0;
+}
+
+static int cam_vfe_bus_rd_get_secure_mode(void *priv, void *cmd_args,
+	uint32_t arg_size)
+{
+	return 0;
+}
+
+static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args,
+	uint32_t args_size)
+{
+	int                                           rc = -ENODEV;
+	int                                           i;
+	enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type      bus_rd_res_id;
+	int                                           num_rm;
+	uint32_t                                      subscribe_irq;
+	uint32_t                                      client_done_mask;
+	struct cam_vfe_bus_rd_ver1_priv              *ver1_bus_rd_priv =
+		bus_priv;
+	struct cam_vfe_acquire_args                  *acq_args = acquire_args;
+	struct cam_vfe_hw_vfe_out_acquire_args       *bus_rd_acquire_args;
+	struct cam_isp_resource_node                 *rsrc_node = NULL;
+	struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data   *rsrc_data = NULL;
+	uint32_t                                      secure_caps = 0, mode;
+
+	if (!bus_priv || !acquire_args) {
+		CAM_ERR(CAM_ISP, "Invalid Param");
+		return -EINVAL;
+	}
+
+	bus_rd_acquire_args = &acq_args->vfe_bus_rd;
+
+	CAM_DBG(CAM_ISP, "Acquiring resource type 0x%x",
+		acq_args->rsrc_type);
+
+	bus_rd_res_id = cam_vfe_bus_get_bus_rd_res_id(
+		acq_args->rsrc_type);
+	if (bus_rd_res_id == CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX)
+		return -ENODEV;
+
+	num_rm = cam_vfe_bus_get_num_rm(bus_rd_res_id);
+	if (num_rm < 1)
+		return -EINVAL;
+
+	rsrc_node = &ver1_bus_rd_priv->vfe_bus_rd[bus_rd_res_id];
+	if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+		CAM_ERR(CAM_ISP, "Resource not available: Res_id %d state:%d",
+			bus_rd_res_id, rsrc_node->res_state);
+		return -EBUSY;
+	}
+
+	rsrc_data = rsrc_node->res_priv;
+	secure_caps = cam_vfe_bus_can_be_secure(
+		rsrc_data->bus_rd_type);
+
+	mode = bus_rd_acquire_args->out_port_info->secure_mode;
+	mutex_lock(&rsrc_data->common_data->bus_mutex);
+	if (secure_caps) {
+		if (!rsrc_data->common_data->num_sec_out) {
+			rsrc_data->secure_mode = mode;
+			rsrc_data->common_data->secure_mode = mode;
+		} else {
+			if (mode == rsrc_data->common_data->secure_mode) {
+				rsrc_data->secure_mode =
+					rsrc_data->common_data->secure_mode;
+			} else {
+				rc = -EINVAL;
+				CAM_ERR_RATE_LIMIT(CAM_ISP,
+					"Mismatch: Acquire mode[%d], drvr mode[%d]",
+					rsrc_data->common_data->secure_mode,
+					mode);
+				mutex_unlock(
+					&rsrc_data->common_data->bus_mutex);
+				return -EINVAL;
+			}
+		}
+		rsrc_data->common_data->num_sec_out++;
+	}
+	mutex_unlock(&rsrc_data->common_data->bus_mutex);
+
+	rsrc_data->num_rm = num_rm;
+	rsrc_node->tasklet_info = acq_args->tasklet;
+	rsrc_node->cdm_ops = bus_rd_acquire_args->cdm_ops;
+	rsrc_data->cdm_util_ops = bus_rd_acquire_args->cdm_ops;
+
+	subscribe_irq = 1;
+
+	for (i = 0; i < num_rm; i++) {
+		rc = cam_vfe_bus_acquire_rm(ver1_bus_rd_priv,
+			bus_rd_acquire_args->out_port_info,
+			acq_args->tasklet,
+			bus_rd_acquire_args->ctx,
+			bus_rd_res_id,
+			i,
+			subscribe_irq,
+			&rsrc_data->rm_res[i],
+			&client_done_mask,
+			bus_rd_acquire_args->is_dual);
+		if (rc) {
+			CAM_ERR(CAM_ISP,
+				"VFE%d RM acquire failed for Out %d rc=%d",
+				rsrc_data->common_data->core_index,
+				bus_rd_res_id, rc);
+			goto release_rm;
+		}
+	}
+
+	rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+	bus_rd_acquire_args->rsrc_node = rsrc_node;
+
+	CAM_DBG(CAM_ISP, "Acquire successful");
+	return rc;
+
+release_rm:
+	for (i--; i >= 0; i--)
+		cam_vfe_bus_release_rm(ver1_bus_rd_priv, rsrc_data->rm_res[i]);
+	return rc;
+}
+
+static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *release_args,
+	uint32_t args_size)
+{
+	uint32_t i;
+	struct cam_isp_resource_node          *vfe_bus_rd = NULL;
+	struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data  *rsrc_data = NULL;
+	uint32_t                               secure_caps = 0;
+
+	if (!bus_priv || !release_args) {
+		CAM_ERR(CAM_ISP, "Invalid input bus_priv %pK release_args %pK",
+			bus_priv, release_args);
+		return -EINVAL;
+	}
+
+	vfe_bus_rd = release_args;
+	rsrc_data = vfe_bus_rd->res_priv;
+
+	if (vfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
+		CAM_ERR(CAM_ISP, "Invalid resource state:%d",
+			vfe_bus_rd->res_state);
+	}
+
+	for (i = 0; i < rsrc_data->num_rm; i++)
+		cam_vfe_bus_release_rm(bus_priv, rsrc_data->rm_res[i]);
+	rsrc_data->num_rm = 0;
+
+	vfe_bus_rd->tasklet_info = NULL;
+	vfe_bus_rd->cdm_ops = NULL;
+	rsrc_data->cdm_util_ops = NULL;
+
+	secure_caps = cam_vfe_bus_can_be_secure(rsrc_data->bus_rd_type);
+	mutex_lock(&rsrc_data->common_data->bus_mutex);
+	if (secure_caps) {
+		if (rsrc_data->secure_mode ==
+			rsrc_data->common_data->secure_mode) {
+			rsrc_data->common_data->num_sec_out--;
+			rsrc_data->secure_mode =
+				CAM_SECURE_MODE_NON_SECURE;
+		} else {
+			/*
+			 * The validity of the mode is properly
+			 * checked while acquiring the output port.
+			 * not expected to reach here, unless there is
+			 * some corruption.
+			 */
+			CAM_ERR(CAM_ISP, "driver[%d],resource[%d] mismatch",
+				rsrc_data->common_data->secure_mode,
+				rsrc_data->secure_mode);
+		}
+
+		if (!rsrc_data->common_data->num_sec_out)
+			rsrc_data->common_data->secure_mode =
+				CAM_SECURE_MODE_NON_SECURE;
+	}
+	mutex_unlock(&rsrc_data->common_data->bus_mutex);
+
+	if (vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
+		vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+
+	return 0;
+}
+
+static int cam_vfe_bus_start_vfe_bus_rd(
+	struct cam_isp_resource_node          *vfe_out)
+{
+	int rc = 0, i;
+	struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data  *rsrc_data = NULL;
+	struct cam_vfe_bus_rd_ver1_common_data   *common_data = NULL;
+
+	if (!vfe_out) {
+		CAM_ERR(CAM_ISP, "Invalid input");
+		return -EINVAL;
+	}
+
+	rsrc_data = vfe_out->res_priv;
+	common_data = rsrc_data->common_data;
+
+	CAM_DBG(CAM_ISP, "Start resource type: %x", rsrc_data->bus_rd_type);
+
+	if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
+		CAM_ERR(CAM_ISP, "Invalid resource state:%d",
+			vfe_out->res_state);
+		return -EACCES;
+	}
+
+	for (i = 0; i < rsrc_data->num_rm; i++)
+		rc = cam_vfe_bus_start_rm(rsrc_data->rm_res[i]);
+	vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
+	return rc;
+}
+
+static int cam_vfe_bus_stop_vfe_bus_rd(
+	struct cam_isp_resource_node          *vfe_bus_rd)
+{
+	int rc = 0, i;
+	struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data  *rsrc_data = NULL;
+
+	CAM_DBG(CAM_ISP, "E:Stop rd Res");
+	if (!vfe_bus_rd) {
+		CAM_ERR(CAM_ISP, "Invalid input");
+		return -EINVAL;
+	}
+
+	rsrc_data = vfe_bus_rd->res_priv;
+
+	if (vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
+		vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
+		CAM_DBG(CAM_ISP, "vfe_out res_state is %d",
+			vfe_bus_rd->res_state);
+		return rc;
+	}
+	for (i = 0; i < rsrc_data->num_rm; i++)
+		rc = cam_vfe_bus_stop_rm(rsrc_data->rm_res[i]);
+
+	vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+	return rc;
+}
+
+static int cam_vfe_bus_init_vfe_bus_read_resource(uint32_t  index,
+	struct cam_vfe_bus_rd_ver1_priv                  *bus_rd_priv,
+	struct cam_vfe_bus_rd_ver1_hw_info               *bus_rd_hw_info)
+{
+	struct cam_isp_resource_node         *vfe_bus_rd = NULL;
+	struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+	int rc = 0;
+	int32_t vfe_bus_rd_resc_type =
+		bus_rd_hw_info->vfe_bus_rd_hw_info[index].vfe_bus_rd_type;
+
+	if (vfe_bus_rd_resc_type < 0 ||
+		vfe_bus_rd_resc_type > CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0) {
+		CAM_ERR(CAM_ISP, "Init VFE Out failed, Invalid type=%d",
+			vfe_bus_rd_resc_type);
+		return -EINVAL;
+	}
+
+	vfe_bus_rd = &bus_rd_priv->vfe_bus_rd[vfe_bus_rd_resc_type];
+	if (vfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE ||
+		vfe_bus_rd->res_priv) {
+		CAM_ERR(CAM_ISP,
+			"Error. Looks like same resource is init again");
+		return -EFAULT;
+	}
+
+	rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data),
+		GFP_KERNEL);
+	if (!rsrc_data) {
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	vfe_bus_rd->res_priv = rsrc_data;
+
+	vfe_bus_rd->res_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
+	vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+	INIT_LIST_HEAD(&vfe_bus_rd->list);
+
+	rsrc_data->bus_rd_type    =
+		bus_rd_hw_info->vfe_bus_rd_hw_info[index].vfe_bus_rd_type;
+	rsrc_data->common_data = &bus_rd_priv->common_data;
+	rsrc_data->max_width   =
+		bus_rd_hw_info->vfe_bus_rd_hw_info[index].max_width;
+	rsrc_data->max_height  =
+		bus_rd_hw_info->vfe_bus_rd_hw_info[index].max_height;
+	rsrc_data->secure_mode = CAM_SECURE_MODE_NON_SECURE;
+
+	vfe_bus_rd->start = cam_vfe_bus_start_vfe_bus_rd;
+	vfe_bus_rd->stop = cam_vfe_bus_stop_vfe_bus_rd;
+	vfe_bus_rd->process_cmd = cam_vfe_bus_process_cmd;
+	vfe_bus_rd->hw_intf = bus_rd_priv->common_data.hw_intf;
+
+	return 0;
+}
+
+static int cam_vfe_bus_deinit_vfe_bus_rd_resource(
+	struct cam_isp_resource_node    *vfe_bus_rd_res)
+{
+	struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data =
+		vfe_bus_rd_res->res_priv;
+
+	if (vfe_bus_rd_res->res_state == CAM_ISP_RESOURCE_STATE_UNAVAILABLE) {
+		/*
+		 * This is not error. It can happen if the resource is
+		 * never supported in the HW.
+		 */
+		CAM_DBG(CAM_ISP, "HW%d Res %d already deinitialized");
+		return 0;
+	}
+
+	vfe_bus_rd_res->start = NULL;
+	vfe_bus_rd_res->stop = NULL;
+	vfe_bus_rd_res->top_half_handler = NULL;
+	vfe_bus_rd_res->bottom_half_handler = NULL;
+	vfe_bus_rd_res->hw_intf = NULL;
+
+	vfe_bus_rd_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+	INIT_LIST_HEAD(&vfe_bus_rd_res->list);
+	vfe_bus_rd_res->res_priv = NULL;
+
+	if (!rsrc_data)
+		return -ENOMEM;
+	kfree(rsrc_data);
+
+	return 0;
+}
+
+static int cam_vfe_bus_rd_ver1_handle_irq(uint32_t    evt_id,
+	struct cam_irq_th_payload                 *th_payload)
+{
+	struct cam_vfe_bus_rd_ver1_priv          *bus_priv;
+
+	bus_priv     = th_payload->handler_priv;
+	CAM_DBG(CAM_ISP, "BUS READ IRQ Received");
+	return 0;
+}
+
+static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args,
+	uint32_t arg_size)
+{
+	struct cam_vfe_bus_rd_ver1_priv          *bus_priv;
+	struct cam_isp_hw_get_cmd_update         *update_buf;
+	struct cam_buf_io_cfg                    *io_cfg;
+	struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data     *vfe_bus_rd_data = NULL;
+	struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data = NULL;
+	uint32_t *reg_val_pair;
+	uint32_t  i, j, size = 0;
+	uint32_t  val;
+	uint32_t buf_size = 0;
+
+	bus_priv = (struct cam_vfe_bus_rd_ver1_priv  *) priv;
+	update_buf =  (struct cam_isp_hw_get_cmd_update *) cmd_args;
+
+	vfe_bus_rd_data = (struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *)
+		update_buf->res->res_priv;
+
+	if (!vfe_bus_rd_data || !vfe_bus_rd_data->cdm_util_ops) {
+		CAM_ERR(CAM_ISP, "Failed! Invalid data");
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_ISP, "#of RM: %d",  vfe_bus_rd_data->num_rm);
+	if (update_buf->rm_update->num_buf != vfe_bus_rd_data->num_rm) {
+		CAM_ERR(CAM_ISP,
+			"Failed! Invalid number buffers:%d required:%d",
+			update_buf->rm_update->num_buf,
+			vfe_bus_rd_data->num_rm);
+		return -EINVAL;
+	}
+
+	reg_val_pair = &vfe_bus_rd_data->common_data->io_buf_update[0];
+	io_cfg = update_buf->rm_update->io_cfg;
+
+	for (i = 0, j = 0; i < vfe_bus_rd_data->num_rm; i++) {
+		if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
+			CAM_ERR(CAM_ISP,
+				"reg_val_pair %d exceeds the array limit %lu",
+				j, MAX_REG_VAL_PAIR_SIZE);
+			return -ENOMEM;
+		}
+
+		rm_data = vfe_bus_rd_data->rm_res[i]->res_priv;
+
+		/* update size register */
+		rm_data->width = io_cfg->planes[i].width;
+		rm_data->height = io_cfg->planes[i].height;
+		CAM_DBG(CAM_ISP, "RM %d image w 0x%x h 0x%x image size 0x%x",
+			rm_data->index, rm_data->width, rm_data->height,
+			buf_size);
+
+		buf_size = ((rm_data->width)&(0x0000FFFF)) |
+			((rm_data->height<<16)&(0xFFFF0000));
+
+		CAM_DBG(CAM_ISP, "size offset 0x%x buf_size 0x%x",
+			rm_data->hw_regs->buf_size, buf_size);
+		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+			rm_data->hw_regs->buffer_width_cfg,
+			buf_size);
+		CAM_DBG(CAM_ISP, "RM %d image size 0x%x",
+			rm_data->index, reg_val_pair[j-1]);
+
+		val = rm_data->width;
+		CAM_DBG(CAM_ISP, "io_cfg stride 0x%x", val);
+		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+			rm_data->hw_regs->stride,
+			val);
+		rm_data->stride = val;
+		CAM_DBG(CAM_ISP, "RM %d image stride 0x%x",
+			rm_data->index, reg_val_pair[j-1]);
+
+		/* RM Image address */
+		CAM_DBG(CAM_ISP, "image_addr offset %x",
+			rm_data->hw_regs->image_addr);
+		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+			rm_data->hw_regs->image_addr,
+			update_buf->rm_update->image_buf[i] +
+				rm_data->offset);
+		CAM_DBG(CAM_ISP, "RM %d image address 0x%x",
+			rm_data->index, reg_val_pair[j-1]);
+		rm_data->img_addr = reg_val_pair[j-1];
+
+	}
+
+	size = vfe_bus_rd_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+
+	/* cdm util returns dwords, need to convert to bytes */
+	if ((size * 4) > update_buf->cmd.size) {
+		CAM_ERR(CAM_ISP,
+			"Failed! Buf size:%d insufficient, expected size:%d",
+			update_buf->cmd.size, size);
+		return -ENOMEM;
+	}
+
+	vfe_bus_rd_data->cdm_util_ops->cdm_write_regrandom(
+		update_buf->cmd.cmd_buf_addr, j/2, reg_val_pair);
+
+	/* cdm util returns dwords, need to convert to bytes */
+	update_buf->cmd.used_bytes = size * 4;
+
+	return 0;
+}
+
+static int cam_vfe_bus_rd_update_hfr(void *priv, void *cmd_args,
+	uint32_t arg_size)
+{
+	return 0;
+}
+
+static int cam_vfe_bus_rd_update_fs_cfg(void *priv, void *cmd_args,
+	uint32_t arg_size)
+{
+	struct cam_vfe_bus_rd_ver1_priv              *bus_priv;
+	struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data   *vfe_bus_rd_data = NULL;
+	struct cam_vfe_bus_rd_ver1_rm_resource_data  *rm_data = NULL;
+	struct cam_vfe_fe_update_args                *fe_upd_args;
+	struct cam_fe_config                         *fe_cfg;
+	struct cam_vfe_bus_rd_ver1_common_data        *common_data;
+	int i = 0;
+
+	bus_priv = (struct cam_vfe_bus_rd_ver1_priv  *) priv;
+	fe_upd_args = (struct cam_vfe_fe_update_args *)cmd_args;
+
+	vfe_bus_rd_data = (struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *)
+		fe_upd_args->node_res->res_priv;
+
+	if (!vfe_bus_rd_data || !vfe_bus_rd_data->cdm_util_ops) {
+		CAM_ERR(CAM_ISP, "Failed! Invalid data");
+		return -EINVAL;
+	}
+
+	fe_cfg = &fe_upd_args->fe_config;
+
+	for (i = 0; i < vfe_bus_rd_data->num_rm; i++) {
+
+		rm_data = vfe_bus_rd_data->rm_res[i]->res_priv;
+		common_data = rm_data->common_data;
+
+		rm_data->format = fe_cfg->format;
+		CAM_DBG(CAM_ISP, "format: 0x%x", rm_data->format);
+
+		rm_data->unpacker_cfg = fe_cfg->unpacker_cfg;
+		CAM_DBG(CAM_ISP, "unpacker_cfg: 0x%x", rm_data->unpacker_cfg);
+
+		rm_data->latency_buf_allocation = fe_cfg->latency_buf_size;
+		CAM_DBG(CAM_ISP, "latency_buf_allocation: 0x%x",
+			rm_data->latency_buf_allocation);
+
+		rm_data->stride = fe_cfg->stride;
+		CAM_DBG(CAM_ISP, "stride: 0x%x", rm_data->stride);
+
+		rm_data->go_cmd_sel = fe_cfg->go_cmd_sel;
+		CAM_DBG(CAM_ISP, "go_cmd_sel: 0x%x", rm_data->go_cmd_sel);
+
+		rm_data->fs_sync_enable = fe_cfg->fs_sync_enable;
+		CAM_DBG(CAM_ISP, "fs_sync_enable: 0x%x",
+			rm_data->fs_sync_enable);
+
+		rm_data->hbi_count = fe_cfg->hbi_count;
+		CAM_DBG(CAM_ISP, "hbi_count: 0x%x", rm_data->hbi_count);
+
+		rm_data->fs_line_sync_en = fe_cfg->fs_line_sync_en;
+		CAM_DBG(CAM_ISP, "fs_line_sync_en: 0x%x",
+			rm_data->fs_line_sync_en);
+
+		rm_data->fs_mode = fe_cfg->fs_mode;
+		CAM_DBG(CAM_ISP, "fs_mode: 0x%x", rm_data->fs_mode);
+
+		rm_data->min_vbi = fe_cfg->min_vbi;
+		CAM_DBG(CAM_ISP, "min_vbi: 0x%x", rm_data->min_vbi);
+	}
+	bus_priv->common_data.fs_sync_enable = fe_cfg->fs_sync_enable;
+	bus_priv->common_data.go_cmd_sel = fe_cfg->go_cmd_sel;
+	return 0;
+}
+
+static int cam_vfe_bus_start_hw(void *hw_priv,
+	void *start_hw_args, uint32_t arg_size)
+{
+	return cam_vfe_bus_start_vfe_bus_rd(hw_priv);
+}
+
+static int cam_vfe_bus_stop_hw(void *hw_priv,
+	void *stop_hw_args, uint32_t arg_size)
+{
+	return cam_vfe_bus_stop_vfe_bus_rd(hw_priv);
+}
+
+static int cam_vfe_bus_init_hw(void *hw_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_vfe_bus_rd_ver1_priv    *bus_priv = hw_priv;
+	uint32_t                            top_irq_reg_mask[2] = {0};
+	uint32_t                            offset = 0, val = 0;
+	struct cam_vfe_bus_rd_ver1_reg_offset_common  *common_reg;
+
+	if (!bus_priv) {
+		CAM_ERR(CAM_ISP, "Invalid args");
+		return -EINVAL;
+	}
+	common_reg = bus_priv->common_data.common_reg;
+	top_irq_reg_mask[0] = (1 << 23);
+
+	bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
+		bus_priv->common_data.vfe_irq_controller,
+		CAM_IRQ_PRIORITY_2,
+		top_irq_reg_mask,
+		bus_priv,
+		cam_vfe_bus_rd_ver1_handle_irq,
+		NULL,
+		NULL,
+		NULL);
+
+	if (bus_priv->irq_handle <= 0) {
+		CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
+		return -EFAULT;
+	}
+	/* no clock gating at bus input */
+	offset = common_reg->cgc_ovd;
+	cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset);
+
+	/* BUS_RD_TEST_BUS_CTRL */
+	offset = common_reg->test_bus_ctrl;
+	cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset);
+
+	/* Read irq mask */
+	offset = common_reg->irq_reg_info.irq_reg_set->mask_reg_offset;
+	cam_io_w_mb(0x5, bus_priv->common_data.mem_base + offset);
+
+	/* INPUT_IF_CMD */
+	val = (bus_priv->common_data.fs_sync_enable << 5) |
+		(bus_priv->common_data.go_cmd_sel << 4);
+	offset = common_reg->input_if_cmd;
+	cam_io_w_mb(val, bus_priv->common_data.mem_base + offset);
+	return 0;
+}
+
+static int cam_vfe_bus_deinit_hw(void *hw_priv,
+	void *deinit_hw_args, uint32_t arg_size)
+{
+	struct cam_vfe_bus_rd_ver1_priv    *bus_priv = hw_priv;
+	int                              rc = 0;
+
+	if (!bus_priv) {
+		CAM_ERR(CAM_ISP, "Error: Invalid args");
+		return -EINVAL;
+	}
+
+	if (bus_priv->error_irq_handle) {
+		rc = cam_irq_controller_unsubscribe_irq(
+			bus_priv->common_data.bus_irq_controller,
+			bus_priv->error_irq_handle);
+		if (rc)
+			CAM_ERR(CAM_ISP,
+				"Failed to unsubscribe error irq rc=%d", rc);
+
+		bus_priv->error_irq_handle = 0;
+	}
+
+	if (bus_priv->irq_handle) {
+		rc = cam_irq_controller_unsubscribe_irq(
+			bus_priv->common_data.vfe_irq_controller,
+			bus_priv->irq_handle);
+		if (rc)
+			CAM_ERR(CAM_ISP,
+				"Failed to unsubscribe irq rc=%d", rc);
+
+		bus_priv->irq_handle = 0;
+	}
+
+	return rc;
+}
+
+static int __cam_vfe_bus_process_cmd(void *priv,
+	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
+{
+	return cam_vfe_bus_process_cmd(priv, cmd_type, cmd_args, arg_size);
+}
+
+static int cam_vfe_bus_process_cmd(
+	struct cam_isp_resource_node *priv,
+	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
+{
+	int rc = -EINVAL;
+
+	if (!priv || !cmd_args) {
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments");
+		return -EINVAL;
+	}
+
+	switch (cmd_type) {
+	case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
+		rc = cam_vfe_bus_rd_update_rm(priv, cmd_args, arg_size);
+		break;
+	case CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM:
+		rc = cam_vfe_bus_rd_update_hfr(priv, cmd_args, arg_size);
+		break;
+	case CAM_ISP_HW_CMD_GET_SECURE_MODE:
+		rc = cam_vfe_bus_rd_get_secure_mode(priv, cmd_args, arg_size);
+		break;
+	case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
+		rc = cam_vfe_bus_rd_update_fs_cfg(priv, cmd_args, arg_size);
+		break;
+	default:
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d",
+			cmd_type);
+		break;
+	}
+
+	return rc;
+}
+
+int cam_vfe_bus_rd_ver1_init(
+	struct cam_hw_soc_info               *soc_info,
+	struct cam_hw_intf                   *hw_intf,
+	void                                 *bus_hw_info,
+	void                                 *vfe_irq_controller,
+	struct cam_vfe_bus                  **vfe_bus)
+{
+	int i, rc = 0;
+	struct cam_vfe_bus_rd_ver1_priv    *bus_priv = NULL;
+	struct cam_vfe_bus                 *vfe_bus_local;
+	struct cam_vfe_bus_rd_ver1_hw_info *bus_rd_hw_info = bus_hw_info;
+
+	if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
+		CAM_ERR(CAM_ISP,
+			"Inval_prms soc_info:%pK hw_intf:%pK hw_info%pK",
+			soc_info, hw_intf, bus_rd_hw_info);
+		CAM_ERR(CAM_ISP, "controller: %pK", vfe_irq_controller);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
+	if (!vfe_bus_local) {
+		CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus");
+		rc = -ENOMEM;
+		goto end;
+	}
+
+	bus_priv = kzalloc(sizeof(struct cam_vfe_bus_rd_ver1_priv),
+		GFP_KERNEL);
+	if (!bus_priv) {
+		CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus_priv");
+		rc = -ENOMEM;
+		goto free_bus_local;
+	}
+
+	vfe_bus_local->bus_priv = bus_priv;
+
+	bus_priv->num_client                     = bus_rd_hw_info->num_client;
+	bus_priv->num_bus_rd_resc                =
+		bus_rd_hw_info->num_bus_rd_resc;
+	bus_priv->common_data.num_sec_out        = 0;
+	bus_priv->common_data.secure_mode        = CAM_SECURE_MODE_NON_SECURE;
+	bus_priv->common_data.core_index         = soc_info->index;
+	bus_priv->common_data.mem_base           =
+		CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
+	bus_priv->common_data.hw_intf            = hw_intf;
+	bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
+	bus_priv->common_data.common_reg         = &bus_rd_hw_info->common_reg;
+
+	mutex_init(&bus_priv->common_data.bus_mutex);
+
+	rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
+		&bus_rd_hw_info->common_reg.irq_reg_info,
+		&bus_priv->common_data.bus_irq_controller);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "cam_irq_controller_init failed");
+		goto free_bus_priv;
+	}
+
+	for (i = 0; i < bus_priv->num_client; i++) {
+		rc = cam_vfe_bus_init_rm_resource(i, bus_priv, bus_hw_info,
+			&bus_priv->bus_client[i]);
+		if (rc < 0) {
+			CAM_ERR(CAM_ISP, "Init RM failed rc=%d", rc);
+			goto deinit_rm;
+		}
+	}
+
+	for (i = 0; i < bus_priv->num_bus_rd_resc; i++) {
+		rc = cam_vfe_bus_init_vfe_bus_read_resource(i, bus_priv,
+			bus_rd_hw_info);
+		if (rc < 0) {
+			CAM_ERR(CAM_ISP, "Init VFE Out failed rc=%d", rc);
+			goto deinit_vfe_bus_rd;
+		}
+	}
+
+	spin_lock_init(&bus_priv->common_data.spin_lock);
+
+	vfe_bus_local->hw_ops.reserve      = cam_vfe_bus_acquire_vfe_bus_rd;
+	vfe_bus_local->hw_ops.release      = cam_vfe_bus_release_vfe_bus_rd;
+	vfe_bus_local->hw_ops.start        = cam_vfe_bus_start_hw;
+	vfe_bus_local->hw_ops.stop         = cam_vfe_bus_stop_hw;
+	vfe_bus_local->hw_ops.init         = cam_vfe_bus_init_hw;
+	vfe_bus_local->hw_ops.deinit       = cam_vfe_bus_deinit_hw;
+	vfe_bus_local->top_half_handler    = cam_vfe_bus_rd_ver1_handle_irq;
+	vfe_bus_local->bottom_half_handler = NULL;
+	vfe_bus_local->hw_ops.process_cmd  = __cam_vfe_bus_process_cmd;
+
+	*vfe_bus = vfe_bus_local;
+
+	return rc;
+
+deinit_vfe_bus_rd:
+	if (i < 0)
+		i = CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX;
+	for (--i; i >= 0; i--)
+		cam_vfe_bus_deinit_vfe_bus_rd_resource(
+			&bus_priv->vfe_bus_rd[i]);
+deinit_rm:
+	if (i < 0)
+		i = bus_priv->num_client;
+	for (--i; i >= 0; i--)
+		cam_vfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]);
+
+free_bus_priv:
+	kfree(vfe_bus_local->bus_priv);
+
+free_bus_local:
+	kfree(vfe_bus_local);
+
+end:
+	return rc;
+}
+
+int cam_vfe_bus_rd_bus_ver1_deinit(
+	struct cam_vfe_bus                  **vfe_bus)
+{
+	int i, rc = 0;
+	struct cam_vfe_bus_rd_ver1_priv    *bus_priv = NULL;
+	struct cam_vfe_bus                 *vfe_bus_local;
+
+	if (!vfe_bus || !*vfe_bus) {
+		CAM_ERR(CAM_ISP, "Invalid input");
+		return -EINVAL;
+	}
+	vfe_bus_local = *vfe_bus;
+
+	bus_priv = vfe_bus_local->bus_priv;
+	if (!bus_priv) {
+		CAM_ERR(CAM_ISP, "bus_priv is NULL");
+		rc = -ENODEV;
+		goto free_bus_local;
+	}
+
+	for (i = 0; i < bus_priv->num_client; i++) {
+		rc = cam_vfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]);
+		if (rc < 0)
+			CAM_ERR(CAM_ISP,
+				"Deinit RM failed rc=%d", rc);
+	}
+	for (i = 0; i < CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX; i++) {
+		rc = cam_vfe_bus_deinit_vfe_bus_rd_resource(
+			&bus_priv->vfe_bus_rd[i]);
+		if (rc < 0)
+			CAM_ERR(CAM_ISP,
+				"Deinit VFE Out failed rc=%d", rc);
+	}
+
+	rc = cam_irq_controller_deinit(
+		&bus_priv->common_data.bus_irq_controller);
+	if (rc)
+		CAM_ERR(CAM_ISP,
+			"Deinit IRQ Controller failed rc=%d", rc);
+
+	mutex_destroy(&bus_priv->common_data.bus_mutex);
+	kfree(vfe_bus_local->bus_priv);
+
+free_bus_local:
+	kfree(vfe_bus_local);
+
+	*vfe_bus = NULL;
+
+	return rc;
+}
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h
new file mode 100644
index 0000000..d5bfbc8
--- /dev/null
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h
@@ -0,0 +1,143 @@
+/* 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_VFE_BUS_R_VER1_H_
+#define _CAM_VFE_BUS_R_VER1_H_
+
+#include "cam_irq_controller.h"
+#include "cam_vfe_bus.h"
+
+#define CAM_VFE_BUS_RD_VER1_MAX_CLIENTS 1
+
+enum cam_vfe_bus_rd_ver1_vfe_core_id {
+	CAM_VFE_BUS_RD_VER1_VFE_CORE_0,
+	CAM_VFE_BUS_RD_VER1_VFE_CORE_1,
+	CAM_VFE_BUS_RD_VER1_VFE_CORE_MAX,
+};
+
+enum cam_vfe_bus_rd_ver1_comp_grp_type {
+	CAM_VFE_BUS_RD_VER1_COMP_GRP_0,
+	CAM_VFE_BUS_RD_VER1_COMP_GRP_MAX,
+};
+
+
+enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type {
+	CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0,
+	CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX,
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_reg_offset_common:
+ *
+ * @Brief:        Common registers across all BUS Clients
+ */
+struct cam_vfe_bus_rd_ver1_reg_offset_common {
+	uint32_t hw_version;
+	uint32_t hw_capability;
+	uint32_t sw_reset;
+	uint32_t cgc_ovd;
+	uint32_t pwr_iso_cfg;
+	uint32_t input_if_cmd;
+	uint32_t test_bus_ctrl;
+	struct cam_irq_controller_reg_info irq_reg_info;
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_reg_offset_bus_client:
+ *
+ * @Brief:        Register offsets for BUS Clients
+ */
+struct cam_vfe_bus_rd_ver1_reg_offset_bus_client {
+	uint32_t status0;
+	uint32_t status1;
+	uint32_t cfg;
+	uint32_t header_addr;
+	uint32_t header_cfg;
+	uint32_t image_addr;
+	uint32_t image_addr_offset;
+	uint32_t buffer_width_cfg;
+	uint32_t buffer_height_cfg;
+	uint32_t unpacker_cfg;
+	uint32_t stride;
+	void    *ubwc_regs;
+	uint32_t burst_limit;
+	uint32_t latency_buf_allocation;
+	uint32_t buf_size;
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info:
+ *
+ * @Brief:        HW capability of VFE Bus Client
+ */
+struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info {
+	enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type  vfe_bus_rd_type;
+	uint32_t                            max_width;
+	uint32_t                            max_height;
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_hw_info:
+ *
+ * @Brief:            HW register info for entire Bus
+ *
+ * @common_reg:       Common register details
+ * @bus_client_reg:   Bus client register info
+ * @comp_reg_grp:     Composite group register info
+ * @vfe_out_hw_info:  VFE output capability
+ */
+struct cam_vfe_bus_rd_ver1_hw_info {
+	struct cam_vfe_bus_rd_ver1_reg_offset_common common_reg;
+	uint32_t num_client;
+	struct cam_vfe_bus_rd_ver1_reg_offset_bus_client
+		bus_client_reg[CAM_VFE_BUS_RD_VER1_MAX_CLIENTS];
+	uint32_t num_bus_rd_resc;
+	struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info
+		vfe_bus_rd_hw_info[CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX];
+};
+
+/*
+ * cam_vfe_bus_rd_ver1_init()
+ *
+ * @Brief:                   Initialize Bus layer
+ *
+ * @soc_info:                Soc Information for the associated HW
+ * @hw_intf:                 HW Interface of HW to which this resource belongs
+ * @bus_hw_info:             BUS HW info that contains details of BUS registers
+ * @vfe_irq_controller:      VFE IRQ Controller to use for subscribing to Top
+ *                           level IRQs
+ * @vfe_bus:                 Pointer to vfe_bus structure which will be filled
+ *                           and returned on successful initialize
+ *
+ * @Return:                  0: Success
+ *                           Non-zero: Failure
+ */
+int cam_vfe_bus_rd_ver1_init(
+	struct cam_hw_soc_info               *soc_info,
+	struct cam_hw_intf                   *hw_intf,
+	void                                 *bus_hw_info,
+	void                                 *vfe_irq_controller,
+	struct cam_vfe_bus                  **vfe_bus);
+
+/*
+ * cam_vfe_bus_rd_bus_ver1_deinit()
+ *
+ * @Brief:                   Deinitialize Bus layer
+ *
+ * @vfe_bus:                 Pointer to vfe_bus structure to deinitialize
+ *
+ * @Return:                  0: Success
+ *                           Non-zero: Failure
+ */
+int cam_vfe_bus_rd_bus_ver1_deinit(struct cam_vfe_bus     **vfe_bus);
+
+#endif /* _CAM_VFE_BUS_R_VER1_H_ */
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
index 6f88bc7..4cdb28a 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.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
@@ -19,6 +19,7 @@
 
 #define CAM_VFE_BUS_VER_1_0             0x1000
 #define CAM_VFE_BUS_VER_2_0             0x2000
+#define CAM_VFE_BUS_RD_VER_4_0          0x4000
 
 enum cam_vfe_bus_plane_type {
 	PLANE_Y,
@@ -26,6 +27,12 @@ enum cam_vfe_bus_plane_type {
 	PLANE_MAX,
 };
 
+enum cam_vfe_bus_type {
+	BUS_TYPE_WR,
+	BUS_TYPE_RD,
+	BUS_TYPE_MAX,
+};
+
 /*
  * struct cam_vfe_bus:
  *
@@ -50,6 +57,7 @@ struct cam_vfe_bus {
  * @Brief:                   Initialize Bus layer
  *
  * @bus_version:             Version of BUS to initialize
+ * @bus_type:                Bus Type RD/WR
  * @soc_info:                Soc Information for the associated HW
  * @hw_intf:                 HW Interface of HW to which this resource belongs
  * @bus_hw_info:             BUS HW info that contains details of BUS registers
@@ -62,6 +70,7 @@ struct cam_vfe_bus {
  *                           Non-zero: Failure
  */
 int cam_vfe_bus_init(uint32_t          bus_version,
+	int                            bus_type,
 	struct cam_hw_soc_info        *soc_info,
 	struct cam_hw_intf            *hw_intf,
 	void                          *bus_hw_info,
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile
index 55b2db6..084453a 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile
@@ -12,3 +12,4 @@
 
 obj-$(CONFIG_MSM_AIS) += cam_vfe_camif_lite_ver2.o
 obj-$(CONFIG_MSM_AIS) += cam_vfe_top.o cam_vfe_top_ver2.o cam_vfe_camif_ver2.o cam_vfe_rdi.o
+obj-$(CONFIG_MSM_AIS) += cam_vfe_fe_ver1.o
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index 8933326..be3d5e9 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.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
@@ -212,8 +212,7 @@ static int cam_vfe_camif_resource_start(
 	uint32_t                             epoch0_irq_mask;
 	uint32_t                             epoch1_irq_mask;
 	uint32_t                             computed_epoch_line_cfg;
-	uint32_t                             camera_hw_version = 0;
-	int                                  rc = 0;
+	struct cam_vfe_soc_private          *soc_private;
 
 	if (!camif_res) {
 		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
@@ -228,6 +227,13 @@ static int cam_vfe_camif_resource_start(
 
 	rsrc_data = (struct cam_vfe_mux_camif_data  *)camif_res->res_priv;
 
+	soc_private = rsrc_data->soc_info->soc_private;
+
+	if (!soc_private) {
+		CAM_ERR(CAM_ISP, "Error! soc_private NULL");
+		return -ENODEV;
+	}
+
 	/*config vfe core*/
 	val = (rsrc_data->pix_pattern <<
 			rsrc_data->reg_data->pixel_pattern_shift);
@@ -253,18 +259,16 @@ static int cam_vfe_camif_resource_start(
 		rsrc_data->common_reg->module_ctrl[
 		CAM_VFE_TOP_VER2_MODULE_STATS]->cgc_ovd);
 
-	/* get the HW version */
-	rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
-
-	if (rc) {
-		CAM_ERR(CAM_ISP, "Couldn't find HW version. rc: %d", rc);
-		return rc;
-	}
-
 	/* epoch config */
-	switch (camera_hw_version) {
-	case CAM_CPAS_TITAN_175_V101:
-	case CAM_CPAS_TITAN_175_V100:
+	switch (soc_private->cpas_version) {
+	case CAM_CPAS_TITAN_170_V100:
+	case CAM_CPAS_TITAN_170_V110:
+	case CAM_CPAS_TITAN_170_V120:
+		cam_io_w_mb(rsrc_data->reg_data->epoch_line_cfg,
+				rsrc_data->mem_base +
+				rsrc_data->camif_reg->epoch_irq);
+		break;
+	default:
 		epoch0_irq_mask = ((rsrc_data->last_line -
 				rsrc_data->first_line) / 2) +
 				rsrc_data->first_line;
@@ -282,21 +286,6 @@ static int cam_vfe_camif_resource_start(
 				rsrc_data->last_line,
 				computed_epoch_line_cfg);
 		break;
-	case CAM_CPAS_TITAN_170_V100:
-	case CAM_CPAS_TITAN_170_V110:
-	case CAM_CPAS_TITAN_170_V120:
-	case CAM_CPAS_TITAN_150_V100:
-		cam_io_w_mb(rsrc_data->reg_data->epoch_line_cfg,
-				rsrc_data->mem_base +
-				rsrc_data->camif_reg->epoch_irq);
-		break;
-	default:
-		cam_io_w_mb(rsrc_data->reg_data->epoch_line_cfg,
-				rsrc_data->mem_base +
-				rsrc_data->camif_reg->epoch_irq);
-		CAM_WARN(CAM_ISP, "Hardware version not proper: 0x%x",
-				camera_hw_version);
-		break;
 	}
 
 	camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
@@ -325,27 +314,16 @@ static int cam_vfe_camif_resource_start(
 }
 
 static int cam_vfe_camif_reg_dump(
-	struct cam_isp_resource_node *camif_res)
+	struct cam_vfe_mux_camif_data *camif_priv)
 {
-	struct cam_vfe_mux_camif_data *camif_priv;
-	struct cam_vfe_soc_private *soc_private;
-	int rc = 0, i;
-	uint32_t val = 0;
+	uint32_t val = 0, wm_idx, offset;
+	int i = 0;
 
-	if (!camif_res) {
-		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
-		return -EINVAL;
-	}
-
-	if ((camif_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
-		(camif_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
-		return 0;
-
-	camif_priv = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
-	soc_private = camif_priv->soc_info->soc_private;
-	for (i = 0xA3C; i <= 0xA90; i += 4) {
-		val = cam_io_r_mb(camif_priv->mem_base + i);
-		CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+	for (i = 0xA3C; i <= 0xA90; i += 8) {
+		CAM_INFO(CAM_ISP,
+			"SCALING offset 0x%x val 0x%x offset 0x%x val 0x%x",
+			i, cam_io_r_mb(camif_priv->mem_base + i), i + 4,
+			cam_io_r_mb(camif_priv->mem_base + i + 4));
 	}
 
 	for (i = 0xE0C; i <= 0xE3C; i += 4) {
@@ -353,53 +331,17 @@ static int cam_vfe_camif_reg_dump(
 		CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
 	}
 
-	for (i = 0x2000; i <= 0x20B8; i += 4) {
-		val = cam_io_r_mb(camif_priv->mem_base + i);
-		CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
-	}
-
-	for (i = 0x2500; i <= 0x255C; i += 4) {
-		val = cam_io_r_mb(camif_priv->mem_base + i);
-		CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
-	}
-
-	for (i = 0x2600; i <= 0x265C; i += 4) {
-		val = cam_io_r_mb(camif_priv->mem_base + i);
-		CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
-	}
-
-	cam_cpas_reg_read(soc_private->cpas_handle,
-		CAM_CPAS_REG_CAMNOC, 0x420, true, &val);
-	CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val);
-
-	cam_cpas_reg_read(soc_private->cpas_handle,
-		CAM_CPAS_REG_CAMNOC, 0x820, true, &val);
-	CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val);
-
-	return rc;
-}
-
-static int cam_vfe_camif_reg_dump_bh(struct cam_vfe_mux_camif_data *camif_priv)
-{
-	uint32_t offset, val, wm_idx;
-
-	for (offset = 0x0; offset < 0x1000; offset += 0x4) {
-		val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
-		CAM_INFO(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
-	}
-
-	for (offset = 0x2000; offset <= 0x20B8; offset += 0x4) {
-		val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
-		CAM_INFO(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
-	}
-
 	for (wm_idx = 0; wm_idx <= 23; wm_idx++) {
-		for (offset = 0x2200 + 0x100 * wm_idx;
-			offset < 0x2278 + 0x100 * wm_idx; offset += 0x4) {
-			val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
-			CAM_INFO(CAM_ISP,
-				"offset 0x%x value 0x%x", offset, val);
-		}
+		offset = 0x2214 + 0x100 * wm_idx;
+		CAM_INFO(CAM_ISP,
+			"BUS_WM%u offset 0x%x val 0x%x offset 0x%x val 0x%x",
+			wm_idx, offset,
+			cam_io_r_mb(camif_priv->mem_base + offset),
+			offset + 4, cam_io_r_mb(camif_priv->mem_base +
+			offset + 4), offset + 8,
+			cam_io_r_mb(camif_priv->mem_base + offset + 8),
+			offset + 12, cam_io_r_mb(camif_priv->mem_base +
+			offset + 12));
 	}
 
 	offset = 0x420;
@@ -415,6 +357,71 @@ static int cam_vfe_camif_reg_dump_bh(struct cam_vfe_mux_camif_data *camif_priv)
 	return 0;
 }
 
+static int cam_vfe_camif_reg_dump_bh(
+	struct cam_isp_resource_node *camif_res)
+{
+	struct cam_vfe_mux_camif_data *camif_priv;
+	struct cam_vfe_soc_private *soc_private;
+	uint32_t offset, val, wm_idx;
+
+	if (!camif_res) {
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+		return -EINVAL;
+	}
+
+	if ((camif_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
+		(camif_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
+		return 0;
+
+	camif_priv = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
+	for (offset = 0x0; offset < 0x1000; offset += 0x4) {
+		val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
+		CAM_DBG(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
+	}
+
+	for (offset = 0x2000; offset <= 0x20B8; offset += 0x4) {
+		val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
+		CAM_DBG(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
+	}
+
+	for (wm_idx = 0; wm_idx <= 23; wm_idx++) {
+		for (offset = 0x2200 + 0x100 * wm_idx;
+			offset < 0x2278 + 0x100 * wm_idx; offset += 0x4) {
+			val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
+			CAM_DBG(CAM_ISP,
+				"offset 0x%x value 0x%x", offset, val);
+		}
+	}
+
+	soc_private = camif_priv->soc_info->soc_private;
+	if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120) {
+		cam_cpas_reg_read(soc_private->cpas_handle[0],
+			CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val);
+		CAM_DBG(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x",
+			val);
+
+		cam_cpas_reg_read(soc_private->cpas_handle[0],
+			CAM_CPAS_REG_CAMNOC, 0x5420, true, &val);
+		CAM_DBG(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x",
+			val);
+
+		cam_cpas_reg_read(soc_private->cpas_handle[1],
+			CAM_CPAS_REG_CAMNOC, 0x3620, true, &val);
+		CAM_DBG(CAM_ISP,
+			"IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val);
+	} else {
+		cam_cpas_reg_read(soc_private->cpas_handle[0],
+			CAM_CPAS_REG_CAMNOC, 0x420, true, &val);
+		CAM_DBG(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val);
+
+		cam_cpas_reg_read(soc_private->cpas_handle[0],
+			CAM_CPAS_REG_CAMNOC, 0x820, true, &val);
+		CAM_DBG(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val);
+	}
+
+	return 0;
+}
+
 static int cam_vfe_camif_resource_stop(
 	struct cam_isp_resource_node        *camif_res)
 {
@@ -492,7 +499,7 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
 			arg_size);
 		break;
 	case CAM_ISP_HW_CMD_GET_REG_DUMP:
-		rc = cam_vfe_camif_reg_dump(rsrc_node);
+		rc = cam_vfe_camif_reg_dump_bh(rsrc_node);
 		break;
 	case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG:
 		rc = cam_vfe_camif_sof_irq_debug(rsrc_node, cmd_args);
@@ -585,7 +592,7 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv,
 		if (irq_status1 & camif_priv->reg_data->error_irq_mask1) {
 			CAM_DBG(CAM_ISP, "Received ERROR\n");
 			ret = CAM_ISP_HW_ERROR_OVERFLOW;
-			cam_vfe_camif_reg_dump_bh(camif_node->res_priv);
+			cam_vfe_camif_reg_dump(camif_node->res_priv);
 		} else {
 			ret = CAM_ISP_HW_ERROR_NONE;
 		}
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c
new file mode 100644
index 0000000..af26cae
--- /dev/null
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c
@@ -0,0 +1,630 @@
+/* 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/slab.h>
+#include <uapi/media/cam_isp.h>
+#include "cam_io_util.h"
+#include "cam_isp_hw_mgr_intf.h"
+#include "cam_isp_hw.h"
+#include "cam_vfe_hw_intf.h"
+#include "cam_vfe_soc.h"
+#include "cam_vfe_top.h"
+#include "cam_vfe_top_ver2.h"
+#include "cam_vfe_fe_ver1.h"
+#include "cam_debug_util.h"
+#include "cam_cdm_util.h"
+#include "cam_cpas_api.h"
+
+#define CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX 2
+
+struct cam_vfe_mux_fe_data {
+	void __iomem                                *mem_base;
+	struct cam_hw_intf                          *hw_intf;
+	struct cam_vfe_fe_ver1_reg              *fe_reg;
+	struct cam_vfe_top_ver2_reg_offset_common   *common_reg;
+	struct cam_vfe_fe_reg_data               *reg_data;
+	struct cam_hw_soc_info                      *soc_info;
+
+	enum cam_isp_hw_sync_mode          sync_mode;
+	uint32_t                           dsp_mode;
+	uint32_t                           pix_pattern;
+	uint32_t                           first_pixel;
+	uint32_t                           first_line;
+	uint32_t                           last_pixel;
+	uint32_t                           last_line;
+	bool                               enable_sof_irq_debug;
+	uint32_t                           irq_debug_cnt;
+	uint32_t                           fe_cfg_data;
+	uint32_t                           hbi_count;
+};
+
+static int cam_vfe_fe_validate_pix_pattern(uint32_t pattern)
+{
+	int rc;
+
+	switch (pattern) {
+	case CAM_ISP_PATTERN_BAYER_RGRGRG:
+	case CAM_ISP_PATTERN_BAYER_GRGRGR:
+	case CAM_ISP_PATTERN_BAYER_BGBGBG:
+	case CAM_ISP_PATTERN_BAYER_GBGBGB:
+	case CAM_ISP_PATTERN_YUV_YCBYCR:
+	case CAM_ISP_PATTERN_YUV_YCRYCB:
+	case CAM_ISP_PATTERN_YUV_CBYCRY:
+	case CAM_ISP_PATTERN_YUV_CRYCBY:
+		rc = 0;
+		break;
+	default:
+		CAM_ERR(CAM_ISP, "Error! Invalid pix pattern:%d", pattern);
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
+static int cam_vfe_fe_update(
+	struct cam_isp_resource_node  *fe_res,
+	void *cmd_data, uint32_t arg_size)
+{
+	struct cam_vfe_mux_fe_data    *rsrc_data = NULL;
+	struct cam_vfe_fe_update_args    *args = cmd_data;
+	uint32_t                         fe_cfg_data;
+
+	if (arg_size != sizeof(struct cam_vfe_fe_update_args)) {
+		CAM_ERR(CAM_ISP, "Invalid cmd size");
+		return -EINVAL;
+	}
+
+	if (!args) {
+		CAM_ERR(CAM_ISP, "Invalid args");
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_ISP, "fe_update->min_vbi = 0x%x", args->fe_config.min_vbi);
+	CAM_DBG(CAM_ISP, "fe_update->hbi_count = 0x%x",
+		args->fe_config.hbi_count);
+	CAM_DBG(CAM_ISP, "fe_update->fs_mode = 0x%x", args->fe_config.fs_mode);
+	CAM_DBG(CAM_ISP, "fe_update->fs_line_sync_en = 0x%x",
+		args->fe_config.fs_line_sync_en);
+
+	fe_cfg_data = args->fe_config.min_vbi |
+			args->fe_config.fs_mode << 8 |
+			args->fe_config.fs_line_sync_en;
+
+	rsrc_data = fe_res->res_priv;
+	rsrc_data->fe_cfg_data = fe_cfg_data;
+	rsrc_data->hbi_count = args->fe_config.hbi_count;
+
+	CAM_DBG(CAM_ISP, "fe_cfg_data = 0x%x", fe_cfg_data);
+	return 0;
+}
+
+static int cam_vfe_fe_get_reg_update(
+	struct cam_isp_resource_node  *fe_res,
+	void *cmd_args, uint32_t arg_size)
+{
+	uint32_t                          size = 0;
+	uint32_t                          reg_val_pair[2];
+	struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args;
+	struct cam_cdm_utils_ops         *cdm_util_ops = NULL;
+	struct cam_vfe_mux_fe_data    *rsrc_data = NULL;
+
+	if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) {
+		CAM_ERR(CAM_ISP, "Invalid cmd size");
+		return -EINVAL;
+	}
+
+	if (!cdm_args || !cdm_args->res) {
+		CAM_ERR(CAM_ISP, "Invalid args");
+		return -EINVAL;
+	}
+
+	cdm_util_ops = (struct cam_cdm_utils_ops *)cdm_args->res->cdm_ops;
+
+	if (!cdm_util_ops) {
+		CAM_ERR(CAM_ISP, "Invalid CDM ops");
+		return -EINVAL;
+	}
+
+	size = cdm_util_ops->cdm_required_size_reg_random(1);
+	/* since cdm returns dwords, we need to convert it into bytes */
+	if ((size * 4) > cdm_args->cmd.size) {
+		CAM_ERR(CAM_ISP, "buf size:%d is not sufficient, expected: %d",
+			cdm_args->cmd.size, size);
+		return -EINVAL;
+	}
+
+	rsrc_data = fe_res->res_priv;
+	reg_val_pair[0] = rsrc_data->fe_reg->reg_update_cmd;
+	reg_val_pair[1] = rsrc_data->reg_data->reg_update_cmd_data;
+	CAM_DBG(CAM_ISP, "CAMIF reg_update_cmd 0x%x offset 0x%x",
+		reg_val_pair[1], reg_val_pair[0]);
+
+	cdm_util_ops->cdm_write_regrandom(cdm_args->cmd.cmd_buf_addr,
+		1, reg_val_pair);
+
+	cdm_args->cmd.used_bytes = size * 4;
+
+	return 0;
+}
+
+int cam_vfe_fe_ver1_acquire_resource(
+	struct cam_isp_resource_node  *fe_res,
+	void                          *acquire_param)
+{
+	struct cam_vfe_mux_fe_data    *fe_data;
+	struct cam_vfe_acquire_args      *acquire_data;
+
+	int rc = 0;
+
+	fe_data   = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+	acquire_data = (struct cam_vfe_acquire_args   *)acquire_param;
+
+	rc = cam_vfe_fe_validate_pix_pattern(
+			acquire_data->vfe_in.in_port->test_pattern);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "pix validation failed: id:%d pix_pattern %d",
+			fe_res->hw_intf->hw_idx,
+			acquire_data->vfe_in.in_port->test_pattern);
+		return rc;
+	}
+
+	fe_data->sync_mode   = acquire_data->vfe_in.sync_mode;
+	fe_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern;
+	fe_data->dsp_mode    = acquire_data->vfe_in.in_port->dsp_mode;
+	fe_data->first_pixel = acquire_data->vfe_in.in_port->left_start;
+	fe_data->last_pixel  = acquire_data->vfe_in.in_port->left_stop;
+	fe_data->first_line  = acquire_data->vfe_in.in_port->line_start;
+	fe_data->last_line   = acquire_data->vfe_in.in_port->line_stop;
+
+	CAM_DBG(CAM_ISP, "hw id:%d pix_pattern:%d dsp_mode=%d",
+		fe_res->hw_intf->hw_idx,
+		fe_data->pix_pattern, fe_data->dsp_mode);
+	return rc;
+}
+
+static int cam_vfe_fe_resource_init(
+	struct cam_isp_resource_node        *fe_res,
+	void *init_args, uint32_t arg_size)
+{
+	struct cam_vfe_mux_fe_data    *fe_data;
+	struct cam_hw_soc_info           *soc_info;
+	int rc = 0;
+
+	if (!fe_res) {
+		CAM_ERR(CAM_ISP, "Error Invalid input arguments");
+		return -EINVAL;
+	}
+
+	fe_data   = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+
+	soc_info = fe_data->soc_info;
+
+	if ((fe_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+		(fe_data->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+		rc = cam_vfe_soc_enable_clk(soc_info, CAM_VFE_DSP_CLK_NAME);
+		if (rc)
+			CAM_ERR(CAM_ISP, "failed to enable dsp clk");
+	}
+
+	return rc;
+}
+
+static int cam_vfe_fe_resource_deinit(
+	struct cam_isp_resource_node        *fe_res,
+	void *init_args, uint32_t arg_size)
+{
+	struct cam_vfe_mux_fe_data    *fe_data;
+	struct cam_hw_soc_info           *soc_info;
+	int rc = 0;
+
+	if (!fe_res) {
+		CAM_ERR(CAM_ISP, "Error Invalid input arguments");
+		return -EINVAL;
+	}
+
+	fe_data   = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+
+	soc_info = fe_data->soc_info;
+
+	if ((fe_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+		(fe_data->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+		rc = cam_vfe_soc_disable_clk(soc_info, CAM_VFE_DSP_CLK_NAME);
+		if (rc)
+			CAM_ERR(CAM_ISP, "failed to disable dsp clk");
+	}
+
+	return rc;
+
+}
+
+static int cam_vfe_fe_resource_start(
+	struct cam_isp_resource_node        *fe_res)
+{
+	struct cam_vfe_mux_fe_data       *rsrc_data;
+	uint32_t                             val = 0;
+	uint32_t                             epoch0_irq_mask;
+	uint32_t                             epoch1_irq_mask;
+	uint32_t                             computed_epoch_line_cfg;
+
+	if (!fe_res) {
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+		return -EINVAL;
+	}
+
+	if (fe_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
+		CAM_ERR(CAM_ISP, "Error! Invalid fe res res_state:%d",
+			fe_res->res_state);
+		return -EINVAL;
+	}
+
+	rsrc_data = (struct cam_vfe_mux_fe_data  *)fe_res->res_priv;
+
+	/* config vfe core */
+	val = (rsrc_data->pix_pattern <<
+			rsrc_data->reg_data->pixel_pattern_shift);
+	if (rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE)
+		val |= (1 << rsrc_data->reg_data->extern_reg_update_shift);
+
+	if ((rsrc_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+		(rsrc_data->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+		/* DSP mode reg val is CAM_ISP_DSP_MODE - 1 */
+		val |= (((rsrc_data->dsp_mode - 1) &
+			rsrc_data->reg_data->dsp_mode_mask) <<
+			rsrc_data->reg_data->dsp_mode_shift);
+		val |= (0x1 << rsrc_data->reg_data->dsp_en_shift);
+	}
+
+	if (rsrc_data->fe_cfg_data) {
+		/*set Mux mode value to EXT_RD_PATH */
+		val |= (rsrc_data->reg_data->fe_mux_data <<
+				rsrc_data->reg_data->input_mux_sel_shift);
+	}
+
+	if (rsrc_data->hbi_count) {
+		/*set hbi count*/
+		val |= (rsrc_data->hbi_count <<
+			rsrc_data->reg_data->hbi_cnt_shift);
+	}
+	cam_io_w_mb(val, rsrc_data->mem_base + rsrc_data->common_reg->core_cfg);
+
+	CAM_DBG(CAM_ISP, "hw id:%d core_cfg (off:0x%x, val:0x%x)",
+		fe_res->hw_intf->hw_idx,
+		rsrc_data->common_reg->core_cfg,
+		val);
+
+	/* disable the CGC for stats */
+	cam_io_w_mb(0xFFFFFFFF, rsrc_data->mem_base +
+		rsrc_data->common_reg->module_ctrl[
+		CAM_VFE_TOP_VER2_MODULE_STATS]->cgc_ovd);
+
+	/* epoch config */
+	epoch0_irq_mask = ((rsrc_data->last_line - rsrc_data->first_line) / 2) +
+		rsrc_data->first_line;
+
+	epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF;
+	computed_epoch_line_cfg = (epoch0_irq_mask << 16) | epoch1_irq_mask;
+	cam_io_w_mb(computed_epoch_line_cfg,
+		rsrc_data->mem_base + rsrc_data->fe_reg->epoch_irq);
+	CAM_DBG(CAM_ISP, "first_line:0x%x last_line:0x%x epoch_line_cfg: 0x%x",
+		rsrc_data->first_line, rsrc_data->last_line,
+		computed_epoch_line_cfg);
+
+	fe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
+
+	/* Read Back cfg */
+	cam_io_w_mb(rsrc_data->fe_cfg_data,
+		rsrc_data->mem_base + rsrc_data->fe_reg->fe_cfg);
+	CAM_DBG(CAM_ISP, "hw id:%d fe_cfg_data(off:0x%x val:0x%x)",
+		fe_res->hw_intf->hw_idx,
+		rsrc_data->fe_reg->fe_cfg,
+		rsrc_data->fe_cfg_data);
+
+	/* Reg Update */
+	cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data,
+		rsrc_data->mem_base + rsrc_data->fe_reg->reg_update_cmd);
+	CAM_DBG(CAM_ISP, "hw id:%d RUP (off:0x%x, val:0x%x)",
+		fe_res->hw_intf->hw_idx,
+		rsrc_data->fe_reg->reg_update_cmd,
+		rsrc_data->reg_data->reg_update_cmd_data);
+
+	/* disable sof irq debug flag */
+	rsrc_data->enable_sof_irq_debug = false;
+	rsrc_data->irq_debug_cnt = 0;
+
+	CAM_DBG(CAM_ISP, "Start Camif IFE %d Done", fe_res->hw_intf->hw_idx);
+	return 0;
+}
+
+static int cam_vfe_fe_reg_dump(
+	struct cam_isp_resource_node *fe_res)
+{
+	struct cam_vfe_mux_fe_data *fe_priv;
+	struct cam_vfe_soc_private *soc_private;
+	int rc = 0, i;
+	uint32_t val = 0;
+
+	if (!fe_res) {
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+		return -EINVAL;
+	}
+
+	if ((fe_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
+		(fe_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
+		return 0;
+
+	fe_priv = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+	soc_private = fe_priv->soc_info->soc_private;
+	for (i = 0xA3C; i <= 0xA90; i += 4) {
+		val = cam_io_r_mb(fe_priv->mem_base + i);
+		CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+	}
+
+	for (i = 0xE0C; i <= 0xE3C; i += 4) {
+		val = cam_io_r_mb(fe_priv->mem_base + i);
+		CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+	}
+
+	for (i = 0x2000; i <= 0x20B8; i += 4) {
+		val = cam_io_r_mb(fe_priv->mem_base + i);
+		CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+	}
+
+	for (i = 0x2500; i <= 0x255C; i += 4) {
+		val = cam_io_r_mb(fe_priv->mem_base + i);
+		CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+	}
+
+	for (i = 0x2600; i <= 0x265C; i += 4) {
+		val = cam_io_r_mb(fe_priv->mem_base + i);
+		CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+	}
+
+	cam_cpas_reg_read((uint32_t)soc_private->cpas_handle,
+		CAM_CPAS_REG_CAMNOC, 0x420, true, &val);
+	CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val);
+
+	cam_cpas_reg_read((uint32_t)soc_private->cpas_handle,
+		CAM_CPAS_REG_CAMNOC, 0x820, true, &val);
+	CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val);
+
+	return rc;
+}
+
+static int cam_vfe_fe_resource_stop(
+	struct cam_isp_resource_node        *fe_res)
+{
+	struct cam_vfe_mux_fe_data       *fe_priv;
+	struct cam_vfe_fe_ver1_reg       *fe_reg;
+	int rc = 0;
+	uint32_t val = 0;
+
+	if (!fe_res) {
+		CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+		return -EINVAL;
+	}
+
+	if (fe_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED ||
+		fe_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE)
+		return 0;
+
+	fe_priv = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+	fe_reg = fe_priv->fe_reg;
+
+	if ((fe_priv->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+		(fe_priv->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+		val = cam_io_r_mb(fe_priv->mem_base +
+				fe_priv->common_reg->core_cfg);
+		val &= (~(1 << fe_priv->reg_data->dsp_en_shift));
+		cam_io_w_mb(val, fe_priv->mem_base +
+			fe_priv->common_reg->core_cfg);
+	}
+
+	if (fe_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING)
+		fe_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+
+	return rc;
+}
+
+static int cam_vfe_fe_sof_irq_debug(
+	struct cam_isp_resource_node *rsrc_node, void *cmd_args)
+{
+	struct cam_vfe_mux_fe_data *fe_priv;
+	uint32_t *enable_sof_irq = (uint32_t *)cmd_args;
+
+	fe_priv =
+		(struct cam_vfe_mux_fe_data *)rsrc_node->res_priv;
+
+	if (*enable_sof_irq == 1)
+		fe_priv->enable_sof_irq_debug = true;
+	else
+		fe_priv->enable_sof_irq_debug = false;
+
+	return 0;
+}
+
+static int cam_vfe_fe_process_cmd(struct cam_isp_resource_node *rsrc_node,
+	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
+{
+	int rc = -EINVAL;
+
+	if (!rsrc_node || !cmd_args) {
+		CAM_ERR(CAM_ISP, "Invalid input arguments");
+		return -EINVAL;
+	}
+
+	switch (cmd_type) {
+	case CAM_ISP_HW_CMD_GET_REG_UPDATE:
+		rc = cam_vfe_fe_get_reg_update(rsrc_node, cmd_args,
+			arg_size);
+		break;
+	case CAM_ISP_HW_CMD_GET_REG_DUMP:
+		rc = cam_vfe_fe_reg_dump(rsrc_node);
+		break;
+	case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG:
+		rc = cam_vfe_fe_sof_irq_debug(rsrc_node, cmd_args);
+		break;
+	case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
+		rc = cam_vfe_fe_update(rsrc_node, cmd_args, arg_size);
+		break;
+	default:
+		CAM_ERR(CAM_ISP,
+			"unsupported process command:%d", cmd_type);
+		break;
+	}
+
+	return rc;
+}
+
+static int cam_vfe_fe_handle_irq_top_half(uint32_t evt_id,
+	struct cam_irq_th_payload *th_payload)
+{
+	return -EPERM;
+}
+
+static int cam_vfe_fe_handle_irq_bottom_half(void *handler_priv,
+	void *evt_payload_priv)
+{
+	int                                   ret = CAM_VFE_IRQ_STATUS_ERR;
+	struct cam_isp_resource_node         *fe_node;
+	struct cam_vfe_mux_fe_data        *fe_priv;
+	struct cam_vfe_top_irq_evt_payload   *payload;
+	uint32_t                              irq_status0;
+	uint32_t                              irq_status1;
+
+	if (!handler_priv || !evt_payload_priv) {
+		CAM_ERR(CAM_ISP, "Invalid params");
+		return ret;
+	}
+
+	fe_node = handler_priv;
+	fe_priv = fe_node->res_priv;
+	payload = evt_payload_priv;
+	irq_status0 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS0];
+	irq_status1 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS1];
+
+	CAM_DBG(CAM_ISP, "event ID:%d, irq_status_0 = 0x%x",
+			payload->evt_id, irq_status0);
+
+	switch (payload->evt_id) {
+	case CAM_ISP_HW_EVENT_SOF:
+		if (irq_status0 & fe_priv->reg_data->sof_irq_mask) {
+			if ((fe_priv->enable_sof_irq_debug) &&
+				(fe_priv->irq_debug_cnt <=
+				CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX)) {
+				CAM_INFO_RATE_LIMIT(CAM_ISP, "Received SOF");
+
+				fe_priv->irq_debug_cnt++;
+				if (fe_priv->irq_debug_cnt ==
+					CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX) {
+					fe_priv->enable_sof_irq_debug =
+						false;
+					fe_priv->irq_debug_cnt = 0;
+				}
+			} else {
+				CAM_DBG(CAM_ISP, "Received SOF");
+			}
+			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+		}
+		break;
+	case CAM_ISP_HW_EVENT_EPOCH:
+		if (irq_status0 & fe_priv->reg_data->epoch0_irq_mask) {
+			CAM_DBG(CAM_ISP, "Received EPOCH");
+			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+		}
+		break;
+	case CAM_ISP_HW_EVENT_REG_UPDATE:
+		if (irq_status0 & fe_priv->reg_data->reg_update_irq_mask) {
+			CAM_DBG(CAM_ISP, "Received REG_UPDATE_ACK");
+			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+		}
+		break;
+	case CAM_ISP_HW_EVENT_EOF:
+		if (irq_status0 & fe_priv->reg_data->eof_irq_mask) {
+			CAM_DBG(CAM_ISP, "Received EOF\n");
+			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+		}
+		break;
+	case CAM_ISP_HW_EVENT_ERROR:
+		if (irq_status1 & fe_priv->reg_data->error_irq_mask1) {
+			CAM_DBG(CAM_ISP, "Received ERROR\n");
+			ret = CAM_ISP_HW_ERROR_OVERFLOW;
+			cam_vfe_fe_reg_dump(fe_node);
+		} else {
+			ret = CAM_ISP_HW_ERROR_NONE;
+		}
+		break;
+	default:
+		break;
+	}
+
+	CAM_DBG(CAM_ISP, "returing status = %d", ret);
+	return ret;
+}
+
+int cam_vfe_fe_ver1_init(
+	struct cam_hw_intf            *hw_intf,
+	struct cam_hw_soc_info        *soc_info,
+	void                          *fe_hw_info,
+	struct cam_isp_resource_node  *fe_node)
+{
+	struct cam_vfe_mux_fe_data     *fe_priv = NULL;
+	struct cam_vfe_fe_ver1_hw_info *fe_info = fe_hw_info;
+
+	fe_priv = kzalloc(sizeof(struct cam_vfe_mux_fe_data),
+		GFP_KERNEL);
+	if (!fe_priv) {
+		CAM_ERR(CAM_ISP, "Error! Failed to alloc for fe_priv");
+		return -ENOMEM;
+	}
+
+	fe_node->res_priv = fe_priv;
+
+	fe_priv->mem_base    = soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base;
+	fe_priv->fe_reg  = fe_info->fe_reg;
+	fe_priv->common_reg  = fe_info->common_reg;
+	fe_priv->reg_data    = fe_info->reg_data;
+	fe_priv->hw_intf     = hw_intf;
+	fe_priv->soc_info    = soc_info;
+
+	fe_node->init    = cam_vfe_fe_resource_init;
+	fe_node->deinit  = cam_vfe_fe_resource_deinit;
+	fe_node->start   = cam_vfe_fe_resource_start;
+	fe_node->stop    = cam_vfe_fe_resource_stop;
+	fe_node->process_cmd = cam_vfe_fe_process_cmd;
+	fe_node->top_half_handler = cam_vfe_fe_handle_irq_top_half;
+	fe_node->bottom_half_handler = cam_vfe_fe_handle_irq_bottom_half;
+
+	return 0;
+}
+
+int cam_vfe_fe_ver1_deinit(
+	struct cam_isp_resource_node  *fe_node)
+{
+	struct cam_vfe_mux_fe_data *fe_priv = fe_node->res_priv;
+
+	fe_node->start = NULL;
+	fe_node->stop  = NULL;
+	fe_node->process_cmd = NULL;
+	fe_node->top_half_handler = NULL;
+	fe_node->bottom_half_handler = NULL;
+
+	fe_node->res_priv = NULL;
+
+	if (!fe_priv) {
+		CAM_ERR(CAM_ISP, "Error! fe_priv is NULL");
+		return -ENODEV;
+	}
+
+	kfree(fe_priv);
+
+	return 0;
+}
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h
new file mode 100644
index 0000000..2a8cd1d
--- /dev/null
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h
@@ -0,0 +1,94 @@
+/* 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_VFE_FE_VER1_H_
+#define _CAM_VFE_FE_VER1_H_
+
+#include "cam_isp_hw.h"
+#include "cam_vfe_top.h"
+
+struct cam_vfe_fe_ver1_reg {
+	uint32_t     camif_cmd;
+	uint32_t     camif_config;
+	uint32_t     line_skip_pattern;
+	uint32_t     pixel_skip_pattern;
+	uint32_t     skip_period;
+	uint32_t     irq_subsample_pattern;
+	uint32_t     epoch_irq;
+	uint32_t     raw_crop_width_cfg;
+	uint32_t     raw_crop_height_cfg;
+	uint32_t     reg_update_cmd;
+	uint32_t     vfe_diag_config;
+	uint32_t     vfe_diag_sensor_status;
+	uint32_t     fe_cfg;
+};
+
+struct cam_vfe_fe_reg_data {
+	uint32_t     raw_crop_first_pixel_shift;
+	uint32_t     raw_crop_first_pixel_mask;
+
+	uint32_t     raw_crop_last_pixel_shift;
+	uint32_t     raw_crop_last_pixel_mask;
+
+	uint32_t     raw_crop_first_line_shift;
+	uint32_t     raw_crop_first_line_mask;
+
+	uint32_t     raw_crop_last_line_shift;
+	uint32_t     raw_crop_last_line_mask;
+
+	uint32_t     input_mux_sel_shift;
+	uint32_t     input_mux_sel_mask;
+	uint32_t     extern_reg_update_shift;
+	uint32_t     extern_reg_update_mask;
+
+	uint32_t     pixel_pattern_shift;
+	uint32_t     pixel_pattern_mask;
+
+	uint32_t     dsp_mode_shift;
+	uint32_t     dsp_mode_mask;
+	uint32_t     dsp_en_shift;
+	uint32_t     dsp_en_mask;
+
+	uint32_t     reg_update_cmd_data;
+	uint32_t     epoch_line_cfg;
+	uint32_t     sof_irq_mask;
+	uint32_t     epoch0_irq_mask;
+	uint32_t     reg_update_irq_mask;
+	uint32_t     eof_irq_mask;
+	uint32_t     error_irq_mask0;
+	uint32_t     error_irq_mask1;
+
+	uint32_t     enable_diagnostic_hw;
+	uint32_t     fe_mux_data;
+	uint32_t     hbi_cnt_shift;
+};
+
+struct cam_vfe_fe_ver1_hw_info {
+	struct cam_vfe_top_ver2_reg_offset_common   *common_reg;
+	struct cam_vfe_fe_ver1_reg              *fe_reg;
+	struct cam_vfe_fe_reg_data              *reg_data;
+};
+
+int cam_vfe_fe_ver1_acquire_resource(
+	struct cam_isp_resource_node  *camif_res,
+	void                          *acquire_param);
+
+int cam_vfe_fe_ver1_init(
+	struct cam_hw_intf            *hw_intf,
+	struct cam_hw_soc_info        *soc_info,
+	void                          *camif_hw_info,
+	struct cam_isp_resource_node  *camif_node);
+
+int cam_vfe_fe_ver1_deinit(
+	struct cam_isp_resource_node  *camif_node);
+
+#endif /* _CAM_VFE_FE_VER1_H_ */
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index c4351a6..fea6089 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.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
@@ -37,11 +37,13 @@ struct cam_vfe_top_ver2_priv {
 	struct cam_axi_vote                 applied_axi_vote;
 	struct cam_axi_vote             req_axi_vote[CAM_VFE_TOP_VER2_MUX_MAX];
 	unsigned long                   req_clk_rate[CAM_VFE_TOP_VER2_MUX_MAX];
-	struct cam_axi_vote             last_vote[CAM_VFE_TOP_VER2_MUX_MAX *
+	struct cam_axi_vote             last_vote[CAM_CPAS_HANDLE_MAX]
+					[CAM_VFE_TOP_VER2_MUX_MAX *
 					CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES];
-	uint32_t                        last_counter;
+	uint32_t                        last_counter[CAM_CPAS_HANDLE_MAX];
 	enum cam_vfe_bw_control_action
 		axi_vote_control[CAM_VFE_TOP_VER2_MUX_MAX];
+	enum cam_cpas_handle_id cpashdl_type[CAM_VFE_TOP_VER2_MUX_MAX];
 };
 
 static int cam_vfe_top_mux_get_base(struct cam_vfe_top_ver2_priv *top_priv,
@@ -133,99 +135,131 @@ static int cam_vfe_top_set_axi_bw_vote(
 	struct cam_vfe_soc_private *soc_private =
 		soc_info->soc_private;
 	bool apply_bw_update = false;
+	enum cam_cpas_handle_id cpashdl_type;
+	struct cam_axi_vote *last_vote = NULL;
 
 	if (!soc_private) {
 		CAM_ERR(CAM_ISP, "Error soc_private NULL");
 		return -EINVAL;
 	}
 
-	for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
-		if (top_priv->axi_vote_control[i] ==
-			CAM_VFE_BW_CONTROL_INCLUDE) {
-			sum.uncompressed_bw +=
+	for (cpashdl_type = 0; cpashdl_type < CAM_CPAS_HANDLE_MAX;
+		cpashdl_type++) {
+
+		if ((soc_private->cpas_version != CAM_CPAS_TITAN_175_V120)
+			&& cpashdl_type)
+			continue;
+
+		sum.uncompressed_bw = sum.compressed_bw = 0;
+		to_be_applied_axi_vote.uncompressed_bw = 0;
+		to_be_applied_axi_vote.compressed_bw = 0;
+		apply_bw_update = false;
+
+		for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
+			if (top_priv->axi_vote_control[i] ==
+				CAM_VFE_BW_CONTROL_INCLUDE &&
+				top_priv->cpashdl_type[i] ==
+				cpashdl_type) {
+				sum.uncompressed_bw +=
 				top_priv->req_axi_vote[i].uncompressed_bw;
-			sum.compressed_bw +=
+				sum.compressed_bw +=
 				top_priv->req_axi_vote[i].compressed_bw;
+			}
 		}
-	}
 
-	CAM_DBG(CAM_ISP, "Updating BW from (%llu %llu) to (%llu %llu)",
-		top_priv->applied_axi_vote.uncompressed_bw,
-		top_priv->applied_axi_vote.compressed_bw,
-		sum.uncompressed_bw,
-		sum.compressed_bw);
-
-	top_priv->last_vote[top_priv->last_counter] = sum;
-	top_priv->last_counter = (top_priv->last_counter + 1) %
-		(CAM_VFE_TOP_VER2_MUX_MAX *
-		CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES);
-
-	if ((top_priv->applied_axi_vote.uncompressed_bw ==
-		sum.uncompressed_bw) &&
-		(top_priv->applied_axi_vote.compressed_bw ==
-		sum.compressed_bw)) {
-		CAM_DBG(CAM_ISP, "BW config unchanged %llu %llu",
+		CAM_DBG(CAM_ISP, "Updating BW from (%llu %llu) to (%llu %llu)",
 			top_priv->applied_axi_vote.uncompressed_bw,
-			top_priv->applied_axi_vote.compressed_bw);
-		return 0;
-	}
+			top_priv->applied_axi_vote.compressed_bw,
+			sum.uncompressed_bw,
+			sum.compressed_bw);
 
-	if (start_stop == true) {
-		/* need to vote current request immediately */
-		to_be_applied_axi_vote = sum;
-		/* Reset everything, we can start afresh */
-		memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) *
-			(CAM_VFE_TOP_VER2_MUX_MAX *
-			CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES));
-		top_priv->last_counter = 0;
-		top_priv->last_vote[top_priv->last_counter] = sum;
-		top_priv->last_counter = (top_priv->last_counter + 1) %
+		last_vote = top_priv->last_vote[cpashdl_type];
+
+		last_vote[top_priv->last_counter[cpashdl_type]] = sum;
+		top_priv->last_counter[cpashdl_type] =
+			(top_priv->last_counter[cpashdl_type] + 1) %
 			(CAM_VFE_TOP_VER2_MUX_MAX *
 			CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES);
-	} else {
+
+		if ((top_priv->applied_axi_vote.uncompressed_bw ==
+			sum.uncompressed_bw) &&
+			(top_priv->applied_axi_vote.compressed_bw ==
+			sum.compressed_bw)) {
+			CAM_DBG(CAM_ISP, "BW config unchanged %llu %llu",
+				top_priv->applied_axi_vote.uncompressed_bw,
+				top_priv->applied_axi_vote.compressed_bw);
+			return 0;
+		}
+
+		if (start_stop == true) {
+			rc = cam_cpas_update_axi_vote(
+				soc_private->cpas_handle[cpashdl_type],
+				&to_be_applied_axi_vote);
+			if (!rc) {
+				top_priv->applied_axi_vote.uncompressed_bw =
+					to_be_applied_axi_vote.uncompressed_bw;
+				top_priv->applied_axi_vote.compressed_bw =
+					to_be_applied_axi_vote.compressed_bw;
+			}
+			return rc;
+		}
+
 		/*
-		 * Find max bw request in last few frames. This will the bw
-		 *that we want to vote to CPAS now.
+		 * Find max bw request in last few frames. This is the bw
+		 * that we want to vote to CPAS now.
 		 */
 		for (i = 0; i < (CAM_VFE_TOP_VER2_MUX_MAX *
 			CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); i++) {
 			if (to_be_applied_axi_vote.compressed_bw <
-				top_priv->last_vote[i].compressed_bw)
+				last_vote[i].compressed_bw)
 				to_be_applied_axi_vote.compressed_bw =
-					top_priv->last_vote[i].compressed_bw;
+					last_vote[i].compressed_bw;
 
 			if (to_be_applied_axi_vote.uncompressed_bw <
-				top_priv->last_vote[i].uncompressed_bw)
+					last_vote[i].uncompressed_bw)
 				to_be_applied_axi_vote.uncompressed_bw =
-					top_priv->last_vote[i].uncompressed_bw;
+					last_vote[i].uncompressed_bw;
 		}
-	}
 
-	if ((to_be_applied_axi_vote.uncompressed_bw !=
-		top_priv->applied_axi_vote.uncompressed_bw) ||
-		(to_be_applied_axi_vote.compressed_bw !=
-		top_priv->applied_axi_vote.compressed_bw))
-		apply_bw_update = true;
+		if ((to_be_applied_axi_vote.uncompressed_bw !=
+			top_priv->applied_axi_vote.uncompressed_bw) ||
+			(to_be_applied_axi_vote.compressed_bw !=
+			top_priv->applied_axi_vote.compressed_bw))
+			apply_bw_update = true;
 
-	CAM_DBG(CAM_ISP, "apply_bw_update=%d", apply_bw_update);
+		CAM_DBG(CAM_ISP, "apply_bw_update=%d", apply_bw_update);
 
-	if (apply_bw_update == true) {
-		rc = cam_cpas_update_axi_vote(
-			soc_private->cpas_handle,
-			&to_be_applied_axi_vote);
-		if (!rc) {
-			top_priv->applied_axi_vote.uncompressed_bw =
+		if (apply_bw_update == true) {
+			rc = cam_cpas_update_axi_vote(
+				soc_private->cpas_handle[cpashdl_type],
+				&to_be_applied_axi_vote);
+			if (!rc) {
+				top_priv->applied_axi_vote.uncompressed_bw =
 				to_be_applied_axi_vote.uncompressed_bw;
-			top_priv->applied_axi_vote.compressed_bw =
-				to_be_applied_axi_vote.compressed_bw;
-		} else {
-			CAM_ERR(CAM_ISP, "BW request failed, rc=%d", rc);
+				top_priv->applied_axi_vote.compressed_bw =
+					to_be_applied_axi_vote.compressed_bw;
+			} else {
+				CAM_ERR(CAM_ISP, "BW request failed, rc=%d",
+					rc);
+			}
 		}
 	}
-
 	return rc;
 }
 
+static int cam_vfe_top_fs_update(
+	struct cam_vfe_top_ver2_priv *top_priv,
+	void *cmd_args, uint32_t arg_size)
+{
+	struct cam_vfe_fe_update_args *cmd_update = cmd_args;
+
+	if (cmd_update->node_res->process_cmd)
+		return cmd_update->node_res->process_cmd(cmd_update->node_res,
+			CAM_ISP_HW_CMD_FE_UPDATE_IN_RD, cmd_args, arg_size);
+
+	return 0;
+}
+
 static int cam_vfe_top_clock_update(
 	struct cam_vfe_top_ver2_priv *top_priv,
 	void *cmd_args, uint32_t arg_size)
@@ -476,6 +510,14 @@ int cam_vfe_top_reserve(void *device_priv,
 					break;
 			}
 
+			if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_RD) {
+				rc = cam_vfe_fe_ver1_acquire_resource(
+					&top_priv->mux_rsrc[i],
+					args);
+				if (rc)
+					break;
+			}
+
 			top_priv->mux_rsrc[i].cdm_ops = acquire_args->cdm_ops;
 			top_priv->mux_rsrc[i].tasklet_info = args->tasklet;
 			top_priv->mux_rsrc[i].res_state =
@@ -583,6 +625,7 @@ int cam_vfe_top_stop(void *device_priv,
 
 	if ((mux_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) ||
 		(mux_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF_LITE) ||
+		(mux_res->res_id == CAM_ISP_HW_VFE_IN_RD) ||
 		((mux_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) &&
 		(mux_res->res_id <= CAM_ISP_HW_VFE_IN_RDI3))) {
 		rc = mux_res->stop(mux_res);
@@ -643,6 +686,10 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type,
 		rc = cam_vfe_top_clock_update(top_priv, cmd_args,
 			arg_size);
 		break;
+	case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
+		rc = cam_vfe_top_fs_update(top_priv, cmd_args,
+			arg_size);
+		break;
 	case CAM_ISP_HW_CMD_BW_UPDATE:
 		rc = cam_vfe_top_bw_update(top_priv, cmd_args,
 			arg_size);
@@ -669,6 +716,7 @@ int cam_vfe_top_ver2_init(
 	struct cam_vfe_top_ver2_priv           *top_priv = NULL;
 	struct cam_vfe_top_ver2_hw_info        *ver2_hw_info = top_hw_info;
 	struct cam_vfe_top                     *vfe_top;
+	struct cam_vfe_soc_private             *soc_private = NULL;
 
 	vfe_top = kzalloc(sizeof(struct cam_vfe_top), GFP_KERNEL);
 	if (!vfe_top) {
@@ -684,14 +732,22 @@ int cam_vfe_top_ver2_init(
 		rc = -ENOMEM;
 		goto free_vfe_top;
 	}
+
+	soc_private = soc_info->soc_private;
+	if (!soc_private) {
+		CAM_ERR(CAM_ISP, "Error! soc_private NULL");
+		rc = -ENODEV;
+		goto free_vfe_top_priv;
+	}
 	vfe_top->top_priv = top_priv;
 	top_priv->hw_clk_rate = 0;
 	top_priv->applied_axi_vote.compressed_bw = 0;
 	top_priv->applied_axi_vote.uncompressed_bw = 0;
 	memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) *
-		(CAM_VFE_TOP_VER2_MUX_MAX *
+		(CAM_VFE_TOP_VER2_MUX_MAX * CAM_CPAS_HANDLE_MAX *
 		CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES));
-	top_priv->last_counter = 0;
+	top_priv->last_counter[0] = 0;
+	top_priv->last_counter[1] = 0;
 
 	for (i = 0, j = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
 		top_priv->mux_rsrc[i].res_type = CAM_ISP_RESOURCE_VFE_IN;
@@ -707,6 +763,7 @@ int cam_vfe_top_ver2_init(
 		if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) {
 			top_priv->mux_rsrc[i].res_id =
 				CAM_ISP_HW_VFE_IN_CAMIF;
+			top_priv->cpashdl_type[i] = CAM_CPAS_HANDLE_CAMIF;
 
 			rc = cam_vfe_camif_ver2_init(hw_intf, soc_info,
 				&ver2_hw_info->camif_hw_info,
@@ -717,6 +774,13 @@ int cam_vfe_top_ver2_init(
 			CAM_VFE_CAMIF_LITE_VER_2_0) {
 			top_priv->mux_rsrc[i].res_id =
 				CAM_ISP_HW_VFE_IN_CAMIF_LITE;
+			if (soc_private->cpas_version ==
+				CAM_CPAS_TITAN_175_V120)
+				top_priv->cpashdl_type[i] =
+					CAM_CPAS_HANDLE_RAW;
+			else
+				top_priv->cpashdl_type[i] =
+					CAM_CPAS_HANDLE_CAMIF;
 
 			rc = cam_vfe_camif_lite_ver2_init(hw_intf, soc_info,
 				&ver2_hw_info->camif_lite_hw_info,
@@ -729,12 +793,30 @@ int cam_vfe_top_ver2_init(
 			/* set the RDI resource id */
 			top_priv->mux_rsrc[i].res_id =
 				CAM_ISP_HW_VFE_IN_RDI0 + j++;
+			if (soc_private->cpas_version ==
+				CAM_CPAS_TITAN_175_V120)
+				top_priv->cpashdl_type[i] =
+					CAM_CPAS_HANDLE_RAW;
+			else
+				top_priv->cpashdl_type[i] =
+					CAM_CPAS_HANDLE_CAMIF;
 
 			rc = cam_vfe_rdi_ver2_init(hw_intf, soc_info,
 				&ver2_hw_info->rdi_hw_info,
 				&top_priv->mux_rsrc[i]);
 			if (rc)
 				goto deinit_resources;
+		} else if (ver2_hw_info->mux_type[i] ==
+			CAM_VFE_IN_RD_VER_1_0) {
+			/* set the RD resource id */
+			top_priv->mux_rsrc[i].res_id =
+				CAM_ISP_HW_VFE_IN_RD;
+
+			rc = cam_vfe_fe_ver1_init(hw_intf, soc_info,
+				&ver2_hw_info->fe_hw_info,
+				&top_priv->mux_rsrc[i]);
+			if (rc)
+				goto deinit_resources;
 		} else {
 			CAM_WARN(CAM_ISP, "Invalid mux type: %u",
 				ver2_hw_info->mux_type[i]);
@@ -769,6 +851,12 @@ int cam_vfe_top_ver2_init(
 			if (cam_vfe_camif_lite_ver2_deinit(
 				&top_priv->mux_rsrc[i]))
 				CAM_ERR(CAM_ISP, "Camif lite deinit failed");
+		} else if (ver2_hw_info->mux_type[i] ==
+			CAM_ISP_HW_VFE_IN_RDI0) {
+			if (cam_vfe_rdi_ver2_init(hw_intf, soc_info,
+				&ver2_hw_info->rdi_hw_info,
+				&top_priv->mux_rsrc[i]))
+				CAM_ERR(CAM_ISP, "RDI deinit failed");
 		} else {
 			if (cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]))
 				CAM_ERR(CAM_ISP, "RDI Deinit failed");
@@ -776,7 +864,7 @@ int cam_vfe_top_ver2_init(
 		top_priv->mux_rsrc[i].res_state =
 			CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
 	}
-
+free_vfe_top_priv:
 	kfree(vfe_top->top_priv);
 free_vfe_top:
 	kfree(vfe_top);
@@ -829,6 +917,12 @@ int cam_vfe_top_ver2_deinit(struct cam_vfe_top  **vfe_top_ptr)
 			rc = cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]);
 			if (rc)
 				CAM_ERR(CAM_ISP, "RDI deinit failed rc=%d", rc);
+		} else if (top_priv->mux_rsrc[i].res_type ==
+			CAM_VFE_IN_RD_VER_1_0) {
+			rc = cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i]);
+			if (rc)
+				CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d",
+					rc);
 		}
 	}
 
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
index 11ca78c..33435df 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.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
@@ -16,8 +16,9 @@
 #include "cam_vfe_camif_ver2.h"
 #include "cam_vfe_camif_lite_ver2.h"
 #include "cam_vfe_rdi.h"
+#include "cam_vfe_fe_ver1.h"
 
-#define CAM_VFE_TOP_VER2_MUX_MAX     5
+#define CAM_VFE_TOP_VER2_MUX_MAX     6
 
 enum cam_vfe_top_ver2_module_type {
 	CAM_VFE_TOP_VER2_MODULE_LENS,
@@ -55,6 +56,7 @@ struct cam_vfe_top_ver2_hw_info {
 	struct cam_vfe_camif_ver2_hw_info           camif_hw_info;
 	struct cam_vfe_camif_lite_ver2_hw_info      camif_lite_hw_info;
 	struct cam_vfe_rdi_ver2_hw_info             rdi_hw_info;
+	struct cam_vfe_fe_ver1_hw_info              fe_hw_info;
 	uint32_t mux_type[CAM_VFE_TOP_VER2_MUX_MAX];
 };
 
diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
index 90c7529..cee2b4a 100644
--- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
+++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.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
@@ -24,7 +24,8 @@
 
 #define CAM_VFE_CAMIF_LITE_VER_2_0 0x02
 
-#define CAM_VFE_RDI_VER_1_0 0x1000
+#define CAM_VFE_RDI_VER_1_0    0x1000
+#define CAM_VFE_IN_RD_VER_1_0  0x2000
 
 struct cam_vfe_top {
 	void                   *top_priv;
diff --git a/drivers/media/platform/msm/ais/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/ais/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
index fe82ca9..316e0ad 100644
--- a/drivers/media/platform/msm/ais/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
+++ b/drivers/media/platform/msm/ais/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_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
@@ -42,7 +42,10 @@ static void cam_lrme_hw_util_fill_fe_reg(struct cam_lrme_hw_io_buffer *io_buf,
 	uint32_t reg_val;
 
 	/* 1. config buffer size */
-	reg_val = io_buf->io_cfg->planes[0].width;
+	if (io_buf->io_cfg->format == CAM_FORMAT_PLAIN16_10)
+		reg_val = io_buf->io_cfg->planes[0].width * 2;
+	else
+		reg_val = io_buf->io_cfg->planes[0].width;
 	reg_val |= (io_buf->io_cfg->planes[0].height << 16);
 	cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd,
 		hw_info->bus_rd_reg.bus_client_reg[index].rd_buffer_size,
diff --git a/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.c
index 78937a7..aa8ed7d 100644
--- a/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.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
@@ -25,6 +25,7 @@
 #include "cam_debug_util.h"
 
 static struct cam_mem_table tbl;
+static atomic_t cam_mem_mgr_state = ATOMIC_INIT(CAM_MEM_MGR_UNINITIALIZED);
 
 static int cam_mem_util_get_dma_dir(uint32_t flags)
 {
@@ -146,6 +147,8 @@ int cam_mem_mgr_init(void)
 	}
 	mutex_init(&tbl.m_lock);
 
+	atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_INITIALIZED);
+
 	return 0;
 }
 
@@ -186,6 +189,11 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle,
 
 	*len_ptr = 0;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	idx = CAM_MEM_MGR_GET_HDL_IDX(buf_handle);
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0)
 		return -EINVAL;
@@ -231,6 +239,11 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len)
 	int idx;
 	struct dma_buf *dmabuf = NULL;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	if (!buf_handle || !vaddr_ptr || !len)
 		return -EINVAL;
 
@@ -275,6 +288,11 @@ int cam_mem_put_cpu_buf(int32_t buf_handle)
 	int idx;
 	struct dma_buf *dmabuf = NULL;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	if (!buf_handle)
 		return -EINVAL;
 
@@ -316,6 +334,11 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd)
 	uint32_t cache_dir;
 	unsigned long dmabuf_flag = 0;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	if (!cmd)
 		return -EINVAL;
 
@@ -410,6 +433,7 @@ static int cam_mem_util_get_dma_buf_fd(size_t len,
 	struct dma_buf **buf,
 	int *fd)
 {
+	struct dma_buf *dmabuf = NULL;
 	int rc = 0;
 
 	if (!buf || !fd) {
@@ -433,7 +457,11 @@ static int cam_mem_util_get_dma_buf_fd(size_t len,
 	 * when we close fd, refcount becomes 1 and when we do
 	 * dmap_put_buf, ref count becomes 0 and memory will be freed.
 	 */
-	dma_buf_get(*fd);
+	dmabuf = dma_buf_get(*fd);
+	if (IS_ERR_OR_NULL(dmabuf)) {
+		CAM_ERR(CAM_MEM, "dma_buf_get failed, *fd=%d", *fd);
+		rc = -EINVAL;
+	}
 
 	return rc;
 
@@ -605,6 +633,11 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd)
 	uintptr_t kvaddr = 0;
 	size_t klen;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	if (!cmd) {
 		CAM_ERR(CAM_MEM, " Invalid argument");
 		return -EINVAL;
@@ -722,6 +755,11 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd)
 	dma_addr_t hw_vaddr = 0;
 	size_t len = 0;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	if (!cmd || (cmd->fd < 0)) {
 		CAM_ERR(CAM_MEM, "Invalid argument");
 		return -EINVAL;
@@ -929,6 +967,7 @@ static int cam_mem_mgr_cleanup_table(void)
 
 void cam_mem_mgr_deinit(void)
 {
+	atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_UNINITIALIZED);
 	cam_mem_mgr_cleanup_table();
 	mutex_lock(&tbl.m_lock);
 	bitmap_zero(tbl.bitmap, tbl.bits);
@@ -966,7 +1005,7 @@ static int cam_mem_util_unmap(int32_t idx,
 				tbl.bufq[idx].kmdvaddr);
 			if (rc)
 				CAM_ERR(CAM_MEM,
-					"Failed, dmabuf=%pK, kmdvaddr=%pK",
+					"Failed, dmabuf=%pK, kmdvaddr=%llxK",
 					tbl.bufq[idx].dma_buf,
 					tbl.bufq[idx].kmdvaddr);
 		}
@@ -1025,6 +1064,11 @@ int cam_mem_mgr_release(struct cam_mem_mgr_release_cmd *cmd)
 	int idx;
 	int rc;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	if (!cmd) {
 		CAM_ERR(CAM_MEM, "Invalid argument");
 		return -EINVAL;
@@ -1073,6 +1117,11 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp,
 
 	enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	if (!inp || !out) {
 		CAM_ERR(CAM_MEM, "Invalid params");
 		return -EINVAL;
@@ -1193,6 +1242,11 @@ int cam_mem_mgr_release_mem(struct cam_mem_mgr_memory_desc *inp)
 	int32_t idx;
 	int rc;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	if (!inp) {
 		CAM_ERR(CAM_MEM, "Invalid argument");
 		return -EINVAL;
@@ -1241,6 +1295,11 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp,
 	int32_t smmu_hdl = 0;
 	int32_t num_hdl = 0;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	if (!inp || !out) {
 		CAM_ERR(CAM_MEM, "Invalid param(s)");
 		return -EINVAL;
@@ -1330,6 +1389,11 @@ int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp)
 	int rc;
 	int32_t smmu_hdl;
 
+	if (!atomic_read(&cam_mem_mgr_state)) {
+		CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
+		return -EINVAL;
+	}
+
 	if (!inp) {
 		CAM_ERR(CAM_MEM, "Invalid argument");
 		return -EINVAL;
diff --git a/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.h b/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.h
index 4c75b0e..91d1c39 100644
--- a/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.h
+++ b/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.h
@@ -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
@@ -20,6 +20,12 @@
 
 #define CAM_MEM_BUFQ_MAX 1024
 
+/* Enum for possible mem mgr states */
+enum cam_mem_mgr_state {
+	CAM_MEM_MGR_UNINITIALIZED,
+	CAM_MEM_MGR_INITIALIZED,
+};
+
 /*Enum for possible SMMU operations */
 enum cam_smmu_mapping_client {
 	CAM_SMMU_MAPPING_USER,
diff --git a/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.c
index 796cdbb..566ea53 100644
--- a/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.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
@@ -43,9 +43,6 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
 	link->subscribe_event = 0;
 	link->trigger_mask = 0;
 	link->sync_link = 0;
-	link->sof_counter = 0;
-	link->sync_self_ref = 0;
-	link->frame_skip_flag = false;
 	link->sync_link_sof_skip = false;
 	link->open_req_cnt = 0;
 	link->last_flush_id = 0;
@@ -143,31 +140,35 @@ static void __cam_req_mgr_dec_idx(int32_t *val, int32_t step, int32_t max_val)
 }
 
 /**
- * __cam_req_mgr_validate_inject_delay()
+ * __cam_req_mgr_inject_delay()
  *
- * @brief    : Check if any pd device is introducing inject delay
+ * @brief    : Check if any pd device is injecting delay
  * @tbl      : cam_req_mgr_req_tbl
  * @curr_idx : slot idx
  *
  * @return   : 0 for success, negative for failure
  */
-static int __cam_req_mgr_validate_inject_delay(
+static int __cam_req_mgr_inject_delay(
 	struct cam_req_mgr_req_tbl  *tbl,
 	int32_t curr_idx)
 {
 	struct cam_req_mgr_tbl_slot *slot = NULL;
+	int rc = 0;
 
 	while (tbl) {
 		slot = &tbl->slot[curr_idx];
 		if (slot->inject_delay > 0) {
 			slot->inject_delay--;
-			return -EAGAIN;
+			CAM_DBG(CAM_CRM,
+				"Delay injected by pd %d device",
+				tbl->pd);
+			rc = -EAGAIN;
 		}
 		__cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta,
 			tbl->num_slots);
 		tbl = tbl->next;
 	}
-	return 0;
+	return rc;
 }
 
 /**
@@ -209,19 +210,6 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data)
 		tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status,
 		traverse_data->in_q->slot[curr_idx].skip_idx);
 
-	if ((traverse_data->self_link == true) &&
-		(!traverse_data->inject_delay_chk)) {
-		rc = __cam_req_mgr_validate_inject_delay(tbl, curr_idx);
-		if (rc) {
-			CAM_DBG(CAM_CRM, "Injecting Delay of one frame");
-			apply_data[tbl->pd].req_id = -1;
-			/* This pd tbl not ready to proceed with asked idx */
-			SET_FAILURE_BIT(traverse_data->result, tbl->pd);
-			return -EAGAIN;
-		}
-		traverse_data->inject_delay_chk = true;
-	}
-
 	/* Check if req is ready or in skip mode or pd tbl is in skip mode */
 	if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY ||
 		traverse_data->in_q->slot[curr_idx].skip_idx == 1 ||
@@ -552,14 +540,12 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
  *             traversed through
  * @idx      : index within input request queue
  * @validate_only : Whether to validate only and/or update settings
- * @self_link : To indicate whether the validation is for the given link or
- *              other sync link
  *
  * @return   : 0 for success, negative for failure
  *
  */
 static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
-	int32_t idx, bool validate_only, bool self_link)
+	int32_t idx, bool validate_only)
 {
 	int                            rc;
 	struct cam_req_mgr_traverse    traverse_data;
@@ -581,19 +567,16 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
 	traverse_data.in_q = in_q;
 	traverse_data.result = 0;
 	traverse_data.validate_only = validate_only;
-	traverse_data.self_link = self_link;
-	traverse_data.inject_delay_chk = false;
 	traverse_data.open_req_cnt = link->open_req_cnt;
+
 	/*
 	 *  Traverse through all pd tables, if result is success,
 	 *  apply the settings
 	 */
-
 	rc = __cam_req_mgr_traverse(&traverse_data);
 	CAM_DBG(CAM_CRM,
-		"SOF: idx %d self_link %d validate %d result %x pd_mask %x rc %d",
-		idx, traverse_data.self_link, traverse_data.validate_only,
-		traverse_data.result, link->pd_mask, rc);
+		"SOF: idx %d result %x pd_mask %x rc %d",
+		idx, traverse_data.result, link->pd_mask, rc);
 
 	if (!rc && traverse_data.result == link->pd_mask) {
 		CAM_DBG(CAM_CRM,
@@ -642,113 +625,198 @@ static int32_t __cam_req_mgr_find_slot_for_req(
 }
 
 /**
- * __cam_req_mgr_reset_sof_cnt()
+ * __cam_req_mgr_check_sync_for_mslave()
  *
- * @brief    : the sof_count for both the links are reset
- * @link     : pointer to link whose input queue and req tbl are
+ * @brief    : Processes requests during sync mode [master-slave]
+ *             Here master corresponds to the link having a higher
+ *             max_delay (pd) compared to the slave link.
+ * @link     : Pointer to link whose input queue and req tbl are
  *             traversed through
- *
- */
-static void __cam_req_mgr_reset_sof_cnt(
-	struct cam_req_mgr_core_link *link)
-{
-	link->sof_counter = -1;
-	link->sync_link->sof_counter = -1;
-	link->frame_skip_flag = false;
-
-	CAM_DBG(CAM_CRM,
-		"link_hdl %x self_counter %lld other_counter %lld frame_skip_lag %d",
-		link->link_hdl, link->sof_counter,
-		link->sync_link->sof_counter, link->frame_skip_flag);
-}
-
-/**
- * __cam_req_mgr_sof_cnt_initialize()
- *
- * @brief    : when the sof count is intially -1 it increments count
- *             and computes the sync_self_ref for this link
- *             the count needs to be wrapped back starting from 0
- * @link     : pointer to link whose input queue and req tbl are
- *             traversed through
- *
- */
-static void __cam_req_mgr_sof_cnt_initialize(
-	struct cam_req_mgr_core_link *link)
-{
-	link->sof_counter++;
-	link->sync_self_ref = link->sof_counter -
-		link->sync_link->sof_counter;
-
-	CAM_DBG(CAM_CRM,
-		"link_hdl %x self_counter %lld other_counter %lld",
-		link->link_hdl, link->sof_counter,
-		link->sync_link->sof_counter);
-}
-
-/**
- * __cam_req_mgr_wrap_sof_cnt()
- *
- * @brief    : once the sof count reaches a predefined maximum
- *             the count needs to be wrapped back starting from 0
- * @link     : pointer to link whose input queue and req tbl are
- *             traversed through
- *
- */
-static void __cam_req_mgr_wrap_sof_cnt(
-	struct cam_req_mgr_core_link *link)
-{
-	link->sof_counter = (MAX_SYNC_COUNT -
-		(link->sync_link->sof_counter));
-	link->sync_link->sof_counter = 0;
-
-	CAM_DBG(CAM_CRM,
-		"link_hdl %x self_counter %lld sync_link_hdl %x other_counter %lld",
-		link->link_hdl, link->sof_counter,
-		link->sync_link->link_hdl, link->sync_link->sof_counter);
-}
-
-/**
- * __cam_req_mgr_validate_sof_cnt()
- *
- * @brief     : validates sof count difference for a given link
- * @link      : pointer to link whose input queue and req tbl are
- *              traversed through
- * @sync_link : pointer to the sync link
+ * @slot     : Pointer to the current slot being processed
  * @return   : 0 for success, negative for failure
  *
  */
-static int __cam_req_mgr_validate_sof_cnt(
+static int __cam_req_mgr_check_sync_for_mslave(
 	struct cam_req_mgr_core_link *link,
-	struct cam_req_mgr_core_link *sync_link)
+	struct cam_req_mgr_slot *slot)
 {
-	int64_t sync_diff = 0;
-	int rc = 0;
+	struct cam_req_mgr_core_link *sync_link = NULL;
+	int sync_slot_idx = 0, prev_idx, next_idx, rd_idx, rc = 0;
+	int64_t req_id = 0, sync_req_id = 0;
 
-	if (link->sof_counter == MAX_SYNC_COUNT)
-		__cam_req_mgr_wrap_sof_cnt(link);
-
-	sync_diff = link->sof_counter - sync_link->sof_counter;
-
-	CAM_DBG(CAM_CRM,
-		"link[%x] self_counter=%lld other_counter=%lld diff=%lld sync_self_ref=%lld",
-		link->link_hdl, link->sof_counter,
-		sync_link->sof_counter, sync_diff, link->sync_self_ref);
-
-	if (sync_diff > SYNC_LINK_SOF_CNT_MAX_LMT) {
-		link->sync_link->frame_skip_flag = true;
-		CAM_WARN(CAM_CRM,
-			"Detected anomaly, skip link_hdl %x self_counter=%lld other_counter=%lld sync_self_ref=%lld",
-			link->link_hdl, link->sof_counter,
-			sync_link->sof_counter, link->sync_self_ref);
-		rc = -EPERM;
+	if (!link->sync_link) {
+		CAM_ERR(CAM_CRM, "Sync link null");
+		return -EINVAL;
 	}
 
-	return rc;
+	sync_link = link->sync_link;
+	req_id = slot->req_id;
+
+	CAM_DBG(CAM_CRM,
+		"link_hdl %x req %lld frame_skip_flag %d ",
+		link->link_hdl, req_id, link->sync_link_sof_skip);
+
+	if (sync_link->sync_link_sof_skip) {
+		CAM_DBG(CAM_CRM,
+			"No req applied on corresponding SOF on sync link: %x",
+				sync_link->link_hdl);
+		sync_link->sync_link_sof_skip = false;
+		__cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+		return -EAGAIN;
+	}
+
+	if (link->is_master) {
+		rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+		if (rc) {
+			CAM_DBG(CAM_CRM,
+				"Skip Process Req: %lld on link: %x",
+				req_id, link->link_hdl);
+			link->sync_link_sof_skip = true;
+			return rc;
+		}
+
+		if (sync_link->initial_skip) {
+			CAM_DBG(CAM_CRM,  "Link 0x%x [slave] not streamed on",
+				sync_link->link_hdl);
+			return -EAGAIN;
+		}
+
+		rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
+		if (rc) {
+			CAM_DBG(CAM_CRM,
+				"Req: %lld [master] not ready on link: %x, rc=%d",
+				req_id, link->link_hdl, rc);
+			return rc;
+		}
+
+		prev_idx = slot->idx;
+		__cam_req_mgr_dec_idx(&prev_idx,
+			(link->max_delay - sync_link->max_delay),
+			link->req.in_q->num_slots);
+
+		rd_idx = sync_link->req.in_q->rd_idx;
+		sync_req_id = link->req.in_q->slot[prev_idx].req_id;
+		if (sync_req_id != -1) {
+			sync_slot_idx = __cam_req_mgr_find_slot_for_req(
+				sync_link->req.in_q, sync_req_id);
+
+			if (sync_slot_idx == -1) {
+				CAM_DBG(CAM_CRM,
+					"Prev Req: %lld [master] not found on link: %x [slave]",
+					sync_req_id, sync_link->link_hdl);
+				return -EINVAL;
+			}
+
+			if ((sync_link->req.in_q->slot[sync_slot_idx].status !=
+				CRM_SLOT_STATUS_REQ_APPLIED) &&
+				((sync_slot_idx - rd_idx) >= 1) &&
+				(sync_link->req.in_q->slot[rd_idx].status !=
+				CRM_SLOT_STATUS_REQ_APPLIED)) {
+				CAM_DBG(CAM_CRM,
+					"Prev Req: %lld [master] not next on link: %x [slave]",
+					sync_req_id,
+					sync_link->link_hdl);
+				return -EINVAL;
+			}
+
+			rc = __cam_req_mgr_check_link_is_ready(sync_link,
+				sync_slot_idx, true);
+			if (rc &&
+				(sync_link->req.in_q->slot[sync_slot_idx].status
+				!= CRM_SLOT_STATUS_REQ_APPLIED)) {
+				CAM_DBG(CAM_CRM,
+					"Req: %lld not ready on [slave] link: %x, rc=%d",
+					sync_req_id, sync_link->link_hdl, rc);
+				return rc;
+			}
+		}
+	} else {
+		if (link->initial_skip)
+			link->initial_skip = false;
+
+		sync_slot_idx = __cam_req_mgr_find_slot_for_req(
+			sync_link->req.in_q, req_id);
+		if (sync_slot_idx == -1) {
+			CAM_DBG(CAM_CRM,
+				"Req: %lld not found on link: %x [master]",
+				req_id, sync_link->link_hdl);
+			return -EINVAL;
+		}
+
+		if (sync_link->req.in_q->slot[sync_slot_idx].status !=
+			CRM_SLOT_STATUS_REQ_APPLIED) {
+			CAM_DBG(CAM_CRM,
+				"Req: %lld [master] not applied yet: %x",
+				req_id, sync_link->link_hdl);
+			return -EAGAIN;
+		}
+
+		rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+		if (rc) {
+			CAM_DBG(CAM_CRM,
+				"Skip Process Req: %lld on link: %x",
+				req_id, link->link_hdl);
+			link->sync_link_sof_skip = true;
+			return rc;
+		}
+
+		next_idx = link->req.in_q->rd_idx;
+		rd_idx = sync_link->req.in_q->rd_idx;
+		__cam_req_mgr_inc_idx(&next_idx,
+			(sync_link->max_delay - link->max_delay),
+			link->req.in_q->num_slots);
+
+		sync_req_id = link->req.in_q->slot[next_idx].req_id;
+		sync_slot_idx = __cam_req_mgr_find_slot_for_req(
+					sync_link->req.in_q, sync_req_id);
+		if (sync_slot_idx == -1) {
+			CAM_DBG(CAM_CRM,
+				"Next Req: %lld [slave] not found on link: %x [master]",
+				sync_req_id, sync_link->link_hdl);
+			return -EINVAL;
+		}
+
+		if ((sync_link->req.in_q->slot[sync_slot_idx].status !=
+			CRM_SLOT_STATUS_REQ_APPLIED) &&
+			((sync_slot_idx - rd_idx) >= 1) &&
+			(sync_link->req.in_q->slot[rd_idx].status !=
+			CRM_SLOT_STATUS_REQ_APPLIED)) {
+			CAM_DBG(CAM_CRM,
+				"Next Req: %lld [slave] not next on link: %x [master]",
+				sync_req_id, sync_link->link_hdl);
+			return -EINVAL;
+		}
+
+		rc = __cam_req_mgr_check_link_is_ready(sync_link,
+			sync_slot_idx, true);
+		if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status !=
+			CRM_SLOT_STATUS_REQ_APPLIED)) {
+			CAM_DBG(CAM_CRM,
+				"Next Req: %lld [slave] not ready on [master] link: %x, rc=%d",
+				sync_req_id, sync_link->link_hdl, rc);
+			return rc;
+		}
+	}
+
+	CAM_DBG(CAM_REQ,
+		"Req: %lld ready to apply on link: %x [validation successful]",
+		req_id, link->link_hdl);
+
+	/*
+	 *  At this point all validation is successfully done
+	 *  and we can proceed to apply the given request.
+	 *  Ideally the next call should return success.
+	 */
+	rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false);
+	if (rc)
+		CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
+
+	return 0;
 }
 
 
 /**
- * __cam_req_mgr_process_sync_req()
+ * __cam_req_mgr_check_sync_request_is_ready()
  *
  * @brief    : processes requests during sync mode
  * @link     : pointer to link whose input queue and req tbl are
@@ -757,13 +825,13 @@ static int __cam_req_mgr_validate_sof_cnt(
  * @return   : 0 for success, negative for failure
  *
  */
-static int __cam_req_mgr_process_sync_req(
+static int __cam_req_mgr_check_sync_req_is_ready(
 	struct cam_req_mgr_core_link *link,
 	struct cam_req_mgr_slot *slot)
 {
 	struct cam_req_mgr_core_link *sync_link = NULL;
 	int64_t req_id = 0;
-	int sync_slot_idx = 0, rc = 0;
+	int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0;
 
 	if (!link->sync_link) {
 		CAM_ERR(CAM_CRM, "Sync link null");
@@ -774,94 +842,82 @@ static int __cam_req_mgr_process_sync_req(
 	req_id = slot->req_id;
 
 	CAM_DBG(CAM_REQ,
-		"link_hdl %x req %lld sync_self_ref %lld sof_counter %lld frame_skip_flag %d sync_link_self_ref %lld",
-		link->link_hdl, req_id, link->sync_self_ref, link->sof_counter,
-		link->frame_skip_flag, link->sync_link->sync_self_ref);
+		"link_hdl %x req %lld frame_skip_flag %d ",
+		link->link_hdl, req_id, link->sync_link_sof_skip);
 
 	if (sync_link->sync_link_sof_skip) {
 		CAM_DBG(CAM_REQ,
 			"No req applied on corresponding SOF on sync link: %x",
 			sync_link->link_hdl);
 		sync_link->sync_link_sof_skip = false;
-		/*It is to manage compensate inject delay for each pd*/
-		__cam_req_mgr_check_link_is_ready(link, slot->idx, true, true);
-		return -EINVAL;
+		__cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+		return -EAGAIN;
 	}
 
-	if (link->sof_counter == -1) {
-		__cam_req_mgr_sof_cnt_initialize(link);
-	} else if ((link->frame_skip_flag) &&
-		(sync_link->sync_self_ref != -1)) {
-		CAM_DBG(CAM_REQ, "Link[%x] Req[%lld] Resetting values ",
-			link->link_hdl, req_id);
-		__cam_req_mgr_reset_sof_cnt(link);
-		__cam_req_mgr_sof_cnt_initialize(link);
-	} else {
-		link->sof_counter++;
-	}
-
-	rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true);
+	rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
 	if (rc) {
-		CAM_DBG(CAM_REQ,
+		CAM_DBG(CAM_CRM,
+			"Skip Process Req: %lld on link: %x",
+			req_id, link->link_hdl);
+		link->sync_link_sof_skip = true;
+		return rc;
+	}
+
+	rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
+	if (rc) {
+		CAM_DBG(CAM_CRM,
 			"Req: %lld [My link] not ready on link: %x, rc=%d",
 			req_id, link->link_hdl, rc);
 		link->sync_link_sof_skip = true;
-		goto failure;
+		return rc;
 	}
 
 	sync_slot_idx = __cam_req_mgr_find_slot_for_req(
 		sync_link->req.in_q, req_id);
-
-	if (sync_slot_idx != -1) {
-		rc = __cam_req_mgr_check_link_is_ready(
-			sync_link, sync_slot_idx, true, false);
-		CAM_DBG(CAM_CRM, "sync_slot_idx=%d, status=%d, rc=%d",
-			sync_slot_idx,
-			sync_link->req.in_q->slot[sync_slot_idx].status,
-			rc);
-	} else {
-		CAM_DBG(CAM_CRM, "sync_slot_idx=%d, rc=%d",
-			sync_slot_idx, rc);
-	}
-
-	if ((sync_slot_idx != -1) &&
-		((sync_link->req.in_q->slot[sync_slot_idx].status ==
-		CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) {
-		rc = __cam_req_mgr_validate_sof_cnt(link, sync_link);
-		if (rc) {
-			CAM_DBG(CAM_CRM,
-				"Req: %lld validate failed: %x",
-				req_id, sync_link->link_hdl);
-			goto failure;
-		}
-
-		CAM_DBG(CAM_REQ,
-			"Req: %lld ready to apply on link: %x [validation successful]",
-			req_id, link->link_hdl);
-		/*
-		 *  At this point all validation is successfully done
-		 *  and we can proceed to apply the given request.
-		 *  Ideally the next call should return success.
-		 */
-		rc = __cam_req_mgr_check_link_is_ready(link,
-			slot->idx, false, true);
-
-		if (rc)
-			CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
-	} else {
-		CAM_DBG(CAM_REQ,
-			"Req: %lld [Other link] not ready to apply on link: %x",
+	if (sync_slot_idx == -1) {
+		CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]",
 			req_id, sync_link->link_hdl);
-		rc = -EPERM;
 		link->sync_link_sof_skip = true;
-		goto failure;
+		return -EINVAL;
 	}
 
-	return rc;
+	sync_rd_idx = sync_link->req.in_q->rd_idx;
+	if ((sync_link->req.in_q->slot[sync_slot_idx].status !=
+		CRM_SLOT_STATUS_REQ_APPLIED) &&
+		((sync_slot_idx - sync_rd_idx) >= 1) &&
+		(sync_link->req.in_q->slot[sync_rd_idx].status !=
+		CRM_SLOT_STATUS_REQ_APPLIED)) {
+		CAM_DBG(CAM_CRM,
+			"Req: %lld [other link] not next req to be applied on link: %x",
+			req_id, sync_link->link_hdl);
+		link->sync_link_sof_skip = true;
+		return -EAGAIN;
+	}
 
-failure:
-	link->sof_counter--;
-	return rc;
+	rc = __cam_req_mgr_check_link_is_ready(sync_link, sync_slot_idx, true);
+	if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status !=
+		CRM_SLOT_STATUS_REQ_APPLIED)) {
+		CAM_DBG(CAM_CRM,
+			"Req: %lld not ready on [other link] link: %x, rc=%d",
+			req_id, sync_link->link_hdl, rc);
+		link->sync_link_sof_skip = true;
+		return rc;
+	}
+
+	CAM_DBG(CAM_REQ,
+		"Req: %lld ready to apply on link: %x [validation successful]",
+		req_id, link->link_hdl);
+
+	/*
+	 *  At this point all validation is successfully done
+	 *  and we can proceed to apply the given request.
+	 *  Ideally the next call should return success.
+	 */
+	rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false);
+	if (rc)
+		CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
+
+	return 0;
 }
 
 /**
@@ -922,11 +978,21 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 			goto error;
 		}
 
-		if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)
-			rc = __cam_req_mgr_process_sync_req(link, slot);
-		else
-			rc = __cam_req_mgr_check_link_is_ready(link,
-				slot->idx, false, true);
+		if ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) &&
+			(link->sync_link)) {
+			if (link->is_master || link->sync_link->is_master)
+				rc =  __cam_req_mgr_check_sync_for_mslave(
+					link, slot);
+			else
+				rc = __cam_req_mgr_check_sync_req_is_ready(
+					link, slot);
+		} else {
+			rc = __cam_req_mgr_inject_delay(link->req.l_tbl,
+				slot->idx);
+			if (!rc)
+				rc = __cam_req_mgr_check_link_is_ready(link,
+					slot->idx, false);
+		}
 
 		if (rc < 0) {
 			/*
@@ -970,9 +1036,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 		}
 		spin_unlock_bh(&link->link_state_spin_lock);
 
-		if (link->sync_link_sof_skip)
-			link->sync_link_sof_skip = false;
-
 		if (link->trigger_mask == link->subscribe_event) {
 			slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
 			link->trigger_mask = 0;
@@ -1481,21 +1544,14 @@ static void __cam_req_mgr_unreserve_link(
 	for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
 		if (session->links[i] == link)
 			session->links[i] = NULL;
-	}
 
-	if ((session->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC) &&
-		(link->sync_link)) {
-		/*
-		 * make sure to unlink sync setup under the assumption
-		 * of only having 2 links in a given session
-		 */
-		session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
-		for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
-			if (session->links[i])
+		if (link->sync_link) {
+			if (link->sync_link == session->links[i])
 				session->links[i]->sync_link = NULL;
 		}
 	}
 
+	link->sync_link = NULL;
 	session->num_links--;
 	CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links);
 	mutex_unlock(&session->lock);
@@ -1769,8 +1825,9 @@ int cam_req_mgr_process_add_req(void *priv, void *data)
 	trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device);
 
 	if (slot->req_ready_map == tbl->dev_mask) {
-		CAM_DBG(CAM_REQ, "idx %d req_id %lld pd %d SLOT READY",
-			idx, add_req->req_id, tbl->pd);
+		CAM_DBG(CAM_REQ,
+			"link 0x%x idx %d req_id %lld pd %d SLOT READY",
+			link->link_hdl, idx, add_req->req_id, tbl->pd);
 		slot->state = CRM_REQ_STATE_READY;
 	}
 	mutex_unlock(&link->req.lock);
@@ -2479,16 +2536,17 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
 		return -EINVAL;
 	}
 
+	mutex_lock(&g_crm_core_dev->crm_lock);
+
 	/* session hdl's priv data is cam session struct */
 	cam_session = (struct cam_req_mgr_core_session *)
 		cam_get_device_priv(link_info->session_hdl);
 	if (!cam_session) {
 		CAM_DBG(CAM_CRM, "NULL pointer");
+		mutex_unlock(&g_crm_core_dev->crm_lock);
 		return -EINVAL;
 	}
 
-	mutex_lock(&g_crm_core_dev->crm_lock);
-
 	/* Allocate link struct and map it with session's request queue */
 	link = __cam_req_mgr_reserve_link(cam_session);
 	if (!link) {
@@ -2673,6 +2731,33 @@ int cam_req_mgr_schedule_request(
 	return rc;
 }
 
+/**
+ * __cam_req_mgr_set_master_link()
+ *
+ * @brief    : Each links sets its max pd delay based on the devices on the
+ *             link. The link with higher pd is assigned master.
+ * @link1    : One of the sync links
+ * @link2    : The other sync link
+ */
+static void __cam_req_mgr_set_master_link(
+	struct cam_req_mgr_core_link *link1,
+	struct cam_req_mgr_core_link *link2)
+{
+
+	if (link1->max_delay > link2->max_delay) {
+		link1->is_master = true;
+		link2->initial_skip = true;
+	} else if (link2->max_delay > link1->max_delay) {
+		link2->is_master = true;
+		link1->initial_skip = true;
+	}
+
+	CAM_DBG(CAM_CRM,
+		"link_hdl1[0x%x] is_master [%u] link_hdl2[0x%x] is_master[%u]",
+		link1->link_hdl, link1->is_master,
+		link2->link_hdl, link2->is_master);
+}
+
 int cam_req_mgr_sync_config(
 	struct cam_req_mgr_sync_mode *sync_info)
 {
@@ -2693,6 +2778,12 @@ int cam_req_mgr_sync_config(
 		return -EINVAL;
 	}
 
+	if ((sync_info->sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC) &&
+		(sync_info->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC)) {
+		CAM_ERR(CAM_CRM, "Invalid sync mode %d", sync_info->sync_mode);
+		return -EINVAL;
+	}
+
 	if ((!sync_info->link_hdls[0]) || (!sync_info->link_hdls[1])) {
 		CAM_WARN(CAM_CRM, "Invalid link handles 0x%x 0x%x",
 			sync_info->link_hdls[0], sync_info->link_hdls[1]);
@@ -2729,17 +2820,22 @@ int cam_req_mgr_sync_config(
 		goto done;
 	}
 
-	link1->sof_counter = -1;
-	link1->sync_self_ref = -1;
-	link1->frame_skip_flag = false;
 	link1->sync_link_sof_skip = false;
-	link1->sync_link = link2;
+	link1->sync_link = NULL;
 
-	link2->sof_counter = -1;
-	link2->sync_self_ref = -1;
-	link2->frame_skip_flag = false;
 	link2->sync_link_sof_skip = false;
-	link2->sync_link = link1;
+	link2->sync_link = NULL;
+
+	link1->is_master = false;
+	link2->is_master = false;
+	link1->initial_skip = false;
+	link2->initial_skip = false;
+
+	if (sync_info->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) {
+		link1->sync_link = link2;
+		link2->sync_link = link1;
+		__cam_req_mgr_set_master_link(link1, link2);
+	}
 
 	cam_session->sync_mode = sync_info->sync_mode;
 	CAM_DBG(CAM_REQ,
@@ -2837,7 +2933,8 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
 		goto end;
 	}
 
-	if (control->num_links > MAX_LINKS_PER_SESSION) {
+	if ((control->num_links <= 0) ||
+		(control->num_links > MAX_LINKS_PER_SESSION)) {
 		CAM_ERR(CAM_CRM, "Invalid number of links %d",
 			control->num_links);
 		rc = -EINVAL;
diff --git a/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.h
index 3bb05127..c564e72 100644
--- a/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/ais/cam_req_mgr/cam_req_mgr_core.h
@@ -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
@@ -135,9 +135,6 @@ enum cam_req_mgr_link_state {
  * @apply_data       : pointer which various tables will update during traverse
  * @in_q             : input request queue pointer
  * @validate_only    : Whether to validate only and/or update settings
- * @self_link        : To indicate whether the check is for the given link or
- *                     the other sync link
- * @inject_delay_chk : if inject delay has been validated for all pd devices
  * @open_req_cnt     : Count of open requests yet to be serviced in the kernel.
  */
 struct cam_req_mgr_traverse {
@@ -147,8 +144,6 @@ struct cam_req_mgr_traverse {
 	struct cam_req_mgr_apply     *apply_data;
 	struct cam_req_mgr_req_queue *in_q;
 	bool                          validate_only;
-	bool                          self_link;
-	bool                          inject_delay_chk;
 	int32_t                       open_req_cnt;
 };
 
@@ -308,10 +303,6 @@ struct cam_req_mgr_connected_device {
  *                         notification to CRM at those hw events.
  * @trigger_mask         : mask on which irq the req is already applied
  * @sync_link            : pointer to the sync link for synchronization
- * @sof_counter          : sof counter during sync_mode
- * @sync_self_ref        : reference sync count against which the difference
- *                         between sync_counts for a given link is checked
- * @frame_skip_flag      : flag that determines if a frame needs to be skipped
  * @sync_link_sof_skip   : flag determines if a pkt is not available for a given
  *                         frame in a particular link skip corresponding
  *                         frame in sync link as well.
@@ -319,6 +310,10 @@ struct cam_req_mgr_connected_device {
  *                         to be serviced in the kernel.
  * @last_flush_id        : Last request to flush
  * @is_used              : 1 if link is in use else 0
+ * @is_master            : Based on pd among links, the link with the highest pd
+ *                         is assigned as master
+ * @initial_skip         : Flag to determine if slave has started streaming in
+ *                         master-slave sync
  *
  */
 struct cam_req_mgr_core_link {
@@ -338,13 +333,12 @@ struct cam_req_mgr_core_link {
 	uint32_t                             subscribe_event;
 	uint32_t                             trigger_mask;
 	struct cam_req_mgr_core_link        *sync_link;
-	int64_t                              sof_counter;
-	int64_t                              sync_self_ref;
-	bool                                 frame_skip_flag;
 	bool                                 sync_link_sof_skip;
 	int32_t                              open_req_cnt;
 	uint32_t                             last_flush_id;
 	atomic_t                             is_used;
+	bool                                 is_master;
+	bool                                 initial_skip;
 };
 
 /**
diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 9f05a42..9bdbdde 100644
--- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/ais/cam_sensor_module/cam_csiphy/cam_csiphy_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
@@ -164,7 +164,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
 	struct cam_cmd_buf_desc *cmd_desc = NULL;
 	uint32_t                *cmd_buf = NULL;
 	struct cam_csiphy_info  *cam_cmd_csiphy_info = NULL;
-	size_t                  len = 0;
+	size_t                  len;
 
 	if (!cfg_dev || !csiphy_dev) {
 		CAM_ERR(CAM_CSIPHY, "Invalid Args");
@@ -577,6 +577,14 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 
 		struct cam_create_dev_hdl bridge_params;
 
+		if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) {
+			CAM_ERR(CAM_CSIPHY,
+				"Not in right state to acquire : %d",
+				csiphy_dev->csiphy_state);
+			rc = -EINVAL;
+			goto release_mutex;
+		}
+
 		rc = copy_from_user(&csiphy_acq_dev,
 			u64_to_user_ptr(cmd->handle),
 			sizeof(csiphy_acq_dev));
diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_core.c
index c47e38e..225a164 100644
--- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/ais/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
@@ -137,7 +137,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
 		CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG &&
 		csl_packet->header.request_id <= s_ctrl->last_flush_req
 		&& s_ctrl->last_flush_req != 0) {
-		CAM_DBG(CAM_SENSOR,
+		CAM_ERR(CAM_SENSOR,
 			"reject request %lld, last request to flush %lld",
 			csl_packet->header.request_id, s_ctrl->last_flush_req);
 		rc = -EINVAL;
@@ -615,9 +615,7 @@ void cam_sensor_shutdown(struct cam_sensor_ctrl_t *s_ctrl)
 
 	cam_sensor_release_stream_rsc(s_ctrl);
 	cam_sensor_release_per_frame_resource(s_ctrl);
-
-	if (s_ctrl->sensor_state != CAM_SENSOR_INIT)
-		cam_sensor_power_down(s_ctrl);
+	cam_sensor_power_down(s_ctrl);
 
 	rc = cam_destroy_device_hdl(s_ctrl->bridge_intf.device_hdl);
 	if (rc < 0)
@@ -1316,7 +1314,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
 	case CAM_CONFIG_DEV: {
 		rc = cam_sensor_i2c_pkt_parse(s_ctrl, arg);
 		if (rc < 0) {
-			CAM_ERR(CAM_SENSOR, "Failed CCI Config: %d", rc);
+			CAM_ERR(CAM_SENSOR, "Failed i2c pkt parse: %d", rc);
 			goto release_mutex;
 		}
 		if (s_ctrl->i2c_data.init_settings.is_settings_valid &&
@@ -1693,12 +1691,19 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req)
 		return -EINVAL;
 	}
 
+	mutex_lock(&(s_ctrl->cam_sensor_mutex));
+	if (s_ctrl->sensor_state != CAM_SENSOR_START ||
+		s_ctrl->sensor_state != CAM_SENSOR_CONFIG) {
+		mutex_unlock(&(s_ctrl->cam_sensor_mutex));
+		return rc;
+	}
+
 	if (s_ctrl->i2c_data.per_frame == NULL) {
 		CAM_ERR(CAM_SENSOR, "i2c frame data is NULL");
+		mutex_unlock(&(s_ctrl->cam_sensor_mutex));
 		return -EINVAL;
 	}
 
-	mutex_lock(&(s_ctrl->cam_sensor_mutex));
 	if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
 		s_ctrl->last_flush_req = flush_req->req_id;
 		CAM_DBG(CAM_SENSOR, "last reqest to flush is %lld",
diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
index 12fd679..7bd7e80 100644
--- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
+++ b/drivers/media/platform/msm/ais/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
@@ -334,6 +334,9 @@ enum msm_sensor_camera_id_t {
 	CAMERA_1,
 	CAMERA_2,
 	CAMERA_3,
+	CAMERA_4,
+	CAMERA_5,
+	CAMERA_6,
 	MAX_CAMERAS,
 };
 
diff --git a/drivers/media/platform/msm/ais/cam_utils/Makefile b/drivers/media/platform/msm/ais/cam_utils/Makefile
index 62e0ef4..b238218 100644
--- a/drivers/media/platform/msm/ais/cam_utils/Makefile
+++ b/drivers/media/platform/msm/ais/cam_utils/Makefile
@@ -3,3 +3,4 @@
 ccflags-y += -Idrivers/media/platform/msm/ais/cam_smmu/
 
 obj-$(CONFIG_MSM_AIS) += cam_soc_util.o cam_io_util.o cam_packet_util.o cam_debug_util.o cam_trace.o cam_common_util.o
+obj-$(CONFIG_MSM_AIS) += cam_cx_ipeak.o
diff --git a/drivers/media/platform/msm/ais/cam_utils/cam_cx_ipeak.c b/drivers/media/platform/msm/ais/cam_utils/cam_cx_ipeak.c
new file mode 100644
index 0000000..91da7ab
--- /dev/null
+++ b/drivers/media/platform/msm/ais/cam_utils/cam_cx_ipeak.c
@@ -0,0 +1,135 @@
+/* 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/clk.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <soc/qcom/cx_ipeak.h>
+#include "cam_soc_util.h"
+#include "cam_debug_util.h"
+
+static struct cx_ipeak_client *cam_cx_ipeak;
+static int cx_ipeak_level = CAM_NOMINAL_VOTE;
+static int cx_default_ipeak_mask;
+static int cx_current_ipeak_mask;
+static int cam_cx_client_cnt;
+
+int cam_cx_ipeak_register_cx_ipeak(struct cam_hw_soc_info *soc_info)
+{
+	int rc = 0;
+
+	soc_info->cam_cx_ipeak_enable = true;
+	soc_info->cam_cx_ipeak_bit = 1 << cam_cx_client_cnt++;
+	cx_default_ipeak_mask |= soc_info->cam_cx_ipeak_bit;
+
+	if (cam_cx_ipeak)
+		goto exit;
+
+	cam_cx_ipeak = cx_ipeak_register(soc_info->dev->of_node,
+		"qcom,cam-cx-ipeak");
+
+	if (cam_cx_ipeak) {
+		goto exit;
+	} else {
+		rc = -EINVAL;
+		goto exit;
+	}
+
+exit:
+	CAM_DBG(CAM_UTIL, "cam_cx_ipeak is enabled for %s\n"
+		"mask = %x cx_default_ipeak_mask = %x",
+		soc_info->dev_name, soc_info->cam_cx_ipeak_bit,
+		cx_default_ipeak_mask);
+	return rc;
+}
+
+int cam_cx_ipeak_update_vote_cx_ipeak(struct cam_hw_soc_info *soc_info,
+	int32_t apply_level)
+{
+	int32_t soc_cx_ipeak_bit = soc_info->cam_cx_ipeak_bit;
+	int ret = 0;
+
+	CAM_DBG(CAM_UTIL, "E: apply_level = %d cx_current_ipeak_mask = %x\n"
+			"soc_cx_ipeak_bit = %x",
+			apply_level, cx_current_ipeak_mask, soc_cx_ipeak_bit);
+
+	if (apply_level < cx_ipeak_level &&
+		(cx_current_ipeak_mask & soc_cx_ipeak_bit)) {
+		if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
+			ret = cx_ipeak_update(cam_cx_ipeak, false);
+			if (ret)
+				goto exit;
+			CAM_DBG(CAM_UTIL,
+				"X: apply_level = %d cx_current_ipeak_mask = %x\n"
+				"soc_cx_ipeak_bit = %x  %s UNVOTE",
+				apply_level, cx_current_ipeak_mask,
+				soc_cx_ipeak_bit, soc_info->dev_name);
+		}
+		cx_current_ipeak_mask &= (~soc_cx_ipeak_bit);
+		CAM_DBG(CAM_UTIL,
+			"X: apply_level = %d cx_current_ipeak_mask = %x\n"
+			"soc_cx_ipeak_bit = %x  %s DISABLE_BIT",
+			apply_level, cx_current_ipeak_mask,
+			soc_cx_ipeak_bit, soc_info->dev_name);
+		goto exit;
+	} else if (apply_level < cx_ipeak_level) {
+		CAM_DBG(CAM_UTIL,
+			"X: apply_level = %d cx_current_ipeak_mask = %x\n"
+			"soc_cx_ipeak_bit = %x NO AI",
+			apply_level, cx_current_ipeak_mask, soc_cx_ipeak_bit);
+		goto exit;
+	}
+
+	cx_current_ipeak_mask |= soc_cx_ipeak_bit;
+	CAM_DBG(CAM_UTIL,
+		"X: apply_level = %d cx_current_ipeak_mask = %x\n"
+		"soc_cx_ipeak_bit = %x  %s ENABLE_BIT",
+		apply_level, cx_current_ipeak_mask,
+		soc_cx_ipeak_bit, soc_info->dev_name);
+	if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
+		ret = cx_ipeak_update(cam_cx_ipeak, true);
+		if (ret)
+			goto exit;
+		CAM_DBG(CAM_UTIL,
+			"X: apply_level = %d cx_current_ipeak_mask = %x\n"
+			"soc_cx_ipeak_bit = %x  %s VOTE",
+			apply_level, cx_current_ipeak_mask,
+			soc_cx_ipeak_bit, soc_info->dev_name);
+	}
+
+exit:
+	return ret;
+}
+
+int cam_cx_ipeak_unvote_cx_ipeak(struct cam_hw_soc_info *soc_info)
+{
+	int32_t soc_cx_ipeak_bit = soc_info->cam_cx_ipeak_bit;
+
+	CAM_DBG(CAM_UTIL, "E:cx_current_ipeak_mask = %x\n"
+		"soc_cx_ipeak_bit = %x",
+		cx_current_ipeak_mask, soc_cx_ipeak_bit);
+	if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
+		if (cam_cx_ipeak)
+			cx_ipeak_update(cam_cx_ipeak, false);
+		CAM_DBG(CAM_UTIL, "X:cx_current_ipeak_mask = %x\n"
+			"soc_cx_ipeak_bit = %x UNVOTE",
+			cx_current_ipeak_mask, soc_cx_ipeak_bit);
+	}
+	cx_current_ipeak_mask &= (~soc_cx_ipeak_bit);
+	CAM_DBG(CAM_UTIL, "X:cx_current_ipeak_mask = %x\n"
+		"soc_cx_ipeak_bit = %x",
+		cx_current_ipeak_mask, soc_cx_ipeak_bit);
+
+	return 0;
+}
diff --git a/drivers/media/platform/msm/ais/cam_utils/cam_cx_ipeak.h b/drivers/media/platform/msm/ais/cam_utils/cam_cx_ipeak.h
new file mode 100644
index 0000000..fb3a9ea
--- /dev/null
+++ b/drivers/media/platform/msm/ais/cam_utils/cam_cx_ipeak.h
@@ -0,0 +1,26 @@
+/* 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_CX_IPEAK_H_
+#define _CAM_CX_IPEAK_H_
+
+#include <linux/clk/qcom.h>
+#include <soc/qcom/cx_ipeak.h>
+#include "cam_io_util.h"
+
+int cam_cx_ipeak_register_cx_ipeak(struct cam_hw_soc_info *soc_info);
+
+int cam_cx_ipeak_update_vote_cx_ipeak(struct cam_hw_soc_info *soc_info,
+	int32_t apply_level);
+int cam_cx_ipeak_unvote_cx_ipeak(struct cam_hw_soc_info *soc_info);
+
+#endif /* _CAM_CX_IPEAK_H_ */
diff --git a/drivers/media/platform/msm/ais/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/ais/cam_utils/cam_soc_util.c
index 9056b2b..02382451 100644
--- a/drivers/media/platform/msm/ais/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/ais/cam_utils/cam_soc_util.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
@@ -17,10 +17,38 @@
 #include <linux/of_gpio.h>
 #include "cam_soc_util.h"
 #include "cam_debug_util.h"
+#include "cam_cx_ipeak.h"
 
 static char supported_clk_info[256];
 static char debugfs_dir_name[64];
 
+static int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info,
+	int32_t src_clk_idx, int32_t clk_rate)
+{
+	int i;
+	long clk_rate_round;
+
+	clk_rate_round = clk_round_rate(soc_info->clk[src_clk_idx], clk_rate);
+	if (clk_rate_round < 0) {
+		CAM_ERR(CAM_UTIL, "round failed rc = %ld",
+			clk_rate_round);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < CAM_MAX_VOTE; i++) {
+		if (soc_info->clk_rate[i][src_clk_idx] >= clk_rate_round) {
+			CAM_DBG(CAM_UTIL,
+				"soc = %d round rate = %ld actual = %d",
+				soc_info->clk_rate[i][src_clk_idx],
+				clk_rate_round,	clk_rate);
+			return i;
+		}
+	}
+
+	CAM_WARN(CAM_UTIL, "Invalid clock rate %ld", clk_rate_round);
+	return -EINVAL;
+}
+
 /**
  * cam_soc_util_get_string_from_level()
  *
@@ -407,6 +435,7 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
 {
 	int32_t src_clk_idx;
 	struct clk *clk = NULL;
+	int32_t apply_level;
 
 	if (!soc_info || (soc_info->src_clk_idx < 0))
 		return -EINVAL;
@@ -417,6 +446,17 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
 	src_clk_idx = soc_info->src_clk_idx;
 	clk = soc_info->clk[src_clk_idx];
 
+	if (soc_info->cam_cx_ipeak_enable && clk_rate >= 0) {
+		apply_level = cam_soc_util_get_clk_level(soc_info, src_clk_idx,
+				clk_rate);
+		CAM_DBG(CAM_UTIL, "set %s, rate %d dev_name = %s\n"
+			"apply level = %d",
+			soc_info->clk_name[src_clk_idx], clk_rate,
+			soc_info->dev_name, apply_level);
+		if (apply_level >= 0)
+			cam_cx_ipeak_update_vote_cx_ipeak(soc_info,
+				apply_level);
+	}
 	return cam_soc_util_set_clk_rate(clk,
 		soc_info->clk_name[src_clk_idx], clk_rate);
 
@@ -569,17 +609,30 @@ int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info,
 	if (rc)
 		return rc;
 
+	if (soc_info->cam_cx_ipeak_enable)
+		cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level);
+
 	for (i = 0; i < soc_info->num_clk; i++) {
 		rc = cam_soc_util_clk_enable(soc_info->clk[i],
 			soc_info->clk_name[i],
 			soc_info->clk_rate[apply_level][i]);
 		if (rc)
 			goto clk_disable;
+		if (soc_info->cam_cx_ipeak_enable) {
+			CAM_DBG(CAM_UTIL,
+			"dev name = %s clk name = %s idx = %d\n"
+			"apply_level = %d clc idx = %d",
+			soc_info->dev_name, soc_info->clk_name[i], i,
+			apply_level, i);
+		}
+
 	}
 
 	return rc;
 
 clk_disable:
+	if (soc_info->cam_cx_ipeak_enable)
+		cam_cx_ipeak_update_vote_cx_ipeak(soc_info, 0);
 	for (i--; i >= 0; i--) {
 		cam_soc_util_clk_disable(soc_info->clk[i],
 			soc_info->clk_name[i]);
@@ -605,6 +658,8 @@ void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info)
 	if (soc_info->num_clk == 0)
 		return;
 
+	if (soc_info->cam_cx_ipeak_enable)
+		cam_cx_ipeak_unvote_cx_ipeak(soc_info);
 	for (i = soc_info->num_clk - 1; i >= 0; i--)
 		cam_soc_util_clk_disable(soc_info->clk[i],
 			soc_info->clk_name[i]);
@@ -646,7 +701,8 @@ static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info)
 
 	count = of_property_count_strings(of_node, "clock-names");
 
-	CAM_DBG(CAM_UTIL, "count = %d", count);
+	CAM_DBG(CAM_UTIL, "E: dev_name = %s count = %d",
+		soc_info->dev_name, count);
 	if (count > CAM_SOC_MAX_CLK) {
 		CAM_ERR(CAM_UTIL, "invalid count of clocks, count=%d", count);
 		rc = -EINVAL;
@@ -765,6 +821,8 @@ static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info)
 	if (strcmp("true", clk_control_debugfs) == 0)
 		soc_info->clk_control_enable = true;
 
+	CAM_DBG(CAM_UTIL, "X: dev_name = %s count = %d",
+		soc_info->dev_name, count);
 end:
 	return rc;
 }
@@ -787,12 +845,23 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info,
 	if (rc)
 		return rc;
 
+	if (soc_info->cam_cx_ipeak_enable)
+		cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level);
+
 	for (i = 0; i < soc_info->num_clk; i++) {
 		rc = cam_soc_util_set_clk_rate(soc_info->clk[i],
 			soc_info->clk_name[i],
 			soc_info->clk_rate[apply_level][i]);
-		if (rc)
+		if (rc < 0) {
+			CAM_DBG(CAM_UTIL,
+				"dev name = %s clk_name = %s idx = %d\n"
+				"apply_level = %d",
+				soc_info->dev_name, soc_info->clk_name[i],
+				i, apply_level);
+			if (soc_info->cam_cx_ipeak_enable)
+				cam_cx_ipeak_update_vote_cx_ipeak(soc_info, 0);
 			break;
+		}
 	}
 
 	return rc;
@@ -1160,6 +1229,9 @@ int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info)
 	if (rc)
 		return rc;
 
+	if (of_find_property(of_node, "qcom,cam-cx-ipeak", NULL))
+		rc = cam_cx_ipeak_register_cx_ipeak(soc_info);
+
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/ais/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/ais/cam_utils/cam_soc_util.h
index f6dac35..c14a563 100644
--- a/drivers/media/platform/msm/ais/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/ais/cam_utils/cam_soc_util.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
@@ -149,6 +149,7 @@ struct cam_soc_gpio_data {
  * @clk:                    Array of associated clock resources
  * @clk_rate:               2D array of clock rates representing clock rate
  *                          values at different vote levels
+ * @prev_clk_level          Last vote level
  * @src_clk_idx:            Source clock index that is rate-controllable
  * @clk_level_valid:        Indicates whether corresponding level is valid
  * @gpio_data:              Pointer to gpio info
@@ -156,6 +157,8 @@ struct cam_soc_gpio_data {
  * @dentry:                 Debugfs entry
  * @clk_level_override:     Clk level set from debugfs
  * @clk_control:            Enable/disable clk rate control through debugfs
+ * @cam_cx_ipeak_enable     cx-ipeak enable/disable flag
+ * @cam_cx_ipeak_bit        cx-ipeak mask for driver
  * @soc_private:            Soc private data
  */
 struct cam_hw_soc_info {
@@ -191,6 +194,7 @@ struct cam_hw_soc_info {
 	const char                     *clk_name[CAM_SOC_MAX_CLK];
 	struct clk                     *clk[CAM_SOC_MAX_CLK];
 	int32_t                         clk_rate[CAM_MAX_VOTE][CAM_SOC_MAX_CLK];
+	int32_t                         prev_clk_level;
 	int32_t                         src_clk_idx;
 	bool                            clk_level_valid[CAM_MAX_VOTE];
 
@@ -200,6 +204,8 @@ struct cam_hw_soc_info {
 	struct dentry                  *dentry;
 	uint32_t                        clk_level_override;
 	bool                            clk_control_enable;
+	bool                            cam_cx_ipeak_enable;
+	int32_t                         cam_cx_ipeak_bit;
 
 	void                           *soc_private;
 };
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
index 5ea2a00..e5034c5 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_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
@@ -120,7 +120,7 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
 			(len >= cdm_cmd->cmd[i].offset)) {
 
 
-			if ((len - cdm_cmd->cmd[i].offset) <=
+			if ((len - cdm_cmd->cmd[i].offset) <
 				cdm_cmd->cmd[i].len) {
 				CAM_ERR(CAM_CDM, "Not enough buffer");
 				rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c
index 1a46f88..0ed9675aa 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.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
@@ -244,6 +244,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova,
 		return -EINVAL;
 	}
 
+	mutex_lock(&ctx->ctx_mutex);
 	if (ctx->state_machine[ctx->state].pagefault_ops) {
 		rc = ctx->state_machine[ctx->state].pagefault_ops(ctx, iova,
 			buf_info);
@@ -251,6 +252,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova,
 		CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d",
 			ctx->dev_hdl, ctx->state);
 	}
+	mutex_unlock(&ctx->ctx_mutex);
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
index a1b9e08..90e1611 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.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
@@ -262,6 +262,7 @@ int32_t cam_context_release_dev_to_hw(struct cam_context *ctx,
 	ctx->session_hdl = -1;
 	ctx->dev_hdl = -1;
 	ctx->link_hdl = -1;
+	ctx->last_flush_req = 0;
 
 	return 0;
 }
@@ -398,7 +399,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
 		(uint32_t)cmd->offset);
 
 	if (packet->header.request_id <= ctx->last_flush_req) {
-		CAM_DBG(CAM_CORE,
+		CAM_ERR(CAM_CORE,
 			"request %lld has been flushed, reject packet",
 			packet->header.request_id);
 		rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
index 3d0ee72..f3a0fe4 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
@@ -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
@@ -38,6 +38,7 @@ struct hfi_mem {
  * @sfr_buf: buffer for subsystem failure reason[SFR]
  * @sec_heap: secondary heap hfi memory for firmware
  * @qdss: qdss mapped memory for fw
+ * @io_mem: io memory info
  * @icp_base: icp base address
  */
 struct hfi_mem_info {
@@ -49,6 +50,7 @@ struct hfi_mem_info {
 	struct hfi_mem sec_heap;
 	struct hfi_mem shmem;
 	struct hfi_mem qdss;
+	struct hfi_mem io_mem;
 	void __iomem *icp_base;
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
index f652cfa..2579153 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
@@ -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
@@ -42,8 +42,11 @@
 #define HFI_REG_UNCACHED_HEAP_PTR               0x5C
 #define HFI_REG_UNCACHED_HEAP_SIZE              0x60
 #define HFI_REG_QDSS_IOVA                       0x6C
-#define HFI_REG_QDSS_IOVA_SIZE                  0x70
 #define HFI_REG_SFR_PTR                         0x68
+#define HFI_REG_QDSS_IOVA_SIZE                  0x70
+#define HFI_REG_IO_REGION_IOVA                  0x74
+#define HFI_REG_IO_REGION_SIZE                  0x78
+
 /* end of ICP CSR registers */
 
 /* flags for ICP CSR registers */
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_session_defs.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_session_defs.h
index 38137b8..9f81c9c 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_session_defs.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_session_defs.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
@@ -472,7 +472,6 @@ struct ica_stab_params {
 
 struct frame_set {
 	struct frame_buffer buffers[IPE_IO_IMAGES_MAX];
-	struct ica_stab_params ica_params;
 	uint32_t cdm_ica1_addr;
 	uint32_t cdm_ica2_addr;
 } __packed;
diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c
index c82a3b9..54c0eca 100644
--- a/drivers/media/platform/msm/camera/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera/cam_icp/hfi.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
@@ -632,6 +632,10 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
 		icp_base + HFI_REG_QDSS_IOVA);
 	cam_io_w_mb((uint32_t)hfi_mem->qdss.len,
 		icp_base + HFI_REG_QDSS_IOVA_SIZE);
+	cam_io_w_mb((uint32_t)hfi_mem->io_mem.iova,
+		icp_base + HFI_REG_IO_REGION_IOVA);
+	cam_io_w_mb((uint32_t)hfi_mem->io_mem.len,
+		icp_base + HFI_REG_IO_REGION_SIZE);
 
 	return rc;
 }
@@ -820,6 +824,10 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem,
 		icp_base + HFI_REG_QDSS_IOVA);
 	cam_io_w_mb((uint32_t)hfi_mem->qdss.len,
 		icp_base + HFI_REG_QDSS_IOVA_SIZE);
+	cam_io_w_mb((uint32_t)hfi_mem->io_mem.iova,
+		icp_base + HFI_REG_IO_REGION_IOVA);
+	cam_io_w_mb((uint32_t)hfi_mem->io_mem.len,
+		icp_base + HFI_REG_IO_REGION_SIZE);
 
 	hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION);
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index fbbbbc7..6850866 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -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
@@ -62,6 +62,8 @@
 
 static struct cam_icp_hw_mgr icp_hw_mgr;
 
+static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl);
+
 static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr)
 {
 	struct cam_hw_intf *a5_dev_intf = NULL;
@@ -1834,12 +1836,13 @@ static int cam_icp_mgr_process_fatal_error(
 	if (event_notify->event_id == HFI_EVENT_SYS_ERROR) {
 		CAM_INFO(CAM_ICP, "received HFI_EVENT_SYS_ERROR");
 		rc = cam_icp_mgr_trigger_recovery(hw_mgr);
+		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
 	}
 
 	return rc;
 }
 
-static void cam_icp_mgr_process_dbg_buf(void)
+static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl)
 {
 	uint32_t *msg_ptr = NULL, *pkt_ptr = NULL;
 	struct hfi_msg_debug *dbg_msg;
@@ -1861,6 +1864,8 @@ static void cam_icp_mgr_process_dbg_buf(void)
 			timestamp = ((((uint64_t)(dbg_msg->timestamp_hi) << 32)
 				| dbg_msg->timestamp_lo) >> 16);
 			trace_cam_icp_fw_dbg(dbg_buf, timestamp/2);
+			if (!debug_lvl)
+				CAM_INFO(CAM_ICP, "FW_DBG:%s", dbg_buf);
 		}
 		size_processed += (pkt_ptr[ICP_PACKET_SIZE] >>
 			BYTE_WORD_SHIFT);
@@ -1986,9 +1991,7 @@ static int32_t cam_icp_mgr_process_msg(void *priv, void *data)
 		}
 	}
 
-	if (icp_hw_mgr.a5_debug_type ==
-		HFI_DEBUG_MODE_QUEUE)
-		cam_icp_mgr_process_dbg_buf();
+	cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
 
 	if ((task_data->irq_status & A5_WDT_0) ||
 		(task_data->irq_status & A5_WDT_1)) {
@@ -2179,6 +2182,25 @@ static int cam_icp_allocate_qdss_mem(void)
 	return rc;
 }
 
+static int cam_icp_get_io_mem_info(void)
+{
+	int rc;
+	size_t len;
+	dma_addr_t iova;
+
+	rc = cam_smmu_get_io_region_info(icp_hw_mgr.iommu_hdl,
+		&iova, &len);
+	if (rc)
+		return rc;
+
+	icp_hw_mgr.hfi_mem.io_mem.iova_len = len;
+	icp_hw_mgr.hfi_mem.io_mem.iova_start = iova;
+
+	CAM_DBG(CAM_ICP, "iova: %llx, len: %zu", iova, len);
+
+	return rc;
+}
+
 static int cam_icp_allocate_hfi_mem(void)
 {
 	int rc;
@@ -2239,7 +2261,15 @@ static int cam_icp_allocate_hfi_mem(void)
 		goto sec_heap_alloc_failed;
 	}
 
+	rc = cam_icp_get_io_mem_info();
+	if (rc) {
+		CAM_ERR(CAM_ICP, "Unable to get I/O region info");
+		goto get_io_mem_failed;
+	}
+
 	return rc;
+get_io_mem_failed:
+	cam_mem_mgr_free_memory_region(&icp_hw_mgr.hfi_mem.sec_heap);
 sec_heap_alloc_failed:
 	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.sfr_buf);
 sfr_buf_alloc_failed:
@@ -2458,6 +2488,14 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr)
 
 	hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova;
 	hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len;
+
+	hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start;
+	hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len;
+
+	CAM_DBG(CAM_ICP, "IO region IOVA = %X length = %lld",
+			hfi_mem.io_mem.iova,
+			hfi_mem.io_mem.len);
+
 	return cam_hfi_resume(&hfi_mem,
 		a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base,
 		hw_mgr->a5_jtag_debug);
@@ -2469,7 +2507,7 @@ static int cam_icp_mgr_abort_handle(
 	int rc = 0;
 	unsigned long rem_jiffies;
 	size_t packet_size;
-	int timeout = 100;
+	int timeout = 1000;
 	struct hfi_cmd_ipebps_async *abort_cmd;
 
 	packet_size =
@@ -2508,6 +2546,7 @@ static int cam_icp_mgr_abort_handle(
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW timeout/err in abort handle command");
+		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
 		cam_hfi_queue_dump();
 	}
 
@@ -2519,7 +2558,7 @@ static int cam_icp_mgr_destroy_handle(
 	struct cam_icp_hw_ctx_data *ctx_data)
 {
 	int rc = 0;
-	int timeout = 100;
+	int timeout = 1000;
 	unsigned long rem_jiffies;
 	size_t packet_size;
 	struct hfi_cmd_ipebps_async *destroy_cmd;
@@ -2562,9 +2601,7 @@ static int cam_icp_mgr_destroy_handle(
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timeout: %d for %u",
 			rc, ctx_data->ctx_id);
-		if (icp_hw_mgr.a5_debug_type ==
-			HFI_DEBUG_MODE_QUEUE)
-			cam_icp_mgr_process_dbg_buf();
+		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
 		cam_hfi_queue_dump();
 	}
 	kfree(destroy_cmd);
@@ -2839,6 +2876,9 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr)
 	hfi_mem.qdss.iova = icp_hw_mgr.hfi_mem.qdss_buf.iova;
 	hfi_mem.qdss.len = icp_hw_mgr.hfi_mem.qdss_buf.len;
 
+	hfi_mem.io_mem.iova = icp_hw_mgr.hfi_mem.io_mem.iova_start;
+	hfi_mem.io_mem.len = icp_hw_mgr.hfi_mem.io_mem.iova_len;
+
 	return cam_hfi_init(0, &hfi_mem,
 		a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base,
 		hw_mgr->a5_jtag_debug);
@@ -2871,6 +2911,7 @@ static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr)
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
 		cam_hfi_queue_dump();
 	}
 	CAM_DBG(CAM_ICP, "Done Waiting for INIT DONE Message");
@@ -3122,6 +3163,7 @@ static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
 		cam_hfi_queue_dump();
 	}
 
@@ -3396,6 +3438,13 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr,
 					num_cmd_buf-- : 0;
 				goto rel_cmd_buf;
 			}
+			if ((len <= cmd_desc[i].offset) ||
+				(cmd_desc[i].size < cmd_desc[i].length) ||
+				((len - cmd_desc[i].offset) <
+				cmd_desc[i].length)) {
+				CAM_ERR(CAM_ICP, "Invalid offset or length");
+				goto rel_cmd_buf;
+			}
 			cpu_addr = cpu_addr + cmd_desc[i].offset;
 		}
 	}
@@ -3883,8 +3932,9 @@ static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet,
 			}
 
 			CAM_INFO(CAM_ICP,
-				"pln %d w %d h %d s %u sh %u size %d addr 0x%x offset 0x%x memh %x",
-				j, io_cfg[i].planes[j].width,
+				"pln %d dir %d w %d h %d s %u sh %u sz %d addr 0x%x off 0x%x memh %x",
+				j, io_cfg[i].direction,
+				io_cfg[i].planes[j].width,
 				io_cfg[i].planes[j].height,
 				io_cfg[i].planes[j].plane_stride,
 				io_cfg[i].planes[j].slice_height,
@@ -4342,6 +4392,7 @@ static int cam_icp_mgr_create_handle(uint32_t dev_type,
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
 		cam_hfi_queue_dump();
 	}
 
@@ -4388,6 +4439,7 @@ static int cam_icp_mgr_send_ping(struct cam_icp_hw_ctx_data *ctx_data)
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
 		cam_hfi_queue_dump();
 	}
 
@@ -4661,6 +4713,7 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 	hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info = NULL;
 acquire_info_failed:
 	cam_icp_mgr_put_ctx(ctx_data);
+	cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
 	mutex_unlock(&ctx_data->ctx_mutex);
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 	return rc;
@@ -4940,6 +4993,7 @@ static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 			hw_mgr->iommu_sec_hdl,
 			hw_cmd_args->u.pf_args.buf_info,
 			hw_cmd_args->u.pf_args.mem_found);
+
 		break;
 	default:
 		CAM_ERR(CAM_ICP, "Invalid cmd");
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index 15fc7a6..c226c10 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -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
@@ -80,6 +80,8 @@
  * @fw_buf: Memory info of firmware
  * @qdss_buf: Memory info of qdss
  * @sfr_buf: Memory info for sfr buffer
+ * @shmem: Memory info for shared region
+ * @io_mem: Memory info for io region
  */
 struct icp_hfi_mem_info {
 	struct cam_mem_mgr_memory_desc qtbl;
@@ -91,6 +93,7 @@ struct icp_hfi_mem_info {
 	struct cam_mem_mgr_memory_desc qdss_buf;
 	struct cam_mem_mgr_memory_desc sfr_buf;
 	struct cam_smmu_region_info shmem;
+	struct cam_smmu_region_info io_mem;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
index 7bb9b9ed..2ebe414 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.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
@@ -23,7 +23,7 @@
 
 #define CAM_ICP_A5_BW_BYTES_VOTE 40000000
 
-#define CAM_ICP_CTX_MAX          36
+#define CAM_ICP_CTX_MAX          54
 
 #define CPAS_IPE1_BIT            0x2000
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index 03e3f07..2c00454 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.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
@@ -1079,7 +1079,9 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
 	}
 
 	req_isp = (struct cam_isp_ctx_req *) req_to_dump->req_priv;
-	cam_isp_ctx_dump_req(req_isp);
+
+	if (error_event_data->enable_reg_dump)
+		cam_isp_ctx_dump_req(req_isp);
 
 	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
 		CAM_ISP_STATE_CHANGE_TRIGGER_ERROR, req_to_dump->request_id);
@@ -1861,7 +1863,9 @@ static int __cam_isp_ctx_flush_req_in_top_state(
 	struct cam_req_mgr_flush_request *flush_req)
 {
 	int rc = 0;
+	struct cam_isp_context *ctx_isp;
 
+	ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
 	if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
 		CAM_INFO(CAM_ISP, "Last request id to flush is %lld",
 			flush_req->req_id);
@@ -1873,6 +1877,7 @@ static int __cam_isp_ctx_flush_req_in_top_state(
 	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
 	spin_unlock_bh(&ctx->lock);
 
+	atomic_set(&ctx_isp->process_bubble, 0);
 	return rc;
 }
 
@@ -3159,12 +3164,13 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
 	start_isp.hw_config.init_packet = 1;
 	start_isp.start_only = false;
 
+	atomic_set(&ctx_isp->process_bubble, 0);
 	ctx_isp->frame_id = 0;
 	ctx_isp->active_req_cnt = 0;
 	ctx_isp->reported_req_id = 0;
 	ctx_isp->substate_activated = ctx_isp->rdi_only_context ?
 		CAM_ISP_CTX_ACTIVATED_APPLIED :
-		(req_isp->num_fence_map_out) ? CAM_ISP_CTX_ACTIVATED_EPOCH :
+		(req_isp->num_fence_map_out) ? CAM_ISP_CTX_ACTIVATED_APPLIED :
 		CAM_ISP_CTX_ACTIVATED_SOF;
 
 	/*
@@ -3186,13 +3192,8 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
 	CAM_DBG(CAM_ISP, "start device success ctx %u", ctx->ctx_id);
 
 	list_del_init(&req->list);
+	list_add_tail(&req->list, &ctx->wait_req_list);
 
-	if (req_isp->num_fence_map_out) {
-		list_add_tail(&req->list, &ctx->active_req_list);
-		ctx_isp->active_req_cnt++;
-	} else {
-		list_add_tail(&req->list, &ctx->wait_req_list);
-	}
 end:
 	return rc;
 }
@@ -3294,6 +3295,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock(
 	ctx_isp->frame_id = 0;
 	ctx_isp->active_req_cnt = 0;
 	ctx_isp->reported_req_id = 0;
+	atomic_set(&ctx_isp->process_bubble, 0);
 
 	CAM_DBG(CAM_ISP, "Stop device success next state %d on ctx %u",
 		ctx->state, ctx->ctx_id);
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 28e96a7..53ac8c7 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
@@ -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
@@ -3496,6 +3496,53 @@ static int cam_isp_blob_clock_update(
 	return rc;
 }
 
+void fill_res_bitmap(uint32_t resource_type, unsigned long *res_bitmap)
+{
+
+	switch (resource_type) {
+	case CAM_ISP_IFE_OUT_RES_FULL:
+	case CAM_ISP_IFE_OUT_RES_DS4:
+	case CAM_ISP_IFE_OUT_RES_DS16:
+	case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
+	case CAM_ISP_IFE_OUT_RES_FD:
+	case CAM_ISP_IFE_OUT_RES_PDAF:
+	case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
+	case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
+	case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
+	case CAM_ISP_IFE_OUT_RES_STATS_BF:
+	case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
+	case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
+	case CAM_ISP_IFE_OUT_RES_STATS_RS:
+	case CAM_ISP_IFE_OUT_RES_STATS_CS:
+	case CAM_ISP_IFE_OUT_RES_STATS_IHIST:
+	case CAM_ISP_IFE_OUT_RES_FULL_DISP:
+	case CAM_ISP_IFE_OUT_RES_DS4_DISP:
+	case CAM_ISP_IFE_OUT_RES_DS16_DISP:
+	case CAM_ISP_IFE_IN_RES_RD:
+		set_bit(CAM_IFE_REG_UPD_CMD_PIX_BIT, res_bitmap);
+		break;
+	case CAM_ISP_IFE_OUT_RES_RDI_0:
+		set_bit(CAM_IFE_REG_UPD_CMD_RDI0_BIT, res_bitmap);
+		break;
+	case CAM_ISP_IFE_OUT_RES_RDI_1:
+		set_bit(CAM_IFE_REG_UPD_CMD_RDI1_BIT, res_bitmap);
+		break;
+	case CAM_ISP_IFE_OUT_RES_RDI_2:
+		set_bit(CAM_IFE_REG_UPD_CMD_RDI2_BIT, res_bitmap);
+		break;
+	case CAM_ISP_IFE_OUT_RES_RDI_3:
+		set_bit(CAM_IFE_REG_UPD_CMD_RDI3_BIT, res_bitmap);
+		break;
+	case CAM_ISP_IFE_OUT_RES_2PD:
+		set_bit(CAM_IFE_REG_UPD_CMD_DUAL_PD_BIT,
+			res_bitmap);
+		break;
+	default:
+		CAM_ERR(CAM_ISP, "Invalid resource");
+		break;
+	}
+}
+
 static int cam_isp_packet_generic_blob_handler(void *user_data,
 	uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
 {
@@ -3504,8 +3551,8 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 	struct cam_hw_prepare_update_args *prepare = NULL;
 
 	if (!blob_data || (blob_size == 0) || !blob_info) {
-		CAM_ERR(CAM_ISP, "Invalid info blob %pK %d prepare %pK",
-			blob_data, blob_size, prepare);
+		CAM_ERR(CAM_ISP, "Invalid args data %pK size %d info %pK",
+			blob_data, blob_size, blob_info);
 		return -EINVAL;
 	}
 
@@ -3525,8 +3572,29 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 	CAM_DBG(CAM_ISP, "FS2: BLOB Type: %d", blob_type);
 	switch (blob_type) {
 	case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG: {
-		struct cam_isp_resource_hfr_config    *hfr_config =
-			(struct cam_isp_resource_hfr_config *)blob_data;
+		struct cam_isp_resource_hfr_config    *hfr_config;
+
+		if (blob_size < sizeof(struct cam_isp_resource_hfr_config)) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+			return -EINVAL;
+		}
+
+		hfr_config = (struct cam_isp_resource_hfr_config *)blob_data;
+
+		if (hfr_config->num_ports > CAM_ISP_IFE_OUT_RES_MAX) {
+			CAM_ERR(CAM_ISP, "Invalid num_ports %u in hfr config",
+				hfr_config->num_ports);
+			return -EINVAL;
+		}
+
+		if (blob_size < (sizeof(uint32_t) * 2 + hfr_config->num_ports *
+			sizeof(struct cam_isp_port_hfr_config))) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %u expected %u",
+				blob_size, sizeof(uint32_t) * 2 +
+				sizeof(struct cam_isp_port_hfr_config) *
+				hfr_config->num_ports);
+			return -EINVAL;
+		}
 
 		rc = cam_isp_blob_hfr_update(blob_type, blob_info,
 			hfr_config, prepare);
@@ -3535,8 +3603,29 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 	}
 		break;
 	case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG: {
-		struct cam_isp_clock_config    *clock_config =
-			(struct cam_isp_clock_config *)blob_data;
+		struct cam_isp_clock_config    *clock_config;
+
+		if (blob_size < sizeof(struct cam_isp_clock_config)) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+			return -EINVAL;
+		}
+
+		clock_config = (struct cam_isp_clock_config *)blob_data;
+
+		if (clock_config->num_rdi > CAM_IFE_RDI_NUM_MAX) {
+			CAM_ERR(CAM_ISP, "Invalid num_rdi %u in clock config",
+				clock_config->num_rdi);
+			return -EINVAL;
+		}
+
+		if (blob_size < (sizeof(uint32_t) * 2 + sizeof(uint64_t) *
+			(clock_config->num_rdi + 2))) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %u expected %u",
+				blob_size,
+				sizeof(uint32_t) * 2 + sizeof(uint64_t) *
+				(clock_config->num_rdi + 2));
+			return -EINVAL;
+		}
 
 		rc = cam_isp_blob_clock_update(blob_type, blob_info,
 			clock_config, prepare);
@@ -3545,10 +3634,31 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 	}
 		break;
 	case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: {
-		struct cam_isp_bw_config    *bw_config =
-			(struct cam_isp_bw_config *)blob_data;
+		struct cam_isp_bw_config    *bw_config;
 		struct cam_isp_prepare_hw_update_data   *prepare_hw_data;
 
+		if (blob_size < sizeof(struct cam_isp_bw_config)) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+			return -EINVAL;
+		}
+
+		bw_config = (struct cam_isp_bw_config *)blob_data;
+
+		if (bw_config->num_rdi > CAM_IFE_RDI_NUM_MAX) {
+			CAM_ERR(CAM_ISP, "Invalid num_rdi %u in bw config",
+				bw_config->num_rdi);
+			return -EINVAL;
+		}
+
+		if (blob_size < (sizeof(uint32_t) * 2 + (bw_config->num_rdi + 2)
+			* sizeof(struct cam_isp_bw_vote))) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %u expected %u",
+				blob_size,
+				sizeof(uint32_t) * 2 + (bw_config->num_rdi + 2)
+				* sizeof(struct cam_isp_bw_vote));
+			return -EINVAL;
+		}
+
 		if (!prepare || !prepare->priv ||
 			(bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) {
 			CAM_ERR(CAM_ISP, "Invalid inputs");
@@ -3566,8 +3676,29 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 	}
 		break;
 	case CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG: {
-		struct cam_ubwc_config *ubwc_config =
-			(struct cam_ubwc_config *)blob_data;
+		struct cam_ubwc_config *ubwc_config;
+
+		if (blob_size < sizeof(struct cam_ubwc_config)) {
+			CAM_ERR(CAM_ISP, "Invalid blob_size %u", blob_size);
+			return -EINVAL;
+		}
+
+		ubwc_config = (struct cam_ubwc_config *)blob_data;
+
+		if (ubwc_config->num_ports > CAM_ISP_IFE_OUT_RES_MAX) {
+			CAM_ERR(CAM_ISP, "Invalid num_ports %u in ubwc config",
+				ubwc_config->num_ports);
+			return -EINVAL;
+		}
+
+		if (blob_size < (sizeof(uint32_t) * 2 + ubwc_config->num_ports *
+			sizeof(struct cam_ubwc_plane_cfg_v1) * 2)) {
+			CAM_ERR(CAM_ISP, "Invalid blob_size %u expected %u",
+				blob_size,
+				sizeof(uint32_t) * 2 + ubwc_config->num_ports *
+				sizeof(struct cam_ubwc_plane_cfg_v1) * 2);
+			return -EINVAL;
+		}
 
 		rc = cam_isp_blob_ubwc_update(blob_type, blob_info,
 			ubwc_config, prepare);
@@ -3576,8 +3707,16 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 	}
 		break;
 	case CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG: {
-		struct cam_isp_csid_clock_config    *clock_config =
-			(struct cam_isp_csid_clock_config *)blob_data;
+		struct cam_isp_csid_clock_config    *clock_config;
+
+		if (blob_size < sizeof(struct cam_isp_csid_clock_config)) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %u expected %u",
+				blob_size,
+				sizeof(struct cam_isp_csid_clock_config));
+			return -EINVAL;
+		}
+
+		clock_config = (struct cam_isp_csid_clock_config *)blob_data;
 
 		rc = cam_isp_blob_csid_clock_update(blob_type, blob_info,
 			clock_config, prepare);
@@ -3586,8 +3725,16 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 	}
 		break;
 	case CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG: {
-		struct cam_fe_config *fe_config =
-			(struct cam_fe_config *)blob_data;
+		struct cam_fe_config *fe_config;
+
+		if (blob_size < sizeof(struct cam_fe_config)) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %u expected %u",
+				blob_size, sizeof(struct cam_fe_config));
+			return -EINVAL;
+		}
+
+		fe_config = (struct cam_fe_config *)blob_data;
+
 		rc = cam_isp_blob_fe_update(blob_type, blob_info,
 			fe_config, prepare);
 		if (rc)
@@ -3693,7 +3840,9 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
 			prepare, ctx->base[i].idx,
 			&kmd_buf, ctx->res_list_ife_out,
 			&ctx->res_list_ife_in_rd,
-			CAM_IFE_HW_OUT_RES_MAX, fill_fence);
+			CAM_IFE_HW_OUT_RES_MAX, fill_fence,
+			&ctx->res_bitmap,
+			fill_res_bitmap);
 
 		if (rc) {
 			CAM_ERR(CAM_ISP,
@@ -3734,7 +3883,8 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
 
 		/*Add reg update */
 		rc = cam_isp_add_reg_update(prepare, &ctx->res_list_ife_src,
-			ctx->base[i].idx, &kmd_buf);
+				ctx->base[i].idx, &kmd_buf, ctx->is_fe_enable,
+				ctx->res_bitmap);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
 				"Add Reg_update cmd Failed i=%d, idx=%d, rc=%d",
@@ -3742,6 +3892,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
 			goto end;
 		}
 	}
+	ctx->res_bitmap = 0;
 
 end:
 	return rc;
@@ -4261,6 +4412,8 @@ static int cam_ife_hw_mgr_get_err_type(
 
 	core_idx = evt_payload->core_index;
 	evt_payload->evt_id = CAM_ISP_HW_EVENT_ERROR;
+	evt_payload->enable_reg_dump =
+		g_ife_hw_mgr.debug_cfg.enable_reg_dump;
 
 	list_for_each_entry(isp_ife_camif_res,
 		&ife_hwr_mgr_ctx->res_list_ife_src, list) {
@@ -4348,6 +4501,9 @@ static int  cam_ife_hw_mgr_handle_camif_error(
 		error_event_data.error_type =
 				CAM_ISP_HW_ERROR_OVERFLOW;
 
+		error_event_data.enable_reg_dump =
+			g_ife_hw_mgr.debug_cfg.enable_reg_dump;
+
 		cam_ife_hw_mgr_find_affected_ctx(ife_hwr_mgr_ctx,
 			&error_event_data,
 			core_idx,
@@ -5325,6 +5481,14 @@ static int cam_ife_hw_mgr_debug_register(void)
 		goto err;
 	}
 
+	if (!debugfs_create_u32("enable_reg_dump",
+		0644,
+		g_ife_hw_mgr.debug_cfg.dentry,
+		&g_ife_hw_mgr.debug_cfg.enable_reg_dump)) {
+		CAM_ERR(CAM_ISP, "failed to create enable_reg_dump");
+		goto err;
+	}
+
 	if (!debugfs_create_file("ife_camif_debug",
 		0644,
 		g_ife_hw_mgr.debug_cfg.dentry, NULL,
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index 4560882..bf5f152 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.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
@@ -88,6 +88,7 @@ struct ctx_base_info {
  * @csid_debug:                csid debug information
  * @enable_recovery:           enable recovery
  * @enable_diag_sensor_status: enable sensor diagnosis status
+ * @enable_reg_dump:           enable register dump on error
  *
  */
 struct cam_ife_hw_mgr_debug {
@@ -95,6 +96,7 @@ struct cam_ife_hw_mgr_debug {
 	uint64_t       csid_debug;
 	uint32_t       enable_recovery;
 	uint32_t       camif_debug;
+	uint32_t       enable_reg_dump;
 };
 
 /**
@@ -131,6 +133,7 @@ struct cam_ife_hw_mgr_debug {
  * @config_done_complete    indicator for configuration complete
  * @init_done               indicate whether init hw is done
  * @is_fe_enable            indicate whether fetch engine\read path is enabled
+ * @res_bitmap              fill resource bitmap for which rup to be set
  */
 struct cam_ife_hw_mgr_ctx {
 	struct list_head                list;
@@ -167,6 +170,7 @@ struct cam_ife_hw_mgr_ctx {
 	struct completion               config_done_complete;
 	bool                            init_done;
 	bool                            is_fe_enable;
+	unsigned long                   res_bitmap;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
index b30a1f7..1b64913 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.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
@@ -451,7 +451,9 @@ int cam_isp_add_io_buffers(
 	struct cam_ife_hw_mgr_res            *res_list_isp_out,
 	struct list_head                     *res_list_ife_in_rd,
 	uint32_t                              size_isp_out,
-	bool                                  fill_fence)
+	bool                                  fill_fence,
+	unsigned long                         *res_bitmap,
+	cam_fill_res_bitmap                   fill_res_bitmap)
 {
 	int rc = 0;
 	uint64_t                            io_addr[CAM_PACKET_MAX_PLANES];
@@ -796,6 +798,8 @@ int cam_isp_add_io_buffers(
 			}
 			io_cfg_used_bytes += update_buf.cmd.used_bytes;
 		}
+
+		fill_res_bitmap(io_cfg[i].resource_type, res_bitmap);
 	}
 
 	CAM_DBG(CAM_ISP, "io_cfg_used_bytes %d, fill_fence %d",
@@ -834,13 +838,16 @@ int cam_isp_add_reg_update(
 	struct cam_hw_prepare_update_args    *prepare,
 	struct list_head                     *res_list_isp_src,
 	uint32_t                              base_idx,
-	struct cam_kmd_buf_info              *kmd_buf_info)
+	struct cam_kmd_buf_info              *kmd_buf_info,
+	bool                                  is_fe_en,
+	unsigned long                         res_bitmap)
 {
 	int rc = -EINVAL;
 	struct cam_isp_resource_node         *res;
 	struct cam_ife_hw_mgr_res            *hw_mgr_res;
 	struct cam_hw_update_entry           *hw_entry;
 	struct cam_isp_hw_get_cmd_update      get_regup;
+	struct cam_isp_hw_rup_data            rup_data;
 	uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size;
 
 	hw_entry = prepare->hw_update_entries;
@@ -886,6 +893,9 @@ int cam_isp_add_reg_update(
 			get_regup.cmd.size = kmd_buf_remain_size;
 			get_regup.cmd_type = CAM_ISP_HW_CMD_GET_REG_UPDATE;
 			get_regup.res = res;
+			rup_data.is_fe_enable = is_fe_en;
+			rup_data.res_bitmap = res_bitmap;
+			get_regup.rup_data = &rup_data;
 
 			rc = res->hw_intf->hw_ops.process_cmd(
 				res->hw_intf->hw_priv,
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
index 06f7829..806c2c6 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.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
@@ -126,6 +126,8 @@ int cam_isp_add_command_buffers(
  * @res_list_ife_in_rd:    IFE /VFE in rd resource list
  * @size_isp_out:          Size of the res_list_isp_out array
  * @fill_fence:            If true, Fence map table will be filled
+ * @res_bitmap             resource bitmap to be set for rup
+ * @fill_res_bitmap        callback function to set resource bitmap
  *
  * @return:                0 for success
  *                         -EINVAL for Fail
@@ -139,7 +141,9 @@ int cam_isp_add_io_buffers(
 	struct cam_ife_hw_mgr_res            *res_list_isp_out,
 	struct list_head                     *res_list_ife_in_rd,
 	uint32_t                              size_isp_out,
-	bool                                  fill_fence);
+	bool                                  fill_fence,
+	unsigned long                        *res_bitmap,
+	cam_fill_res_bitmap                   fill_res_bitmap);
 
 /*
  * cam_isp_add_reg_update()
@@ -152,6 +156,9 @@ int cam_isp_add_io_buffers(
  * @res_list_isp_src:      Resource list for IFE/VFE source
  * @base_idx:              Base or dev index of the IFE/VFE HW instance
  * @kmd_buf_info:          Kmd buffer to store the change base command
+ * @is_fe_enable           If fetch engine enable
+ * @res_bitmap             resource bitmap to be set for rup
+ *
  * @return:                0 for success
  *                         -EINVAL for Fail
  */
@@ -159,6 +166,8 @@ int cam_isp_add_reg_update(
 	struct cam_hw_prepare_update_args    *prepare,
 	struct list_head                     *res_list_isp_src,
 	uint32_t                              base_idx,
-	struct cam_kmd_buf_info              *kmd_buf_info);
+	struct cam_kmd_buf_info              *kmd_buf_info,
+	bool                                  is_fe_enable,
+	unsigned long                         res_bitmap);
 
 #endif /*_CAM_ISP_HW_PARSER_H */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
index 2510302..e9bcc98 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
@@ -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
@@ -19,6 +19,16 @@
 #include <uapi/media/cam_isp.h>
 #include "cam_hw_mgr_intf.h"
 
+/*
+ * bit position in resource bitmap
+ */
+#define CAM_IFE_REG_UPD_CMD_PIX_BIT     0
+#define CAM_IFE_REG_UPD_CMD_RDI0_BIT    1
+#define CAM_IFE_REG_UPD_CMD_RDI1_BIT    2
+#define CAM_IFE_REG_UPD_CMD_RDI2_BIT    3
+#define CAM_IFE_REG_UPD_CMD_RDI3_BIT    4
+#define CAM_IFE_REG_UPD_CMD_DUAL_PD_BIT 5
+
 /* MAX IFE instance */
 #define CAM_IFE_HW_NUM_MAX   4
 #define CAM_IFE_RDI_NUM_MAX  4
@@ -186,11 +196,13 @@ struct cam_isp_hw_eof_event_data {
  * @timestamp:             Timestamp for the error event
  * @recovery_enabled:      Identifies if the context needs to recover & reapply
  *                         this request
+ * @enable_reg_dump:       enable register dump
  */
 struct cam_isp_hw_error_event_data {
 	uint32_t             error_type;
 	uint64_t             timestamp;
 	bool                 recovery_enabled;
+	bool                 enable_reg_dump;
 };
 
 /* enum cam_isp_hw_mgr_command - Hardware manager command type */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index 58c136f..31e58a7 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -1059,7 +1059,7 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw  *csid_hw)
 	CAM_DBG(CAM_ISP, "CSID:%d init CSID HW",
 		csid_hw->hw_intf->hw_idx);
 
-	clk_lvl = cam_ife_csid_get_vote_level(soc_info, csid_hw->clk_rate);
+	clk_lvl = cam_soc_util_get_vote_level(soc_info, csid_hw->clk_rate);
 	CAM_DBG(CAM_ISP, "CSID clock lvl %u", clk_lvl);
 
 	rc = cam_ife_csid_enable_soc_resources(soc_info, clk_lvl);
@@ -1122,6 +1122,7 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw)
 	int rc = -EINVAL;
 	struct cam_hw_soc_info                   *soc_info;
 	const struct cam_ife_csid_reg_offset     *csid_reg;
+	unsigned long                             flags;
 
 	/* Check for refcount */
 	if (!csid_hw->hw_info->open_count) {
@@ -1156,6 +1157,9 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw)
 		CAM_ERR(CAM_ISP, "CSID:%d Disable CSID SOC failed",
 			csid_hw->hw_intf->hw_idx);
 
+	spin_lock_irqsave(&csid_hw->lock_state, flags);
+	csid_hw->device_enabled = 0;
+	spin_unlock_irqrestore(&csid_hw->lock_state, flags);
 	csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
 	csid_hw->error_irq_count = 0;
 
@@ -2611,6 +2615,7 @@ static int cam_ife_csid_init_hw(void *hw_priv,
 	struct cam_hw_info                     *csid_hw_info;
 	struct cam_isp_resource_node           *res;
 	const struct cam_ife_csid_reg_offset   *csid_reg;
+	unsigned long                           flags;
 
 	if (!hw_priv || !init_args ||
 		(arg_size != sizeof(struct cam_isp_resource_node))) {
@@ -2679,6 +2684,10 @@ static int cam_ife_csid_init_hw(void *hw_priv,
 
 	if (rc)
 		cam_ife_csid_disable_hw(csid_hw);
+
+	spin_lock_irqsave(&csid_hw->lock_state, flags);
+	csid_hw->device_enabled = 1;
+	spin_unlock_irqrestore(&csid_hw->lock_state, flags);
 end:
 	mutex_unlock(&csid_hw->hw_info->hw_mutex);
 	return rc;
@@ -3031,6 +3040,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
 	uint32_t val, irq_status_ppp = 0;
 	bool fatal_err_detected = false;
 	uint32_t sof_irq_debug_en = 0;
+	unsigned long flags;
 
 	csid_hw = (struct cam_ife_csid_hw *)data;
 
@@ -3096,67 +3106,74 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
 		complete(&csid_hw->csid_csi2_complete);
 	}
 
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 0 over flow",
-			 csid_hw->hw_intf->hw_idx);
-		fatal_err_detected = true;
+	spin_lock_irqsave(&csid_hw->lock_state, flags);
+	if (csid_hw->device_enabled == 1) {
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 0 over flow",
+				 csid_hw->hw_intf->hw_idx);
+			fatal_err_detected = true;
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 1 over flow",
+				 csid_hw->hw_intf->hw_idx);
+			fatal_err_detected = true;
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 2 over flow",
+				 csid_hw->hw_intf->hw_idx);
+			fatal_err_detected = true;
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 3 over flow",
+				 csid_hw->hw_intf->hw_idx);
+			fatal_err_detected = true;
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d TG OVER FLOW",
+				 csid_hw->hw_intf->hw_idx);
+			fatal_err_detected = true;
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP,
+				"CSID:%d CPHY_EOT_RECEPTION",
+				 csid_hw->hw_intf->hw_idx);
+			csid_hw->error_irq_count++;
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP,
+				"CSID:%d CPHY_SOT_RECEPTION",
+				 csid_hw->hw_intf->hw_idx);
+			csid_hw->error_irq_count++;
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC",
+				 csid_hw->hw_intf->hw_idx);
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_CRC) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC",
+				 csid_hw->hw_intf->hw_idx);
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_ECC) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC",
+				 csid_hw->hw_intf->hw_idx);
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d MMAPPED_VC_DT",
+				 csid_hw->hw_intf->hw_idx);
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP,
+				"CSID:%d ERROR_STREAM_UNDERFLOW",
+				 csid_hw->hw_intf->hw_idx);
+			csid_hw->error_irq_count++;
+		}
+		if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
+			CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME",
+				 csid_hw->hw_intf->hw_idx);
+			csid_hw->error_irq_count++;
+		}
 	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 1 over flow",
-			 csid_hw->hw_intf->hw_idx);
-		fatal_err_detected = true;
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 2 over flow",
-			 csid_hw->hw_intf->hw_idx);
-		fatal_err_detected = true;
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 3 over flow",
-			 csid_hw->hw_intf->hw_idx);
-		fatal_err_detected = true;
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d TG OVER FLOW",
-			 csid_hw->hw_intf->hw_idx);
-		fatal_err_detected = true;
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_EOT_RECEPTION",
-			 csid_hw->hw_intf->hw_idx);
-		csid_hw->error_irq_count++;
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_SOT_RECEPTION",
-			 csid_hw->hw_intf->hw_idx);
-		csid_hw->error_irq_count++;
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC",
-			 csid_hw->hw_intf->hw_idx);
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_CRC) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC",
-			 csid_hw->hw_intf->hw_idx);
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_ECC) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC",
-			 csid_hw->hw_intf->hw_idx);
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d MMAPPED_VC_DT",
-			 csid_hw->hw_intf->hw_idx);
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_STREAM_UNDERFLOW",
-			 csid_hw->hw_intf->hw_idx);
-		csid_hw->error_irq_count++;
-	}
-	if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME",
-			 csid_hw->hw_intf->hw_idx);
-		csid_hw->error_irq_count++;
-	}
+	spin_unlock_irqrestore(&csid_hw->lock_state, flags);
 
 	if (csid_hw->error_irq_count >
 		CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT) {
@@ -3407,9 +3424,11 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf  *csid_hw_intf,
 		ife_csid_hw->hw_intf->hw_type, csid_idx);
 
 
+	ife_csid_hw->device_enabled = 0;
 	ife_csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
 	mutex_init(&ife_csid_hw->hw_info->hw_mutex);
 	spin_lock_init(&ife_csid_hw->hw_info->hw_lock);
+	spin_lock_init(&ife_csid_hw->lock_state);
 	init_completion(&ife_csid_hw->hw_info->hw_complete);
 
 	init_completion(&ife_csid_hw->csid_top_complete);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
index 9a4a95d..3a093d2 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.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
@@ -494,6 +494,8 @@ struct cam_ife_csid_hw {
 	bool                             sof_irq_triggered;
 	uint32_t                         irq_debug_cnt;
 	uint32_t                         error_irq_count;
+	uint32_t                         device_enabled;
+	spinlock_t                       lock_state;
 };
 
 int cam_ife_csid_hw_probe_init(struct cam_hw_intf  *csid_hw_intf,
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
index 890dad3..5e02609 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_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
@@ -117,7 +117,7 @@ int cam_ife_csid_deinit_soc_resources(
 }
 
 int cam_ife_csid_enable_soc_resources(
-	struct cam_hw_soc_info *soc_info, uint32_t clk_lvl)
+	struct cam_hw_soc_info *soc_info, enum cam_vote_level clk_level)
 {
 	int rc = 0;
 	struct cam_csid_soc_private       *soc_private;
@@ -142,7 +142,7 @@ int cam_ife_csid_enable_soc_resources(
 	}
 
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
-		clk_lvl, true);
+		clk_level, true);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "enable platform failed");
 		goto stop_cpas;
@@ -235,24 +235,3 @@ int cam_ife_csid_disable_ife_force_clock_on(struct cam_hw_soc_info *soc_info,
 
 	return rc;
 }
-
-uint32_t cam_ife_csid_get_vote_level(struct cam_hw_soc_info *soc_info,
-	uint64_t clock_rate)
-{
-	int i = 0;
-
-	if (!clock_rate)
-		return CAM_SVS_VOTE;
-
-	for (i = 0; i < CAM_MAX_VOTE; i++) {
-		if (soc_info->clk_rate[i][soc_info->num_clk - 1] >=
-			clock_rate) {
-			CAM_DBG(CAM_ISP,
-				"Clock rate %lld, selected clock level %d",
-				clock_rate, i);
-			return i;
-		}
-	}
-
-	return CAM_TURBO_VOTE;
-}
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index 3f0cbf5..6154256 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.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
@@ -191,6 +191,20 @@ struct cam_isp_hw_get_wm_update {
 };
 
 /*
+ * struct cam_isp_hw_rup_data:
+ *
+ * @Brief:         RUP for required resources.
+ *
+ * @is_fe_enable   if fetch engine enabled
+ * @res_bitmap     resource bitmap for set resources
+ *
+ */
+struct cam_isp_hw_rup_data {
+	bool                            is_fe_enable;
+	unsigned long                   res_bitmap;
+};
+
+/*
  * struct cam_isp_hw_get_cmd_update:
  *
  * @Brief:         Get cmd buffer update for different CMD types
@@ -213,6 +227,7 @@ struct cam_isp_hw_get_cmd_update {
 		struct cam_isp_bw_config             *bw_update;
 		struct cam_ubwc_plane_cfg_v1         *ubwc_update;
 		struct cam_fe_config                 *fe_update;
+		struct cam_isp_hw_rup_data           *rup_data;
 	};
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
index 41ec8783..f60bf6e 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.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
@@ -232,6 +232,7 @@ struct cam_vfe_bw_control_args {
  * @irq_reg_val:             IRQ and Error register values, read when IRQ was
  *                           handled
  * @error_type:              Identify different errors
+ * @enable_reg_dump:         enable register dump on error
  * @ts:                      Timestamp
  */
 struct cam_vfe_top_irq_evt_payload {
@@ -241,6 +242,7 @@ struct cam_vfe_top_irq_evt_payload {
 	uint32_t                   evt_id;
 	uint32_t                   irq_reg_val[CAM_IFE_IRQ_REGISTERS_MAX];
 	uint32_t                   error_type;
+	bool                       enable_reg_dump;
 	struct cam_isp_timestamp   ts;
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
index 81426c1..b577626 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_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
@@ -106,7 +106,7 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
 		CAM_VFE_DSP_CLK_NAME, &soc_private->dsp_clk,
 		&soc_private->dsp_clk_index, &soc_private->dsp_clk_rate);
 	if (rc)
-		CAM_WARN(CAM_ISP, "option clk get failed");
+		CAM_WARN(CAM_ISP, "Option clk get failed with rc %d", rc);
 
 	rc = cam_vfe_request_platform_resource(soc_info, vfe_irq_handler,
 		irq_data);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h
index 88d5b13..61c1e9e 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.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
@@ -828,6 +828,12 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
 			.max_height    = -1,
 		},
 	},
+	.reg_data = {
+		.ubwc_10bit_threshold_lossy_0 = 0,
+		.ubwc_10bit_threshold_lossy_1 = 0,
+		.ubwc_8bit_threshold_lossy_0 = 0,
+		.ubwc_8bit_threshold_lossy_1 = 0,
+	},
 };
 
 struct cam_vfe_hw_info cam_vfe170_hw_info = {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
index d322b27..edb595e 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
@@ -225,54 +225,63 @@ static struct cam_irq_register_set vfe175_bus_irq_reg[3] = {
 
 static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
 	vfe175_ubwc_regs_client_3 = {
-	.tile_cfg         = 0x0000252C,
-	.h_init           = 0x00002530,
-	.v_init           = 0x00002534,
-	.meta_addr        = 0x00002538,
-	.meta_offset      = 0x0000253C,
-	.meta_stride      = 0x00002540,
-	.mode_cfg_0       = 0x00002544,
-	.mode_cfg_1       = 0x000025A4,
-	.bw_limit         = 0x000025A0,
+	.tile_cfg          = 0x0000252C,
+	.h_init            = 0x00002530,
+	.v_init            = 0x00002534,
+	.meta_addr         = 0x00002538,
+	.meta_offset       = 0x0000253C,
+	.meta_stride       = 0x00002540,
+	.mode_cfg_0        = 0x00002544,
+	.mode_cfg_1        = 0x000025A4,
+	.bw_limit          = 0x000025A0,
+	.threshlod_lossy_0 = 0x000025A8,
+	.threshlod_lossy_1 = 0x000025AC,
+
 };
 
 static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
 	vfe175_ubwc_regs_client_4 = {
-	.tile_cfg         = 0x0000262C,
-	.h_init           = 0x00002630,
-	.v_init           = 0x00002634,
-	.meta_addr        = 0x00002638,
-	.meta_offset      = 0x0000263C,
-	.meta_stride      = 0x00002640,
-	.mode_cfg_0       = 0x00002644,
-	.mode_cfg_1       = 0x000026A4,
-	.bw_limit         = 0x000026A0,
+	.tile_cfg          = 0x0000262C,
+	.h_init            = 0x00002630,
+	.v_init            = 0x00002634,
+	.meta_addr         = 0x00002638,
+	.meta_offset       = 0x0000263C,
+	.meta_stride       = 0x00002640,
+	.mode_cfg_0        = 0x00002644,
+	.mode_cfg_1        = 0x000026A4,
+	.bw_limit          = 0x000026A0,
+	.threshlod_lossy_0 = 0x000026A8,
+	.threshlod_lossy_1 = 0x000026AC,
 };
 
 static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
 	vfe175_ubwc_regs_client_20 = {
-	.tile_cfg         = 0x0000362C,
-	.h_init           = 0x00003630,
-	.v_init           = 0x00003634,
-	.meta_addr        = 0x00003638,
-	.meta_offset      = 0x0000363C,
-	.meta_stride      = 0x00003640,
-	.mode_cfg_0       = 0x00003644,
-	.mode_cfg_1       = 0x000036A4,
-	.bw_limit         = 0x000036A0,
+	.tile_cfg          = 0x0000362C,
+	.h_init            = 0x00003630,
+	.v_init            = 0x00003634,
+	.meta_addr         = 0x00003638,
+	.meta_offset       = 0x0000363C,
+	.meta_stride       = 0x00003640,
+	.mode_cfg_0        = 0x00003644,
+	.mode_cfg_1        = 0x000036A4,
+	.bw_limit          = 0x000036A0,
+	.threshlod_lossy_0 = 0x000036A8,
+	.threshlod_lossy_1 = 0x000036AC,
 };
 
 static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
 	vfe175_ubwc_regs_client_21 = {
-	.tile_cfg         = 0x0000372C,
-	.h_init           = 0x00003730,
-	.v_init           = 0x00003734,
-	.meta_addr        = 0x00003738,
-	.meta_offset      = 0x0000373C,
-	.meta_stride      = 0x00003740,
-	.mode_cfg_0       = 0x00003744,
-	.mode_cfg_1       = 0x000037A4,
-	.bw_limit         = 0x000037A0,
+	.tile_cfg          = 0x0000372C,
+	.h_init            = 0x00003730,
+	.v_init            = 0x00003734,
+	.meta_addr         = 0x00003738,
+	.meta_offset       = 0x0000373C,
+	.meta_stride       = 0x00003740,
+	.mode_cfg_0        = 0x00003744,
+	.mode_cfg_1        = 0x000037A4,
+	.bw_limit          = 0x000037A0,
+	.threshlod_lossy_0 = 0x000037A8,
+	.threshlod_lossy_1 = 0x000037AC,
 };
 
 static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = {
@@ -986,6 +995,12 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = {
 			.max_height    = 1080,
 		},
 	},
+	.reg_data = {
+		.ubwc_10bit_threshold_lossy_0 = 0x8330002,
+		.ubwc_10bit_threshold_lossy_1 = 0x20204,
+		.ubwc_8bit_threshold_lossy_0 = 0x6210022,
+		.ubwc_8bit_threshold_lossy_1 = 0xE0E,
+	},
 };
 
 struct cam_vfe_hw_info cam_vfe175_hw_info = {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
index df287b0..3ca5bec 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
@@ -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
@@ -289,54 +289,62 @@ static struct cam_irq_register_set vfe175_130_bus_irq_reg[3] = {
 
 static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
 	vfe175_130_ubwc_regs_client_3 = {
-	.tile_cfg         = 0x0000252C,
-	.h_init           = 0x00002530,
-	.v_init           = 0x00002534,
-	.meta_addr        = 0x00002538,
-	.meta_offset      = 0x0000253C,
-	.meta_stride      = 0x00002540,
-	.mode_cfg_0       = 0x00002544,
-	.mode_cfg_1       = 0x000025A4,
-	.bw_limit         = 0x000025A0,
+	.tile_cfg          = 0x0000252C,
+	.h_init            = 0x00002530,
+	.v_init            = 0x00002534,
+	.meta_addr         = 0x00002538,
+	.meta_offset       = 0x0000253C,
+	.meta_stride       = 0x00002540,
+	.mode_cfg_0        = 0x00002544,
+	.mode_cfg_1        = 0x000025A4,
+	.bw_limit          = 0x000025A0,
+	.threshlod_lossy_0 = 0x000025A8,
+	.threshlod_lossy_1 = 0x000025AC,
 };
 
 static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
 	vfe175_130_ubwc_regs_client_4 = {
-	.tile_cfg         = 0x0000262C,
-	.h_init           = 0x00002630,
-	.v_init           = 0x00002634,
-	.meta_addr        = 0x00002638,
-	.meta_offset      = 0x0000263C,
-	.meta_stride      = 0x00002640,
-	.mode_cfg_0       = 0x00002644,
-	.mode_cfg_1       = 0x000026A4,
-	.bw_limit         = 0x000026A0,
+	.tile_cfg          = 0x0000262C,
+	.h_init            = 0x00002630,
+	.v_init            = 0x00002634,
+	.meta_addr         = 0x00002638,
+	.meta_offset       = 0x0000263C,
+	.meta_stride       = 0x00002640,
+	.mode_cfg_0        = 0x00002644,
+	.mode_cfg_1        = 0x000026A4,
+	.bw_limit          = 0x000026A0,
+	.threshlod_lossy_0 = 0x000026A8,
+	.threshlod_lossy_1 = 0x000026AC,
 };
 
 static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
 	vfe175_130_ubwc_regs_client_20 = {
-	.tile_cfg         = 0x0000362C,
-	.h_init           = 0x00003630,
-	.v_init           = 0x00003634,
-	.meta_addr        = 0x00003638,
-	.meta_offset      = 0x0000363C,
-	.meta_stride      = 0x00003640,
-	.mode_cfg_0       = 0x00003644,
-	.mode_cfg_1       = 0x000036A4,
-	.bw_limit         = 0x000036A0,
+	.tile_cfg          = 0x0000362C,
+	.h_init            = 0x00003630,
+	.v_init            = 0x00003634,
+	.meta_addr         = 0x00003638,
+	.meta_offset       = 0x0000363C,
+	.meta_stride       = 0x00003640,
+	.mode_cfg_0        = 0x00003644,
+	.mode_cfg_1        = 0x000036A4,
+	.bw_limit          = 0x000036A0,
+	.threshlod_lossy_0 = 0x000036A8,
+	.threshlod_lossy_1 = 0x000036AC,
 };
 
 static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
 	vfe175_130_ubwc_regs_client_21 = {
-	.tile_cfg         = 0x0000372C,
-	.h_init           = 0x00003730,
-	.v_init           = 0x00003734,
-	.meta_addr        = 0x00003738,
-	.meta_offset      = 0x0000373C,
-	.meta_stride      = 0x00003740,
-	.mode_cfg_0       = 0x00003744,
-	.mode_cfg_1       = 0x000037A4,
-	.bw_limit         = 0x000037A0,
+	.tile_cfg          = 0x0000372C,
+	.h_init            = 0x00003730,
+	.v_init            = 0x00003734,
+	.meta_addr         = 0x00003738,
+	.meta_offset       = 0x0000373C,
+	.meta_stride       = 0x00003740,
+	.mode_cfg_0        = 0x00003744,
+	.mode_cfg_1        = 0x000037A4,
+	.bw_limit          = 0x000037A0,
+	.threshlod_lossy_0 = 0x000037A8,
+	.threshlod_lossy_1 = 0x000037AC,
 };
 
 static struct cam_vfe_bus_rd_ver1_hw_info vfe175_130_bus_rd_hw_info = {
@@ -1092,6 +1100,12 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = {
 			.max_height    = 1080,
 		},
 	},
+	.reg_data = {
+		.ubwc_10bit_threshold_lossy_0 = 0x8330002,
+		.ubwc_10bit_threshold_lossy_1 = 0x20204,
+		.ubwc_8bit_threshold_lossy_0 = 0x6210022,
+		.ubwc_8bit_threshold_lossy_1 = 0xE0E,
+	},
 };
 
 struct cam_vfe_hw_info cam_vfe175_130_hw_info = {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c
index 78e2a5c..0748ebb 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.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
@@ -90,9 +90,6 @@ struct cam_vfe_bus_rd_ver1_rm_resource_data {
 	void                *ctx;
 
 	uint32_t             irq_enabled;
-	bool                 init_cfg_done;
-	bool                 hfr_cfg_done;
-
 	uint32_t             offset;
 
 	uint32_t             min_vbi;
@@ -288,8 +285,6 @@ static int cam_vfe_bus_release_rm(void   *bus_priv,
 	rsrc_data->format = 0;
 	rsrc_data->unpacker_cfg = 0;
 	rsrc_data->burst_len = 0;
-	rsrc_data->init_cfg_done = false;
-	rsrc_data->hfr_cfg_done = false;
 	rsrc_data->en_cfg = 0;
 	rsrc_data->is_dual = 0;
 
@@ -366,8 +361,6 @@ static int cam_vfe_bus_stop_rm(struct cam_isp_resource_node *rm_res)
 		common_data->mem_base + rsrc_data->hw_regs->cfg);
 
 	rm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
-	rsrc_data->init_cfg_done = false;
-	rsrc_data->hfr_cfg_done = false;
 
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 7ee9f00..8ad4d96 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.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
@@ -103,6 +103,7 @@ struct cam_vfe_bus_ver2_common_data {
 	void                                       *bus_irq_controller;
 	void                                       *vfe_irq_controller;
 	struct cam_vfe_bus_ver2_reg_offset_common  *common_reg;
+	struct cam_vfe_bus_ver2_reg_data           *reg_data;
 	uint32_t                                    io_buf_update[
 		MAX_REG_VAL_PAIR_SIZE];
 
@@ -114,6 +115,7 @@ struct cam_vfe_bus_ver2_common_data {
 	uint32_t                                    secure_mode;
 	uint32_t                                    num_sec_out;
 	uint32_t                                    addr_no_sync;
+	uint32_t                                    camera_hw_version;
 };
 
 struct cam_vfe_bus_ver2_wm_resource_data {
@@ -123,8 +125,6 @@ struct cam_vfe_bus_ver2_wm_resource_data {
 	void                                *ctx;
 
 	uint32_t             irq_enabled;
-	bool                 init_cfg_done;
-	bool                 hfr_cfg_done;
 
 	uint32_t             offset;
 	uint32_t             width;
@@ -306,10 +306,10 @@ static int cam_vfe_bus_put_evt_payload(void     *core_info,
 static int cam_vfe_bus_ver2_get_intra_client_mask(
 	enum cam_vfe_bus_ver2_vfe_core_id  dual_slave_core,
 	enum cam_vfe_bus_ver2_vfe_core_id  current_core,
-	uint32_t                          *intra_client_mask)
+	uint32_t                          *intra_client_mask,
+	uint32_t camera_hw_version)
 {
 	int rc = 0;
-	uint32_t camera_hw_version = 0;
 	uint32_t version_based_intra_client_mask = 0x1;
 
 	*intra_client_mask = 0;
@@ -321,10 +321,6 @@ static int cam_vfe_bus_ver2_get_intra_client_mask(
 		return -EINVAL;
 	}
 
-	rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
-
-	CAM_DBG(CAM_ISP, "CPAS VERSION %d", camera_hw_version);
-
 	switch (camera_hw_version) {
 	case CAM_CPAS_TITAN_170_V100:
 		version_based_intra_client_mask = 0x3;
@@ -1130,8 +1126,6 @@ static int cam_vfe_bus_release_wm(void   *bus_priv,
 	rsrc_data->ubwc_mode_cfg_0 = 0;
 	rsrc_data->ubwc_mode_cfg_1 = 0;
 	rsrc_data->ubwc_meta_offset = 0;
-	rsrc_data->init_cfg_done = false;
-	rsrc_data->hfr_cfg_done = false;
 	rsrc_data->en_cfg = 0;
 	rsrc_data->is_dual = 0;
 
@@ -1149,7 +1143,7 @@ static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
 	struct cam_vfe_bus_ver2_common_data        *common_data =
 		rsrc_data->common_data;
 	uint32_t                   bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
-	uint32_t camera_hw_version;
+	uint32_t camera_hw_version = 0;
 
 	cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
 
@@ -1185,12 +1179,7 @@ static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
 
 	/* enable ubwc if needed*/
 	if (rsrc_data->en_ubwc) {
-		rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Failed to get HW version:%d rc:%d",
-				camera_hw_version, rc);
-			return rc;
-		}
+		camera_hw_version = rsrc_data->common_data->camera_hw_version;
 		if ((camera_hw_version > CAM_CPAS_TITAN_NONE) &&
 			(camera_hw_version < CAM_CPAS_TITAN_175_V100)) {
 			struct cam_vfe_bus_ver2_reg_offset_ubwc_client
@@ -1268,8 +1257,6 @@ static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
 			wm_res->irq_handle);
 
 	wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
-	rsrc_data->init_cfg_done = false;
-	rsrc_data->hfr_cfg_done = false;
 
 	return rc;
 }
@@ -1571,7 +1558,8 @@ static int cam_vfe_bus_acquire_comp_grp(
 			rc = cam_vfe_bus_ver2_get_intra_client_mask(
 				dual_slave_core,
 				comp_grp_local->hw_intf->hw_idx,
-				&rsrc_data->intra_client_mask);
+				&rsrc_data->intra_client_mask,
+				rsrc_data->common_data->camera_hw_version);
 			if (rc)
 				return rc;
 		} else {
@@ -2526,9 +2514,9 @@ static void cam_vfe_bus_update_ubwc_meta_addr(
 	uint32_t *reg_val_pair,
 	uint32_t  *j,
 	void     *regs,
-	uint64_t  image_buf)
+	uint64_t  image_buf,
+	uint32_t  camera_hw_version)
 {
-	uint32_t  camera_hw_version;
 	struct cam_vfe_bus_ver2_reg_offset_ubwc_client *ubwc_regs;
 	struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *ubwc_3_regs;
 	int rc = 0;
@@ -2539,11 +2527,7 @@ static void cam_vfe_bus_update_ubwc_meta_addr(
 		goto end;
 	}
 
-	rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
-	if (rc) {
-		CAM_ERR(CAM_ISP, "Failed to get HW version rc: %d", rc);
-		goto end;
-	} else if ((camera_hw_version < CAM_CPAS_TITAN_170_V100) ||
+	if ((camera_hw_version < CAM_CPAS_TITAN_170_V100) ||
 		(camera_hw_version > CAM_CPAS_TITAN_175_V120)) {
 		CAM_ERR(CAM_ISP, "Invalid HW version: %d",
 			camera_hw_version);
@@ -2582,7 +2566,9 @@ static int cam_vfe_bus_update_ubwc_3_regs(
 	uint32_t *reg_val_pair,	uint32_t i, uint32_t *j)
 {
 	struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *ubwc_regs;
+	struct cam_vfe_bus_ver2_reg_data           *reg_data;
 	uint32_t ubwc_bw_limit = 0;
+	uint32_t camera_hw_version = 0;
 	int rc = 0;
 
 	if (!wm_data || !reg_val_pair || !j) {
@@ -2593,6 +2579,7 @@ static int cam_vfe_bus_update_ubwc_3_regs(
 
 	ubwc_regs = (struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *)
 		wm_data->hw_regs->ubwc_regs;
+	reg_data = wm_data->common_data->reg_data;
 
 	CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
 		wm_data->hw_regs->packer_cfg, wm_data->packer_cfg);
@@ -2663,6 +2650,39 @@ static int cam_vfe_bus_update_ubwc_3_regs(
 			wm_data->index, ubwc_bw_limit);
 	}
 
+	camera_hw_version = wm_data->common_data->camera_hw_version;
+	if (camera_hw_version == CAM_CPAS_TITAN_175_V120) {
+		switch (wm_data->format) {
+		case CAM_FORMAT_UBWC_TP10:
+		case CAM_FORMAT_UBWC_P010:
+			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
+				ubwc_regs->threshlod_lossy_0,
+				reg_data->ubwc_10bit_threshold_lossy_0);
+			CAM_DBG(CAM_ISP, "WM %d threshlod_lossy_0 0x%x",
+				wm_data->index, reg_val_pair[*j-1]);
+
+			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
+				ubwc_regs->threshlod_lossy_1,
+				reg_data->ubwc_10bit_threshold_lossy_1);
+			CAM_DBG(CAM_ISP, "WM %d threshlod_lossy_1 0x%x",
+				wm_data->index, reg_val_pair[*j-1]);
+			break;
+		default:
+			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
+				ubwc_regs->threshlod_lossy_0,
+				reg_data->ubwc_8bit_threshold_lossy_0);
+			CAM_DBG(CAM_ISP, "WM %d threshlod_lossy_0 0x%x",
+				wm_data->index, reg_val_pair[*j-1]);
+
+			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
+				ubwc_regs->threshlod_lossy_1,
+				reg_data->ubwc_8bit_threshold_lossy_1);
+			CAM_DBG(CAM_ISP, "WM %d threshlod_lossy_1 0x%x",
+				wm_data->index, reg_val_pair[*j-1]);
+			break;
+		}
+	}
+
 end:
 	return rc;
 }
@@ -2866,8 +2886,7 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
 				io_cfg->planes[i].plane_stride,
 				val);
 
-		if ((wm_data->stride != val ||
-			!wm_data->init_cfg_done) && (wm_data->index >= 3)) {
+		if (wm_data->index >= 3) {
 			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
 				wm_data->hw_regs->stride,
 				io_cfg->planes[i].plane_stride);
@@ -2882,17 +2901,16 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
 					"No UBWC register to configure.");
 				return -EINVAL;
 			}
-			if (wm_data->ubwc_updated) {
-				wm_data->ubwc_updated = false;
-				cam_vfe_bus_update_ubwc_regs(
-					wm_data, reg_val_pair, i, &j);
-			}
+
+			cam_vfe_bus_update_ubwc_regs(
+				wm_data, reg_val_pair, i, &j);
 
 			/* UBWC meta address */
 			cam_vfe_bus_update_ubwc_meta_addr(
 				reg_val_pair, &j,
 				wm_data->hw_regs->ubwc_regs,
-				update_buf->wm_update->image_buf[i]);
+				update_buf->wm_update->image_buf[i],
+				wm_data->common_data->camera_hw_version);
 			CAM_DBG(CAM_ISP, "WM %d ubwc meta addr 0x%llx",
 				wm_data->index,
 				update_buf->wm_update->image_buf[i]);
@@ -2946,9 +2964,6 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
 			wm_data->hw_regs->cfg,
 			wm_data->en_cfg);
 
-		/* set initial configuration done */
-		if (!wm_data->init_cfg_done)
-			wm_data->init_cfg_done = true;
 	}
 
 	size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
@@ -3012,52 +3027,36 @@ static int cam_vfe_bus_update_hfr(void *priv, void *cmd_args,
 			return -EINVAL;
 		}
 
-		if ((wm_data->framedrop_pattern !=
-			hfr_cfg->framedrop_pattern) ||
-			!wm_data->hfr_cfg_done) {
-			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
-				wm_data->hw_regs->framedrop_pattern,
-				hfr_cfg->framedrop_pattern);
-			wm_data->framedrop_pattern = hfr_cfg->framedrop_pattern;
-			CAM_DBG(CAM_ISP, "WM %d framedrop pattern 0x%x",
-				wm_data->index, wm_data->framedrop_pattern);
-		}
+		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+			wm_data->hw_regs->framedrop_pattern,
+			hfr_cfg->framedrop_pattern);
+		wm_data->framedrop_pattern = hfr_cfg->framedrop_pattern;
+		CAM_DBG(CAM_ISP, "WM %d framedrop pattern 0x%x",
+			wm_data->index, wm_data->framedrop_pattern);
 
-		if (wm_data->framedrop_period != hfr_cfg->framedrop_period ||
-			!wm_data->hfr_cfg_done) {
-			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
-				wm_data->hw_regs->framedrop_period,
-				hfr_cfg->framedrop_period);
-			wm_data->framedrop_period = hfr_cfg->framedrop_period;
-			CAM_DBG(CAM_ISP, "WM %d framedrop period 0x%x",
-				wm_data->index, wm_data->framedrop_period);
-		}
+		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+			wm_data->hw_regs->framedrop_period,
+			hfr_cfg->framedrop_period);
+		wm_data->framedrop_period = hfr_cfg->framedrop_period;
+		CAM_DBG(CAM_ISP, "WM %d framedrop period 0x%x",
+			wm_data->index, wm_data->framedrop_period);
 
-		if (wm_data->irq_subsample_period != hfr_cfg->subsample_period
-			|| !wm_data->hfr_cfg_done) {
-			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
-				wm_data->hw_regs->irq_subsample_period,
-				hfr_cfg->subsample_period);
-			wm_data->irq_subsample_period =
-				hfr_cfg->subsample_period;
-			CAM_DBG(CAM_ISP, "WM %d irq subsample period 0x%x",
-				wm_data->index, wm_data->irq_subsample_period);
-		}
+		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+			wm_data->hw_regs->irq_subsample_period,
+			hfr_cfg->subsample_period);
+		wm_data->irq_subsample_period =
+			hfr_cfg->subsample_period;
+		CAM_DBG(CAM_ISP, "WM %d irq subsample period 0x%x",
+			wm_data->index, wm_data->irq_subsample_period);
 
-		if (wm_data->irq_subsample_pattern != hfr_cfg->subsample_pattern
-			|| !wm_data->hfr_cfg_done) {
-			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
-				wm_data->hw_regs->irq_subsample_pattern,
-				hfr_cfg->subsample_pattern);
-			wm_data->irq_subsample_pattern =
-				hfr_cfg->subsample_pattern;
-			CAM_DBG(CAM_ISP, "WM %d irq subsample pattern 0x%x",
-				wm_data->index, wm_data->irq_subsample_pattern);
-		}
+		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+			wm_data->hw_regs->irq_subsample_pattern,
+			hfr_cfg->subsample_pattern);
+		wm_data->irq_subsample_pattern =
+			hfr_cfg->subsample_pattern;
+		CAM_DBG(CAM_ISP, "WM %d irq subsample pattern 0x%x",
+			wm_data->index, wm_data->irq_subsample_pattern);
 
-		/* set initial configuration done */
-		if (!wm_data->hfr_cfg_done)
-			wm_data->hfr_cfg_done = true;
 	}
 
 	size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
@@ -3126,62 +3125,14 @@ static int cam_vfe_bus_update_ubwc_config(void *cmd_args)
 			goto end;
 		}
 
-		if (wm_data->packer_cfg !=
-			ubwc_plane_cfg->packer_config ||
-			!wm_data->init_cfg_done) {
-			wm_data->packer_cfg = ubwc_plane_cfg->packer_config;
-			wm_data->ubwc_updated = true;
-		}
-
-		if ((!wm_data->is_dual) && ((wm_data->tile_cfg !=
-			ubwc_plane_cfg->tile_config)
-			|| !wm_data->init_cfg_done)) {
-			wm_data->tile_cfg = ubwc_plane_cfg->tile_config;
-			wm_data->ubwc_updated = true;
-		}
-
-		if ((!wm_data->is_dual) && ((wm_data->h_init !=
-			ubwc_plane_cfg->h_init) ||
-			!wm_data->init_cfg_done)) {
-			wm_data->h_init = ubwc_plane_cfg->h_init;
-			wm_data->ubwc_updated = true;
-		}
-
-		if (wm_data->v_init != ubwc_plane_cfg->v_init ||
-			!wm_data->init_cfg_done) {
-			wm_data->v_init = ubwc_plane_cfg->v_init;
-			wm_data->ubwc_updated = true;
-		}
-
-		if (wm_data->ubwc_meta_stride !=
-			ubwc_plane_cfg->meta_stride ||
-			!wm_data->init_cfg_done) {
-			wm_data->ubwc_meta_stride = ubwc_plane_cfg->meta_stride;
-			wm_data->ubwc_updated = true;
-		}
-
-		if (wm_data->ubwc_mode_cfg_0 !=
-			ubwc_plane_cfg->mode_config_0 ||
-			!wm_data->init_cfg_done) {
-			wm_data->ubwc_mode_cfg_0 =
-				ubwc_plane_cfg->mode_config_0;
-			wm_data->ubwc_updated = true;
-		}
-
-		if (wm_data->ubwc_mode_cfg_1 !=
-			ubwc_plane_cfg->mode_config_1 ||
-			!wm_data->init_cfg_done) {
-			wm_data->ubwc_mode_cfg_1 =
-				ubwc_plane_cfg->mode_config_1;
-			wm_data->ubwc_updated = true;
-		}
-
-		if (wm_data->ubwc_meta_offset !=
-			ubwc_plane_cfg->meta_offset ||
-			!wm_data->init_cfg_done) {
-			wm_data->ubwc_meta_offset = ubwc_plane_cfg->meta_offset;
-			wm_data->ubwc_updated = true;
-		}
+		wm_data->packer_cfg = ubwc_plane_cfg->packer_config;
+		wm_data->tile_cfg = ubwc_plane_cfg->tile_config;
+		wm_data->h_init = ubwc_plane_cfg->h_init;
+		wm_data->v_init = ubwc_plane_cfg->v_init;
+		wm_data->ubwc_meta_stride = ubwc_plane_cfg->meta_stride;
+		wm_data->ubwc_mode_cfg_0 = ubwc_plane_cfg->mode_config_0;
+		wm_data->ubwc_mode_cfg_1 = ubwc_plane_cfg->mode_config_1;
+		wm_data->ubwc_meta_offset = ubwc_plane_cfg->meta_offset;
 	}
 
 end:
@@ -3268,24 +3219,27 @@ static int cam_vfe_bus_init_hw(void *hw_priv,
 		NULL,
 		NULL);
 
-	if (bus_priv->irq_handle <= 0) {
+	if ((int)bus_priv->irq_handle <= 0) {
 		CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
 		return -EFAULT;
 	}
 
-	bus_priv->error_irq_handle = cam_irq_controller_subscribe_irq(
-		bus_priv->common_data.bus_irq_controller,
-		CAM_IRQ_PRIORITY_0,
-		bus_error_irq_mask,
-		bus_priv,
-		cam_vfe_bus_error_irq_top_half,
-		cam_vfe_bus_err_bottom_half,
-		bus_priv->tasklet_info,
-		&tasklet_bh_api);
+	if (bus_priv->tasklet_info != NULL) {
+		bus_priv->error_irq_handle = cam_irq_controller_subscribe_irq(
+			bus_priv->common_data.bus_irq_controller,
+			CAM_IRQ_PRIORITY_0,
+			bus_error_irq_mask,
+			bus_priv,
+			cam_vfe_bus_error_irq_top_half,
+			cam_vfe_bus_err_bottom_half,
+			bus_priv->tasklet_info,
+			&tasklet_bh_api);
 
-	if (bus_priv->irq_handle <= 0) {
-		CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
-		return -EFAULT;
+		if ((int)bus_priv->error_irq_handle <= 0) {
+			CAM_ERR(CAM_ISP, "Failed to subscribe BUS error IRQ %d",
+				bus_priv->error_irq_handle);
+			return -EFAULT;
+		}
 	}
 
 	/*Set Debug Registers*/
@@ -3422,6 +3376,7 @@ int cam_vfe_bus_ver2_init(
 	struct cam_vfe_bus_ver2_priv    *bus_priv = NULL;
 	struct cam_vfe_bus              *vfe_bus_local;
 	struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
+	uint32_t camera_hw_version = 0;
 
 	CAM_DBG(CAM_ISP, "Enter");
 
@@ -3434,6 +3389,14 @@ int cam_vfe_bus_ver2_init(
 		goto end;
 	}
 
+	rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Failed to get HW version:%d rc:%d",
+			camera_hw_version, rc);
+		rc = -EINVAL;
+		goto end;
+	}
+
 	vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
 	if (!vfe_bus_local) {
 		CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus");
@@ -3460,8 +3423,10 @@ int cam_vfe_bus_ver2_init(
 	bus_priv->common_data.hw_intf            = hw_intf;
 	bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
 	bus_priv->common_data.common_reg         = &ver2_hw_info->common_reg;
+	bus_priv->common_data.reg_data           = &ver2_hw_info->reg_data;
 	bus_priv->common_data.addr_no_sync       =
 		CAM_VFE_BUS_ADDR_NO_SYNC_DEFAULT_VAL;
+	bus_priv->common_data.camera_hw_version = camera_hw_version;
 
 	mutex_init(&bus_priv->common_data.bus_mutex);
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
index 73b7eb2..39d8fa5 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.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
@@ -122,6 +122,8 @@ struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client {
 	uint32_t mode_cfg_0;
 	uint32_t mode_cfg_1;
 	uint32_t bw_limit;
+	uint32_t threshlod_lossy_0;
+	uint32_t threshlod_lossy_1;
 };
 
 
@@ -175,6 +177,19 @@ struct cam_vfe_bus_ver2_vfe_out_hw_info {
 };
 
 /*
+ * struct cam_vfe_bus_ver2_reg_data:
+ *
+ * @Brief:        Holds the bus register data
+ */
+
+struct cam_vfe_bus_ver2_reg_data {
+	uint32_t      ubwc_10bit_threshold_lossy_0;
+	uint32_t      ubwc_10bit_threshold_lossy_1;
+	uint32_t      ubwc_8bit_threshold_lossy_0;
+	uint32_t      ubwc_8bit_threshold_lossy_1;
+};
+
+/*
  * struct cam_vfe_bus_ver2_hw_info:
  *
  * @Brief:            HW register info for entire Bus
@@ -183,6 +198,7 @@ struct cam_vfe_bus_ver2_vfe_out_hw_info {
  * @bus_client_reg:   Bus client register info
  * @comp_reg_grp:     Composite group register info
  * @vfe_out_hw_info:  VFE output capability
+ * @reg_data:         bus register data;
  */
 struct cam_vfe_bus_ver2_hw_info {
 	struct cam_vfe_bus_ver2_reg_offset_common common_reg;
@@ -194,6 +210,7 @@ struct cam_vfe_bus_ver2_hw_info {
 	uint32_t num_out;
 	struct cam_vfe_bus_ver2_vfe_out_hw_info
 		vfe_out_hw_info[CAM_VFE_BUS_VER2_VFE_OUT_MAX];
+	struct cam_vfe_bus_ver2_reg_data  reg_data;
 };
 
 /*
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index a3a9d5e..13b588f 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.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
@@ -589,7 +589,8 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv,
 		}
 		break;
 	case CAM_ISP_HW_EVENT_ERROR:
-		if (irq_status1 & camif_priv->reg_data->error_irq_mask1) {
+		if (irq_status1 & camif_priv->reg_data->error_irq_mask1 &&
+			payload->enable_reg_dump) {
 			CAM_DBG(CAM_ISP, "Received ERROR\n");
 			ret = CAM_ISP_HW_ERROR_OVERFLOW;
 			cam_vfe_camif_reg_dump(camif_node->res_priv);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c
index cd17ea7..6f833b3 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.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
@@ -134,6 +134,14 @@ static int cam_vfe_fe_get_reg_update(
 		return -EINVAL;
 	}
 
+	if (cdm_args->rup_data->is_fe_enable &&
+		(cdm_args->rup_data->res_bitmap &
+			(1 << CAM_IFE_REG_UPD_CMD_RDI1_BIT))) {
+		CAM_DBG(CAM_ISP, "Avoiding rup_upd for fe");
+		cdm_args->cmd.used_bytes = 0;
+		return 0;
+	}
+
 	size = cdm_util_ops->cdm_required_size_reg_random(1);
 	/* since cdm returns dwords, we need to convert it into bytes */
 	if ((size * 4) > cdm_args->cmd.size) {
@@ -145,8 +153,8 @@ static int cam_vfe_fe_get_reg_update(
 	rsrc_data = fe_res->res_priv;
 	reg_val_pair[0] = rsrc_data->fe_reg->reg_update_cmd;
 	reg_val_pair[1] = rsrc_data->reg_data->reg_update_cmd_data;
-	CAM_DBG(CAM_ISP, "CAMIF reg_update_cmd 0x%x offset 0x%x",
-		reg_val_pair[1], reg_val_pair[0]);
+	CAM_DBG(CAM_ISP, "CAMIF res_id %d reg_update_cmd 0x%x offset 0x%x",
+		fe_res->res_id, reg_val_pair[1], reg_val_pair[0]);
 
 	cdm_util_ops->cdm_write_regrandom(cdm_args->cmd.cmd_buf_addr,
 		1, reg_val_pair);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
index 230698f..3f0beb1 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.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
@@ -64,6 +64,14 @@ static int cam_vfe_rdi_get_reg_update(
 		return -EINVAL;
 	}
 
+	if (cdm_args->rup_data->is_fe_enable &&
+		(cdm_args->rup_data->res_bitmap &
+			(1 << CAM_IFE_REG_UPD_CMD_PIX_BIT))) {
+		cdm_args->cmd.used_bytes = 0;
+		CAM_DBG(CAM_ISP, "Avoiding reg_upd for fe for rdi");
+		return 0;
+	}
+
 	rsrc_data = rdi_res->res_priv;
 	reg_val_pair[0] = rsrc_data->rdi_reg->reg_update_cmd;
 	reg_val_pair[1] = rsrc_data->reg_data->reg_update_cmd_data;
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
index e037a29..11e9069 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.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
@@ -167,13 +167,6 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
 			io_cfg[i].resource_type,
 			io_cfg[i].fence, io_cfg[i].format);
 
-		if ((num_in_buf > io_buf_size) ||
-			(num_out_buf > io_buf_size)) {
-			CAM_ERR(CAM_LRME, "Invalid number of buffers %d %d %d",
-				num_in_buf, num_out_buf, io_buf_size);
-			return -EINVAL;
-		}
-
 		memset(io_addr, 0, sizeof(io_addr));
 		for (plane = 0; plane < CAM_PACKET_MAX_PLANES; plane++) {
 			if (!io_cfg[i].mem_handle[plane])
@@ -201,6 +194,12 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
 
 		switch (io_cfg[i].direction) {
 		case CAM_BUF_INPUT: {
+			if (num_in_buf >= io_buf_size) {
+				CAM_ERR(CAM_LRME,
+					"Invalid number of buffers %d %d %d",
+					num_in_buf, num_out_buf, io_buf_size);
+				return -EINVAL;
+			}
 			prepare->in_map_entries[num_in_buf].resource_handle =
 				io_cfg[i].resource_type;
 			prepare->in_map_entries[num_in_buf].sync_id =
@@ -216,6 +215,12 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
 			break;
 		}
 		case CAM_BUF_OUTPUT: {
+			if (num_out_buf >= io_buf_size) {
+				CAM_ERR(CAM_LRME,
+					"Invalid number of buffers %d %d %d",
+					num_in_buf, num_out_buf, io_buf_size);
+				return -EINVAL;
+			}
 			prepare->out_map_entries[num_out_buf].resource_handle =
 				io_cfg[i].resource_type;
 			prepare->out_map_entries[num_out_buf].sync_id =
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
index e3104bd..aa8ed7d 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
@@ -433,6 +433,7 @@ static int cam_mem_util_get_dma_buf_fd(size_t len,
 	struct dma_buf **buf,
 	int *fd)
 {
+	struct dma_buf *dmabuf = NULL;
 	int rc = 0;
 
 	if (!buf || !fd) {
@@ -456,7 +457,11 @@ static int cam_mem_util_get_dma_buf_fd(size_t len,
 	 * when we close fd, refcount becomes 1 and when we do
 	 * dmap_put_buf, ref count becomes 0 and memory will be freed.
 	 */
-	dma_buf_get(*fd);
+	dmabuf = dma_buf_get(*fd);
+	if (IS_ERR_OR_NULL(dmabuf)) {
+		CAM_ERR(CAM_MEM, "dma_buf_get failed, *fd=%d", *fd);
+		rc = -EINVAL;
+	}
 
 	return rc;
 
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index bda29b6..4be4c6f 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -372,6 +372,30 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link,
 }
 
 /**
+ * __cam_req_mgr_check_for_lower_pd_devices()
+ *
+ * @brief    : Checks if there are any devices on the link having a lesser
+ *             pd than the max pd of the link
+ * @link     : Pointer to link which needs to be checked
+ *
+ * @return   : 0 if a lower pd device is found negative otherwise
+ */
+static int __cam_req_mgr_check_for_lower_pd_devices(
+	struct cam_req_mgr_core_link	*link)
+{
+	int i = 0;
+	struct cam_req_mgr_connected_device *dev = NULL;
+
+	for (i = 0; i < link->num_devs; i++) {
+		dev = &link->l_dev[i];
+		if (dev->dev_info.p_delay < link->max_delay)
+			return 0;
+	}
+
+	return -EAGAIN;
+}
+
+/**
  * __cam_req_mgr_check_next_req_slot()
  *
  * @brief    : While streaming if input queue does not contain any pending
@@ -379,11 +403,14 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link,
  *             devices with lower pipeline delay value.
  * @in_q     : Pointer to input queue where req mgr wil peep into
  *
+ * @return   : 0 for success, negative for failure
  */
-static void __cam_req_mgr_check_next_req_slot(
-	struct cam_req_mgr_req_queue *in_q)
+static int __cam_req_mgr_check_next_req_slot(
+	struct cam_req_mgr_core_link *link)
 {
-	int32_t                  idx = in_q->rd_idx;
+	int rc = 0;
+	struct cam_req_mgr_req_queue *in_q = link->req.in_q;
+	int32_t idx = in_q->rd_idx;
 	struct cam_req_mgr_slot *slot;
 
 	__cam_req_mgr_inc_idx(&idx, 1, in_q->num_slots);
@@ -393,12 +420,20 @@ static void __cam_req_mgr_check_next_req_slot(
 
 	/* Check if there is new req from CSL, if not complete req */
 	if (slot->status == CRM_SLOT_STATUS_NO_REQ) {
+		rc = __cam_req_mgr_check_for_lower_pd_devices(link);
+		if (rc) {
+			CAM_DBG(CAM_CRM, "No lower pd devices on link 0x%x",
+				link->link_hdl);
+			return rc;
+		}
 		__cam_req_mgr_in_q_skip_idx(in_q, idx);
 		if (in_q->wr_idx != idx)
 			CAM_WARN(CAM_CRM,
 				"CHECK here wr %d, rd %d", in_q->wr_idx, idx);
 		__cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots);
 	}
+
+	return rc;
 }
 
 /**
@@ -499,8 +534,6 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
 				continue;
 			}
 
-			trace_cam_req_mgr_apply_request(link, &apply_req, dev);
-
 			apply_req.trigger_point = trigger;
 			CAM_DBG(CAM_REQ,
 				"SEND: link_hdl: %x pd %d req_id %lld",
@@ -513,6 +546,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
 				if (pd == link->max_delay)
 					link->open_req_cnt--;
 			}
+			trace_cam_req_mgr_apply_request(link, &apply_req, dev);
 		}
 	}
 	if (rc < 0) {
@@ -644,7 +678,7 @@ static int __cam_req_mgr_check_sync_for_mslave(
 {
 	struct cam_req_mgr_core_link *sync_link = NULL;
 	struct cam_req_mgr_slot      *sync_slot = NULL;
-	int sync_slot_idx = 0, prev_idx, next_idx, rd_idx, rc = 0;
+	int sync_slot_idx = 0, prev_idx, next_idx, rd_idx, sync_rd_idx, rc = 0;
 	int64_t req_id = 0, sync_req_id = 0;
 
 	if (!link->sync_link) {
@@ -654,6 +688,7 @@ static int __cam_req_mgr_check_sync_for_mslave(
 
 	sync_link = link->sync_link;
 	req_id = slot->req_id;
+	sync_rd_idx = sync_link->req.in_q->rd_idx;
 
 	CAM_DBG(CAM_CRM,
 		"link_hdl %x req %lld frame_skip_flag %d open_req_cnt:%d initial_sync_req [%lld,%lld] is_master:%d",
@@ -670,6 +705,19 @@ static int __cam_req_mgr_check_sync_for_mslave(
 		return -EAGAIN;
 	}
 
+	if (link->in_msync_mode &&
+		sync_link->in_msync_mode &&
+		(req_id - sync_link->req.in_q->slot[sync_rd_idx].req_id >
+		link->max_delay - sync_link->max_delay)) {
+		CAM_DBG(CAM_CRM,
+			"Req: %lld on link:%x need to hold for link: %x req:%d",
+			req_id,
+			link->link_hdl,
+			sync_link->link_hdl,
+			sync_link->req.in_q->slot[sync_rd_idx].req_id);
+		return -EINVAL;
+	}
+
 	if (link->is_master) {
 		rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
 		if (rc) {
@@ -941,6 +989,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 	uint32_t trigger)
 {
 	int                                  rc = 0, idx;
+	int                                  reset_step = 0;
 	struct cam_req_mgr_slot             *slot = NULL;
 	struct cam_req_mgr_req_queue        *in_q;
 	struct cam_req_mgr_core_session     *session;
@@ -1008,8 +1057,10 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 					link->link_hdl);
 				link->in_msync_mode = false;
 				link->initial_sync_req = -1;
-				if (link->sync_link)
+				if (link->sync_link) {
 					link->sync_link->initial_sync_req = -1;
+					link->sync_link->in_msync_mode = false;
+				}
 			}
 
 			rc = __cam_req_mgr_inject_delay(link->req.l_tbl,
@@ -1071,8 +1122,15 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 				slot->req_id,
 				link->link_hdl);
 			idx = in_q->rd_idx;
+			reset_step = link->max_delay;
+			if (link->sync_link) {
+				if ((link->in_msync_mode) &&
+					(link->sync_link->is_master))
+					reset_step =
+						link->sync_link->max_delay;
+			}
 			__cam_req_mgr_dec_idx(
-				&idx, link->max_delay + 1,
+				&idx, reset_step + 1,
 				in_q->num_slots);
 			__cam_req_mgr_reset_req_slot(link, idx);
 		}
@@ -1762,6 +1820,8 @@ int cam_req_mgr_process_sched_req(void *priv, void *data)
 			link->initial_sync_req = slot->req_id;
 	} else {
 		link->initial_sync_req = -1;
+		if (link->sync_link)
+			link->sync_link->initial_sync_req = -1;
 	}
 
 	mutex_unlock(&link->req.lock);
@@ -2022,12 +2082,20 @@ static int cam_req_mgr_process_trigger(void *priv, void *data)
 		 */
 		CAM_DBG(CAM_CRM, "link[%x] Req[%lld] invalidating slot",
 			link->link_hdl, in_q->slot[in_q->rd_idx].req_id);
-		__cam_req_mgr_check_next_req_slot(in_q);
+		rc = __cam_req_mgr_check_next_req_slot(link);
+		if (rc) {
+			CAM_DBG(CAM_REQ,
+				"No pending req to apply to lower pd devices");
+			rc = 0;
+			goto release_lock;
+		}
 		__cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots);
 	}
-	rc = __cam_req_mgr_process_req(link, trigger_data->trigger);
-	mutex_unlock(&link->req.lock);
 
+	rc = __cam_req_mgr_process_req(link, trigger_data->trigger);
+
+release_lock:
+	mutex_unlock(&link->req.lock);
 end:
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
index b0e8107..ed88282 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
@@ -892,20 +892,39 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
 
 	soc_info = &cci_dev->soc_info;
 	base = soc_info->reg_map[0].mem_base;
-	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
 
-	/*
-	 * Todo: If there is a change in frequency of operation
-	 * Wait for previos transaction to complete
-	 */
+	mutex_lock(&cci_dev->cci_master_info[master].mutex);
+	if (cci_dev->cci_master_info[master].is_first_req == true) {
+		cci_dev->cci_master_info[master].is_first_req = false;
+		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+			master, cci_dev->i2c_freq_mode[master],
+			c_ctrl->cci_info->i2c_freq_mode);
+		down(&cci_dev->cci_master_info[master].master_sem);
+	} else if (c_ctrl->cci_info->i2c_freq_mode
+		!= cci_dev->i2c_freq_mode[master]) {
+		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+			master, cci_dev->i2c_freq_mode[master],
+			c_ctrl->cci_info->i2c_freq_mode);
+		down(&cci_dev->cci_master_info[master].master_sem);
+	} else {
+		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+			master, cci_dev->i2c_freq_mode[master],
+			c_ctrl->cci_info->i2c_freq_mode);
+		spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+		cci_dev->cci_master_info[master].freq_ref_cnt++;
+		spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
+	}
 
 	/* Set the I2C Frequency */
 	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
 	if (rc < 0) {
 		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
-		goto rel_mutex;
+		mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+		goto rel_master;
 	}
+	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 
+	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
 	/*
 	 * Call validate queue to make sure queue is empty before starting.
 	 * If this call fails, don't proceed with i2c_read call. This is to
@@ -916,24 +935,24 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
 		master, queue);
 	if (rc < 0) {
 		CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
 		CAM_ERR(CAM_CCI, "More than max retries");
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	if (read_cfg->data == NULL) {
 		CAM_ERR(CAM_CCI, "Data ptr is NULL");
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
 		CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
 			read_cfg->addr_type);
 		rc = -EINVAL;
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
@@ -945,14 +964,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	val = CCI_I2C_LOCK_CMD;
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
@@ -964,21 +983,21 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	val = CCI_I2C_UNLOCK_CMD;
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
@@ -1009,7 +1028,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
 			cam_cci_dump_registers(cci_dev, master, queue);
 #endif
 			cam_cci_flush_queue(cci_dev, master);
-			goto rel_mutex;
+			goto rel_mutex_q;
 		}
 
 		read_words = cam_io_r_mb(base +
@@ -1090,7 +1109,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
 						master, queue);
 				#endif
 					cam_cci_flush_queue(cci_dev, master);
-				goto rel_mutex;
+				goto rel_mutex_q;
 			}
 			break;
 		}
@@ -1099,8 +1118,15 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
 	CAM_DBG(CAM_CCI, "Burst read successful words_read %d",
 		total_read_words);
 
-rel_mutex:
+rel_mutex_q:
 	mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
+rel_master:
+	spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+	if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
+		up(&cci_dev->cci_master_info[master].master_sem);
+	else
+		cci_dev->cci_master_info[master].freq_ref_cnt--;
+	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
 	return rc;
 }
 
@@ -1132,20 +1158,38 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
 	soc_info = &cci_dev->soc_info;
 	base = soc_info->reg_map[0].mem_base;
 
-	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
-
-	/*
-	 * Todo: If there is a change in frequency of operation
-	 * Wait for previos transaction to complete
-	 */
+	mutex_lock(&cci_dev->cci_master_info[master].mutex);
+	if (cci_dev->cci_master_info[master].is_first_req == true) {
+		cci_dev->cci_master_info[master].is_first_req = false;
+		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+			master, cci_dev->i2c_freq_mode[master],
+			c_ctrl->cci_info->i2c_freq_mode);
+		down(&cci_dev->cci_master_info[master].master_sem);
+	} else if (c_ctrl->cci_info->i2c_freq_mode
+		!= cci_dev->i2c_freq_mode[master]) {
+		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+			master, cci_dev->i2c_freq_mode[master],
+			c_ctrl->cci_info->i2c_freq_mode);
+		down(&cci_dev->cci_master_info[master].master_sem);
+	} else {
+		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+			master, cci_dev->i2c_freq_mode[master],
+			c_ctrl->cci_info->i2c_freq_mode);
+		spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+		cci_dev->cci_master_info[master].freq_ref_cnt++;
+		spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
+	}
 
 	/* Set the I2C Frequency */
 	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
 	if (rc < 0) {
+		mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
-		goto rel_mutex;
+		goto rel_master;
 	}
+	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 
+	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
 	/*
 	 * Call validate queue to make sure queue is empty before starting.
 	 * If this call fails, don't proceed with i2c_read call. This is to
@@ -1156,17 +1200,17 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
 		master, queue);
 	if (rc < 0) {
 		CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
 		CAM_ERR(CAM_CCI, "More than max retries");
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	if (read_cfg->data == NULL) {
 		CAM_ERR(CAM_CCI, "Data ptr is NULL");
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	CAM_DBG(CAM_CCI, "master %d, queue %d", master, queue);
@@ -1179,21 +1223,21 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	val = CCI_I2C_LOCK_CMD;
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
 		CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
 			read_cfg->addr_type);
 		rc = -EINVAL;
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
@@ -1205,21 +1249,21 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	val = CCI_I2C_UNLOCK_CMD;
 	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
 	if (rc < 0) {
 		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 
 	val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
@@ -1247,7 +1291,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
 			"wait_for_completion_timeout rc = %d FIFO buf_lvl: 0x%x",
 			rc, val);
 		cam_cci_flush_queue(cci_dev, master);
-		goto rel_mutex;
+		goto rel_mutex_q;
 	} else {
 		rc = 0;
 	}
@@ -1260,7 +1304,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
 			read_words, exp_words);
 		memset(read_cfg->data, 0, read_cfg->num_byte);
 		rc = -EINVAL;
-		goto rel_mutex;
+		goto rel_mutex_q;
 	}
 	index = 0;
 	CAM_DBG(CAM_CCI, "index %d num_type %d", index, read_cfg->num_byte);
@@ -1284,8 +1328,15 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
 		}
 		read_words--;
 	}
-rel_mutex:
+rel_mutex_q:
 	mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
+rel_master:
+	spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+	if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
+		up(&cci_dev->cci_master_info[master].master_sem);
+	else
+		cci_dev->cci_master_info[master].freq_ref_cnt--;
+	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
 	return rc;
 }
 
@@ -1309,12 +1360,36 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
 		c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
 		c_ctrl->cci_info->id_map);
 
+	mutex_lock(&cci_dev->cci_master_info[master].mutex);
+	if (cci_dev->cci_master_info[master].is_first_req == true) {
+		cci_dev->cci_master_info[master].is_first_req = false;
+		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+			master, cci_dev->i2c_freq_mode[master],
+			c_ctrl->cci_info->i2c_freq_mode);
+		down(&cci_dev->cci_master_info[master].master_sem);
+	} else if (c_ctrl->cci_info->i2c_freq_mode
+		!= cci_dev->i2c_freq_mode[master]) {
+		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+			master, cci_dev->i2c_freq_mode[master],
+			c_ctrl->cci_info->i2c_freq_mode);
+		down(&cci_dev->cci_master_info[master].master_sem);
+	} else {
+		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+			master, cci_dev->i2c_freq_mode[master],
+			c_ctrl->cci_info->i2c_freq_mode);
+		spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+		cci_dev->cci_master_info[master].freq_ref_cnt++;
+		spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
+	}
+
 	/* Set the I2C Frequency */
 	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
 	if (rc < 0) {
 		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
-		return rc;
+		mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+		goto ERROR;
 	}
+	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
 	/*
 	 * Call validate queue to make sure queue is empty before starting.
 	 * If this call fails, don't proceed with i2c_write call. This is to
@@ -1326,18 +1401,25 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
 	if (rc < 0) {
 		CAM_ERR(CAM_CCI, "Initial validataion failed rc %d",
 			rc);
-		return rc;
+		goto ERROR;
 	}
 	if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
 		CAM_ERR(CAM_CCI, "More than max retries");
-		return rc;
+		goto ERROR;
 	}
 	rc = cam_cci_data_queue(cci_dev, c_ctrl, queue, sync_en);
 	if (rc < 0) {
 		CAM_ERR(CAM_CCI, "failed rc: %d", rc);
-		return rc;
+		goto ERROR;
 	}
 
+ERROR:
+	spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+	if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
+		up(&cci_dev->cci_master_info[master].master_sem);
+	else
+		cci_dev->cci_master_info[master].freq_ref_cnt--;
+	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h
index 12abeab..83c935b 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h
@@ -26,6 +26,7 @@
 #include <linux/timer.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/semaphore.h>
 #include <media/cam_sensor.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-ioctl.h>
@@ -144,6 +145,10 @@ struct cam_cci_master_info {
 	struct completion report_q[NUM_QUEUES];
 	atomic_t done_pending[NUM_QUEUES];
 	spinlock_t lock_q[NUM_QUEUES];
+	spinlock_t freq_cnt;
+	struct semaphore master_sem;
+	bool is_first_req;
+	uint16_t freq_ref_cnt;
 };
 
 struct cam_cci_clk_params_t {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
index da714af..cd17e29 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
@@ -196,7 +196,10 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev)
 
 	for (i = 0; i < NUM_MASTERS; i++) {
 		new_cci_dev->cci_master_info[i].status = 0;
+		new_cci_dev->cci_master_info[i].is_first_req = true;
 		mutex_init(&new_cci_dev->cci_master_info[i].mutex);
+		sema_init(&new_cci_dev->cci_master_info[i].master_sem, 1);
+		spin_lock_init(&new_cci_dev->cci_master_info[i].freq_cnt);
 		init_completion(
 			&new_cci_dev->cci_master_info[i].reset_complete);
 		init_completion(
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
index a16fb88..945910e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
@@ -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
@@ -20,7 +20,7 @@ struct csiphy_reg_parms_t csiphy_v1_2 = {
 	.mipi_csiphy_interrupt_clear0_addr = 0x858,
 	.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
 	.csiphy_common_array_size = 4,
-	.csiphy_reset_array_size = 4,
+	.csiphy_reset_array_size = 5,
 	.csiphy_2ph_config_array_size = 21,
 	.csiphy_3ph_config_array_size = 31,
 	.csiphy_2ph_clock_lane = 0x1,
@@ -38,6 +38,7 @@ struct csiphy_reg_t csiphy_reset_reg_1_2[] = {
 	{0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE},
 	{0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
 	{0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
 	{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h
index 8d7a5b58..b7345d4 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h
@@ -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
@@ -19,8 +19,8 @@ struct csiphy_reg_parms_t csiphy_v2_0 = {
 	.mipi_csiphy_interrupt_status0_addr = 0x8B0,
 	.mipi_csiphy_interrupt_clear0_addr = 0x858,
 	.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
-	.csiphy_common_array_size = 6,
-	.csiphy_reset_array_size = 3,
+	.csiphy_common_array_size = 8,
+	.csiphy_reset_array_size = 5,
 	.csiphy_2ph_config_array_size = 15,
 	.csiphy_3ph_config_array_size = 17,
 	.csiphy_2ph_clock_lane = 0x1,
@@ -31,6 +31,8 @@ struct csiphy_reg_t csiphy_common_reg_2_0[] = {
 	{0x0814, 0x00, 0x00, CSIPHY_LANE_ENABLE},
 	{0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
 	{0x081C, 0x06, 0x00, CSIPHY_3PH_REGS},
+	{0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
+	{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
 	{0x0164, 0x00, 0x00, CSIPHY_2PH_REGS},
 	{0x0364, 0x00, 0x00, CSIPHY_2PH_REGS},
 	{0x0564, 0x00, 0x00, CSIPHY_2PH_REGS},
@@ -40,6 +42,8 @@ struct csiphy_reg_t csiphy_reset_reg_2_0[] = {
 	{0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE},
 	{0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
 	{0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
+	{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
 };
 
 struct csiphy_reg_t csiphy_irq_reg_2_0[] = {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index b2ef241..faece70 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -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
@@ -912,7 +912,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
 	vfree(e_ctrl->cal_data.map);
 	e_ctrl->cal_data.num_data = 0;
 	e_ctrl->cal_data.num_map = 0;
-	e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
+	e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE;
 release_buf:
 	if (cam_mem_put_cpu_buf(dev_config.packet_handle))
 		CAM_WARN(CAM_EEPROM, "Put cpu buffer failed : 0x%x",
diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
index a5579a2..5fb5fea 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.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
@@ -1374,6 +1374,42 @@ int cam_smmu_dealloc_qdss(int32_t smmu_hdl)
 }
 EXPORT_SYMBOL(cam_smmu_dealloc_qdss);
 
+int cam_smmu_get_io_region_info(int32_t smmu_hdl,
+	dma_addr_t *iova, size_t *len)
+{
+	int32_t idx;
+
+	if (!iova || !len || (smmu_hdl == HANDLE_INIT)) {
+		CAM_ERR(CAM_SMMU, "Error: Input args are invalid");
+		return -EINVAL;
+	}
+
+	idx = GET_SMMU_TABLE_IDX(smmu_hdl);
+	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
+		CAM_ERR(CAM_SMMU,
+			"Error: handle or index invalid. idx = %d hdl = %x",
+			idx, smmu_hdl);
+		return -EINVAL;
+	}
+
+	if (!iommu_cb_set.cb_info[idx].io_support) {
+		CAM_ERR(CAM_SMMU,
+			"I/O memory not supported for this SMMU handle");
+		return -EINVAL;
+	}
+
+	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
+	*iova = iommu_cb_set.cb_info[idx].io_info.iova_start;
+	*len = iommu_cb_set.cb_info[idx].io_info.iova_len;
+
+	CAM_DBG(CAM_SMMU,
+		"I/O area for hdl = %x start addr = %pK len = %zu",
+		smmu_hdl, *iova, *len);
+	mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
+
+	return 0;
+}
+
 int cam_smmu_get_region_info(int32_t smmu_hdl,
 	enum cam_smmu_region_id region_id,
 	struct cam_smmu_region_info *region_info)
diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h
index 8aa80ac..6518641 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h
+++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.h
@@ -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
@@ -388,4 +388,16 @@ int cam_smmu_alloc_qdss(int32_t smmu_hdl,
  */
 int cam_smmu_dealloc_qdss(int32_t smmu_hdl);
 
+/**
+ * @brief Get start addr & len of I/O region for a given cb
+ *
+ * @param smmu_hdl: SMMU handle identifying the context bank
+ * @param iova: IOVA address of allocated I/O region
+ * @param len: Length of allocated I/O memory
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int cam_smmu_get_io_region_info(int32_t smmu_hdl,
+	dma_addr_t *iova, size_t *len);
+
 #endif /* _CAM_SMMU_API_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
index 7a772f1..d3f62d6 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.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
@@ -196,8 +196,8 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status)
 	if (row->state != CAM_SYNC_STATE_ACTIVE) {
 		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
 		CAM_ERR(CAM_SYNC,
-			"Error: Sync object already signaled sync_obj = %d",
-			sync_obj);
+			"Sync object already signaled sync_obj = %d state = %d",
+			sync_obj, row->state);
 		return -EALREADY;
 	}
 
@@ -322,9 +322,9 @@ int cam_sync_get_obj_ref(int32_t sync_obj)
 
 	if (row->state != CAM_SYNC_STATE_ACTIVE) {
 		spin_unlock(&sync_dev->row_spinlocks[sync_obj]);
-		CAM_ERR(CAM_SYNC,
-			"Error: accessing an uninitialized sync obj = %d",
-			sync_obj);
+		CAM_ERR_RATE_LIMIT_CUSTOM(CAM_SYNC, 1, 5,
+			"accessing an uninitialized sync obj = %d state = %d",
+			sync_obj, row->state);
 		return -EINVAL;
 	}
 
@@ -433,6 +433,7 @@ static int cam_sync_handle_create(struct cam_private_ioctl_arg *k_ioctl)
 
 static int cam_sync_handle_signal(struct cam_private_ioctl_arg *k_ioctl)
 {
+	int rc = 0;
 	struct cam_sync_signal sync_signal;
 
 	if (k_ioctl->size != sizeof(struct cam_sync_signal))
@@ -447,7 +448,14 @@ static int cam_sync_handle_signal(struct cam_private_ioctl_arg *k_ioctl)
 		return -EFAULT;
 
 	/* need to get ref for UMD signaled fences */
-	cam_sync_get_obj_ref(sync_signal.sync_obj);
+	rc = cam_sync_get_obj_ref(sync_signal.sync_obj);
+	if (rc) {
+		CAM_DBG(CAM_SYNC,
+			"Error: cannot signal an uninitialized sync obj = %d",
+			sync_signal.sync_obj);
+		return rc;
+	}
+
 	return cam_sync_signal(sync_signal.sync_obj,
 		sync_signal.sync_state);
 }
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 99db566..3fa92df 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
@@ -121,6 +121,27 @@ const char *cam_get_module_name(unsigned int module_id);
 		cam_get_module_name(__module), __func__,  __LINE__, ##args)
 
 /*
+ * CAM_INFO_RATE_LIMIT_CUSTOM
+ * @brief    :  This Macro will print info logs with custom ratelimit
+ *
+ * @__module :  Respective module id which is been calling this Macro
+ * @interval :  Time interval in seconds
+ * @burst    :  No of logs to print in interval time
+ * @fmt      :  Formatted string which needs to be print in log
+ * @args     :  Arguments which needs to be print in log
+ */
+#define CAM_INFO_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \
+	({								\
+		static DEFINE_RATELIMIT_STATE(_rs,			\
+			(interval * HZ),				\
+			burst);						\
+		if (__ratelimit(&_rs))					\
+			pr_info("CAM_INFO: %s: %s: %d " fmt "\n",	\
+				cam_get_module_name(__module), __func__,\
+				__LINE__, ##args);			\
+	})
+
+/*
  * CAM_DBG
  * @brief    :  This Macro will print debug logs when enabled using GROUP
  *
@@ -139,4 +160,25 @@ const char *cam_get_module_name(unsigned int module_id);
 	pr_err_ratelimited("CAM_ERR: %s: %s: %d " fmt "\n",            \
 		cam_get_module_name(__module), __func__,  __LINE__, ##args)
 
+/*
+ * CAM_ERR_RATE_LIMIT_CUSTOM
+ * @brief    :  This Macro will print error logs with custom ratelimit
+ *
+ * @__module :  Respective module id which is been calling this Macro
+ * @interval :  Time interval in seconds
+ * @burst    :  No of logs to print in interval time
+ * @fmt      :  Formatted string which needs to be print in log
+ * @args     :  Arguments which needs to be print in log
+ */
+#define CAM_ERR_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \
+	({								\
+		static DEFINE_RATELIMIT_STATE(_rs,			\
+			(interval * HZ),				\
+			burst);						\
+		if (__ratelimit(&_rs))					\
+			pr_err("CAM_ERR: %s: %s: %d " fmt "\n",		\
+				cam_get_module_name(__module), __func__,\
+				__LINE__, ##args);			\
+	})
+
 #endif /* _CAM_DEBUG_UTIL_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
index 797bab2..da8c6e3 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.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
@@ -109,7 +109,7 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
 	}
 
 	if ((packet->kmd_cmd_buf_index < 0) ||
-		(packet->kmd_cmd_buf_index > packet->num_cmd_buf)) {
+		(packet->kmd_cmd_buf_index >= packet->num_cmd_buf)) {
 		CAM_ERR(CAM_UTIL, "Invalid kmd buf index: %d",
 			packet->kmd_cmd_buf_index);
 		return -EINVAL;
@@ -131,7 +131,7 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
 
 	remain_len = len;
 	if (((size_t)cmd_desc->offset >= len) ||
-		((size_t)cmd_desc->size >= (len - (size_t)cmd_desc->offset))) {
+		((size_t)cmd_desc->size > (len - (size_t)cmd_desc->offset))) {
 		CAM_ERR(CAM_UTIL, "invalid memory len:%zd and cmd desc size:%d",
 			len, cmd_desc->size);
 		rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h
index 9418a3e..412eba5 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_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
@@ -37,6 +37,9 @@ struct cam_kmd_buf_info {
 typedef int (*cam_packet_generic_blob_handler)(void *user_data,
 	uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data);
 
+/* set resource bitmap callback function type */
+typedef void (*cam_fill_res_bitmap)(uint32_t res_type, unsigned long *bitmap);
+
 /**
  * cam_packet_util_get_cmd_mem_addr()
  *
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
index f51b9d8..f706a72 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.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
@@ -1718,3 +1718,24 @@ int cam_soc_util_reg_dump(struct cam_hw_soc_info *soc_info,
 	return 0;
 }
 
+uint32_t cam_soc_util_get_vote_level(struct cam_hw_soc_info *soc_info,
+	uint64_t clock_rate)
+{
+	int i = 0;
+
+	if (!clock_rate)
+		return CAM_SVS_VOTE;
+
+	for (i = 0; i < CAM_MAX_VOTE; i++) {
+		if (soc_info->clk_level_valid[i] &&
+			soc_info->clk_rate[i][soc_info->src_clk_idx] >=
+			clock_rate) {
+			CAM_DBG(CAM_UTIL,
+				"Clock rate %lld, selected clock level %d",
+				clock_rate, i);
+			return i;
+		}
+	}
+
+	return CAM_TURBO_VOTE;
+}
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index 0880572..0ee8445 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.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
@@ -631,4 +631,7 @@ void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info);
 int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info,
 	enum cam_vote_level clk_level);
 
+uint32_t cam_soc_util_get_vote_level(struct cam_hw_soc_info *soc_info,
+	uint64_t clock_rate);
+
 #endif /* _CAM_SOC_UTIL_H_ */
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index 7b62b06..43af2a5 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -934,6 +934,7 @@ int camera_init_v4l2(struct device *dev, unsigned int *session)
 	pvdev->vdev->ioctl_ops = &camera_v4l2_ioctl_ops;
 	pvdev->vdev->minor     = -1;
 	pvdev->vdev->vfl_type  = VFL_TYPE_GRABBER;
+	pvdev->vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 	rc = video_register_device(pvdev->vdev,
 		VFL_TYPE_GRABBER, -1);
 	if (WARN_ON(rc < 0))
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
index e43ff7d..0e2d419 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
@@ -121,6 +121,7 @@ struct cam_iommu_cb_set {
 	struct cam_context_bank_info *cb_info;
 	u32 cb_num;
 	u32 cb_init_count;
+	bool camera_secure_sid;
 	struct work_struct smmu_work;
 	struct mutex payload_list_lock;
 	struct list_head payload_list;
@@ -882,9 +883,7 @@ static int cam_smmu_attach_sec_cpp(int idx)
 		 * entered the secure mode.
 		 */
 	}
-
 	iommu_cb_set.cb_info[idx].state = CAM_SMMU_ATTACH;
-
 	return 0;
 }
 
@@ -921,34 +920,35 @@ static int cam_smmu_attach_sec_vfe_ns_stats(int idx)
 {
 	int32_t rc = 0;
 
-	/*
-	 *When switching to secure, for secure pix and non-secure stats
-	 *localizing scm/attach of non-secure SID's in attach secure
-	 */
-	if (cam_smmu_send_syscall_pix_intf(VMID_CP_CAMERA, idx)) {
-		pr_err("error: syscall failed\n");
-		return -EINVAL;
+	if (iommu_cb_set.camera_secure_sid == false) {
+		/*
+		 *When switching to secure, for secure pix and non-secure stats
+		 *localizing scm/attach of non-secure SID's in attach secure
+		 */
+		if (cam_smmu_send_syscall_pix_intf(VMID_CP_CAMERA, idx)) {
+			pr_err("error: syscall failed\n");
+			return -EINVAL;
+		}
 	}
-
 	if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) {
 		if (cam_smmu_attach(idx)) {
 			pr_err("error: failed to attach\n");
 			return -EINVAL;
 		}
 	}
-
-	rc = msm_camera_tz_set_mode(MSM_CAMERA_TZ_MODE_SECURE,
-		MSM_CAMERA_TZ_HW_BLOCK_ISP);
-	if (rc != 0) {
-		pr_err("secure mode TA notification for vfe unsuccessful, rc %d\n",
-			rc);
-		/*
-		 * Although the TA notification failed, the flow should proceed
-		 * without returning an error as at this point vfe had already
-		 * entered the secure mode
-		 */
+	if (iommu_cb_set.camera_secure_sid == false) {
+		rc = msm_camera_tz_set_mode(MSM_CAMERA_TZ_MODE_SECURE,
+			MSM_CAMERA_TZ_HW_BLOCK_ISP);
+		if (rc != 0) {
+			pr_err("secure mode TA notify vfe unsuccessful rc %d\n",
+				rc);
+			/*
+			 * Although the TA notification failed, the flow should
+			 * proceed without returning an error as at this point
+			 * vfe had already entered the secure mode
+			 */
+		}
 	}
-
 	return 0;
 }
 
@@ -956,18 +956,20 @@ static int cam_smmu_detach_sec_vfe_ns_stats(int idx)
 {
 	int32_t rc = 0;
 
-	rc = msm_camera_tz_set_mode(MSM_CAMERA_TZ_MODE_NON_SECURE,
-		MSM_CAMERA_TZ_HW_BLOCK_ISP);
-	if (rc != 0) {
-		pr_err("secure mode TA notification for vfe unsuccessful, rc %d\n",
-			rc);
-		/*
-		 * Although the TA notification failed, the flow should proceed
-		 * without returning an error, as at this point vfe is in secure
-		 * mode and should be switched to non-secure regardless
-		 */
+	if (iommu_cb_set.camera_secure_sid == false) {
+		rc = msm_camera_tz_set_mode(MSM_CAMERA_TZ_MODE_NON_SECURE,
+			MSM_CAMERA_TZ_HW_BLOCK_ISP);
+		if (rc != 0) {
+			pr_err("secure mode TA notify vfe unsuccessful rc %d\n",
+				rc);
+			/*
+			 * Although the TA notification failed, the flow should
+			 * proceed without returning an error, as at this point
+			 * vfe is in secure mode and should be switched to
+			 * non-secure regardless
+			 */
+		}
 	}
-
 	/*
 	 *While exiting from secure mode for secure pix and non-secure stats,
 	 *localizing detach/scm of non-secure SID's to detach secure
@@ -978,10 +980,11 @@ static int cam_smmu_detach_sec_vfe_ns_stats(int idx)
 			return -ENODEV;
 		}
 	}
-
-	if (cam_smmu_send_syscall_pix_intf(VMID_HLOS, idx)) {
-		pr_err("error: syscall failed\n");
-		return -EINVAL;
+	if (iommu_cb_set.camera_secure_sid == false) {
+		if (cam_smmu_send_syscall_pix_intf(VMID_HLOS, idx)) {
+			pr_err("error: syscall failed\n");
+			return -EINVAL;
+		}
 	}
 	return 0;
 }
@@ -1255,11 +1258,17 @@ int cam_smmu_ops(int handle, enum cam_smmu_ops_param ops)
 		break;
 	}
 	case CAM_SMMU_ATTACH_SEC_CPP: {
-		ret = cam_smmu_attach_sec_cpp(idx);
+		if (iommu_cb_set.camera_secure_sid == false)
+			ret = cam_smmu_attach_sec_cpp(idx);
+		else
+			iommu_cb_set.cb_info[idx].state = CAM_SMMU_ATTACH;
 		break;
 	}
 	case CAM_SMMU_DETACH_SEC_CPP: {
-		ret = cam_smmu_detach_sec_cpp(idx);
+		if (iommu_cb_set.camera_secure_sid == false)
+			ret = cam_smmu_detach_sec_cpp(idx);
+		else
+			iommu_cb_set.cb_info[idx].state = CAM_SMMU_DETACH;
 		break;
 	}
 	case CAM_SMMU_VOTE:
@@ -1773,6 +1782,7 @@ static int cam_smmu_map_stage2_buffer_and_add_to_list(int idx, int ion_fd,
 	mapping_info->len = *len_ptr;
 	mapping_info->dir = dma_dir;
 	mapping_info->ref_count = 1;
+	mapping_info->dmabuf = dmabuf;
 
 	CDBG("ion_fd = %d, dev = %pK, paddr= %pK, len = %u\n", ion_fd,
 			(void *)iommu_cb_set.cb_info[idx].dev,
@@ -2239,6 +2249,11 @@ static int cam_smmu_probe(struct platform_device *pdev)
 		return rc;
 	}
 
+	if (of_property_read_bool(dev->of_node, "qcom,camera-secure-sid"))
+		iommu_cb_set.camera_secure_sid = true;
+	else
+		iommu_cb_set.camera_secure_sid = false;
+
 	/* probe thru all the subdevices */
 	rc = of_platform_populate(pdev->dev.of_node, msm_cam_smmu_dt_match,
 				NULL, &pdev->dev);
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
index 1f8ca8d..c3ccf04 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
+++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
@@ -426,24 +426,6 @@ int msm_camera_clk_enable(struct device *dev,
 }
 EXPORT_SYMBOL(msm_camera_clk_enable);
 
-
-int msm_camera_cpp_clk_disable(struct device *dev,
-		struct msm_cam_clk_info *clk_info,
-		struct clk **clk_ptr, int num_clk, int enable)
-{
-	int i;
-	int rc = 1;
-
-	for (i = num_clk - 1; i >= 0; i--) {
-		if (clk_ptr[i] != NULL) {
-			rc = strcmp(clk_info[i].clk_name, "cpp_src_clk");
-			if (rc == 0)
-				continue;
-			clk_disable_unprepare(clk_ptr[i]);
-		}
-	}
-	return 0;
-}
 /* Set rate on a specific clock */
 long msm_camera_clk_set_rate(struct device *dev,
 			struct clk *clk,
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
index caa379d..0e2291a 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
+++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
@@ -174,10 +174,6 @@ int msm_camera_clk_enable(struct device *dev,
 		int num_clk,
 		int enable);
 
-int msm_camera_cpp_clk_disable(struct device *dev,
-		struct msm_cam_clk_info *clk_info,
-		struct clk **clk_ptr, int num_clk, int enable);
-
 /**
  * @brief      : Set clock rate
  *
diff --git a/drivers/media/platform/msm/camera_v2/common/msm_camera_tz_util.c b/drivers/media/platform/msm/camera_v2/common/msm_camera_tz_util.c
index 0e82625..2e9e5a5 100644
--- a/drivers/media/platform/msm/camera_v2/common/msm_camera_tz_util.c
+++ b/drivers/media/platform/msm/camera_v2/common/msm_camera_tz_util.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
@@ -10,27 +10,58 @@
  * GNU General Public License for more details.
  */
 
+#include <asm/cacheflush.h>
 #include <linux/delay.h>
 #include <linux/ktime.h>
 #include <linux/mutex.h>
 #include <soc/qcom/camera2.h>
+#include <soc/qcom/scm.h>
 #include "qseecom_kernel.h"
+#include "msm_camera_io_util.h"
 #include "msm_camera_tz_util.h"
 
+#define MSM_CAMERA_TZ_DEFERRED_SIZE  40
 #define EMPTY_QSEECOM_HANDLE    NULL
-#define QSEECOM_SBUFF_SIZE      SZ_128K
+#define QSEECOM_SBUFF_SIZE      SZ_64K
+
+#define MSM_CAMERA_TZ_OK        0
+#define MSM_CAMERA_TZ_FAULT     (-EFAULT)
+#define MSM_CAMERA_TZ_TRUE      1
+#define MSM_CAMERA_TZ_FALSE     0
+
+#define MSM_CAMERA_TZ_SVC_CAMERASS_CALL_ID             24
+#define MSM_CAMERA_TZ_SVC_CAMERASS_VER_SHIFT           28
+#define MSM_CAMERA_TZ_SVC_CAMERASS_CURRENT_VER         0x1
+#define MSM_CAMERA_TZ_SVC_CAMERASS_SECURITY_STATUS     0x1
+#define MSM_CAMERA_TZ_SVC_CAMERASS_REG_READ            0x2
+#define MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE           0x3
+#define MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE_BULK      0x4
+#define MSM_CAMERA_TZ_SVC_CAMERASS_RESET_HW_BLOCK      0x5
+#define MSM_CAMERA_TZ_SVC_CAMERASS_HW_BLOCK_SHIFT      21
+
+#undef MSM_CAMERA_TZ_UTIL_VERBOSE
 
 #define MSM_CAMERA_TZ_BOOT_PROTECTED (false)
+#define MSM_CAMERA_TZ_PROTECTION_LEVEL 1
+
+#if MSM_CAMERA_TZ_PROTECTION_LEVEL == 2
+	#define MSM_CAMERA_TZ_SECURED_HW_BLOCKS \
+		(MSM_CAMERA_TZ_HW_BLOCK_CSIDCORE)
+#elif MSM_CAMERA_TZ_PROTECTION_LEVEL == 1
+	#define MSM_CAMERA_TZ_SECURED_HW_BLOCKS \
+		(MSM_CAMERA_TZ_HW_BLOCK_CSIDCORE)
+#else
+	#define MSM_CAMERA_TZ_SECURED_HW_BLOCKS (0)
+#endif
 
 /* Update version major number in case the HLOS-TA interface is changed*/
 #define TA_IF_VERSION_MAJ	    1
-#define TA_IF_VERSION_MIN	    2
+#define TA_IF_VERSION_MIN	    4
 
 #undef CDBG
 #ifdef MSM_CAMERA_TZ_UTIL_VERBOSE
 	#define CDBG(fmt, args...) \
-		pr_info(CONFIG_MSM_SEC_CCI_TA_NAME "::%s:%d - " fmt,\
-		__func__, __LINE__, ##args)
+		pr_info("%s:%d - " fmt, __func__, __LINE__, ##args)
 #else /* MSM_CAMERA_TZ_UTIL_VERBOSE */
 	#define CDBG(fmt, args...) \
 		pr_debug("%s:%d - " fmt,  __func__, __LINE__, ##args)
@@ -39,14 +70,16 @@
 #pragma pack(push, msm_camera_tz_util, 1)
 
 /* MSM_CAMERA_TZ_CMD_GET_IF_VERSION */
-#define msm_camera_tz_i2c_get_if_version_req_t msm_camera_tz_generic_req_t
+#define msm_camera_tz_get_if_version_req_t msm_camera_tz_generic_req_t
 
-struct msm_camera_tz_i2c_get_if_version_rsp_t {
+struct msm_camera_tz_get_if_version_rsp_t {
 	enum msm_camera_tz_status_t rc;
 	uint32_t                    if_version_maj;
 	uint32_t                    if_version_min;
 };
 
+#define msm_camera_tz_set_mode_rsp_t msm_camera_tz_generic_rsp_t
+
 /* MSM_CAMERA_TZ_CMD_SET_MODE */
 struct msm_camera_tz_set_mode_req_t {
 	enum msm_camera_tz_cmd_id_t cmd_id;
@@ -54,12 +87,17 @@ struct msm_camera_tz_set_mode_req_t {
 	uint32_t                    hw_block;
 };
 
-#define msm_camera_tz_set_mode_rsp_t msm_camera_tz_generic_rsp_t
-
 #pragma pack(pop, msm_camera_tz_util)
 
-/* TA communication control structure */
+/* TEE communication control structure
+ * TZBSP Status format:
+ *	bit 0-1     : reserved
+ *	bit 2-20    : corresponding SCM call status, 1 - supported
+ *	bit 21-27   : protected HW blocks
+ *	bit 28-31   : API version
+ */
 struct msm_camera_tz_ctrl_t {
+	uint32_t                tzbsp_status;
 	uint32_t                ta_enabled;
 	struct qseecom_handle   *ta_qseecom_handle;
 	const char              *ta_name;
@@ -67,11 +105,144 @@ struct msm_camera_tz_ctrl_t {
 };
 
 static struct msm_camera_tz_ctrl_t msm_camera_tz_ctrl = {
-	0, NULL, CONFIG_MSM_CAMERA_TZ_TA_NAME, 0
+	0, 0, NULL, CONFIG_MSM_CAMERA_TZ_TA_NAME, 0
+};
+
+/* Register accsess relay */
+struct msm_camera_tz_register_t {
+	uint32_t    offset;
+	uint32_t    data;
+};
+
+struct msm_camera_tz_reg_ctrl_t {
+	uint32_t    num_of_deffered_registers;
+	enum msm_camera_tz_io_region_t deferred_region;
+	void __iomem *deferred_base_addr;
+	struct msm_camera_tz_register_t
+		deferred_registers[MSM_CAMERA_TZ_DEFERRED_SIZE];
+};
+
+static struct msm_camera_tz_reg_ctrl_t msm_camera_tz_reg_ctrl = {
+	0,
+	MSM_CAMERA_TZ_IO_REGION_LAST,
+	NULL
 };
 
 static DEFINE_MUTEX(msm_camera_tz_util_lock);
 
+static int32_t msm_camera_tz_tzbsp_reg_write(uint32_t data, uint32_t offset,
+	enum msm_camera_tz_io_region_t region);
+
+static const char *msm_camera_tz_scm_call_name(uint32_t call_id)
+{
+	switch (call_id) {
+	case MSM_CAMERA_TZ_SVC_CAMERASS_SECURITY_STATUS:
+		return "STATUS";
+	case MSM_CAMERA_TZ_SVC_CAMERASS_REG_READ:
+		return "REG_READ";
+	case MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE:
+		return "REG_WRITE";
+	case MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE_BULK:
+		return "REG_WRITE_BULK";
+	case MSM_CAMERA_TZ_SVC_CAMERASS_RESET_HW_BLOCK:
+		return "RESET_HW_BLOCK";
+	default:
+		return "N/A";
+	}
+};
+
+static const char *msm_camera_tz_region_name(
+	enum msm_camera_tz_io_region_t region)
+{
+	switch (region) {
+	case MSM_CAMERA_TZ_IO_REGION_CSIDCORE0:
+		return "CSIDCORE0";
+	case MSM_CAMERA_TZ_IO_REGION_CSIDCORE1:
+		return "CSIDCORE1";
+	case MSM_CAMERA_TZ_IO_REGION_CSIDCORE2:
+		return "CSIDCORE2";
+	case MSM_CAMERA_TZ_IO_REGION_CSIDCORE3:
+		return "CSIDCORE3";
+	default:
+		return "N/A";
+	}
+};
+
+uint32_t msm_camera_tz_region_to_hw_block(
+	enum msm_camera_tz_io_region_t region)
+{
+	switch (region) {
+	case MSM_CAMERA_TZ_IO_REGION_CSIDCORE0:
+	case MSM_CAMERA_TZ_IO_REGION_CSIDCORE1:
+	case MSM_CAMERA_TZ_IO_REGION_CSIDCORE2:
+	case MSM_CAMERA_TZ_IO_REGION_CSIDCORE3:
+		return MSM_CAMERA_TZ_HW_BLOCK_CSIDCORE;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static uint32_t msm_camera_tz_get_tzbsp_status(uint32_t status_mask)
+{
+	if (msm_camera_tz_ctrl.tzbsp_status == 0) {
+		struct scm_desc desc = {
+			.arginfo = SCM_ARGS(0),
+		};
+		ktime_t startTime = ktime_get();
+
+		int32_t scmcall_status = scm_call2_atomic(
+			SCM_SIP_FNID(
+				MSM_CAMERA_TZ_SVC_CAMERASS_CALL_ID,
+				MSM_CAMERA_TZ_SVC_CAMERASS_SECURITY_STATUS),
+			&desc);
+		if (scmcall_status) {
+			CDBG("SCM call %s failed - %d\n",
+				msm_camera_tz_scm_call_name(
+				MSM_CAMERA_TZ_SVC_CAMERASS_SECURITY_STATUS),
+				scmcall_status);
+			msm_camera_tz_ctrl.tzbsp_status = 0xFFFFFFFF;
+		} else {
+			msm_camera_tz_ctrl.tzbsp_status = desc.ret[0];
+		}
+		CDBG("Done: status=0x%08X, - %lluus\n",
+		msm_camera_tz_ctrl.tzbsp_status,
+			ktime_us_delta(ktime_get(), startTime));
+	}
+	if ((msm_camera_tz_ctrl.tzbsp_status != 0xFFFFFFFF) &&
+		(msm_camera_tz_ctrl.tzbsp_status & status_mask))
+		return MSM_CAMERA_TZ_TRUE;
+
+	/* TZBSP implementation is not available */
+	return MSM_CAMERA_TZ_FALSE;
+}
+
+void msm_camera_tz_clear_tzbsp_status(void)
+{
+	msm_camera_tz_ctrl.tzbsp_status = 0;
+}
+
+uint32_t msm_camera_tz_is_secured(
+	enum msm_camera_tz_io_region_t region)
+{
+	/* Check TZBSP API version */
+	if (msm_camera_tz_get_tzbsp_status(
+		MSM_CAMERA_TZ_SVC_CAMERASS_CURRENT_VER <<
+			MSM_CAMERA_TZ_SVC_CAMERASS_VER_SHIFT) !=
+				MSM_CAMERA_TZ_TRUE)
+		return MSM_CAMERA_TZ_FALSE;
+
+	/* Check if the region is boot protected */
+	if (msm_camera_tz_get_tzbsp_status(
+		(msm_camera_tz_region_to_hw_block(region) <<
+			MSM_CAMERA_TZ_SVC_CAMERASS_HW_BLOCK_SHIFT)) ==
+				MSM_CAMERA_TZ_TRUE)
+		return MSM_CAMERA_TZ_TRUE;
+
+	return MSM_CAMERA_TZ_FALSE;
+}
+
 struct qseecom_handle *msm_camera_tz_get_ta_handle(void)
 {
 	return msm_camera_tz_ctrl.ta_qseecom_handle;
@@ -118,14 +289,14 @@ int32_t get_cmd_rsp_buffers(
 	return 0;
 }
 
-static int32_t msm_camera_tz_i2c_ta_get_if_version(
+static int32_t msm_camera_tz_ta_get_if_version(
 	struct qseecom_handle *ta_qseecom_handle,
 	uint32_t *if_version_maj,
 	uint32_t *if_version_min)
 {
 	int32_t cmd_len, rsp_len;
-	struct msm_camera_tz_i2c_get_if_version_req_t *cmd;
-	struct msm_camera_tz_i2c_get_if_version_rsp_t *rsp;
+	struct msm_camera_tz_get_if_version_req_t *cmd;
+	struct msm_camera_tz_get_if_version_rsp_t *rsp;
 	int32_t rc = 0;
 
 	CDBG("Enter\n");
@@ -136,8 +307,8 @@ static int32_t msm_camera_tz_i2c_ta_get_if_version(
 		return -EINVAL;
 	}
 
-	cmd_len = sizeof(struct msm_camera_tz_i2c_get_if_version_req_t);
-	rsp_len = sizeof(struct msm_camera_tz_i2c_get_if_version_rsp_t);
+	cmd_len = sizeof(struct msm_camera_tz_get_if_version_req_t);
+	rsp_len = sizeof(struct msm_camera_tz_get_if_version_rsp_t);
 
 	rc = get_cmd_rsp_buffers(ta_qseecom_handle,
 		(void **)&cmd, &cmd_len, (void **)&rsp, &rsp_len);
@@ -199,7 +370,7 @@ int32_t msm_camera_tz_load_ta(void)
 				(char *)msm_camera_tz_ctrl.ta_name,
 				QSEECOM_SBUFF_SIZE);
 			if (!rc)
-				rc = msm_camera_tz_i2c_ta_get_if_version(
+				rc = msm_camera_tz_ta_get_if_version(
 					msm_camera_tz_ctrl.ta_qseecom_handle,
 					&if_version_maj, &if_version_min);
 
@@ -349,3 +520,350 @@ uint32_t msm_camera_tz_set_mode(uint32_t mode,
 		rc, mode);
 	return rc;
 }
+
+static int32_t msm_camera_tz_tzbsp_reg_write_bulk(
+	enum msm_camera_tz_io_region_t region)
+{
+	int32_t rc = 0;
+	struct scm_desc desc = {0};
+	uint32_t *offsets = NULL;
+	uint32_t *data = NULL;
+	uint32_t index;
+	uint32_t buffer_size = 0;
+	ktime_t startTime = ktime_get();
+
+	if (msm_camera_tz_reg_ctrl.num_of_deffered_registers == 0 ||
+		msm_camera_tz_reg_ctrl.num_of_deffered_registers >
+			MSM_CAMERA_TZ_DEFERRED_SIZE) {
+		pr_err("%s:%d - Bad parameters\n",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	buffer_size = sizeof(uint32_t) *
+		msm_camera_tz_reg_ctrl.num_of_deffered_registers;
+	offsets = kzalloc(buffer_size, GFP_KERNEL);
+	if (!offsets)
+		return -ENOMEM;
+
+	data = kzalloc(buffer_size, GFP_KERNEL);
+	if (!data) {
+		kfree(offsets);
+		return -ENOMEM;
+	}
+
+	for (index = 0;
+		index < msm_camera_tz_reg_ctrl.num_of_deffered_registers;
+		index++) {
+		offsets[index] =
+			msm_camera_tz_reg_ctrl.deferred_registers[index].offset;
+		data[index] =
+			msm_camera_tz_reg_ctrl.deferred_registers[index].data;
+	}
+
+	desc.arginfo = SCM_ARGS(6,
+		SCM_VAL, SCM_VAL, SCM_RO, SCM_VAL, SCM_RO, SCM_VAL);
+	desc.args[0] = region;
+	desc.args[1] = msm_camera_tz_reg_ctrl.num_of_deffered_registers;
+	desc.args[2] = SCM_BUFFER_PHYS(offsets);
+	desc.args[3] = buffer_size;
+	desc.args[4] = SCM_BUFFER_PHYS(data);
+	desc.args[5] = buffer_size;
+
+	dmac_flush_range(offsets, offsets +
+		msm_camera_tz_reg_ctrl.num_of_deffered_registers);
+	dmac_flush_range(data, data +
+		msm_camera_tz_reg_ctrl.num_of_deffered_registers);
+	rc = scm_call2(
+		SCM_SIP_FNID(
+			MSM_CAMERA_TZ_SVC_CAMERASS_CALL_ID,
+			MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE_BULK),
+		&desc);
+	kfree(offsets);
+	kfree(data);
+	if (rc) {
+		CDBG("SCM call %s failed - %d\n",
+			msm_camera_tz_scm_call_name(
+				MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE_BULK),
+			rc);
+	}
+
+	CDBG("Done: rc=%d, region=%s, num_of=%d - %lluus\n", rc,
+		msm_camera_tz_region_name(region),
+		msm_camera_tz_reg_ctrl.num_of_deffered_registers,
+		ktime_us_delta(ktime_get(), startTime));
+
+	return rc;
+}
+
+static void msm_camera_tz_flush_deferred(void)
+{
+	if (msm_camera_tz_reg_ctrl.num_of_deffered_registers) {
+		int32_t rc = MSM_CAMERA_TZ_FAULT;
+		uint32_t region = msm_camera_tz_reg_ctrl.deferred_region;
+		uint32_t index;
+
+		CDBG("Flush %d deffered registers for %s\n",
+			msm_camera_tz_reg_ctrl.num_of_deffered_registers,
+			msm_camera_tz_region_name(region));
+
+		if (msm_camera_tz_is_secured(region) &&
+			msm_camera_tz_get_tzbsp_status((1 <<
+				MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE_BULK)))
+			rc = msm_camera_tz_tzbsp_reg_write_bulk(region);
+		if (rc && msm_camera_tz_is_secured(region) &&
+			msm_camera_tz_get_tzbsp_status(
+				(1 << MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE))) {
+			for (index = 0; index <
+			msm_camera_tz_reg_ctrl.num_of_deffered_registers;
+			index++) {
+				rc = msm_camera_tz_tzbsp_reg_write(
+				msm_camera_tz_reg_ctrl.deferred_registers[
+								index].data,
+				msm_camera_tz_reg_ctrl.deferred_registers[
+								index].offset,
+								region);
+				if (rc < MSM_CAMERA_TZ_OK) {
+					CDBG("Failed to flush deffered ");
+					CDBG("register: %08X, rc=%d\n",
+				msm_camera_tz_reg_ctrl.deferred_registers[
+					index].offset, rc);
+				}
+			}
+			rc = MSM_CAMERA_TZ_OK;
+		}
+		msm_camera_tz_reg_ctrl.num_of_deffered_registers = 0;
+		msm_camera_tz_reg_ctrl.deferred_region =
+			MSM_CAMERA_TZ_IO_REGION_LAST;
+		msm_camera_tz_reg_ctrl.deferred_base_addr = NULL;
+	}
+}
+
+static int32_t msm_camera_tz_tzbsp_reg_read(uint32_t offset, uint32_t *data,
+	enum msm_camera_tz_io_region_t region)
+{
+	ktime_t startTime = ktime_get();
+	struct scm_desc desc = {
+			.args[0] = region,
+			.args[1] = offset,
+			.arginfo = SCM_ARGS(2),
+	};
+
+	int32_t rc = scm_call2(
+		SCM_SIP_FNID(
+			MSM_CAMERA_TZ_SVC_CAMERASS_CALL_ID,
+			MSM_CAMERA_TZ_SVC_CAMERASS_REG_READ),
+		&desc);
+	if (rc)
+		CDBG("SCM call %s failed - %d\n",
+			msm_camera_tz_scm_call_name(
+				MSM_CAMERA_TZ_SVC_CAMERASS_REG_READ),
+			rc);
+	else
+		*data = desc.ret[0];
+
+	CDBG("Done: rc=%d, region=%s, offset=0x%08X, data=0x%08X - %lluus\n",
+		rc, msm_camera_tz_region_name(region),
+		offset, *data,
+		ktime_us_delta(ktime_get(), startTime));
+
+	return rc;
+}
+
+uint32_t msm_camera_tz_r(void __iomem *base_addr, uint32_t offset,
+	enum msm_camera_tz_io_region_t region)
+{
+	uint32_t data = 0xDEADDEAD;
+
+	if (msm_camera_tz_is_secured(region)) {
+		int32_t rc = MSM_CAMERA_TZ_FAULT;
+
+		msm_camera_tz_flush_deferred();
+		if (msm_camera_tz_is_secured(region) &&
+			msm_camera_tz_get_tzbsp_status(
+			(1 << MSM_CAMERA_TZ_SVC_CAMERASS_REG_READ)))
+			rc = msm_camera_tz_tzbsp_reg_read(offset, &data,
+				region);
+		return data;
+	}
+	data = msm_camera_io_r(base_addr + offset);
+
+	return data;
+}
+
+static int32_t msm_camera_tz_tzbsp_reg_write(uint32_t data, uint32_t offset,
+	enum msm_camera_tz_io_region_t region)
+{
+	ktime_t startTime = ktime_get();
+	struct scm_desc desc = {
+			.args[0] = region,
+			.args[1] = offset,
+			.args[2] = data,
+			.arginfo = SCM_ARGS(3),
+	};
+
+	int32_t rc = scm_call2(
+		SCM_SIP_FNID(
+			MSM_CAMERA_TZ_SVC_CAMERASS_CALL_ID,
+			MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE),
+		&desc);
+	if (rc)
+		CDBG("SCM call %s failed - %d\n",
+			msm_camera_tz_scm_call_name(
+			MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE),
+			rc);
+
+	CDBG("Done: rc=%d, region=%s, offset=0x%08X, data=0x%08X - %lluus\n",
+		rc, msm_camera_tz_region_name(region),
+		offset, data,
+		ktime_us_delta(ktime_get(), startTime));
+
+	return rc;
+}
+
+static void msm_camera_tz_write(uint32_t data,
+	void __iomem *base_addr, uint32_t offset,
+	enum msm_camera_tz_io_region_t region)
+{
+	int32_t rc = MSM_CAMERA_TZ_FAULT;
+
+	if (msm_camera_tz_reg_ctrl.num_of_deffered_registers > 0 &&
+		msm_camera_tz_reg_ctrl.num_of_deffered_registers <
+			MSM_CAMERA_TZ_DEFERRED_SIZE &&
+		msm_camera_tz_reg_ctrl.deferred_region == region &&
+		msm_camera_tz_reg_ctrl.deferred_region !=
+			MSM_CAMERA_TZ_IO_REGION_LAST) {
+		msm_camera_tz_w_deferred(data, base_addr, offset, region);
+		msm_camera_tz_flush_deferred();
+	} else {
+		msm_camera_tz_flush_deferred();
+		if (msm_camera_tz_is_secured(region) &&
+			msm_camera_tz_get_tzbsp_status((1 <<
+				MSM_CAMERA_TZ_SVC_CAMERASS_REG_WRITE)))
+			rc = msm_camera_tz_tzbsp_reg_write(data, offset,
+				region);
+	}
+}
+
+void msm_camera_tz_w_mb(uint32_t data,
+	void __iomem *base_addr, uint32_t offset,
+	enum msm_camera_tz_io_region_t region)
+{
+	if (msm_camera_tz_is_secured(region)) {
+		CDBG("%s::W_MB(%d) - %pK + 0x%08X(0x%08X)\n",
+			msm_camera_tz_region_name(region),
+			msm_camera_tz_is_secured(region),
+			base_addr, offset, data);
+
+		msm_camera_tz_write(data, base_addr, offset, region);
+	} else {
+		msm_camera_io_w_mb(data, base_addr + offset);
+	}
+}
+
+void msm_camera_tz_w(uint32_t data,
+	void __iomem *base_addr, uint32_t offset,
+	enum msm_camera_tz_io_region_t region)
+{
+	if (msm_camera_tz_is_secured(region)) {
+		CDBG("%s::W(%d) - %pK + 0x%08X(0x%08X)\n",
+			msm_camera_tz_region_name(region),
+			msm_camera_tz_is_secured(region),
+			base_addr, offset, data);
+
+		msm_camera_tz_write(data, base_addr, offset, region);
+	} else {
+		msm_camera_io_w(data, base_addr + offset);
+	}
+}
+
+void msm_camera_tz_w_deferred(uint32_t data,
+	void __iomem *base_addr, uint32_t offset,
+	enum msm_camera_tz_io_region_t region)
+{
+	if (msm_camera_tz_is_secured(region)) {
+		CDBG("%s::W(%d) - %pK + 0x%08X(0x%08X)\n",
+			msm_camera_tz_region_name(region),
+			msm_camera_tz_is_secured(region),
+			base_addr, offset, data);
+
+		if ((msm_camera_tz_reg_ctrl.deferred_region != region &&
+				msm_camera_tz_reg_ctrl.deferred_region !=
+				MSM_CAMERA_TZ_IO_REGION_LAST) ||
+			 msm_camera_tz_reg_ctrl.num_of_deffered_registers >=
+				MSM_CAMERA_TZ_DEFERRED_SIZE) {
+			CDBG("Force flush deferred registers");
+			msm_camera_tz_flush_deferred();
+		}
+		if (msm_camera_tz_reg_ctrl.num_of_deffered_registers == 0) {
+			msm_camera_tz_reg_ctrl.deferred_region = region;
+			msm_camera_tz_reg_ctrl.deferred_base_addr = base_addr;
+		}
+		msm_camera_tz_reg_ctrl.deferred_registers[
+		msm_camera_tz_reg_ctrl.num_of_deffered_registers].offset =
+									offset;
+		msm_camera_tz_reg_ctrl.deferred_registers[
+		msm_camera_tz_reg_ctrl.num_of_deffered_registers].data =
+									data;
+		msm_camera_tz_reg_ctrl.num_of_deffered_registers++;
+		return;
+	}
+	msm_camera_io_w(data, base_addr + offset);
+}
+
+static int32_t msm_camera_tz_tzbsp_reset_hw_block(uint32_t mask,
+	enum msm_camera_tz_io_region_t region)
+{
+	uint32_t status = -1;
+	ktime_t startTime = ktime_get();
+	struct scm_desc desc = {
+			.args[0] = region,
+			.args[1] = mask,
+			.arginfo = SCM_ARGS(2),
+	};
+
+	int32_t rc = scm_call2(
+		SCM_SIP_FNID(
+			MSM_CAMERA_TZ_SVC_CAMERASS_CALL_ID,
+			MSM_CAMERA_TZ_SVC_CAMERASS_RESET_HW_BLOCK),
+		&desc);
+	if (rc) {
+		CDBG("SCM call %s failed - %d\n",
+			msm_camera_tz_scm_call_name(
+				MSM_CAMERA_TZ_SVC_CAMERASS_RESET_HW_BLOCK),
+			rc);
+		status = rc;
+	} else {
+		status = desc.ret[0];
+		CDBG("SCM call returned: %d\n", status);
+		if (!status) {
+			/* To emulate success by wait_for_completion_timeout
+			 * the return value should be > 0
+			 */
+			status = 1;
+		}
+	}
+
+	CDBG("Done: staus=%d, region=%s - %lluus\n",
+		status,
+		msm_camera_tz_region_name(region),
+		ktime_us_delta(ktime_get(), startTime));
+
+	return status;
+}
+
+int32_t msm_camera_tz_reset_hw_block(
+	uint32_t mask,
+	enum msm_camera_tz_io_region_t region)
+{
+	int32_t rc = MSM_CAMERA_TZ_FAULT;
+
+	CDBG("%s\n", msm_camera_tz_region_name(region));
+
+	if (msm_camera_tz_is_secured(region) && msm_camera_tz_get_tzbsp_status(
+		(1 << MSM_CAMERA_TZ_SVC_CAMERASS_RESET_HW_BLOCK)))
+		rc = msm_camera_tz_tzbsp_reset_hw_block(mask, region);
+
+	/* 0 - timeout (error) */
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera_v2/common/msm_camera_tz_util.h b/drivers/media/platform/msm/camera_v2/common/msm_camera_tz_util.h
index 8a64af9..8b6dbf7 100644
--- a/drivers/media/platform/msm/camera_v2/common/msm_camera_tz_util.h
+++ b/drivers/media/platform/msm/camera_v2/common/msm_camera_tz_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 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
@@ -28,6 +28,15 @@
 #define MSM_CAMERA_TZ_HW_BLOCK_ISP      0x0000000008
 #define MSM_CAMERA_TZ_HW_BLOCK_CPP      0x0000000010
 
+enum msm_camera_tz_io_region_t {
+	MSM_CAMERA_TZ_IO_REGION_CSIDCORE0,
+	MSM_CAMERA_TZ_IO_REGION_CSIDCORE1,
+	MSM_CAMERA_TZ_IO_REGION_CSIDCORE2,
+	MSM_CAMERA_TZ_IO_REGION_CSIDCORE3,
+
+	MSM_CAMERA_TZ_IO_REGION_LAST
+};
+
 enum msm_camera_tz_cmd_id_t {
 	MSM_CAMERA_TZ_CMD_NONE,
 	MSM_CAMERA_TZ_CMD_GET_IF_VERSION,
@@ -49,6 +58,10 @@ enum msm_camera_tz_cmd_id_t {
 	MSM_CAMERA_TZ_CMD_CCI_UTIL,
 	MSM_CAMERA_TZ_CMD_SET_MODE,
 	MSM_CAMERA_TZ_CMD_FRAME_NOTIFICATION,
+	MSM_CAMERA_TZ_CMD_REG_READ,
+	MSM_CAMERA_TZ_CMD_REG_WRITE,
+	MSM_CAMERA_TZ_CMD_REG_WRITE_BULK,
+	MSM_CAMERA_TZ_CMD_RESET_HW_BLOCK,
 };
 
 enum msm_camera_tz_status_t {
@@ -75,9 +88,37 @@ struct msm_camera_tz_generic_rsp_t {
 
 #pragma pack(pop, msm_camera_tz)
 
+/* Register IO virtualization IF */
+uint32_t msm_camera_tz_is_secured(
+	enum msm_camera_tz_io_region_t region);
+uint32_t msm_camera_tz_secure(uint32_t is_secure);
+uint32_t msm_camera_tz_region_to_hw_block(
+	enum msm_camera_tz_io_region_t region);
+
+int32_t msm_camera_tz_reset_hw_block(
+	uint32_t mask,
+	enum msm_camera_tz_io_region_t region);
+uint32_t msm_camera_tz_r(void __iomem *base_addr, uint32_t offset,
+	enum msm_camera_tz_io_region_t region);
+void msm_camera_tz_w_mb(uint32_t data,
+	void __iomem *base_addr, uint32_t offset,
+	enum msm_camera_tz_io_region_t region);
+void msm_camera_tz_w(uint32_t data,
+	void __iomem *base_addr, uint32_t offset,
+	enum msm_camera_tz_io_region_t region);
+void msm_camera_tz_w_deferred(uint32_t data,
+	void __iomem *base_addr, uint32_t offset,
+	enum msm_camera_tz_io_region_t region);
+void msm_camera_tz_clear_tzbsp_status(void);
+
+void msm_camera_tz_dump(void __iomem *base_addr, int size, int enable,
+	enum msm_camera_tz_io_region_t region);
+
+/* Security Mode IF */
 uint32_t msm_camera_tz_set_mode(
 	uint32_t mode, uint32_t hw_block);
 
+/* Common TZ IF */
 struct qseecom_handle *msm_camera_tz_get_ta_handle(void);
 int32_t get_cmd_rsp_buffers(
 	struct qseecom_handle *ta_qseecom_handle,
@@ -88,4 +129,4 @@ int32_t msm_camera_tz_unload_ta(void);
 void msm_camera_tz_lock(void);
 void msm_camera_tz_unlock(void);
 
-#endif /* __MSM_CAMERA_TZ_UTIL_H */
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
index 0d0fcfe..097046d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
@@ -451,7 +451,7 @@ static int isp_vma_fault(struct vm_fault *vmf)
 {
 	struct page *page;
 	struct vfe_device *vfe_dev = vmf->vma->vm_private_data;
-	struct isp_proc *isp_page = NULL;
+	struct isp_kstate *isp_page = NULL;
 
 	isp_page = vfe_dev->isp_page;
 
@@ -707,7 +707,8 @@ int vfe_hw_probe(struct platform_device *pdev)
 	spin_lock_init(&vfe_dev->shared_data_lock);
 	spin_lock_init(&vfe_dev->reg_update_lock);
 	spin_lock_init(&req_history_lock);
-	spin_lock_init(&vfe_dev->completion_lock);
+	spin_lock_init(&vfe_dev->reset_completion_lock);
+	spin_lock_init(&vfe_dev->halt_completion_lock);
 	media_entity_pads_init(&vfe_dev->subdev.sd.entity, 0, NULL);
 	vfe_dev->subdev.sd.entity.function = MSM_CAMERA_SUBDEV_VFE;
 	//vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE;
@@ -743,7 +744,7 @@ int vfe_hw_probe(struct platform_device *pdev)
 	vfe_dev->buf_mgr->init_done = 1;
 	vfe_dev->vfe_open_cnt = 0;
 	/*Allocate a page in kernel and map it to camera user process*/
-	vfe_dev->isp_page = (struct isp_proc *)get_zeroed_page(GFP_KERNEL);
+	vfe_dev->isp_page = (struct isp_kstate *)get_zeroed_page(GFP_KERNEL);
 	if (vfe_dev->isp_page == NULL) {
 		pr_err("%s: no enough memory\n", __func__);
 		rc = -ENOMEM;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index d044d2b..7050971 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -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
@@ -424,6 +424,12 @@ enum msm_isp_comp_irq_types {
 
 #define MSM_VFE_REQUESTQ_SIZE 8
 
+struct msm_isp_pending_buf_info {
+	uint32_t is_buf_done_pending;
+	struct msm_isp_buffer *buf;
+	uint32_t frame_id;
+};
+
 struct msm_vfe_axi_stream {
 	uint32_t frame_id;
 	enum msm_vfe_axi_state state;
@@ -480,6 +486,7 @@ struct msm_vfe_axi_stream {
 	uint32_t vfe_mask;
 	uint32_t composite_irq[MSM_ISP_COMP_IRQ_MAX];
 	int lpm_mode;
+	struct msm_isp_pending_buf_info pending_buf_info;
 };
 
 struct msm_vfe_axi_composite_info {
@@ -755,6 +762,7 @@ struct msm_vfe_common_dev_data {
 	/* Irq debug Info */
 	struct msm_vfe_irq_dump vfe_irq_dump;
 	struct msm_vfe_tasklet tasklets[MAX_VFE + 1];
+	uint32_t drop_reconfig;
 };
 
 struct msm_vfe_common_subdev {
@@ -771,11 +779,6 @@ struct msm_vfe_common_subdev {
 	struct msm_vfe_common_dev_data *common_data;
 };
 
-struct isp_proc {
-	uint32_t  kernel_sofid;
-	uint32_t  vfeid;
-};
-
 struct vfe_device {
 	/* Driver private data */
 	struct platform_device *pdev;
@@ -814,7 +817,8 @@ struct vfe_device {
 	struct mutex core_mutex;
 	spinlock_t shared_data_lock;
 	spinlock_t reg_update_lock;
-	spinlock_t completion_lock;
+	spinlock_t reset_completion_lock;
+	spinlock_t halt_completion_lock;
 
 	/* Tasklet info */
 	atomic_t irq_cnt;
@@ -862,13 +866,14 @@ struct vfe_device {
 	uint32_t recovery_irq1_mask;
 	/* total bandwidth per vfe */
 	uint64_t total_bandwidth;
-	struct isp_proc *isp_page;
+	struct isp_kstate *isp_page;
 
 	/* Dual VFE IRQ CAMSS Info*/
 	void __iomem *camss_base;
 	struct resource *dual_vfe_irq;
 	/* irq info */
 	uint32_t dual_irq_mask;
+	uint32_t irq_sof_id;
 };
 
 struct vfe_parent_device {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index d6ec8ae..e8dce1f 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -363,15 +363,24 @@ static void msm_vfe40_clear_status_reg(struct vfe_device *vfe_dev)
 static void msm_vfe40_process_reset_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1)
 {
-	if (irq_status0 & (1 << 31))
+	unsigned long flags;
+
+	if (irq_status0 & (1 << 31)) {
+		spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
 		complete(&vfe_dev->reset_complete);
+		spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
+	}
 }
 
 static void msm_vfe40_process_halt_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1)
 {
+	unsigned long flags;
+
 	if (irq_status1 & (1 << 8)) {
+		spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
 		complete(&vfe_dev->halt_complete);
+		spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
 		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x2C0);
 	}
 }
@@ -737,13 +746,13 @@ static void msm_vfe40_process_epoch_irq(struct vfe_device *vfe_dev,
 		return;
 
 	if (irq_status0 & BIT(2)) {
-		msm_isp_notify(vfe_dev, ISP_EVENT_SOF, VFE_PIX_0, ts);
 		ISP_DBG("%s: EPOCH0 IRQ\n", __func__);
 		msm_isp_process_reg_upd_epoch_irq(vfe_dev, VFE_PIX_0,
 					MSM_ISP_COMP_IRQ_EPOCH, ts);
 		msm_isp_process_stats_reg_upd_epoch_irq(vfe_dev,
 					MSM_ISP_COMP_IRQ_EPOCH);
 		msm_isp_update_error_frame_count(vfe_dev);
+		msm_isp_notify(vfe_dev, ISP_EVENT_SOF, VFE_PIX_0, ts);
 		if (vfe_dev->axi_data.src_info[VFE_PIX_0].raw_stream_count > 0
 		  && vfe_dev->axi_data.src_info[VFE_PIX_0].stream_count == 0) {
 			ISP_DBG("%s: SOF IRQ\n", __func__);
@@ -760,8 +769,11 @@ static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev,
 	uint32_t first_start, uint32_t blocking_call)
 {
 	long rc = 0;
+	unsigned long flags;
 
+	spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
 	init_completion(&vfe_dev->reset_complete);
+	spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
 
 	if (first_start) {
 		msm_camera_io_w_mb(0x1FF, vfe_dev->vfe_base + 0xC);
@@ -1777,6 +1789,7 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev,
 	int rc = 0;
 	enum msm_vfe_input_src i;
 	struct msm_isp_timestamp ts;
+	unsigned long flags;
 
 	/* Keep only halt and restart mask */
 	msm_vfe40_config_irq(vfe_dev, (1 << 31), (1 << 8),
@@ -1793,7 +1806,9 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev,
 	msm_isp_stats_stream_update(vfe_dev);
 
 	if (blocking) {
+		spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
 		init_completion(&vfe_dev->halt_complete);
+		spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
 		/* Halt AXI Bus Bridge */
 		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2C0);
 		rc = wait_for_completion_interruptible_timeout(
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index f8f43e8..9213d84 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -443,10 +443,10 @@ void msm_vfe47_process_reset_irq(struct vfe_device *vfe_dev,
 	unsigned long flags;
 
 	if (irq_status0 & (1 << 31)) {
-		spin_lock_irqsave(&vfe_dev->completion_lock, flags);
+		spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
 		complete(&vfe_dev->reset_complete);
 		vfe_dev->reset_pending = 0;
-		spin_unlock_irqrestore(&vfe_dev->completion_lock, flags);
+		spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
 	}
 }
 
@@ -454,9 +454,12 @@ void msm_vfe47_process_halt_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1)
 {
 	uint32_t val = 0;
+	unsigned long flags;
 
 	if (irq_status1 & (1 << 8)) {
+		spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
 		complete(&vfe_dev->halt_complete);
+		spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
 		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x400);
 	}
 
@@ -709,8 +712,10 @@ void msm_isp47_preprocess_camif_irq(struct vfe_device *vfe_dev,
 {
 	if (irq_status0 & BIT(3))
 		vfe_dev->axi_data.src_info[VFE_PIX_0].accept_frame = false;
-	if (irq_status0 & BIT(0))
+	if (irq_status0 & BIT(0)) {
 		vfe_dev->axi_data.src_info[VFE_PIX_0].accept_frame = true;
+		vfe_dev->irq_sof_id++;
+	}
 }
 
 void msm_vfe47_reg_update(struct vfe_device *vfe_dev,
@@ -773,9 +778,9 @@ long msm_vfe47_reset_hardware(struct vfe_device *vfe_dev,
 	uint32_t reset;
 	unsigned long flags;
 
-	spin_lock_irqsave(&vfe_dev->completion_lock, flags);
+	spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
 	init_completion(&vfe_dev->reset_complete);
-	spin_unlock_irqrestore(&vfe_dev->completion_lock, flags);
+	spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
 
 	if (blocking_call)
 		vfe_dev->reset_pending = 1;
@@ -2030,6 +2035,7 @@ int msm_vfe47_axi_halt(struct vfe_device *vfe_dev,
 	enum msm_vfe_input_src i;
 	uint32_t val = 0;
 	struct msm_isp_timestamp ts;
+	unsigned long flags;
 
 	val = msm_camera_io_r(vfe_dev->vfe_vbif_base + VFE47_VBIF_CLK_OFFSET);
 	val |= 0x1;
@@ -2046,7 +2052,9 @@ int msm_vfe47_axi_halt(struct vfe_device *vfe_dev,
 			__func__, vfe_dev->pdev->id, blocking);
 
 	if (blocking) {
+		spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
 		init_completion(&vfe_dev->halt_complete);
+		spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
 		/* Halt AXI Bus Bridge */
 		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x400);
 		rc = wait_for_completion_interruptible_timeout(
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index b1fe6bd..314f490 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -30,6 +30,13 @@ static void __msm_isp_axi_stream_update(
 			struct msm_vfe_axi_stream *stream_info,
 			struct msm_isp_timestamp *ts);
 
+static int msm_isp_process_done_buf(struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info, struct msm_isp_buffer *buf,
+	struct timeval *time_stamp, uint32_t frame_id);
+static void msm_isp_free_pending_buffer(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info,
+	struct msm_isp_timestamp *ts);
 static int msm_isp_update_stream_bandwidth(
 		struct msm_vfe_axi_stream *stream_info, int enable);
 
@@ -175,6 +182,8 @@ static void msm_isp_axi_destroy_stream(
 			stream_info->bufq_handle[k] = 0;
 		stream_info->vfe_mask = 0;
 		stream_info->state = AVAILABLE;
+		memset(&stream_info->request_queue_cmd,
+			0, sizeof(stream_info->request_queue_cmd));
 	}
 }
 
@@ -243,6 +252,7 @@ static int msm_isp_validate_axi_request(struct vfe_device *vfe_dev,
 	case V4L2_PIX_FMT_META:
 	case V4L2_PIX_FMT_META10:
 	case V4L2_PIX_FMT_GREY:
+	case V4L2_PIX_FMT_Y10:
 		stream_info->num_planes = 1;
 		stream_info->format_factor = ISP_Q2;
 		break;
@@ -352,6 +362,7 @@ static uint32_t msm_isp_axi_get_plane_size(
 	case V4L2_PIX_FMT_QGRBG10:
 	case V4L2_PIX_FMT_QRGGB10:
 	case V4L2_PIX_FMT_META10:
+	case V4L2_PIX_FMT_Y10:
 		/* TODO: fix me */
 		size = plane_cfg[plane_idx].output_height *
 		plane_cfg[plane_idx].output_width;
@@ -603,7 +614,8 @@ static int msm_isp_composite_irq(struct vfe_device *vfe_dev,
  *
  * Returns void
  */
-static void msm_isp_update_framedrop_reg(struct msm_vfe_axi_stream *stream_info)
+static void msm_isp_update_framedrop_reg(struct msm_vfe_axi_stream *stream_info,
+		uint32_t drop_reconfig)
 {
 	if (stream_info->stream_type == BURST_STREAM) {
 		if (stream_info->runtime_num_burst_capture == 0 ||
@@ -613,7 +625,8 @@ static void msm_isp_update_framedrop_reg(struct msm_vfe_axi_stream *stream_info)
 				MSM_VFE_STREAM_STOP_PERIOD;
 	}
 
-	if (stream_info->undelivered_request_cnt > 0)
+	if (stream_info->undelivered_request_cnt > 0 &&
+		drop_reconfig != 1)
 		stream_info->current_framedrop_period =
 			MSM_VFE_STREAM_STOP_PERIOD;
 
@@ -664,11 +677,18 @@ void msm_isp_process_reg_upd_epoch_irq(struct vfe_device *vfe_dev,
 		case MSM_ISP_COMP_IRQ_REG_UPD:
 			stream_info->activated_framedrop_period =
 				stream_info->requested_framedrop_period;
+			/* Free Pending Buffers which are backed-up due to
+			 * delay in RUP from userspace to Avoid pageFault
+			 */
+			msm_isp_free_pending_buffer(vfe_dev, stream_info, ts);
 			__msm_isp_axi_stream_update(stream_info, ts);
 			break;
 		case MSM_ISP_COMP_IRQ_EPOCH:
-			if (stream_info->state == ACTIVE)
-				msm_isp_update_framedrop_reg(stream_info);
+			if (stream_info->state == ACTIVE) {
+				msm_isp_update_framedrop_reg(stream_info,
+					vfe_dev->common_data->drop_reconfig);
+				vfe_dev->common_data->drop_reconfig = 0;
+			}
 			break;
 		default:
 			WARN(1, "Invalid irq %d\n", irq);
@@ -1563,6 +1583,40 @@ static void msm_isp_axi_stream_enable_cfg(
 	}
 }
 
+static void msm_isp_free_pending_buffer(
+			struct vfe_device *vfe_dev,
+			struct msm_vfe_axi_stream *stream_info,
+			struct msm_isp_timestamp *ts)
+{
+	struct timeval *time_stamp;
+	struct msm_isp_buffer *done_buf = NULL;
+	uint32_t frame_id;
+	int rc;
+
+	if (!stream_info->controllable_output ||
+		!stream_info->pending_buf_info.is_buf_done_pending)	{
+		return;
+	}
+
+	if (vfe_dev->vt_enable) {
+		msm_isp_get_avtimer_ts(ts);
+		time_stamp = &ts->vt_time;
+	} else {
+		time_stamp = &ts->buf_time;
+	}
+
+	done_buf = stream_info->pending_buf_info.buf;
+	frame_id = stream_info->pending_buf_info.frame_id;
+	if (done_buf) {
+		rc = msm_isp_process_done_buf(vfe_dev, stream_info,
+			done_buf, time_stamp, frame_id);
+		if (rc == 0) {
+			stream_info->pending_buf_info.buf = NULL;
+			stream_info->pending_buf_info.is_buf_done_pending = 0;
+		}
+	}
+}
+
 static void __msm_isp_axi_stream_update(
 			struct msm_vfe_axi_stream *stream_info,
 			struct msm_isp_timestamp *ts)
@@ -1753,6 +1807,10 @@ void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event)
 		/* Recovery is already in Progress */
 		return;
 
+	/* if there are no active streams - do not start recovery */
+	if (!vfe_dev->axi_data.num_active_stream)
+		return;
+
 	if (event == ISP_EVENT_PING_PONG_MISMATCH &&
 		vfe_dev->axi_data.recovery_count < MAX_RECOVERY_THRESHOLD) {
 		pr_err("%s: ping pong mismatch on vfe%d recovery count %d\n",
@@ -2085,7 +2143,6 @@ static int msm_isp_process_done_buf(struct vfe_device *vfe_dev,
 	uint32_t buf_src;
 	uint8_t drop_frame = 0;
 	struct msm_isp_bufq *bufq = NULL;
-
 	memset(&buf_event, 0, sizeof(buf_event));
 
 	if (stream_idx >= VFE_AXI_SRC_MAX) {
@@ -2768,6 +2825,7 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev,
 			axi_data->src_info[SRC_TO_INTF(
 				stream_info->stream_src)].frame_id =
 				reset_cmd->frame_id;
+			temp_vfe_dev->irq_sof_id = reset_cmd->frame_id;
 		}
 		msm_isp_reset_burst_count_and_frame_drop(
 			vfe_dev, stream_info);
@@ -3039,6 +3097,13 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
 		msm_isp_cfg_stream_scratch(stream_info, VFE_PING_FLAG);
 		msm_isp_cfg_stream_scratch(stream_info, VFE_PONG_FLAG);
 		stream_info->undelivered_request_cnt = 0;
+		vfe_dev->irq_sof_id = 0;
+		if (stream_info->controllable_output &&
+			stream_info->pending_buf_info.is_buf_done_pending) {
+			msm_isp_free_pending_buffer(vfe_dev, stream_info,
+				&timestamp);
+			stream_info->pending_buf_info.is_buf_done_pending = 0;
+		}
 		for (k = 0; k < stream_info->num_isp; k++) {
 			vfe_dev = stream_info->vfe_dev[k];
 			if (stream_info->num_planes > 1)
@@ -3202,7 +3267,6 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
 			mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
 			goto error;
 		}
-
 		msm_isp_calculate_bandwidth(stream_info);
 		for (k = 0; k < stream_info->num_isp; k++) {
 			msm_isp_get_stream_wm_mask(stream_info->vfe_dev[k],
@@ -3529,8 +3593,15 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
 
 	frame_src = SRC_TO_INTF(stream_info->stream_src);
 	pingpong_status =
-			vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status(
-					vfe_dev);
+		vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status(vfe_dev);
+
+	/* As MCT is still processing it, need to drop the additional requests*/
+	if (vfe_dev->isp_page->drop_reconfig) {
+		pr_err("%s: MCT has not yet delayed %d drop request %d\n",
+			__func__, vfe_dev->isp_page->drop_reconfig, frame_id);
+		goto error;
+	}
+
 	/*
 	 * If PIX stream is active then RDI path uses SOF frame ID of PIX
 	 * In case of standalone RDI streaming, SOF are used from
@@ -3541,12 +3612,30 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
 	 */
 	if (vfe_dev->axi_data.src_info[frame_src].active &&
 		frame_src == VFE_PIX_0 &&
-		vfe_dev->axi_data.src_info[frame_src].accept_frame == false) {
+		vfe_dev->axi_data.src_info[frame_src].accept_frame == false &&
+		(stream_info->undelivered_request_cnt <=
+			MAX_BUFFERS_IN_HW)
+		) {
 		pr_debug("%s:%d invalid time to request frame %d\n",
 			__func__, __LINE__, frame_id);
-		goto error;
-	}
-	if ((vfe_dev->axi_data.src_info[frame_src].active && (frame_id !=
+		vfe_dev->isp_page->drop_reconfig = 1;
+		/*keep it in vfe_dev variable also to avoid skip pattern
+		 * programming the variable in page can be overwritten by MCT
+		 */
+		vfe_dev->common_data->drop_reconfig = 1;
+	} else if ((vfe_dev->axi_data.src_info[frame_src].active) &&
+			((frame_id ==
+			vfe_dev->axi_data.src_info[frame_src].frame_id) ||
+			(frame_id == vfe_dev->irq_sof_id)) &&
+			(stream_info->undelivered_request_cnt <=
+				MAX_BUFFERS_IN_HW)) {
+		vfe_dev->isp_page->drop_reconfig = 1;
+		vfe_dev->common_data->drop_reconfig = 1;
+		pr_debug("%s: vfe_%d request_frame %d cur frame id %d pix %d\n",
+			__func__, vfe_dev->pdev->id, frame_id,
+			vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id,
+			vfe_dev->axi_data.src_info[VFE_PIX_0].active);
+	} else if ((vfe_dev->axi_data.src_info[frame_src].active && (frame_id !=
 		vfe_dev->axi_data.src_info[frame_src].frame_id +
 		vfe_dev->axi_data.src_info[frame_src].sof_counter_step)) ||
 		((!vfe_dev->axi_data.src_info[frame_src].active))) {
@@ -3650,6 +3739,9 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
 			stream_info->undelivered_request_cnt--;
 			pr_err_ratelimited("%s:%d fail to cfg HAL buffer\n",
 				__func__, __LINE__);
+			queue_req->cmd_used = 0;
+			list_del(&queue_req->list);
+			stream_info->request_q_cnt--;
 			return rc;
 		}
 
@@ -3686,6 +3778,9 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
 						flags);
 			pr_err_ratelimited("%s:%d fail to cfg HAL buffer\n",
 				__func__, __LINE__);
+			queue_req->cmd_used = 0;
+			list_del(&queue_req->list);
+			stream_info->request_q_cnt--;
 			return rc;
 		}
 	} else {
@@ -4275,9 +4370,25 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev,
 			ISP_DBG("%s: Error configuring ping_pong\n",
 				__func__);
 	} else if (done_buf && (done_buf->is_drop_reconfig != 1)) {
+		int32_t frame_id_diff;
+		/* irq_sof should be always >= tasklet SOF id
+		 * For dual camera usecase irq_sof could be behind
+		 * as software frameid sync logic epoch event could
+		 * update slave frame id so update if irqsof < tasklet sof
+		 */
+		if (vfe_dev->irq_sof_id < frame_id)
+			vfe_dev->irq_sof_id = frame_id;
+
+		frame_id_diff  =  vfe_dev->irq_sof_id - frame_id;
+		if (stream_info->controllable_output && frame_id_diff > 1) {
+			/*scheduling problem need to do recovery*/
+			spin_unlock_irqrestore(&stream_info->lock, flags);
+			msm_isp_halt_send_error(vfe_dev,
+				ISP_EVENT_PING_PONG_MISMATCH);
+			return;
+		}
 		msm_isp_cfg_stream_scratch(stream_info, pingpong_status);
 	}
-
 	if (!done_buf) {
 		if (stream_info->buf_divert) {
 			vfe_dev->error_info.stream_framedrop_count[
@@ -4326,11 +4437,28 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev,
 	 * then dont issue buf-done for current buffer
 	 */
 		done_buf->is_drop_reconfig = 0;
+		if (!stream_info->buf[pingpong_bit]) {
+			/*samebuffer is not re-programeed so program scratch*/
+			msm_isp_cfg_stream_scratch(stream_info,
+				pingpong_status);
+		}
 		spin_unlock_irqrestore(&stream_info->lock, flags);
 	} else {
+		/* If there is no regupdate from userspace then dont
+		 * free buffer immediately, delegate it to RegUpdateAck
+		 */
+		if (stream_info->controllable_output &&
+			!(vfe_dev->reg_update_requested &
+				BIT((uint32_t)VFE_PIX_0))) {
+			stream_info->pending_buf_info.is_buf_done_pending = 1;
+			stream_info->pending_buf_info.buf = done_buf;
+			stream_info->pending_buf_info.frame_id = frame_id;
+		}
 		spin_unlock_irqrestore(&stream_info->lock, flags);
-		msm_isp_process_done_buf(vfe_dev, stream_info,
-			done_buf, time_stamp, frame_id);
+		if (stream_info->pending_buf_info.is_buf_done_pending != 1) {
+			msm_isp_process_done_buf(vfe_dev, stream_info,
+				done_buf, time_stamp, frame_id);
+		}
 	}
 }
 
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
index feb6308..2eed3c0 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
@@ -25,12 +25,16 @@ int msm_isp_axi_create_stream(
 	struct msm_vfe_axi_shared_data *axi_data,
 	struct msm_vfe32_axi_stream_request_cmd *stream_cfg_cmd)
 {
-	uint32_t i = stream_cfg_cmd->stream_src;
+	int i, rc = -1;
 
-	if (i >= VFE_AXI_SRC_MAX) {
-		pr_err("%s:%d invalid stream_src %d\n", __func__, __LINE__,
-			stream_cfg_cmd->stream_src);
-		return -EINVAL;
+	for (i = 0; i < MAX_NUM_STREAM; i++) {
+		if (axi_data->stream_info[i].state == AVAILABLE)
+			break;
+	}
+
+	if (i == MAX_NUM_STREAM) {
+		pr_err("%s: No free stream\n", __func__);
+		return rc;
 	}
 
 	if ((axi_data->stream_handle_cnt << 8) == 0)
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index d49ed55..8d5fa22 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -905,7 +905,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
 	case VIDIOC_MSM_ISP_CFG_STREAM:
 		mutex_lock(&vfe_dev->core_mutex);
 		MSM_ISP_DUAL_VFE_MUTEX_LOCK(vfe_dev);
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = msm_isp_cfg_axi_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
 		mutex_unlock(&vfe_dev->core_mutex);
 		break;
@@ -1022,7 +1024,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
 	case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
 		mutex_lock(&vfe_dev->core_mutex);
 		MSM_ISP_DUAL_VFE_MUTEX_LOCK(vfe_dev);
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = msm_isp_cfg_stats_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
 		mutex_unlock(&vfe_dev->core_mutex);
 		break;
@@ -1802,6 +1806,7 @@ int msm_isp_get_bit_per_pixel(uint32_t output_format)
 	case V4L2_PIX_FMT_P16GBRG12:
 	case V4L2_PIX_FMT_P16GRBG12:
 	case V4L2_PIX_FMT_P16RGGB12:
+	case MSM_V4L2_PIX_FMT_META12:
 		return 12;
 	case V4L2_PIX_FMT_SBGGR14:
 	case V4L2_PIX_FMT_SGBRG14:
@@ -2351,7 +2356,8 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 	vfe_dev->isp_raw0_debug = 0;
 	vfe_dev->isp_raw1_debug = 0;
 	vfe_dev->isp_raw2_debug = 0;
-
+	vfe_dev->irq_sof_id = 0;
+	vfe_dev->common_data->drop_reconfig = 0;
 	if (vfe_dev->hw_info->vfe_ops.core_ops.init_hw(vfe_dev) < 0) {
 		pr_err("%s: init hardware failed\n", __func__);
 		vfe_dev->vfe_open_cnt--;
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index 9c54d39..a5e0f25 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.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
@@ -277,13 +277,14 @@ static void msm_buf_mngr_contq_listdel(struct msm_buf_mngr_device *dev,
 	int rc;
 	struct msm_buf_mngr_user_buf_cont_info *cont_bufs, *cont_save;
 
-	list_for_each_entry_safe(cont_bufs,
+	list_for_each_entry_safe_reverse(cont_bufs,
 		cont_save, &dev->cont_qhead, entry) {
 		if ((cont_bufs->sessid == session) &&
 		(cont_bufs->strid == stream)) {
 			if (cnt == 1 && unmap == 1) {
 				/* dma_buf_vunmap ignored vaddr(2nd argument) */
-				dma_buf_vunmap(cont_bufs->dmabuf, NULL);
+				dma_buf_vunmap(cont_bufs->dmabuf,
+					cont_bufs->paddr);
 				rc = dma_buf_end_cpu_access(cont_bufs->dmabuf,
 					DMA_BIDIRECTIONAL);
 				if (rc) {
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index f2b2658..fd693bb 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -35,6 +35,7 @@
 #include "msm_camera_io_util.h"
 #include <linux/debugfs.h>
 #include "cam_smmu_api.h"
+#include "msm_cam_cx_ipeak.h"
 
 #define MSM_CPP_DRV_NAME "msm_cpp"
 
@@ -1203,11 +1204,12 @@ static void cpp_release_hardware(struct cpp_device *cpp_dev)
 	if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP,
 		CAM_AHB_SUSPEND_VOTE) < 0)
 		pr_err("%s: failed to remove vote for AHB\n", __func__);
-	msm_camera_cpp_clk_disable(&cpp_dev->pdev->dev, cpp_dev->clk_info,
+	msm_camera_clk_enable(&cpp_dev->pdev->dev, cpp_dev->clk_info,
 		cpp_dev->cpp_clk, cpp_dev->num_clks, false);
 	msm_camera_regulator_disable(cpp_dev->cpp_vdd, cpp_dev->num_reg, true);
-	if (cpp_dev->stream_cnt > 0) {
-		pr_warn("stream count active\n");
+	if ((cpp_dev->stream_cnt > 0) || (cpp_dev->cpp_open_cnt == 0)) {
+		pr_debug("stream count active %d and close cpp node %d\n",
+			cpp_dev->stream_cnt, cpp_dev->cpp_open_cnt);
 		rc = msm_cpp_update_bandwidth_setting(cpp_dev, 0, 0);
 	}
 	cpp_dev->stream_cnt = 0;
@@ -1484,6 +1486,8 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
 	uint32_t i;
 	int rc = -1;
+	int counter = 0;
+	u32 result = 0;
 	struct cpp_device *cpp_dev = NULL;
 	struct msm_device_queue *processing_q = NULL;
 	struct msm_device_queue *eventData_q = NULL;
@@ -1523,7 +1527,9 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 	}
 
 	if (cpp_dev->turbo_vote == 1) {
-		rc = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, false);
+		pr_debug("%s:cx_ipeak_update unvote. ipeak bit %d\n",
+			__func__, cpp_dev->cx_ipeak_bit);
+		rc = cam_cx_ipeak_unvote_cx_ipeak(cpp_dev->cx_ipeak_bit);
 			if (rc)
 				pr_err("cx_ipeak_update failed");
 			else
@@ -1562,6 +1568,26 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x88));
 		pr_debug("DEBUG_R1: 0x%x\n",
 			msm_camera_io_r(cpp_dev->cpp_hw_base + 0x8C));
+		/* mask IRQ status */
+		msm_camera_io_w(0xB, cpp_dev->cpp_hw_base + 0xC);
+
+		while (counter < MSM_CPP_AXI_RESET_RETRIES) {
+			/* MMSS_A_CPP_AXI_CMD = 0x16C, reset 0x1*/
+			msm_camera_io_w(0x1, cpp_dev->cpp_hw_base + 0x16C);
+			usleep_range(100, 200);
+			result = msm_camera_io_r(cpp_dev->cpp_hw_base + 0x16C);
+			if (result & 0x1) {
+				pr_debug("CPP AXI reset successful result %d",
+					 result);
+				break;
+			}
+			counter++;
+		}
+
+		if (!(result & 0x1))
+			pr_err("CPP AXI reset un-successful result %d",
+				 result);
+
 		msm_camera_io_w(0x0, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL);
 		msm_cpp_clear_timer(cpp_dev);
 		cpp_release_hardware(cpp_dev);
@@ -3095,7 +3121,9 @@ static unsigned long cpp_cx_ipeak_update(struct cpp_device *cpp_dev,
 	if ((clock >= cpp_dev->hw_info.freq_tbl
 		[(cpp_dev->hw_info.freq_tbl_count) - 1]) &&
 		(cpp_dev->turbo_vote == 0)) {
-		ret = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, true);
+		pr_debug("%s: clk is more than Nominal cpp, ipeak bit %d\n",
+			__func__, cpp_dev->cx_ipeak_bit);
+		ret = cam_cx_ipeak_update_vote_cx_ipeak(cpp_dev->cx_ipeak_bit);
 		if (ret) {
 			pr_err("cx_ipeak voting failed setting clock below turbo");
 			clock = cpp_dev->hw_info.freq_tbl
@@ -3108,7 +3136,10 @@ static unsigned long cpp_cx_ipeak_update(struct cpp_device *cpp_dev,
 		[(cpp_dev->hw_info.freq_tbl_count) - 1]) {
 		clock_rate = msm_cpp_set_core_clk(cpp_dev, clock, idx);
 		if (cpp_dev->turbo_vote == 1) {
-			ret = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, false);
+			pr_debug("%s:clk is less than Nominal, ipeak bit %d\n",
+				__func__, cpp_dev->cx_ipeak_bit);
+			ret = cam_cx_ipeak_unvote_cx_ipeak(
+				cpp_dev->cx_ipeak_bit);
 			if (ret)
 				pr_err("cx_ipeak unvoting failed");
 			else
@@ -4583,6 +4614,18 @@ static int cpp_probe(struct platform_device *pdev)
 		}
 	}
 
+	if (of_find_property(pdev->dev.of_node, "qcom,cpp-cx-ipeak", NULL)) {
+		cpp_dev->cpp_cx_ipeak = cx_ipeak_register(
+			pdev->dev.of_node, "qcom,cpp-cx-ipeak");
+		if (cpp_dev->cpp_cx_ipeak) {
+			cam_cx_ipeak_register_cx_ipeak(cpp_dev->cpp_cx_ipeak,
+				&cpp_dev->cx_ipeak_bit);
+			pr_debug("%s register cx_ipeak received bit %d\n",
+				__func__, cpp_dev->cx_ipeak_bit);
+		} else
+			pr_err("Cx ipeak Registration Unsuccessful");
+	}
+
 	rc = msm_camera_get_reset_info(pdev,
 			&cpp_dev->micro_iface_reset);
 	if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index 9f29a94..9a0491b 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -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
@@ -92,6 +92,7 @@
 #define MSM_CPP_START_ADDRESS		0x0
 #define MSM_CPP_END_ADDRESS			0x3F00
 
+#define MSM_CPP_AXI_RESET_RETRIES	5
 #define MSM_CPP_POLL_RETRIES		200
 #define MSM_CPP_TASKLETQ_SIZE		16
 #define MSM_CPP_TX_FIFO_LEVEL		16
@@ -292,6 +293,7 @@ struct cpp_device {
 	struct msm_cpp_vbif_data *vbif_data;
 	bool turbo_vote;
 	struct cx_ipeak_client *cpp_cx_ipeak;
+	int cx_ipeak_bit;
 	enum cpp_iommu_fault_state fault_status;
 };
 
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c
index 1d86a10..3131989 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 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
@@ -84,36 +84,72 @@ int msm_cpp_get_regulator_index(struct cpp_device *cpp_dev,
 	return -EINVAL;
 }
 
-static int cpp_get_clk_freq_tbl(struct clk *clk, struct cpp_hw_info *hw_info,
-	uint32_t min_clk_rate)
+static int cpp_get_clk_freq_tbl_dt(struct cpp_device *cpp_dev)
 {
-	uint32_t i;
+	uint32_t i, count, min_clk_rate;
 	uint32_t idx = 0;
-	signed long freq_tbl_entry = 0;
+	struct device_node *of_node;
+	uint32_t *rates;
+	int32_t rc = 0;
+	struct cpp_hw_info *hw_info;
 
-	if ((clk == NULL) || (hw_info == NULL)) {
+	if (cpp_dev == NULL) {
 		pr_err("Bad parameter\n");
-		return -EINVAL;
+		rc = -EINVAL;
+		goto err;
 	}
 
-	for (i = 0; i < MAX_FREQ_TBL; i++) {
-		freq_tbl_entry = clk_round_rate(clk, min_clk_rate);
-		pr_debug("entry=%ld\n", freq_tbl_entry);
-		if (freq_tbl_entry >= 0) {
-			if (freq_tbl_entry >= min_clk_rate) {
-				hw_info->freq_tbl[idx++] = freq_tbl_entry;
-				pr_debug("tbl[%d]=%ld\n", idx-1,
-					freq_tbl_entry);
+	of_node = cpp_dev->pdev->dev.of_node;
+	min_clk_rate = cpp_dev->min_clk_rate;
+	hw_info = &cpp_dev->hw_info;
+	pr_debug("min_clk_rate=%d\n", min_clk_rate);
+
+	if ((hw_info == NULL) || (of_node == NULL)) {
+		pr_err("Invalid hw_info %pK or ofnode %pK\n", hw_info, of_node);
+		rc = -EINVAL;
+		goto err;
+	}
+	count = of_property_count_u32_elems(of_node, "qcom,src-clock-rates");
+	if ((count == 0) || (count > MAX_FREQ_TBL)) {
+		pr_err("Clock count is invalid\n");
+		rc = -EINVAL;
+		goto err;
+	}
+
+	rates = devm_kcalloc(&cpp_dev->pdev->dev, count, sizeof(uint32_t),
+		GFP_KERNEL);
+	if (!rates) {
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,src-clock-rates",
+		rates, count);
+	if (rc) {
+		rc = -EINVAL;
+		goto mem_free;
+	}
+
+	for (i = 0; i < count; i++) {
+		pr_debug("entry=%d\n", rates[i]);
+		if (rates[i] >= 0) {
+			if (rates[i] >= min_clk_rate) {
+				hw_info->freq_tbl[idx++] = rates[i];
+				pr_debug("tbl[%d]=%d\n", idx-1, rates[i]);
 			}
 		} else {
-			pr_debug("freq table returned invalid entry/end %ld\n",
-				freq_tbl_entry);
+			pr_debug("rate is invalid entry/end %d\n", rates[i]);
 			break;
 		}
 	}
-	pr_debug("%s: idx %d", __func__, idx);
+
+	pr_debug("%s: idx %d\n", __func__, idx);
 	hw_info->freq_tbl_count = idx;
-	return 0;
+
+mem_free:
+	devm_kfree(&cpp_dev->pdev->dev, rates);
+err:
+	return rc;
 }
 
 int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev)
@@ -162,8 +198,7 @@ int msm_update_freq_tbl(struct cpp_device *cpp_dev)
 		rc = msm_cpp_core_clk_idx;
 		return rc;
 	}
-	rc = cpp_get_clk_freq_tbl(cpp_dev->cpp_clk[msm_cpp_core_clk_idx],
-		&cpp_dev->hw_info, cpp_dev->min_clk_rate);
+	rc = cpp_get_clk_freq_tbl_dt(cpp_dev);
 	if (rc < 0)  {
 		pr_err("%s: fail to get frequency table\n", __func__);
 		return rc;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index eb9983c..fd10eb9 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.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
@@ -647,6 +647,8 @@ static int32_t msm_actuator_move_focus(
 		a_ctrl->curr_step_pos, dest_step_pos, curr_lens_pos);
 
 	while (a_ctrl->curr_step_pos != dest_step_pos) {
+		if (a_ctrl->curr_region_index >= a_ctrl->region_size)
+			break;
 		step_boundary =
 			a_ctrl->region_params[
 			a_ctrl->curr_region_index].step_bound[dir];
@@ -1582,6 +1584,13 @@ static int msm_actuator_close(struct v4l2_subdev *sd,
 	}
 	kfree(a_ctrl->i2c_reg_tbl);
 	a_ctrl->i2c_reg_tbl = NULL;
+	if (a_ctrl->actuator_state == ACT_OPS_ACTIVE) {
+		rc = msm_actuator_power_down(a_ctrl);
+		if (rc < 0) {
+			pr_err("%s:%d Actuator Power down failed\n",
+				__func__, __LINE__);
+		}
+	}
 	a_ctrl->actuator_state = ACT_DISABLE_STATE;
 	mutex_unlock(a_ctrl->actuator_mutex);
 	CDBG("Exit\n");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index 08de2ee..54a6ade 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -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
@@ -14,10 +14,12 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/irqreturn.h>
+#include <soc/qcom/scm.h>
 #include "msm_csid.h"
 #include "msm_sd.h"
 #include "msm_camera_io_util.h"
 #include "msm_camera_dt_util.h"
+#include "msm_camera_tz_util.h"
 #include "include/msm_csid_2_0_hwreg.h"
 #include "include/msm_csid_2_2_hwreg.h"
 #include "include/msm_csid_3_0_hwreg.h"
@@ -59,6 +61,9 @@
 #define SOF_DEBUG_ENABLE                     1
 #define SOF_DEBUG_DISABLE                    0
 
+#define SCM_SVC_CAMERASS                     0x18
+#define SECURE_SYSCALL_ID                    0x6
+
 #define TRUE   1
 #define FALSE  0
 
@@ -76,6 +81,24 @@ static struct camera_vreg_t csid_vreg_info[] = {
 static struct v4l2_file_operations msm_csid_v4l2_subdev_fops;
 #endif
 
+static inline uint32_t msm_camera_vio_r(
+	void __iomem *base_addr, uint32_t offset, uint32_t dev_id) {
+	return msm_camera_tz_r(base_addr, offset,
+		MSM_CAMERA_TZ_IO_REGION_CSIDCORE0 + dev_id);
+}
+
+static inline void msm_camera_vio_w(uint32_t data,
+	void __iomem *base_addr, uint32_t offset, uint32_t dev_id) {
+	msm_camera_tz_w(data, base_addr, offset,
+		MSM_CAMERA_TZ_IO_REGION_CSIDCORE0 + dev_id);
+}
+
+static inline void msm_camera_vio_w_def(uint32_t data,
+	void __iomem *base_addr, uint32_t offset, uint32_t dev_id) {
+	msm_camera_tz_w_deferred(data, base_addr, offset,
+		MSM_CAMERA_TZ_IO_REGION_CSIDCORE0 + dev_id);
+}
+
 static int msm_csid_cid_lut(
 	struct msm_camera_csid_lut_params *csid_lut_params,
 	struct csid_device *csid_dev)
@@ -111,21 +134,24 @@ static int msm_csid_cid_lut(
 				 __func__, csid_lut_params->vc_cfg[i]->dt);
 			return rc;
 		}
-		val = msm_camera_io_r(csid_dev->base +
+		val = msm_camera_vio_r(csid_dev->base,
 			csid_dev->ctrl_reg->csid_reg.csid_cid_lut_vc_0_addr +
-			(csid_lut_params->vc_cfg[i]->cid >> 2) * 4)
+			(csid_lut_params->vc_cfg[i]->cid >> 2) * 4,
+			csid_dev->pdev->id)
 			& ~(0xFF << ((csid_lut_params->vc_cfg[i]->cid % 4) *
 			8));
 		val |= (csid_lut_params->vc_cfg[i]->dt <<
 			((csid_lut_params->vc_cfg[i]->cid % 4) * 8));
-		msm_camera_io_w(val, csid_dev->base +
+		msm_camera_vio_w(val, csid_dev->base,
 			csid_dev->ctrl_reg->csid_reg.csid_cid_lut_vc_0_addr +
-			(csid_lut_params->vc_cfg[i]->cid >> 2) * 4);
+			(csid_lut_params->vc_cfg[i]->cid >> 2) * 4,
+			csid_dev->pdev->id);
 
 		val = (csid_lut_params->vc_cfg[i]->decode_format << 4) | 0x3;
-		msm_camera_io_w(val, csid_dev->base +
+		msm_camera_vio_w(val, csid_dev->base,
 			csid_dev->ctrl_reg->csid_reg.csid_cid_n_cfg_addr +
-			(csid_lut_params->vc_cfg[i]->cid * 4));
+			(csid_lut_params->vc_cfg[i]->cid * 4),
+			csid_dev->pdev->id);
 	}
 	return rc;
 }
@@ -139,10 +165,12 @@ static void msm_csid_set_debug_reg(struct csid_device *csid_dev,
 	if ((csid_dev->hw_dts_version == CSID_VERSION_V34_1) ||
 		(csid_dev->hw_dts_version == CSID_VERSION_V36)) {
 		val = ((1 << csid_params->lane_cnt) - 1) << 20;
-		msm_camera_io_w(0x7f010800 | val, csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
-		msm_camera_io_w(0x7f010800 | val, csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+		msm_camera_vio_w(0x7f010800 | val, csid_dev->base,
+			csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr,
+			csid_dev->pdev->id);
+		msm_camera_vio_w(0x7f010800 | val, csid_dev->base,
+			csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr,
+			csid_dev->pdev->id);
 	} else {
 		if (csid_dev->csid_3p_enabled == 1) {
 			val = ((1 << csid_params->lane_cnt) - 1) <<
@@ -154,10 +182,12 @@ static void msm_csid_set_debug_reg(struct csid_device *csid_dev,
 				.csid_err_lane_overflow_offset_2p;
 		}
 		val |= csid_dev->ctrl_reg->csid_reg.csid_irq_mask_val;
-		msm_camera_io_w(val, csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
-		msm_camera_io_w(val, csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+		msm_camera_vio_w(val, csid_dev->base,
+			csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr,
+			csid_dev->pdev->id);
+		msm_camera_vio_w(val, csid_dev->base,
+			csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr,
+			csid_dev->pdev->id);
 	}
 }
 #elif(SHORT_PKT_CAPTURE)
@@ -169,10 +199,12 @@ static void msm_csid_set_debug_reg(struct csid_device *csid_dev,
 	if ((csid_dev->hw_dts_version == CSID_VERSION_V34_1) ||
 		(csid_dev->hw_dts_version == CSID_VERSION_V36)) {
 		val = ((1 << csid_params->lane_cnt) - 1) << 20;
-		msm_camera_io_w(0x7f010a00 | val, csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
-		msm_camera_io_w(0x7f010a00 | val, csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+		msm_camera_vio_w(0x7f010a00 | val, csid_dev->base,
+			csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr,
+			csid_dev->pdev->id);
+		msm_camera_vio_w(0x7f010a00 | val, csid_dev->base,
+			csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr,
+			csid_dev->pdev->id);
 	} else {
 		if (csid_dev->csid_3p_enabled == 1) {
 			val = ((1 << csid_params->lane_cnt) - 1) <<
@@ -185,10 +217,12 @@ static void msm_csid_set_debug_reg(struct csid_device *csid_dev,
 		}
 		val |= csid_dev->ctrl_reg->csid_reg.csid_irq_mask_val;
 		val |= SHORT_PKT_OFFSET;
-		msm_camera_io_w(val, csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
-		msm_camera_io_w(val, csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
+		msm_camera_vio_w(val, csid_dev->base,
+			csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr,
+			csid_dev->pdev->id);
+		msm_camera_vio_w(val, csid_dev->base,
+			csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr,
+			csid_dev->pdev->id);
 	}
 }
 #else
@@ -203,6 +237,14 @@ static void msm_csid_set_sof_freeze_debug_reg(
 {
 	uint32_t val = 0;
 
+	if (csid_dev && msm_camera_tz_is_secured(
+		MSM_CAMERA_TZ_IO_REGION_CSIDCORE0 +
+			csid_dev->pdev->id)) {
+		CDBG("%s, Skip set_sof_freeze_debug_reg in secure mode\n",
+			__func__);
+		return;
+	}
+
 	if (!irq_enable) {
 		val = msm_camera_io_r(csid_dev->base +
 			csid_dev->ctrl_reg->csid_reg.csid_irq_status_addr);
@@ -235,12 +277,23 @@ static int msm_csid_reset(struct csid_device *csid_dev)
 	int32_t rc = 0;
 	uint32_t irq = 0, irq_bitshift;
 
-	irq_bitshift = csid_dev->ctrl_reg->csid_reg.csid_rst_done_irq_bitshift;
-	msm_camera_io_w(csid_dev->ctrl_reg->csid_reg.csid_rst_stb_all,
-		csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_rst_cmd_addr);
-	rc = wait_for_completion_timeout(&csid_dev->reset_complete,
-		CSID_TIMEOUT);
+	CDBG("%s: id %d\n", __func__, csid_dev->pdev->id);
+
+	if (msm_camera_tz_is_secured(
+		MSM_CAMERA_TZ_IO_REGION_CSIDCORE0 + csid_dev->pdev->id)) {
+		msm_camera_enable_irq(csid_dev->irq, false);
+		rc = msm_camera_tz_reset_hw_block(
+			csid_dev->ctrl_reg->csid_reg.csid_rst_stb_all,
+			MSM_CAMERA_TZ_IO_REGION_CSIDCORE0 + csid_dev->pdev->id);
+	} else {
+		irq_bitshift =
+		csid_dev->ctrl_reg->csid_reg.csid_rst_done_irq_bitshift;
+		msm_camera_io_w(csid_dev->ctrl_reg->csid_reg.csid_rst_stb_all,
+			csid_dev->base +
+			csid_dev->ctrl_reg->csid_reg.csid_rst_cmd_addr);
+		rc = wait_for_completion_timeout(&csid_dev->reset_complete,
+			CSID_TIMEOUT);
+	}
 	if (rc < 0) {
 		pr_err("wait_for_completion in %s fail rc = %d\n",
 			__func__, rc);
@@ -317,6 +370,24 @@ static int msm_csid_config(struct csid_device *csid_dev,
 		return -EINVAL;
 	}
 
+	if (csid_params->is_secure == 1) {
+		struct scm_desc desc = {0};
+
+		desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL);
+		desc.args[0] = csid_params->is_secure;
+		desc.args[1] = csid_params->phy_sel;
+
+		CDBG("phy_sel : %d, secure : %d\n",
+			csid_params->phy_sel, csid_params->is_secure);
+		if (scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS,
+			SECURE_SYSCALL_ID), &desc)) {
+			pr_err("%s:%d scm call to hypervisor failed\n",
+				__func__, __LINE__);
+			return -EINVAL;
+		}
+		msm_camera_tz_clear_tzbsp_status();
+	}
+
 	csid_dev->csid_lane_cnt = csid_params->lane_cnt;
 	rc = msm_csid_reset(csid_dev);
 	if (rc < 0) {
@@ -344,27 +415,31 @@ static int msm_csid_config(struct csid_device *csid_dev,
 		/* 31:24 V blank, 23:13 H blank, 3:2 num of active DT, 1:0 VC */
 		val = ((tm->v_blanking_count & 0xFF) << 24) |
 			((tm->h_blanking_count & 0x7FF) << 13);
-		msm_camera_io_w(val, csidbase +
-			csid_dev->ctrl_reg->csid_reg.csid_tg_vc_cfg_addr);
+		msm_camera_vio_w_def(val, csidbase,
+			csid_dev->ctrl_reg->csid_reg.csid_tg_vc_cfg_addr,
+			csid_dev->pdev->id);
 		CDBG("[TG] CSID_TG_VC_CFG_ADDR 0x%08x\n", val);
 
 		/* 28:16 bytes per lines, 12:0 num of lines */
 		val = ((tm->num_bytes_per_line & 0x1FFF) << 16) |
 			(tm->num_lines & 0x1FFF);
-		msm_camera_io_w(val, csidbase +
-			csid_dev->ctrl_reg->csid_reg.csid_tg_dt_n_cfg_0_addr);
+		msm_camera_vio_w_def(val, csidbase,
+			csid_dev->ctrl_reg->csid_reg.csid_tg_dt_n_cfg_0_addr,
+			csid_dev->pdev->id);
 		CDBG("[TG] CSID_TG_DT_n_CFG_0_ADDR 0x%08x\n", val);
 
 		/* 5:0 data type */
 		val = csid_params->lut_params.vc_cfg[0]->dt;
-		msm_camera_io_w(val, csidbase +
-			csid_dev->ctrl_reg->csid_reg.csid_tg_dt_n_cfg_1_addr);
+		msm_camera_vio_w_def(val, csidbase,
+			csid_dev->ctrl_reg->csid_reg.csid_tg_dt_n_cfg_1_addr,
+			csid_dev->pdev->id);
 		CDBG("[TG] CSID_TG_DT_n_CFG_1_ADDR 0x%08x\n", val);
 
 		/* 2:0 output random */
-		msm_camera_io_w(csid_dev->testmode_params.payload_mode,
-			csidbase +
-			csid_dev->ctrl_reg->csid_reg.csid_tg_dt_n_cfg_2_addr);
+		msm_camera_vio_w(csid_dev->testmode_params.payload_mode,
+			csidbase,
+			csid_dev->ctrl_reg->csid_reg.csid_tg_dt_n_cfg_2_addr,
+			csid_dev->pdev->id);
 	} else {
 		val = csid_params->lane_cnt - 1;
 
@@ -398,16 +473,19 @@ static int msm_csid_config(struct csid_device *csid_dev,
 			csid_dev->ctrl_reg->csid_reg.csid_dl_input_sel_shift;
 		if (csid_dev->hw_version < CSID_VERSION_V30) {
 			val |= (0xF << 10);
-			msm_camera_io_w(val, csidbase +
-			csid_dev->ctrl_reg->csid_reg.csid_core_ctrl_0_addr);
+			msm_camera_vio_w(val, csidbase,
+			    csid_dev->ctrl_reg->csid_reg.csid_core_ctrl_0_addr,
+			    csid_dev->pdev->id);
 		} else {
-			msm_camera_io_w(val, csidbase +
-			csid_dev->ctrl_reg->csid_reg.csid_core_ctrl_0_addr);
+			msm_camera_vio_w(val, csidbase,
+			    csid_dev->ctrl_reg->csid_reg.csid_core_ctrl_0_addr,
+				csid_dev->pdev->id);
 			val = csid_params->phy_sel <<
 			    csid_dev->ctrl_reg->csid_reg.csid_phy_sel_shift;
 			val |= 0xF;
-			msm_camera_io_w(val, csidbase +
-			csid_dev->ctrl_reg->csid_reg.csid_core_ctrl_1_addr);
+			msm_camera_vio_w(val, csidbase,
+			    csid_dev->ctrl_reg->csid_reg.csid_core_ctrl_1_addr,
+				csid_dev->pdev->id);
 		}
 		if (csid_dev->hw_version >= CSID_VERSION_V35 &&
 			csid_params->csi_3p_sel == 1) {
@@ -423,8 +501,9 @@ static int msm_csid_config(struct csid_device *csid_dev,
 			val |= csid_params->phy_sel <<
 			    csid_dev->ctrl_reg->csid_reg.csid_phy_sel_shift_3p;
 			val |= ENABLE_3P_BIT;
-			msm_camera_io_w(val, csidbase + csid_dev->ctrl_reg
-				->csid_reg.csid_3p_ctrl_0_addr);
+			msm_camera_vio_w(val, csidbase,
+			    csid_dev->ctrl_reg->csid_reg.csid_3p_ctrl_0_addr,
+				csid_dev->pdev->id);
 		}
 	}
 
@@ -436,8 +515,9 @@ static int msm_csid_config(struct csid_device *csid_dev,
 	msm_csid_set_debug_reg(csid_dev, csid_params);
 
 	if (csid_dev->is_testmode == 1)
-		msm_camera_io_w(0x00A06437, csidbase +
-			csid_dev->ctrl_reg->csid_reg.csid_tg_ctrl_addr);
+		msm_camera_vio_w(0x00A06437, csidbase,
+			csid_dev->ctrl_reg->csid_reg.csid_tg_ctrl_addr,
+			csid_dev->pdev->id);
 
 	return rc;
 }
@@ -487,6 +567,13 @@ static irqreturn_t msm_csid_irq(int irq_num, void *data)
 		return IRQ_HANDLED;
 	}
 
+	/* In secure mode interrupt is handeled by the TZ */
+	if (csid_dev && msm_camera_tz_is_secured(
+		MSM_CAMERA_TZ_IO_REGION_CSIDCORE0 + csid_dev->pdev->id)) {
+		CDBG("%s, skip\n", __func__);
+		return IRQ_HANDLED;
+	}
+
 	if (csid_dev->csid_sof_debug == SOF_DEBUG_ENABLE) {
 		if (csid_dev->csid_sof_debug_count < CSID_SOF_DEBUG_COUNT)
 			csid_dev->csid_sof_debug_count++;
@@ -591,8 +678,9 @@ static int msm_csid_init(struct csid_device *csid_dev, uint32_t *csid_version)
 	}
 	CDBG("%s:%d called\n", __func__, __LINE__);
 	csid_dev->hw_version =
-		msm_camera_io_r(csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_hw_version_addr);
+		msm_camera_vio_r(csid_dev->base,
+			csid_dev->ctrl_reg->csid_reg.csid_hw_version_addr,
+			csid_dev->pdev->id);
 	CDBG("%s:%d called csid_dev->hw_version %x\n", __func__, __LINE__,
 		csid_dev->hw_version);
 	*csid_version = csid_dev->hw_version;
@@ -601,10 +689,18 @@ static int msm_csid_init(struct csid_device *csid_dev, uint32_t *csid_version)
 	csid_dev->is_testmode = 0;
 
 	init_completion(&csid_dev->reset_complete);
-
-	rc = msm_camera_enable_irq(csid_dev->irq, true);
-	if (rc < 0)
-		pr_err("%s: irq enable failed\n", __func__);
+	if (msm_camera_tz_is_secured(
+		MSM_CAMERA_TZ_IO_REGION_CSIDCORE0 + csid_dev->pdev->id)) {
+		/* TEE is not accesible from IRQ handler context.
+		 * Switch IRQ off and rely on TEE to handle interrupt in
+		 * polling mode
+		 */
+		rc = msm_camera_enable_irq(csid_dev->irq, false);
+	} else {
+		rc = msm_camera_enable_irq(csid_dev->irq, true);
+		if (rc < 0)
+			pr_err("%s: irq enable failed\n", __func__);
+	}
 	rc = msm_csid_reset(csid_dev);
 	if (rc < 0) {
 		pr_err("%s:%d msm_csid_reset failed\n", __func__, __LINE__);
@@ -654,12 +750,15 @@ static int msm_csid_release(struct csid_device *csid_dev)
 	CDBG("%s:%d, hw_version = 0x%x\n", __func__, __LINE__,
 		csid_dev->hw_version);
 
-	irq = msm_camera_io_r(csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_status_addr);
-	msm_camera_io_w(irq, csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
-	msm_camera_io_w(0, csid_dev->base +
-		csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
+	irq = msm_camera_vio_r(csid_dev->base,
+		csid_dev->ctrl_reg->csid_reg.csid_irq_status_addr,
+		csid_dev->pdev->id);
+	msm_camera_vio_w(irq, csid_dev->base,
+		csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr,
+		csid_dev->pdev->id);
+	msm_camera_vio_w(0, csid_dev->base,
+		csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr,
+		csid_dev->pdev->id);
 
 	msm_camera_enable_irq(csid_dev->irq, false);
 
@@ -691,6 +790,22 @@ static int msm_csid_release(struct csid_device *csid_dev)
 
 	csid_dev->csid_state = CSID_POWER_DOWN;
 
+	if (csid_dev->current_csid_params.is_secure == 1) {
+		struct scm_desc desc = {0};
+
+		desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL);
+		desc.args[0] = 0;
+		desc.args[1] = csid_dev->current_csid_params.phy_sel;
+
+		if (scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS,
+			SECURE_SYSCALL_ID), &desc)) {
+			pr_err("%s:%d scm call to hyp with protect 0 failed\n",
+				__func__, __LINE__);
+			return -EINVAL;
+		}
+		msm_camera_tz_clear_tzbsp_status();
+	}
+
 	if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSID,
 		CAM_AHB_SUSPEND_VOTE) < 0)
 		pr_err("%s: failed to remove vote from AHB\n", __func__);
@@ -894,6 +1009,7 @@ static int32_t msm_csid_cmd32(struct csid_device *csid_dev, void *arg)
 		csid_params.phy_sel = csid_params32.phy_sel;
 		csid_params.csi_clk = csid_params32.csi_clk;
 		csid_params.csi_3p_sel = csid_params32.csi_3p_sel;
+		csid_params.is_secure = csid_params32.is_secure;
 
 		lut_par32 = csid_params32.lut_params;
 		csid_params.lut_params.num_cid = lut_par32.num_cid;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h
index 409c3e9..cbf8de7 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h
@@ -51,10 +51,10 @@ static struct csiphy_reg_3ph_parms_t csiphy_v3_5_3ph = {
 	{0x148, 0xFE},
 	{0x14C, 0x1},
 	{0x154, 0x0},
-	{0x15C, 0x33},
+	{0x15C, 0x23},
 	{0x160, ULPM_WAKE_UP_TIMER_MODE},
 	{0x164, 0x50},
-	{0x168, 0xA0},
+	{0x168, 0x70},
 	{0x16C, 0x17},
 	{0x170, 0x41},
 	{0x174, 0x41},
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
index c41f8f9..fa875cb 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-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
@@ -727,7 +727,7 @@ static int32_t msm_flash_query_current(
 
 	if (flash_ctrl->switch_trigger) {
 		ret = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
-					QUERY_MAX_CURRENT, &max_current);
+					QUERY_MAX_AVAIL_CURRENT, &max_current);
 		if (ret < 0) {
 			pr_err("%s:%d Query max_avail_curr failed ret = %d\n",
 				__func__, __LINE__, ret);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
index 7449f94..8dece3b 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.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
@@ -1460,9 +1460,10 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
 		switch (power_setting->seq_type) {
 		case SENSOR_CLK:
 			if (power_setting->seq_val >= ctrl->clk_info_size) {
-				pr_err_ratelimited("%s clk index %d >= max %zu\n",
-				  __func__, power_setting->seq_val,
-				ctrl->clk_info_size);
+				pr_err_ratelimited("%s clk %d >=max %zu\n"
+					, __func__,
+					power_setting->seq_val,
+					ctrl->clk_info_size);
 				goto power_up_failed;
 			}
 			if (power_setting->config_val)
@@ -1473,7 +1474,7 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
 				ctrl->clk_info_size, true);
 			if (rc < 0) {
 				pr_err_ratelimited("%s: clk enable failed\n",
-				 __func__);
+					__func__);
 				goto power_up_failed;
 			}
 			break;
diff --git a/drivers/media/platform/msm/npu/npu_hw_access.c b/drivers/media/platform/msm/npu/npu_hw_access.c
index a5b2ea7..8727ab8 100644
--- a/drivers/media/platform/msm/npu/npu_hw_access.c
+++ b/drivers/media/platform/msm/npu/npu_hw_access.c
@@ -33,8 +33,7 @@ uint32_t npu_core_reg_read(struct npu_device *npu_dev, uint32_t off)
 {
 	uint32_t ret = 0;
 
-	ret = readl_relaxed(npu_dev->core_io.base + off);
-	__iormb();
+	ret = readl(npu_dev->core_io.base + off);
 	return ret;
 }
 
@@ -48,8 +47,7 @@ uint32_t npu_bwmon_reg_read(struct npu_device *npu_dev, uint32_t off)
 {
 	uint32_t ret = 0;
 
-	ret = readl_relaxed(npu_dev->bwmon_io.base + off);
-	__iormb();
+	ret = readl(npu_dev->bwmon_io.base + off);
 	return ret;
 }
 
@@ -64,10 +62,8 @@ uint32_t npu_qfprom_reg_read(struct npu_device *npu_dev, uint32_t off)
 {
 	uint32_t ret = 0;
 
-	if (npu_dev->qfprom_io.base) {
-		ret = readl_relaxed(npu_dev->qfprom_io.base + off);
-		__iormb();
-	}
+	if (npu_dev->qfprom_io.base)
+		ret = readl(npu_dev->qfprom_io.base + off);
 
 	return ret;
 }
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
index b0e7160..dcc3191 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
@@ -79,6 +79,7 @@ u32 sde_apply_comp_ratio_factor(u32 quota,
 
 #define RES_1080p		(1088*1920)
 #define RES_UHD		(3840*2160)
+#define RES_WQXGA	(2560*1600)
 #define XIN_HALT_TIMEOUT_US	0x4000
 
 static int sde_mdp_wait_for_xin_halt(u32 xin_id)
@@ -242,18 +243,36 @@ u32 sde_mdp_get_ot_limit(u32 width, u32 height, u32 pixfmt, u32 fps, u32 is_rd)
 	SDEROT_DBG("w:%d h:%d fps:%d pixfmt:%8.8x yuv:%d res:%llu rd:%d\n",
 		width, height, fps, pixfmt, is_yuv, res, is_rd);
 
-	if (!is_yuv)
-		goto exit;
-
 	/*
 	 * If (total_source_pixels <= 62208000  && YUV) -> RD/WROT=2 //1080p30
 	 * If (total_source_pixels <= 124416000 && YUV) -> RD/WROT=4 //1080p60
 	 * If (total_source_pixels <= 2160p && YUV && FPS <= 30) -> RD/WROT = 32
 	 */
-	if (res <= (RES_1080p * 30))
-		ot_lim = 2;
-	else if (res <= (RES_1080p * 60))
-		ot_lim = 4;
+	switch (mdata->mdss_version) {
+	case SDE_MDP_HW_REV_540:
+		if (is_yuv) {
+			if (res <= (RES_1080p * 30))
+				ot_lim = 2;
+			else if (res <= (RES_1080p * 60))
+				ot_lim = 4;
+			else if (res <= (RES_WQXGA * 60))
+				ot_lim = 4;
+			else if (res <= (RES_UHD * 30))
+				ot_lim = 8;
+		} else if (fmt->bpp == 4 && res <= (RES_WQXGA * 60)) {
+			ot_lim = 16;
+		}
+
+		break;
+	default:
+		if (is_yuv) {
+			if (res <= (RES_1080p * 30))
+				ot_lim = 2;
+			else if (res <= (RES_1080p * 60))
+				ot_lim = 4;
+		}
+		break;
+	}
 
 exit:
 	SDEROT_DBG("ot_lim=%d\n", ot_lim);
@@ -535,7 +554,7 @@ static void sde_mdp_parse_vbif_memtype(struct platform_device *pdev,
 			"qcom,mdss-rot-vbif-memtype");
 	mdata->vbif_memtype = kcalloc(mdata->vbif_memtype_count,
 			sizeof(u32), GFP_KERNEL);
-	if (!mdata->vbif_memtype) {
+	if (!mdata->vbif_memtype || !mdata->vbif_memtype_count) {
 		mdata->vbif_memtype_count = 0;
 		return;
 	}
@@ -563,7 +582,7 @@ static void sde_mdp_parse_vbif_qos(struct platform_device *pdev,
 			"qcom,mdss-rot-vbif-qos-setting");
 	mdata->vbif_nrt_qos = kcalloc(mdata->npriority_lvl,
 			sizeof(u32), GFP_KERNEL);
-	if (!mdata->vbif_nrt_qos) {
+	if (!mdata->vbif_nrt_qos || !mdata->npriority_lvl) {
 		mdata->npriority_lvl = 0;
 		return;
 	}
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 4e88706c..9d26279 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -552,9 +552,12 @@ static int get_hfi_extradata_index(enum hal_extradata_id index)
 	case HAL_EXTRADATA_STREAM_USERDATA:
 		ret = HFI_PROPERTY_PARAM_VDEC_STREAM_USERDATA_EXTRADATA;
 		break;
-	case HAL_EXTRADATA_FRAME_QP:
+	case HAL_EXTRADATA_DEC_FRAME_QP:
 		ret = HFI_PROPERTY_PARAM_VDEC_FRAME_QP_EXTRADATA;
 		break;
+	case HAL_EXTRADATA_ENC_FRAME_QP:
+		ret = HFI_PROPERTY_PARAM_VENC_FRAME_QP_EXTRADATA;
+		break;
 	case HAL_EXTRADATA_LTR_INFO:
 		ret = HFI_PROPERTY_PARAM_VENC_LTR_INFO;
 		break;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 6901d54..001bc65 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -440,8 +440,8 @@ static u32 get_frame_size(struct msm_vidc_inst *inst,
 		if (inst->flags & VIDC_SECURE) {
 			dprintk(VIDC_DBG,
 				"Change secure input buffer size from %u to %u\n",
-				frame_size, frame_size / 2);
-			frame_size = frame_size / 2;
+				frame_size, ALIGN(frame_size/2, SZ_4K));
+			frame_size = ALIGN(frame_size/2, SZ_4K);
 		}
 
 		if (inst->buffer_size_limit &&
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 09f3f7d..5dbd467 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.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
@@ -677,7 +677,7 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
 		.name = "Extradata Type",
 		.type = V4L2_CTRL_TYPE_MENU,
 		.minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
-		.maximum = V4L2_MPEG_VIDC_EXTRADATA_UBWC_CR_STATS_INFO,
+		.maximum = V4L2_MPEG_VIDC_EXTRADATA_ENC_FRAME_QP,
 		.default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
 		.menu_skip_mask = ~(
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
@@ -691,7 +691,8 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO) |
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_LTR) |
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_ROI_QP) |
-			(1 << V4L2_MPEG_VIDC_EXTRADATA_HDR10PLUS_METADATA)
+			(1 << V4L2_MPEG_VIDC_EXTRADATA_HDR10PLUS_METADATA) |
+			(1ULL << V4L2_MPEG_VIDC_EXTRADATA_ENC_FRAME_QP)
 			),
 		.qmenu = mpeg_video_vidc_extradata,
 	},
@@ -1808,6 +1809,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
 			inst->bufq[OUTPUT_PORT].num_planes = 2;
 			break;
 		case V4L2_MPEG_VIDC_EXTRADATA_LTR:
+		case V4L2_MPEG_VIDC_EXTRADATA_ENC_FRAME_QP:
 			inst->bufq[CAPTURE_PORT].num_planes = 2;
 			break;
 		default:
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 4693431..d0ad6d8 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -2060,6 +2060,8 @@ static void msm_vidc_cleanup_instance(struct msm_vidc_inst *inst)
 		dprintk(VIDC_ERR,
 			"Failed to release mark_data buffers\n");
 
+	msm_comm_free_buffer_tags(inst);
+
 	msm_comm_release_eos_buffers(inst);
 
 	if (msm_comm_release_output_buffers(inst, true))
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 37341da..af7d797 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -57,7 +57,7 @@ static inline unsigned long int get_ubwc_compression_ratio(
 	struct ubwc_cr_stats_info_type ubwc_stats_info)
 {
 	unsigned long int sum = 0, weighted_sum = 0;
-	unsigned long int compression_ratio = 1 << 16;
+	unsigned long int compression_ratio = 0;
 
 	weighted_sum =
 		32  * ubwc_stats_info.cr_stats_info0 +
@@ -727,7 +727,9 @@ int msm_vidc_set_clocks(struct msm_vidc_core *core)
 	struct hfi_device *hdev;
 	unsigned long freq_core_1 = 0, freq_core_2 = 0, rate = 0;
 	unsigned long freq_core_max = 0;
-	struct msm_vidc_inst *temp = NULL;
+	struct msm_vidc_inst *inst = NULL;
+	struct msm_vidc_buffer *temp, *next;
+	u32 device_addr, filled_len;
 	int rc = 0, i = 0;
 	struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
 	bool increment, decrement;
@@ -743,15 +745,34 @@ int msm_vidc_set_clocks(struct msm_vidc_core *core)
 	mutex_lock(&core->lock);
 	increment = false;
 	decrement = true;
-	list_for_each_entry(temp, &core->instances, list) {
+	list_for_each_entry(inst, &core->instances, list) {
+		device_addr = 0;
+		filled_len = 0;
+		mutex_lock(&inst->registeredbufs.lock);
+		list_for_each_entry_safe(temp, next,
+				&inst->registeredbufs.list, list) {
+			if (temp->vvb.vb2_buf.type ==
+				V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+				filled_len = max(filled_len,
+					temp->vvb.vb2_buf.planes[0].bytesused);
+				device_addr = temp->smem[0].device_addr;
+			}
+		}
+		mutex_unlock(&inst->registeredbufs.lock);
 
-		if (temp->clk_data.core_id == VIDC_CORE_ID_1)
-			freq_core_1 += temp->clk_data.min_freq;
-		else if (temp->clk_data.core_id == VIDC_CORE_ID_2)
-			freq_core_2 += temp->clk_data.min_freq;
-		else if (temp->clk_data.core_id == VIDC_CORE_ID_3) {
-			freq_core_1 += temp->clk_data.min_freq;
-			freq_core_2 += temp->clk_data.min_freq;
+		if (!filled_len || !device_addr) {
+			dprintk(VIDC_DBG, "%s no input for session %x\n",
+				__func__, hash32_ptr(inst->session));
+			continue;
+		}
+
+		if (inst->clk_data.core_id == VIDC_CORE_ID_1)
+			freq_core_1 += inst->clk_data.min_freq;
+		else if (inst->clk_data.core_id == VIDC_CORE_ID_2)
+			freq_core_2 += inst->clk_data.min_freq;
+		else if (inst->clk_data.core_id == VIDC_CORE_ID_3) {
+			freq_core_1 += inst->clk_data.min_freq;
+			freq_core_2 += inst->clk_data.min_freq;
 		}
 
 		freq_core_max = max_t(unsigned long, freq_core_1, freq_core_2);
@@ -765,7 +786,7 @@ int msm_vidc_set_clocks(struct msm_vidc_core *core)
 			break;
 		}
 
-		if (temp->clk_data.turbo_mode) {
+		if (inst->clk_data.turbo_mode) {
 			dprintk(VIDC_PROF,
 				"Found an instance with Turbo request\n");
 			freq_core_max = msm_vidc_max_freq(core);
@@ -773,10 +794,10 @@ int msm_vidc_set_clocks(struct msm_vidc_core *core)
 			break;
 		}
 		/* increment even if one session requested for it */
-		if (temp->clk_data.dcvs_flags & MSM_VIDC_DCVS_INCR)
+		if (inst->clk_data.dcvs_flags & MSM_VIDC_DCVS_INCR)
 			increment = true;
 		/* decrement only if all sessions requested for it */
-		if (!(temp->clk_data.dcvs_flags & MSM_VIDC_DCVS_DECR))
+		if (!(inst->clk_data.dcvs_flags & MSM_VIDC_DCVS_DECR))
 			decrement = false;
 	}
 
@@ -816,8 +837,8 @@ int msm_vidc_validate_operating_rate(struct msm_vidc_inst *inst,
 {
 	struct msm_vidc_inst *temp;
 	struct msm_vidc_core *core;
-	unsigned long max_freq, freq_left, ops_left, load, cycles, freq = 0;
-	unsigned long mbs_per_second;
+	unsigned long max_freq, freq_left, op_rate_possible, load, cycles;
+	unsigned long mbs_per_second, freq_core0 = 0, freq_core1 = 0, freq;
 	int rc = 0;
 	u32 curr_operating_rate = 0;
 
@@ -826,7 +847,13 @@ int msm_vidc_validate_operating_rate(struct msm_vidc_inst *inst,
 		return -EINVAL;
 	}
 	core = inst->core;
-	curr_operating_rate = inst->clk_data.operating_rate >> 16;
+	curr_operating_rate =
+		max(inst->clk_data.operating_rate >> 16, inst->prop.fps);
+	operating_rate = operating_rate >> 16;
+
+	/* always allow decreasing operating rate*/
+	if (curr_operating_rate >= operating_rate)
+		return 0;
 
 	mutex_lock(&core->lock);
 	max_freq = msm_vidc_max_freq(core);
@@ -836,10 +863,24 @@ int msm_vidc_validate_operating_rate(struct msm_vidc_inst *inst,
 				temp->state >= MSM_VIDC_RELEASE_RESOURCES_DONE)
 			continue;
 
-		freq += temp->clk_data.min_freq;
+		if (temp->clk_data.core_id == VIDC_CORE_ID_1)
+			freq_core0 += temp->clk_data.min_freq;
+		else if (temp->clk_data.core_id == VIDC_CORE_ID_2)
+			freq_core1 += temp->clk_data.min_freq;
+		else if (temp->clk_data.core_id == VIDC_CORE_ID_3) {
+			freq_core0 += temp->clk_data.min_freq;
+			freq_core1 += temp->clk_data.min_freq;
+		}
 	}
 
-	freq_left = max_freq - freq;
+	if (inst->clk_data.core_id == VIDC_CORE_ID_1)
+		freq = freq_core0;
+	else if (inst->clk_data.core_id == VIDC_CORE_ID_2)
+		freq = freq_core1;
+	else
+		freq = max(freq_core0, freq_core1);
+
+	freq_left = max_freq > freq ? max_freq - freq : 0;
 
 	mbs_per_second = msm_comm_get_inst_load_per_core(inst,
 		LOAD_CALC_NO_QUIRKS);
@@ -850,13 +891,15 @@ int msm_vidc_validate_operating_rate(struct msm_vidc_inst *inst,
 			inst->clk_data.entry->low_power_cycles :
 			cycles;
 
+	if (inst->clk_data.work_route)
+		cycles /= inst->clk_data.work_route;
+
 	load = cycles * mbs_per_second;
 
-	ops_left = load ? (freq_left / load) : 0;
+	op_rate_possible = load ? (freq_left * curr_operating_rate / load) : 0;
 
-	operating_rate = operating_rate >> 16;
 
-	if ((curr_operating_rate * (1 + ops_left)) >= operating_rate ||
+	if (op_rate_possible >= operating_rate ||
 			msm_vidc_clock_voting ||
 			inst->clk_data.buffer_counter < DCVS_FTB_WINDOW) {
 		dprintk(VIDC_DBG,
@@ -896,7 +939,7 @@ int msm_comm_scale_clocks(struct msm_vidc_inst *inst)
 				temp->vvb.vb2_buf.planes[0].bytesused);
 			if (inst->session_type == MSM_VIDC_ENCODER &&
 				(temp->vvb.flags &
-				 V4L2_QCOM_BUF_FLAG_PERF_MODE)) {
+				V4L2_QCOM_BUF_FLAG_PERF_MODE)) {
 				is_turbo = true;
 			}
 			device_addr = temp->smem[0].device_addr;
@@ -907,7 +950,7 @@ int msm_comm_scale_clocks(struct msm_vidc_inst *inst)
 	if (!filled_len || !device_addr) {
 		dprintk(VIDC_DBG, "%s no input for session %x\n",
 			__func__, hash32_ptr(inst->session));
-		goto no_clock_change;
+		return 0;
 	}
 
 	freq = call_core_op(inst->core, calc_freq, inst, filled_len);
@@ -925,7 +968,6 @@ int msm_comm_scale_clocks(struct msm_vidc_inst *inst)
 
 	msm_vidc_set_clocks(inst->core);
 
-no_clock_change:
 	return 0;
 }
 
@@ -1386,7 +1428,7 @@ int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst)
 static inline int msm_vidc_power_save_mode_enable(struct msm_vidc_inst *inst,
 	bool enable)
 {
-	u32 rc = 0, mbs_per_frame;
+	u32 rc = 0, mbs_per_frame, mbs_per_sec;
 	u32 prop_id = 0;
 	void *pdata = NULL;
 	struct hfi_device *hdev = NULL;
@@ -1401,8 +1443,10 @@ static inline int msm_vidc_power_save_mode_enable(struct msm_vidc_inst *inst,
 		return 0;
 	}
 	mbs_per_frame = msm_vidc_get_mbs_per_frame(inst);
+	mbs_per_sec = mbs_per_frame * msm_vidc_get_fps(inst);
+
 	if (mbs_per_frame > inst->core->resources.max_hq_mbs_per_frame ||
-		msm_vidc_get_fps(inst) > inst->core->resources.max_hq_fps) {
+		mbs_per_sec > inst->core->resources.max_hq_mbs_per_sec) {
 		enable = true;
 	}
 	/* Power saving always disabled for CQ RC mode. */
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index fab9514..f63930e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -70,6 +70,7 @@ const char *const mpeg_video_vidc_extradata[] = {
 	"Extradata display VUI",
 	"Extradata vpx color space",
 	"Extradata UBWC CR stats info",
+	"Extradata enc frame QP",
 };
 
 static void handle_session_error(enum hal_command_response cmd, void *data);
@@ -5397,7 +5398,10 @@ enum hal_extradata_id msm_comm_get_hal_extradata_index(
 		ret = HAL_EXTRADATA_STREAM_USERDATA;
 		break;
 	case V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP:
-		ret = HAL_EXTRADATA_FRAME_QP;
+		ret = HAL_EXTRADATA_DEC_FRAME_QP;
+		break;
+	case V4L2_MPEG_VIDC_EXTRADATA_ENC_FRAME_QP:
+		ret = HAL_EXTRADATA_ENC_FRAME_QP;
 		break;
 	case V4L2_MPEG_VIDC_EXTRADATA_LTR:
 		ret = HAL_EXTRADATA_LTR_INFO;
@@ -6399,8 +6403,8 @@ int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst,
 					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 				if (!i) { /* yuv */
 					skip = false;
-					offset = vb->planes[i].data_offset;
-					size = vb->planes[i].bytesused;
+					offset = 0;
+					size = vb->planes[i].length;
 					cache_op = SMEM_CACHE_INVALIDATE;
 				}
 			}
@@ -6416,8 +6420,8 @@ int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst,
 					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 				if (!i) { /* bitstream */
 					skip = false;
-					offset = vb->planes[i].data_offset;
-					size = vb->planes[i].bytesused;
+					offset = 0;
+					size = vb->planes[i].length;
 					cache_op = SMEM_CACHE_INVALIDATE;
 				}
 			}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index d546716..6e42ea2 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -253,8 +253,6 @@ struct msm_vidc_platform_data {
 	struct msm_vidc_ubwc_config *ubwc_config;
 	unsigned int ubwc_config_length;
 	unsigned int sku_version;
-	phys_addr_t gcc_register_base;
-	uint32_t gcc_register_size;
 	uint32_t vpu_ver;
 };
 
@@ -505,7 +503,7 @@ struct msm_vidc_ctrl {
 	s64 maximum;
 	s64 default_value;
 	u32 step;
-	u32 menu_skip_mask;
+	u64 menu_skip_mask;
 	u32 flags;
 	const char * const *qmenu;
 };
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
index 667f5c6..e4ab7e6 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
@@ -58,9 +58,6 @@
 	.purpose = p	\
 }
 
-#define GCC_VIDEO_AXI_REG_START_ADDR	0x10B024
-#define GCC_VIDEO_AXI_REG_SIZE		0xC
-
 static struct msm_vidc_codec_data default_codec_data[] =  {
 	CODEC_ENTRY(V4L2_PIX_FMT_H264, MSM_VIDC_ENCODER, 125, 675, 320),
 	CODEC_ENTRY(V4L2_PIX_FMT_H264, MSM_VIDC_DECODER, 125, 675, 320),
@@ -194,8 +191,8 @@ static struct msm_vidc_common_data sm6150_common_data[] = {
 		.value = 8160,
 	},
 	{
-		.key = "qcom,max-hq-frames-per-sec",
-		.value = 30,
+		.key = "qcom,max-hq-mbs-per-sec",
+		.value = 244800,  /* 1920 x 1088 @ 30 fps */
 	},
 	{
 		.key = "qcom,max-b-frame-size",
@@ -253,8 +250,8 @@ static struct msm_vidc_common_data trinket_common_data[] = {
 		.value = 8160,
 	},
 	{
-		.key = "qcom,max-hq-frames-per-sec",
-		.value = 30,
+		.key = "qcom,max-hq-mbs-per-sec",
+		.value = 244800,  /* 1920 x 1088 @ 30 fps */
 	},
 	{
 		.key = "qcom,max-b-frame-size",
@@ -317,8 +314,8 @@ static struct msm_vidc_common_data sm8150_common_data[] = {
 		.value = 8160,
 	},
 	{
-		.key = "qcom,max-hq-frames-per-sec",
-		.value = 60,
+		.key = "qcom,max-hq-mbs-per-sec",
+		.value = 244800,  /* 1920 x 1088 @ 30 fps */
 	},
 	{
 		.key = "qcom,max-b-frame-size",
@@ -388,8 +385,8 @@ static struct msm_vidc_common_data sdmmagpie_common_data_v0[] = {
 		.value = 8160,
 	},
 	{
-		.key = "qcom,max-hq-frames-per-sec",
-		.value = 60,
+		.key = "qcom,max-hq-mbs-per-sec",
+		.value = 244800,  /* 1920 x 1088 @ 30 fps */
 	},
 	{
 		.key = "qcom,max-b-frame-size",
@@ -459,8 +456,8 @@ static struct msm_vidc_common_data sdmmagpie_common_data_v1[] = {
 		.value = 8160,
 	},
 	{
-		.key = "qcom,max-hq-frames-per-sec",
-		.value = 60,
+		.key = "qcom,max-hq-mbs-per-sec",
+		.value = 244800,  /* 1920 x 1088 @ 30 fps */
 	},
 	{
 		.key = "qcom,max-b-frame-size",
@@ -534,8 +531,8 @@ static struct msm_vidc_common_data sdm845_common_data[] = {
 		.value = 8160,
 	},
 	{
-		.key = "qcom,max-hq-frames-per-sec",
-		.value = 60,
+		.key = "qcom,max-hq-mbs-per-sec",
+		.value = 244800,  /* 1920 x 1088 @ 30 fps */
 	},
 	{
 		.key = "qcom,max-b-frame-size",
@@ -589,8 +586,8 @@ static struct msm_vidc_common_data sdm670_common_data_v0[] = {
 		.value = 8160,
 	},
 	{
-		.key = "qcom,max-hq-frames-per-sec",
-		.value = 60,
+		.key = "qcom,max-hq-mbs-per-sec",
+		.value = 244800,  /* 1920 x 1088 @ 30 fps */
 	},
 	{
 		.key = "qcom,max-b-frame-size",
@@ -640,8 +637,8 @@ static struct msm_vidc_common_data sdm670_common_data_v1[] = {
 		.value = 8160,
 	},
 	{
-		.key = "qcom,max-hq-frames-per-sec",
-		.value = 60,
+		.key = "qcom,max-hq-mbs-per-sec",
+		.value = 244800,  /* 1920 x 1088 @ 30 fps */
 	},
 	{
 		.key = "qcom,max-b-frame-size",
@@ -690,8 +687,6 @@ static struct msm_vidc_platform_data default_data = {
 	.efuse_data = NULL,
 	.efuse_data_length = 0,
 	.sku_version = 0,
-	.gcc_register_base = 0,
-	.gcc_register_size = 0,
 	.vpu_ver = VPU_VERSION_5,
 };
 
@@ -708,8 +703,6 @@ static struct msm_vidc_platform_data sm6150_data = {
 	.efuse_data = NULL,
 	.efuse_data_length = 0,
 	.sku_version = 0,
-	.gcc_register_base = 0,
-	.gcc_register_size = 0,
 	.vpu_ver = VPU_VERSION_4,
 };
 
@@ -726,8 +719,6 @@ static struct msm_vidc_platform_data trinket_data = {
 	.efuse_data = NULL,
 	.efuse_data_length = 0,
 	.sku_version = 0,
-	.gcc_register_base = 0,
-	.gcc_register_size = 0,
 	.vpu_ver = VPU_VERSION_4,
 };
 
@@ -744,8 +735,6 @@ static struct msm_vidc_platform_data sm8150_data = {
 	.efuse_data = NULL,
 	.efuse_data_length = 0,
 	.sku_version = 0,
-	.gcc_register_base = GCC_VIDEO_AXI_REG_START_ADDR,
-	.gcc_register_size = GCC_VIDEO_AXI_REG_SIZE,
 	.vpu_ver = VPU_VERSION_5,
 };
 
@@ -762,8 +751,6 @@ static struct msm_vidc_platform_data sdmmagpie_data = {
 	.efuse_data = sdmmagpie_efuse_data,
 	.efuse_data_length = ARRAY_SIZE(sdmmagpie_efuse_data),
 	.sku_version = 0,
-	.gcc_register_base = GCC_VIDEO_AXI_REG_START_ADDR,
-	.gcc_register_size = GCC_VIDEO_AXI_REG_SIZE,
 	.vpu_ver = VPU_VERSION_5,
 };
 
@@ -780,8 +767,6 @@ static struct msm_vidc_platform_data sdm845_data = {
 	.efuse_data = NULL,
 	.efuse_data_length = 0,
 	.sku_version = 0,
-	.gcc_register_base = 0,
-	.gcc_register_size = 0,
 	.vpu_ver = VPU_VERSION_4,
 };
 
@@ -798,8 +783,6 @@ static struct msm_vidc_platform_data sdm670_data = {
 	.efuse_data = sdm670_efuse_data,
 	.efuse_data_length = ARRAY_SIZE(sdm670_efuse_data),
 	.sku_version = 0,
-	.gcc_register_base = 0,
-	.gcc_register_size = 0,
 	.vpu_ver = VPU_VERSION_4,
 };
 
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index 4e00cfc..7454f2b 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -694,6 +694,39 @@ static int msm_vidc_load_clock_table(
 	return rc;
 }
 
+static int msm_vidc_load_reset_table(
+		struct msm_vidc_platform_resources *res)
+{
+	struct platform_device *pdev = res->pdev;
+	struct reset_set *rst = &res->reset_set;
+	int num_clocks = 0, c = 0;
+
+	num_clocks = of_property_count_strings(pdev->dev.of_node,
+				"reset-names");
+	if (num_clocks <= 0) {
+		dprintk(VIDC_DBG, "No reset clocks found\n");
+		rst->count = 0;
+		return 0;
+	}
+
+	rst->reset_tbl = devm_kcalloc(&pdev->dev, num_clocks,
+			sizeof(*rst->reset_tbl), GFP_KERNEL);
+	if (!rst->reset_tbl)
+		return -ENOMEM;
+
+	rst->count = num_clocks;
+	dprintk(VIDC_DBG, "Found %d reset clocks\n", num_clocks);
+
+	for (c = 0; c < num_clocks; ++c) {
+		struct reset_info *rc = &res->reset_set.reset_tbl[c];
+
+		of_property_read_string_index(pdev->dev.of_node,
+				"reset-names", c, &rc->name);
+	}
+
+	return 0;
+}
+
 static int msm_decide_dt_node(
 		struct msm_vidc_platform_resources *res)
 {
@@ -761,8 +794,8 @@ int read_platform_resources_from_drv_data(
 	res->max_hq_mbs_per_frame = find_key_value(platform_data,
 			"qcom,max-hq-mbs-per-frame");
 
-	res->max_hq_fps = find_key_value(platform_data,
-			"qcom,max-hq-frames-per-sec");
+	res->max_hq_mbs_per_sec = find_key_value(platform_data,
+			"qcom,max-hq-mbs-per-sec");
 
 	res->sw_power_collapsible = find_key_value(platform_data,
 			"qcom,sw-power-collapse");
@@ -806,9 +839,6 @@ int read_platform_resources_from_drv_data(
 
 	res->csc_coeff_data = &platform_data->csc_data;
 
-	res->gcc_register_base = platform_data->gcc_register_base;
-	res->gcc_register_size = platform_data->gcc_register_size;
-
 	res->vpu_ver = platform_data->vpu_ver;
 
 	res->ubwc_config = platform_data->ubwc_config;
@@ -930,6 +960,13 @@ int read_platform_resources_from_dt(
 		goto err_load_allowed_clocks_table;
 	}
 
+	rc = msm_vidc_load_reset_table(res);
+	if (rc) {
+		dprintk(VIDC_ERR,
+			"Failed to load reset table: %d\n", rc);
+		goto err_load_reset_table;
+	}
+
 	rc = msm_vidc_populate_legacy_context_bank(res);
 	if (rc) {
 		dprintk(VIDC_ERR,
@@ -957,6 +994,7 @@ int read_platform_resources_from_dt(
 
 return rc;
 
+err_load_reset_table:
 err_register_cx_ipeak:
 err_setup_legacy_cb:
 	msm_vidc_free_allowed_clocks_table(res);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index f2049d5..db5e414 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -116,6 +116,16 @@ struct bus_set {
 	u32 count;
 };
 
+struct reset_info {
+	struct reset_control *rst;
+	const char *name;
+};
+
+struct reset_set {
+	struct reset_info *reset_tbl;
+	u32 count;
+};
+
 struct allowed_clock_rates_table {
 	u32 clock_rate;
 };
@@ -151,9 +161,7 @@ struct msm_vidc_mem_cdsp {
 struct msm_vidc_platform_resources {
 	phys_addr_t firmware_base;
 	phys_addr_t register_base;
-	phys_addr_t gcc_register_base;
 	uint32_t register_size;
-	uint32_t gcc_register_size;
 	uint32_t irq;
 	uint32_t sku_version;
 	struct allowed_clock_rates_table *allowed_clks_tbl;
@@ -170,11 +178,12 @@ struct msm_vidc_platform_resources {
 	struct buffer_usage_set buffer_usage_set;
 	uint32_t max_load;
 	uint32_t max_hq_mbs_per_frame;
-	uint32_t max_hq_fps;
+	uint32_t max_hq_mbs_per_sec;
 	struct platform_device *pdev;
 	struct regulator_set regulator_set;
 	struct clock_set clock_set;
 	struct bus_set bus_set;
+	struct reset_set reset_set;
 	bool use_non_secure_pil;
 	bool sw_power_collapsible;
 	bool slave_side_cp;
diff --git a/drivers/media/platform/msm/vidc/venus_boot.c b/drivers/media/platform/msm/vidc/venus_boot.c
index 03e9fcb..7fe7d0e 100644
--- a/drivers/media/platform/msm/vidc/venus_boot.c
+++ b/drivers/media/platform/msm/vidc/venus_boot.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
@@ -66,7 +66,6 @@ static struct {
 	struct regulator *gdsc;
 	const char *reg_name;
 	void __iomem *reg_base;
-	void __iomem *gcc_base;
 	struct device *iommu_ctx_bank_dev;
 	struct dma_iommu_mapping *mapping;
 	dma_addr_t fw_iova;
@@ -446,18 +445,6 @@ int venus_boot_init(struct msm_vidc_platform_resources *res,
 		goto err_ioremap_fail;
 	}
 
-	venus_data->gcc_base = ioremap_nocache(res->gcc_register_base,
-			(unsigned long)res->gcc_register_size);
-	dprintk(VIDC_DBG, "gcc reg: base %llx size %x\n",
-		 res->gcc_register_base, res->gcc_register_size);
-	if (!venus_data->gcc_base) {
-		dprintk(VIDC_ERR,
-				"could not map reg addr %pa of size %d\n",
-				&res->gcc_register_base,
-				res->gcc_register_size);
-		rc = -ENOMEM;
-		goto err_ioremap_fail;
-	}
 	venus_data->venus_notif_hdle = subsys_notif_register_notifier("venus",
 							&venus_notifier);
 	if (IS_ERR(venus_data->venus_notif_hdle)) {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index cd8f31a..7a25a0c 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -36,6 +36,7 @@
 #include <soc/qcom/subsystem_restart.h>
 #include <linux/dma-mapping.h>
 #include <linux/fastcvpd.h>
+#include <linux/reset.h>
 #include "hfi_packetization.h"
 #include "msm_vidc_debug.h"
 #include "venus_hfi.h"
@@ -911,33 +912,6 @@ static void __write_register(struct venus_hfi_device *device,
 	wmb();
 }
 
-static void __write_gcc_register(struct venus_hfi_device *device,
-		u32 reg, u32 value)
-{
-	u32 hwiosymaddr = reg;
-	u8 *base_addr;
-
-	__strict_check(device);
-
-	if (!device->power_enabled) {
-		dprintk(VIDC_WARN,
-			"HFI Write register failed : Power is OFF\n");
-		msm_vidc_res_handle_fatal_hw_error(device->res, true);
-		return;
-	}
-
-	base_addr = device->hal_data->gcc_reg_base;
-	dprintk(VIDC_DBG, "GCC Base addr: %pK, written to: %#x, Value: %#x.\n",
-		base_addr, hwiosymaddr, value);
-	base_addr += hwiosymaddr;
-	writel_relaxed(value, base_addr);
-
-	/*
-	 * Memory barrier to make sure value is written into the register.
-	 */
-	wmb();
-}
-
 static int __read_register(struct venus_hfi_device *device, u32 reg)
 {
 	int rc = 0;
@@ -970,33 +944,6 @@ static int __read_register(struct venus_hfi_device *device, u32 reg)
 
 	return rc;
 }
-static int __read_gcc_register(struct venus_hfi_device *device, u32 reg)
-{
-	int rc = 0;
-	u8 *base_addr;
-
-	__strict_check(device);
-
-	if (!device->power_enabled) {
-		dprintk(VIDC_WARN,
-			"HFI Read register failed : Power is OFF\n");
-		msm_vidc_res_handle_fatal_hw_error(device->res, true);
-		return -EINVAL;
-	}
-
-	base_addr = device->hal_data->gcc_reg_base;
-
-	rc = readl_relaxed(base_addr + reg);
-	/*
-	 * Memory barrier to make sure value is read correctly from the
-	 * register.
-	 */
-	rmb();
-	dprintk(VIDC_DBG, "GCC Base addr: %pK, read from: %#x, value: %#x...\n",
-		base_addr, reg, rc);
-
-	return rc;
-}
 
 static void __set_registers(struct venus_hfi_device *device)
 {
@@ -3846,20 +3793,6 @@ static int __init_regs_and_interrupts(struct venus_hfi_device *device,
 		goto error_irq_fail;
 	}
 
-	if (res->gcc_register_base) {
-		hal->gcc_reg_base = devm_ioremap_nocache(&res->pdev->dev,
-				res->gcc_register_base,
-					res->gcc_register_size);
-		hal->gcc_reg_size = res->gcc_register_size;
-		if (!hal->gcc_reg_base) {
-			dprintk(VIDC_ERR,
-				"could not map gcc reg addr %pa of size %d\n",
-				&res->gcc_register_base,
-				res->gcc_register_size);
-			goto error_irq_fail;
-		}
-	}
-
 	device->hal_data = hal;
 	rc = request_irq(res->irq, venus_hfi_isr, IRQF_TRIGGER_HIGH,
 			"msm_vidc", device);
@@ -3873,9 +3806,7 @@ static int __init_regs_and_interrupts(struct venus_hfi_device *device,
 		"firmware_base = %pa, register_base = %pa, register_size = %d\n",
 		&res->firmware_base, &res->register_base,
 		res->register_size);
-	dprintk(VIDC_INFO,
-		"gcc_register_base = %pa, gcc_register_size = %d\n",
-		&res->gcc_register_base, res->gcc_register_size);
+
 	return rc;
 
 error_irq_fail:
@@ -3934,6 +3865,57 @@ static inline int __init_clocks(struct venus_hfi_device *device)
 	return rc;
 }
 
+static int __handle_reset_clk(struct msm_vidc_platform_resources *res,
+			enum reset_state state)
+{
+	int i, rc = 0;
+	struct reset_control *rst;
+	struct reset_set *rst_set = &res->reset_set;
+
+	if (!rst_set->reset_tbl)
+		return 0;
+
+	for (i = 0; i < rst_set->count; i++) {
+		rst = rst_set->reset_tbl[i].rst;
+		dprintk(VIDC_DBG, "%s reset_state name = %s state %d\n",
+			__func__, rst_set->reset_tbl[i].name, state);
+		switch (state) {
+		case INIT:
+			if (rst)
+				continue;
+
+			rst = devm_reset_control_get(&res->pdev->dev,
+				rst_set->reset_tbl[i].name);
+			if (IS_ERR(rst))
+				rc = PTR_ERR(rst);
+
+			rst_set->reset_tbl[i].rst = rst;
+			break;
+		case ASSERT:
+			if (!rst)
+				goto no_init;
+
+			rc = reset_control_assert(rst);
+			break;
+		case DEASSERT:
+			if (!rst)
+				goto no_init;
+
+			rc = reset_control_deassert(rst);
+			break;
+		default:
+			dprintk(VIDC_ERR, "Invalid reset request\n");
+		}
+
+		if (rc)
+			return rc;
+	}
+	return 0;
+no_init:
+	dprintk(VIDC_ERR, "%s reset_state name = %s failed state %d\n",
+		__func__, rst_set->reset_tbl[i].name, state);
+	return PTR_ERR(rst);
+}
 
 static inline void __disable_unprepare_clks(struct venus_hfi_device *device)
 {
@@ -3966,66 +3948,32 @@ static inline void __disable_unprepare_clks(struct venus_hfi_device *device)
 
 static inline int __prepare_ahb2axi_bridge(struct venus_hfi_device *device)
 {
-
-	u32 count = 0, axic_cbcr_status = 0, mvs_core_cbcr_status = 0;
-	const u32 max_tries = 10;
-	int rc = 0;
+	int rc;
 
 	if (!device) {
 		dprintk(VIDC_ERR, "NULL device\n");
-		rc = -EINVAL;
-		goto fail_ahb2axi_enable;
+		return -EINVAL;
 	}
 
-	if (!device->hal_data->gcc_reg_base) {
-		dprintk(VIDC_WARN, "Skip resetting ahb2axi bridge\n");
-		goto skip_reset_ahb2axi_bridge;
+	if (device->res->vpu_ver != VPU_VERSION_5)
+		return 0;
+
+	rc = __handle_reset_clk(device->res, ASSERT);
+	if (rc) {
+		dprintk(VIDC_ERR, "failed to assert reset clocks\n");
+		return rc;
 	}
 
-	/* read registers */
-	axic_cbcr_status = __read_gcc_register(device, VIDEO_GCC_AXIC_CBCR);
-	mvs_core_cbcr_status = __read_register(device, VIDEO_CC_MVSC_CORE_CBCR);
-
-	/* write enable clk_ares */
-	__write_gcc_register(device, VIDEO_GCC_AXIC_CBCR,
-		axic_cbcr_status|0x4);
-	__write_register(device, VIDEO_CC_MVSC_CORE_CBCR,
-		mvs_core_cbcr_status|0x4);
-
 	/* wait for deassert */
 	usleep_range(150, 250);
 
-	/* write disable clk_ares */
-	axic_cbcr_status = axic_cbcr_status & (~0x4);
-	mvs_core_cbcr_status = mvs_core_cbcr_status & (~0x4);
-	__write_gcc_register(device, VIDEO_GCC_AXIC_CBCR, axic_cbcr_status);
-	__write_register(device, VIDEO_CC_MVSC_CORE_CBCR, mvs_core_cbcr_status);
-
-	/* write enable clk */
-	axic_cbcr_status = __read_gcc_register(device, VIDEO_GCC_AXIC_CBCR);
-	axic_cbcr_status = axic_cbcr_status | 0x1;
-	__write_gcc_register(device, VIDEO_GCC_AXIC_CBCR, axic_cbcr_status);
-	usleep_range(150, 250);
-
-	while (count < max_tries) {
-		axic_cbcr_status =
-			__read_gcc_register(device, VIDEO_GCC_AXIC_CBCR);
-		if (!(axic_cbcr_status & BIT(31)))
-			break;
-		usleep_range(150, 250);
-		count++;
-	}
-	if (count == max_tries) {
-		dprintk(VIDC_ERR,
-			"Unable to enable gcc_axic_cbcr (%#x)\n",
-			axic_cbcr_status);
-		rc = -EINVAL;
-		goto fail_ahb2axi_enable;
+	rc = __handle_reset_clk(device->res, DEASSERT);
+	if (rc) {
+		dprintk(VIDC_ERR, "failed to deassert reset clocks\n");
+		return rc;
 	}
 
-fail_ahb2axi_enable:
-skip_reset_ahb2axi_bridge:
-	return rc;
+	return 0;
 }
 
 static inline int __prepare_enable_clks(struct venus_hfi_device *device)
@@ -4292,6 +4240,13 @@ static int __init_resources(struct venus_hfi_device *device,
 		goto err_init_clocks;
 	}
 
+	rc = __handle_reset_clk(res, INIT);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to init reset clocks\n");
+		rc = -ENODEV;
+		goto err_init_reset_clk;
+	}
+
 	rc = __init_bus(device);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to init bus: %d\n", rc);
@@ -4308,6 +4263,7 @@ static int __init_resources(struct venus_hfi_device *device,
 
 	return rc;
 
+err_init_reset_clk:
 err_init_bus:
 	__deinit_clocks(device);
 err_init_clocks:
@@ -5260,7 +5216,6 @@ void venus_hfi_delete_device(void *device)
 			destroy_workqueue(close->venus_pm_workq);
 			free_irq(dev->hal_data->irq, close);
 			iounmap(dev->hal_data->register_base);
-			iounmap(dev->hal_data->gcc_reg_base);
 			kfree(close->hal_data);
 			kfree(close->response_pkt);
 			kfree(close->raw_packet);
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index e14d6f3..1ba14db 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -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
@@ -215,9 +215,7 @@ struct hal_data {
 	u32 irq;
 	phys_addr_t firmware_base;
 	u8 __iomem *register_base;
-	u8 __iomem *gcc_reg_base;
 	u32 register_size;
-	u32 gcc_reg_size;
 };
 
 struct venus_resources {
@@ -234,6 +232,12 @@ enum venus_hfi_state {
 	VENUS_STATE_INIT,
 };
 
+enum reset_state {
+	INIT = 1,
+	ASSERT,
+	DEASSERT,
+};
+
 struct venus_hfi_device;
 
 struct venus_hfi_vpu_ops {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 8c59118..f9df02a 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -108,7 +108,8 @@ enum hal_extradata_id {
 	HAL_EXTRADATA_ASPECT_RATIO,
 	HAL_EXTRADATA_MPEG2_SEQDISP,
 	HAL_EXTRADATA_STREAM_USERDATA,
-	HAL_EXTRADATA_FRAME_QP,
+	HAL_EXTRADATA_DEC_FRAME_QP,
+	HAL_EXTRADATA_ENC_FRAME_QP,
 	HAL_EXTRADATA_LTR_INFO,
 	HAL_EXTRADATA_ROI_QP,
 	HAL_EXTRADATA_OUTPUT_CROP,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
index bc3be97..0300605 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_io.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
@@ -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
@@ -19,7 +19,6 @@
 #define VIDC_VBIF_BASE_OFFS			0x00080000
 
 #define VIDC_CPU_BASE_OFFS			0x000C0000
-#define VIDEO_GCC_BASE_OFFS			0x00000000
 #define VIDEO_CC_BASE_OFFS			0x00100000
 #define VIDC_CPU_CS_BASE_OFFS		(VIDC_CPU_BASE_OFFS + 0x00012000)
 #define VIDC_CPU_IC_BASE_OFFS		(VIDC_CPU_BASE_OFFS + 0x0001F000)
@@ -194,13 +193,4 @@
 #define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG3_LOW_OFFS	0x0538
 #define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG3_HIGH_OFFS	0x053C
 
-#define VIDEO_GCC_AXIC_CBCR	(VIDEO_GCC_BASE_OFFS + 0x8)
-#define VIDEO_GCC_AXIC_CBCR_CLK_OFF_BMSK	0x80000000
-#define VIDEO_GCC_AXIC_CBCR_CLK_ARES_BMSK	0x4
-#define VIDEO_GCC_AXIC_CBCR_CLK_ENABLE_BMSK	0x1
-
-#define VIDEO_CC_MVSC_CORE_CBCR	(VIDEO_CC_BASE_OFFS + 0x850)
-#define VIDEO_CC_MVSC_CORE_CBCR_CLK_OFF_BMSK	0x80000000
-#define VIDEO_CC_MVSC_CORE_CBCR_CLK_ARES_BMSK	0x4
-#define VIDEO_CC_MVSC_CORE_CBCR_CLK_ENABLE_BMSK	0x1
 #endif
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
index 3e73e9d..7c02504 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
@@ -41,25 +41,27 @@ int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev)
 	node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
 	if (!node) {
 		mtk_v4l2_err("no mediatek,larb found");
-		return -1;
+		return -ENODEV;
 	}
 	pdev = of_find_device_by_node(node);
+	of_node_put(node);
 	if (!pdev) {
 		mtk_v4l2_err("no mediatek,larb device found");
-		return -1;
+		return -ENODEV;
 	}
 	pm->larbvenc = &pdev->dev;
 
 	node = of_parse_phandle(dev->of_node, "mediatek,larb", 1);
 	if (!node) {
 		mtk_v4l2_err("no mediatek,larb found");
-		return -1;
+		return -ENODEV;
 	}
 
 	pdev = of_find_device_by_node(node);
+	of_node_put(node);
 	if (!pdev) {
 		mtk_v4l2_err("no mediatek,larb device found");
-		return -1;
+		return -ENODEV;
 	}
 
 	pm->larbvenclt = &pdev->dev;
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 41eef37..769e9e6 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -187,6 +187,14 @@ static int venus_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	if (!dev->dma_parms) {
+		dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+					      GFP_KERNEL);
+		if (!dev->dma_parms)
+			return -ENOMEM;
+	}
+	dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
 	INIT_LIST_HEAD(&core->instances);
 	mutex_init(&core->lock);
 	INIT_DELAYED_WORK(&core->work, venus_sys_error_handler);
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 6ca71aa..d300e5e 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -877,8 +877,11 @@ int vivid_start_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming)
 			"%s-vid-cap", dev->v4l2_dev.name);
 
 	if (IS_ERR(dev->kthread_vid_cap)) {
+		int err = PTR_ERR(dev->kthread_vid_cap);
+
+		dev->kthread_vid_cap = NULL;
 		v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
-		return PTR_ERR(dev->kthread_vid_cap);
+		return err;
 	}
 	*pstreaming = true;
 	vivid_grab_controls(dev, true);
diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c
index 98eed58..7c8d758 100644
--- a/drivers/media/platform/vivid/vivid-kthread-out.c
+++ b/drivers/media/platform/vivid/vivid-kthread-out.c
@@ -248,8 +248,11 @@ int vivid_start_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
 			"%s-vid-out", dev->v4l2_dev.name);
 
 	if (IS_ERR(dev->kthread_vid_out)) {
+		int err = PTR_ERR(dev->kthread_vid_out);
+
+		dev->kthread_vid_out = NULL;
 		v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
-		return PTR_ERR(dev->kthread_vid_out);
+		return err;
 	}
 	*pstreaming = true;
 	vivid_grab_controls(dev, true);
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index 6f6d4df..11b014b 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -33,7 +33,7 @@ const struct v4l2_dv_timings_cap vivid_dv_timings_cap = {
 	.type = V4L2_DV_BT_656_1120,
 	/* keep this initialization for compatibility with GCC < 4.4.6 */
 	.reserved = { 0 },
-	V4L2_INIT_BT_TIMINGS(0, MAX_WIDTH, 0, MAX_HEIGHT, 14000000, 775000000,
+	V4L2_INIT_BT_TIMINGS(16, MAX_WIDTH, 16, MAX_HEIGHT, 14000000, 775000000,
 		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 		V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF,
 		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED)
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 92a74bc..bd8de78 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -900,8 +900,6 @@ static int em28xx_enable_analog_tuner(struct em28xx *dev)
 	if (!mdev || !v4l2->decoder)
 		return 0;
 
-	dev->v4l2->field_count = 0;
-
 	/*
 	 * This will find the tuner that is connected into the decoder.
 	 * Technically, this is not 100% correct, as the device may be
@@ -1074,6 +1072,8 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
 
 	em28xx_videodbg("%s\n", __func__);
 
+	dev->v4l2->field_count = 0;
+
 	/* Make sure streaming is not already in progress for this type
 	   of filehandle (e.g. video, vbi) */
 	rc = res_get(dev, vq->type);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 9222ba7..e329e91 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -249,6 +249,7 @@ static void v4l_print_format(const void *arg, bool write_only)
 	const struct v4l2_window *win;
 	const struct v4l2_sdr_format *sdr;
 	const struct v4l2_meta_format *meta;
+	u32 planes;
 	unsigned i;
 
 	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
@@ -279,7 +280,8 @@ static void v4l_print_format(const void *arg, bool write_only)
 			prt_names(mp->field, v4l2_field_names),
 			mp->colorspace, mp->num_planes, mp->flags,
 			mp->ycbcr_enc, mp->quantization, mp->xfer_func);
-		for (i = 0; i < mp->num_planes; i++)
+		planes = min_t(u32, mp->num_planes, VIDEO_MAX_PLANES);
+		for (i = 0; i < planes; i++)
 			printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
 					mp->plane_fmt[i].bytesperline,
 					mp->plane_fmt[i].sizeimage);
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 43522a0..f1725da 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1925,9 +1925,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 			return -EINVAL;
 		}
 	}
+
+	mutex_lock(&q->mmap_lock);
+
 	if (vb2_fileio_is_active(q)) {
 		dprintk(1, "mmap: file io in progress\n");
-		return -EBUSY;
+		ret = -EBUSY;
+		goto unlock;
 	}
 
 	/*
@@ -1935,7 +1939,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 	 */
 	ret = __find_plane_by_offset(q, off, &buffer, &plane);
 	if (ret)
-		return ret;
+		goto unlock;
 
 	vb = q->bufs[buffer];
 
@@ -1948,11 +1952,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 	if (length < (vma->vm_end - vma->vm_start)) {
 		dprintk(1,
 			"MMAP invalid, as it would overflow buffer length\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto unlock;
 	}
 
-	mutex_lock(&q->mmap_lock);
 	ret = call_memop(vb, mmap, vb->planes[plane].mem_priv, vma);
+
+unlock:
 	mutex_unlock(&q->mmap_lock);
 	if (ret)
 		return ret;
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index 76382c8..1246d69 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 
 #define DRIVER_NAME "memstick"
 
@@ -436,6 +437,7 @@ static void memstick_check(struct work_struct *work)
 	struct memstick_dev *card;
 
 	dev_dbg(&host->dev, "memstick_check started\n");
+	pm_runtime_get_noresume(host->dev.parent);
 	mutex_lock(&host->lock);
 	if (!host->card) {
 		if (memstick_power_on(host))
@@ -479,6 +481,7 @@ static void memstick_check(struct work_struct *work)
 		host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
 
 	mutex_unlock(&host->lock);
+	pm_runtime_put(host->dev.parent);
 	dev_dbg(&host->dev, "memstick_check finished\n");
 }
 
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 30d09d1..11ab17f 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -261,7 +261,7 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
 	mutex_unlock(&ab8500->lock);
 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
 
-	return ret;
+	return (ret < 0) ? ret : 0;
 }
 
 static int ab8500_get_register(struct device *dev, u8 bank,
diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c
index 64e088d..98192d4 100644
--- a/drivers/mfd/bd9571mwv.c
+++ b/drivers/mfd/bd9571mwv.c
@@ -57,6 +57,7 @@ static const struct regmap_access_table bd9571mwv_writable_table = {
 };
 
 static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = {
+	regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
 	regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
 	regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
 	regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 5970b8de..aec20e1 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2584,7 +2584,7 @@ static struct irq_chip prcmu_irq_chip = {
 	.irq_unmask	= prcmu_irq_unmask,
 };
 
-static __init char *fw_project_name(u32 project)
+static char *fw_project_name(u32 project)
 {
 	switch (project) {
 	case PRCMU_FW_PROJECT_U8500:
@@ -2732,7 +2732,7 @@ void __init db8500_prcmu_early_init(u32 phy_base, u32 size)
 	INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
 }
 
-static void __init init_prcm_registers(void)
+static void init_prcm_registers(void)
 {
 	u32 val;
 
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index d7f54e4..6c16f17 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -274,7 +274,9 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
 
 	mc13xxx->adcflags |= MC13XXX_ADC_WORKING;
 
-	mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
+	ret = mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
+	if (ret)
+		goto out;
 
 	adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2;
 	adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC;
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 04a601f..0afadea 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -309,8 +309,7 @@ static int mt6397_probe(struct platform_device *pdev)
 
 	default:
 		dev_err(&pdev->dev, "unsupported chip: %d\n", id);
-		ret = -ENODEV;
-		break;
+		return -ENODEV;
 	}
 
 	if (ret) {
diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c
index 2020454..0e9064b 100644
--- a/drivers/mfd/qcom-spmi-pmic.c
+++ b/drivers/mfd/qcom-spmi-pmic.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2014, 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -154,7 +155,12 @@ static struct spmi_driver pmic_spmi_driver = {
 		.of_match_table = pmic_spmi_id_table,
 	},
 };
-module_spmi_driver(pmic_spmi_driver);
+
+static int __init pmic_spmi_init(void)
+{
+	return spmi_driver_register(&pmic_spmi_driver);
+}
+arch_initcall(pmic_spmi_init);
 
 MODULE_DESCRIPTION("Qualcomm SPMI PMIC driver");
 MODULE_ALIAS("spmi:spmi-pmic");
diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
index 52fafea..8d420c3 100644
--- a/drivers/mfd/qcom_rpm.c
+++ b/drivers/mfd/qcom_rpm.c
@@ -638,6 +638,10 @@ static int qcom_rpm_probe(struct platform_device *pdev)
 		return -EFAULT;
 	}
 
+	writel(fw_version[0], RPM_CTRL_REG(rpm, 0));
+	writel(fw_version[1], RPM_CTRL_REG(rpm, 1));
+	writel(fw_version[2], RPM_CTRL_REG(rpm, 2));
+
 	dev_info(&pdev->dev, "RPM firmware %u.%u.%u\n", fw_version[0],
 							fw_version[1],
 							fw_version[2]);
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 7dc1cbc..5894d6c 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -265,8 +265,9 @@ static	int ti_tscadc_probe(struct platform_device *pdev)
 		cell->pdata_size = sizeof(tscadc);
 	}
 
-	err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
-			tscadc->used_cells, NULL, 0, NULL);
+	err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+			      tscadc->cells, tscadc->used_cells, NULL,
+			      0, NULL);
 	if (err < 0)
 		goto err_disable_clk;
 
diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c
index 13834a0..612f5ec 100644
--- a/drivers/mfd/tps65218.c
+++ b/drivers/mfd/tps65218.c
@@ -243,9 +243,9 @@ static int tps65218_probe(struct i2c_client *client,
 
 	mutex_init(&tps->tps_lock);
 
-	ret = regmap_add_irq_chip(tps->regmap, tps->irq,
-			IRQF_ONESHOT, 0, &tps65218_irq_chip,
-			&tps->irq_data);
+	ret = devm_regmap_add_irq_chip(&client->dev, tps->regmap, tps->irq,
+				       IRQF_ONESHOT, 0, &tps65218_irq_chip,
+				       &tps->irq_data);
 	if (ret < 0)
 		return ret;
 
@@ -261,26 +261,9 @@ static int tps65218_probe(struct i2c_client *client,
 			      ARRAY_SIZE(tps65218_cells), NULL, 0,
 			      regmap_irq_get_domain(tps->irq_data));
 
-	if (ret < 0)
-		goto err_irq;
-
-	return 0;
-
-err_irq:
-	regmap_del_irq_chip(tps->irq, tps->irq_data);
-
 	return ret;
 }
 
-static int tps65218_remove(struct i2c_client *client)
-{
-	struct tps65218 *tps = i2c_get_clientdata(client);
-
-	regmap_del_irq_chip(tps->irq, tps->irq_data);
-
-	return 0;
-}
-
 static const struct i2c_device_id tps65218_id_table[] = {
 	{ "tps65218", TPS65218 },
 	{ },
@@ -293,7 +276,6 @@ static struct i2c_driver tps65218_driver = {
 		.of_match_table = of_tps65218_match_table,
 	},
 	.probe		= tps65218_probe,
-	.remove		= tps65218_remove,
 	.id_table       = tps65218_id_table,
 };
 
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 5628a6b..c5c320e 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -594,6 +594,29 @@ static int tps6586x_i2c_remove(struct i2c_client *client)
 	return 0;
 }
 
+static int __maybe_unused tps6586x_i2c_suspend(struct device *dev)
+{
+	struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+	if (tps6586x->client->irq)
+		disable_irq(tps6586x->client->irq);
+
+	return 0;
+}
+
+static int __maybe_unused tps6586x_i2c_resume(struct device *dev)
+{
+	struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+	if (tps6586x->client->irq)
+		enable_irq(tps6586x->client->irq);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend,
+			 tps6586x_i2c_resume);
+
 static const struct i2c_device_id tps6586x_id_table[] = {
 	{ "tps6586x", 0 },
 	{ },
@@ -604,6 +627,7 @@ static struct i2c_driver tps6586x_driver = {
 	.driver	= {
 		.name	= "tps6586x",
 		.of_match_table = of_match_ptr(tps6586x_of_match),
+		.pm	= &tps6586x_pm_ops,
 	},
 	.probe		= tps6586x_i2c_probe,
 	.remove		= tps6586x_i2c_remove,
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index d3133a3..8f99327 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -979,7 +979,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
  * letting it generate the right frequencies for USB, MADC, and
  * other purposes.
  */
-static inline int __init protect_pm_master(void)
+static inline int protect_pm_master(void)
 {
 	int e = 0;
 
@@ -988,7 +988,7 @@ static inline int __init protect_pm_master(void)
 	return e;
 }
 
-static inline int __init unprotect_pm_master(void)
+static inline int unprotect_pm_master(void)
 {
 	int e = 0;
 
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 1ee68bd..16c6e2a 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -1618,6 +1618,7 @@ static const struct reg_default wm5110_reg_default[] = {
 	{ 0x00000ECD, 0x0000 },    /* R3789  - HPLPF4_2 */
 	{ 0x00000EE0, 0x0000 },    /* R3808  - ASRC_ENABLE */
 	{ 0x00000EE2, 0x0000 },    /* R3810  - ASRC_RATE1 */
+	{ 0x00000EE3, 0x4000 },    /* R3811  - ASRC_RATE2 */
 	{ 0x00000EF0, 0x0000 },    /* R3824  - ISRC 1 CTRL 1 */
 	{ 0x00000EF1, 0x0000 },    /* R3825  - ISRC 1 CTRL 2 */
 	{ 0x00000EF2, 0x0000 },    /* R3826  - ISRC 1 CTRL 3 */
@@ -2869,6 +2870,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_ASRC_ENABLE:
 	case ARIZONA_ASRC_STATUS:
 	case ARIZONA_ASRC_RATE1:
+	case ARIZONA_ASRC_RATE2:
 	case ARIZONA_ISRC_1_CTRL_1:
 	case ARIZONA_ISRC_1_CTRL_2:
 	case ARIZONA_ISRC_1_CTRL_3:
diff --git a/drivers/misc/compat_qseecom.c b/drivers/misc/compat_qseecom.c
index 96d200f..9fa99e6 100644
--- a/drivers/misc/compat_qseecom.c
+++ b/drivers/misc/compat_qseecom.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-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
@@ -475,6 +475,18 @@ static int compat_put_qseecom_is_es_activated_req(
 	return err;
 }
 
+static int compat_get_qseecom_ice_flag(
+	struct compat_qseecom_ice_data_t __user *data32,
+	struct qseecom_ice_data_t __user *data)
+{
+	int err;
+	compat_int_t ice_flag;
+
+	err = get_user(ice_flag, &data32->flag);
+	err |= put_user(ice_flag, &data->flag);
+	return err;
+}
+
 static unsigned int convert_cmd(unsigned int cmd)
 {
 	switch (cmd) {
@@ -538,7 +550,8 @@ static unsigned int convert_cmd(unsigned int cmd)
 		return QSEECOM_IOCTL_SEND_MODFD_CMD_64_REQ;
 	case COMPAT_QSEECOM_IOCTL_SEND_MODFD_RESP_64:
 		return QSEECOM_IOCTL_SEND_MODFD_RESP_64;
-
+	case COMPAT_QSEECOM_IOCTL_SET_ICE_INFO:
+		return QSEECOM_IOCTL_SET_ICE_INFO;
 	default:
 		return cmd;
 	}
@@ -914,6 +927,24 @@ long compat_qseecom_ioctl(struct file *file,
 						(unsigned long)data);
 	}
 	break;
+	case COMPAT_QSEECOM_IOCTL_SET_ICE_INFO: {
+		struct compat_qseecom_ice_data_t __user *data32;
+		struct qseecom_ice_data_t __user *data;
+		int err;
+
+		data32 = compat_ptr(arg);
+		data = compat_alloc_user_space(sizeof(*data));
+		if (data == NULL)
+			return -EFAULT;
+
+		err = compat_get_qseecom_ice_flag(data32, data);
+		if (err)
+			return err;
+
+		return qseecom_ioctl(file, convert_cmd(cmd),
+				(unsigned long)data);
+	}
+	break;
 	default:
 		return -ENOIOCTLCMD;
 	break;
diff --git a/drivers/misc/compat_qseecom.h b/drivers/misc/compat_qseecom.h
index fa76d4c..8058002 100644
--- a/drivers/misc/compat_qseecom.h
+++ b/drivers/misc/compat_qseecom.h
@@ -110,6 +110,10 @@ struct compat_qseecom_qseos_version_req {
 	compat_uint_t qseos_version; /* in */
 };
 
+struct compat_qseecom_ice_data_t {
+	compat_int_t flag; /* in */
+};
+
 /*
  * struct compat_qseecom_qseos_app_load_query - verify if app is loaded in qsee
  * @app_name[MAX_APP_NAME_SIZE]-  name of the app.
@@ -329,5 +333,8 @@ extern long compat_qseecom_ioctl(struct file *file,
 	_IOWR(QSEECOM_IOC_MAGIC, 42, \
 				struct compat_qseecom_ce_info_req)
 
+#define COMPAT_QSEECOM_IOCTL_SET_ICE_INFO \
+	 _IOWR(QSEECOM_IOC_MAGIC, 43, struct qseecom_ice_data_t)
+
 #endif
 #endif /* _UAPI_COMPAT_QSEECOM_H_ */
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index de58762..3f93e45 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -12,7 +12,7 @@
 	  ones like at24c64, 24lc02 or fm24c04:
 
 	     24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
-	     24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
+	     24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024, 24c2048
 
 	  Unless you like data loss puzzles, always be sure that any chip
 	  you configure as a 24c32 (32 kbit) or larger is NOT really a
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index ded48a0..59dcd97e 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -170,6 +170,7 @@ static const struct i2c_device_id at24_ids[] = {
 	{ "24c256",	AT24_DEVICE_MAGIC(262144 / 8,	AT24_FLAG_ADDR16) },
 	{ "24c512",	AT24_DEVICE_MAGIC(524288 / 8,	AT24_FLAG_ADDR16) },
 	{ "24c1024",	AT24_DEVICE_MAGIC(1048576 / 8,	AT24_FLAG_ADDR16) },
+	{ "24c2048",	AT24_DEVICE_MAGIC(2097152 / 8,	AT24_FLAG_ADDR16) },
 	{ "at24", 0 },
 	{ /* END OF LIST */ }
 };
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
index 147b830..2769eb0 100644
--- a/drivers/misc/genwqe/card_utils.c
+++ b/drivers/misc/genwqe/card_utils.c
@@ -217,7 +217,7 @@ u32 genwqe_crc32(u8 *buff, size_t len, u32 init)
 void *__genwqe_alloc_consistent(struct genwqe_dev *cd, size_t size,
 			       dma_addr_t *dma_handle)
 {
-	if (get_order(size) > MAX_ORDER)
+	if (get_order(size) >= MAX_ORDER)
 		return NULL;
 
 	return dma_zalloc_coherent(&cd->pci_dev->dev, size, dma_handle,
diff --git a/drivers/misc/hdcp_qseecom.c b/drivers/misc/hdcp_qseecom.c
index 5e27b90..7899f8a 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
@@ -1051,11 +1051,7 @@ static int hdcp2_app_start(struct hdcp2_handle *handle)
 	}
 
 	rc = handle->tx_init(handle);
-	if (rc)
-		goto error;
 
-	if (!handle->legacy_app)
-		rc = hdcp2_app_start_auth(handle);
 error:
 	return rc;
 }
@@ -1195,6 +1191,7 @@ int hdcp2_force_encryption(void *ctx, uint32_t enable)
 	pr_err("failed, rc=%d\n", rc);
 	return rc;
 }
+EXPORT_SYMBOL(hdcp2_force_encryption);
 
 static int hdcp2_app_query_stream(struct hdcp2_handle *handle)
 {
@@ -1243,6 +1240,9 @@ int hdcp2_app_comm(void *ctx, enum hdcp2_app_cmd cmd,
 	case HDCP2_CMD_START:
 		rc = hdcp2_app_start(handle);
 		break;
+	case HDCP2_CMD_START_AUTH:
+		rc = hdcp2_app_start_auth(handle);
+		break;
 	case HDCP2_CMD_PROCESS_MSG:
 		rc = hdcp2_app_process_msg(handle);
 		break;
@@ -1275,6 +1275,7 @@ int hdcp2_app_comm(void *ctx, enum hdcp2_app_cmd cmd,
 error:
 	return rc;
 }
+EXPORT_SYMBOL(hdcp2_app_comm);
 
 static int hdcp2_open_stream_helper(struct hdcp2_handle *handle,
 		uint8_t vc_payload_id,
@@ -1329,6 +1330,7 @@ int hdcp2_open_stream(void *ctx, uint8_t vc_payload_id, uint8_t stream_number,
 	return hdcp2_open_stream_helper(handle, vc_payload_id, stream_number,
 		stream_id);
 }
+EXPORT_SYMBOL(hdcp2_open_stream);
 
 static int hdcp2_close_stream_helper(struct hdcp2_handle *handle,
 		uint32_t stream_id)
@@ -1375,6 +1377,7 @@ int hdcp2_close_stream(void *ctx, uint32_t stream_id)
 
 	return hdcp2_close_stream_helper(handle, stream_id);
 }
+EXPORT_SYMBOL(hdcp2_close_stream);
 
 void *hdcp2_init(u32 device_type)
 {
@@ -1389,12 +1392,14 @@ void *hdcp2_init(u32 device_type)
 error:
 	return handle;
 }
+EXPORT_SYMBOL(hdcp2_init);
 
 void hdcp2_deinit(void *ctx)
 {
 	if (ctx)
 		kzfree(ctx);
 }
+EXPORT_SYMBOL(hdcp2_deinit);
 
 void *hdcp1_init(void)
 {
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index e4b10b2..23739a6 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -127,6 +127,8 @@
 #define MEI_DEV_ID_BXT_M      0x1A9A  /* Broxton M */
 #define MEI_DEV_ID_APL_I      0x5A9A  /* Apollo Lake I */
 
+#define MEI_DEV_ID_DNV_IE     0x19E5  /* Denverton IE */
+
 #define MEI_DEV_ID_GLK        0x319A  /* Gemini Lake */
 
 #define MEI_DEV_ID_KBP        0xA2BA  /* Kaby Point */
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index c77e08c..04bf2dd 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -93,6 +93,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
 	{MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)},
 	{MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)},
 
+	{MEI_PCI_DEVICE(MEI_DEV_ID_DNV_IE, MEI_ME_PCH8_CFG)},
+
 	{MEI_PCI_DEVICE(MEI_DEV_ID_GLK, MEI_ME_PCH8_CFG)},
 
 	{MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)},
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index bc13f78..517b0ff 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -343,6 +343,7 @@ struct qseecom_client_handle {
 	char app_name[MAX_APP_NAME_SIZE];
 	u32  app_arch;
 	struct qseecom_sec_buf_fd_info sec_buf_fd[MAX_ION_FD];
+	bool from_smcinvoke;
 };
 
 struct qseecom_listener_handle {
@@ -428,6 +429,29 @@ static int get_qseecom_keymaster_status(char *str)
 }
 __setup("androidboot.keymaster=", get_qseecom_keymaster_status);
 
+
+#define QSEECOM_SCM_EBUSY_WAIT_MS 30
+#define QSEECOM_SCM_EBUSY_MAX_RETRY 67
+
+static int __qseecom_scm_call2_locked(uint32_t smc_id, struct scm_desc *desc)
+{
+	int ret = 0;
+	int retry_count = 0;
+
+	do {
+		ret = scm_call2_noretry(smc_id, desc);
+		if (ret == -EBUSY) {
+			mutex_unlock(&app_access_lock);
+			msleep(QSEECOM_SCM_EBUSY_WAIT_MS);
+			mutex_lock(&app_access_lock);
+		}
+		if (retry_count == 33)
+			pr_warn("secure world has been busy for 1 second!\n");
+	} while (ret == -EBUSY &&
+			(retry_count++ < QSEECOM_SCM_EBUSY_MAX_RETRY));
+	return ret;
+}
+
 static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			const void *req_buf, void *resp_buf)
 {
@@ -455,7 +479,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				svc_id, tz_cmd_id);
 			return -EINVAL;
 		}
-		ret = scm_call2(smc_id, &desc);
+		ret = __qseecom_scm_call2_locked(smc_id, &desc);
 		break;
 	}
 	case SCM_SVC_ES: {
@@ -478,7 +502,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			desc.args[0] = p_hash_req->partition_id;
 			desc.args[1] = virt_to_phys(tzbuf);
 			desc.args[2] = SHA256_DIGEST_LENGTH;
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			kzfree(tzbuf);
 			break;
 		}
@@ -513,7 +537,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[2] = req_64bit->phy_addr;
 			}
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_APP_SHUTDOWN_COMMAND: {
@@ -523,7 +547,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			smc_id = TZ_OS_APP_SHUTDOWN_ID;
 			desc.arginfo = TZ_OS_APP_SHUTDOWN_ID_PARAM_ID;
 			desc.args[0] = req->app_id;
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_APP_LOOKUP_COMMAND: {
@@ -542,7 +566,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			desc.args[0] = virt_to_phys(tzbuf);
 			desc.args[1] = strlen(req->app_name);
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			kzfree(tzbuf);
 			break;
 		}
@@ -566,7 +590,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[1] = req_64bit->size;
 			}
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_LOAD_SERV_IMAGE_COMMAND: {
@@ -590,14 +614,14 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[2] = req_64bit->phy_addr;
 			}
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_UNLOAD_SERV_IMAGE_COMMAND: {
 			smc_id = TZ_OS_UNLOAD_SERVICES_IMAGE_ID;
 			desc.arginfo = TZ_OS_UNLOAD_SERVICES_IMAGE_ID_PARAM_ID;
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_REGISTER_LISTENER: {
@@ -622,12 +646,12 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			}
 			qseecom.smcinvoke_support = true;
 			smc_id = TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID;
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			if (ret == -EIO) {
 				/* smcinvoke is not supported */
 				qseecom.smcinvoke_support = false;
 				smc_id = TZ_OS_REGISTER_LISTENER_ID;
-				ret = scm_call2(smc_id, &desc);
+				ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			}
 			break;
 		}
@@ -639,7 +663,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			smc_id = TZ_OS_DEREGISTER_LISTENER_ID;
 			desc.arginfo = TZ_OS_DEREGISTER_LISTENER_ID_PARAM_ID;
 			desc.args[0] = req->listener_id;
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_LISTENER_DATA_RSP_COMMAND: {
@@ -652,7 +676,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				TZ_OS_LISTENER_RESPONSE_HANDLER_ID_PARAM_ID;
 			desc.args[0] = req->listener_id;
 			desc.args[1] = req->status;
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST: {
@@ -680,7 +704,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[2] = req_64->sglistinfo_ptr;
 				desc.args[3] = req_64->sglistinfo_len;
 			}
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_LOAD_EXTERNAL_ELF_COMMAND: {
@@ -702,14 +726,14 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[2] = req_64bit->phy_addr;
 			}
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_UNLOAD_EXTERNAL_ELF_COMMAND: {
 			smc_id = TZ_OS_UNLOAD_EXTERNAL_IMAGE_ID;
 			desc.arginfo = TZ_OS_UNLOAD_SERVICES_IMAGE_ID_PARAM_ID;
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 			}
 
@@ -737,7 +761,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[3] = req_64bit->rsp_ptr;
 				desc.args[4] = req_64bit->rsp_len;
 			}
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST: {
@@ -769,7 +793,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[5] = req_64bit->sglistinfo_ptr;
 				desc.args[6] = req_64bit->sglistinfo_len;
 			}
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_RPMB_PROVISION_KEY_COMMAND: {
@@ -781,21 +805,21 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			desc.arginfo = TZ_OS_RPMB_PROVISION_KEY_ID_PARAM_ID;
 			desc.args[0] = req->key_type;
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_RPMB_ERASE_COMMAND: {
 			smc_id = TZ_OS_RPMB_ERASE_ID;
 			desc.arginfo = TZ_OS_RPMB_ERASE_ID_PARAM_ID;
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_RPMB_CHECK_PROV_STATUS_COMMAND: {
 			smc_id = TZ_OS_RPMB_CHECK_PROV_STATUS_ID;
 			desc.arginfo = TZ_OS_RPMB_CHECK_PROV_STATUS_ID_PARAM_ID;
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_GENERATE_KEY: {
@@ -816,7 +840,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			desc.args[0] = virt_to_phys(tzbuf);
 			desc.args[1] = tzbuflen;
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			kzfree(tzbuf);
 			break;
 		}
@@ -838,7 +862,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			desc.args[0] = virt_to_phys(tzbuf);
 			desc.args[1] = tzbuflen;
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			kzfree(tzbuf);
 			break;
 		}
@@ -860,7 +884,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			desc.args[0] = virt_to_phys(tzbuf);
 			desc.args[1] = tzbuflen;
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			kzfree(tzbuf);
 			break;
 		}
@@ -882,7 +906,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			desc.args[0] = virt_to_phys(tzbuf);
 			desc.args[1] = tzbuflen;
 			__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			kzfree(tzbuf);
 			break;
 		}
@@ -908,7 +932,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[3] = req_64bit->resp_ptr;
 				desc.args[4] = req_64bit->resp_len;
 			}
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_TEE_OPEN_SESSION_WHITELIST: {
@@ -938,7 +962,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[5] = req_64bit->sglistinfo_ptr;
 				desc.args[6] = req_64bit->sglistinfo_len;
 			}
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_TEE_INVOKE_COMMAND: {
@@ -963,7 +987,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[3] = req_64bit->resp_ptr;
 				desc.args[4] = req_64bit->resp_len;
 			}
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_TEE_INVOKE_COMMAND_WHITELIST: {
@@ -993,7 +1017,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[5] = req_64bit->sglistinfo_ptr;
 				desc.args[6] = req_64bit->sglistinfo_len;
 			}
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_TEE_CLOSE_SESSION: {
@@ -1018,7 +1042,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[3] = req_64bit->resp_ptr;
 				desc.args[4] = req_64bit->resp_len;
 			}
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_TEE_REQUEST_CANCELLATION: {
@@ -1044,7 +1068,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 				desc.args[3] = req_64bit->resp_ptr;
 				desc.args[4] = req_64bit->resp_len;
 			}
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		case QSEOS_CONTINUE_BLOCKED_REQ_COMMAND: {
@@ -1059,7 +1083,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
 			desc.arginfo =
 				TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID;
 			desc.args[0] = req->app_or_session_id;
-			ret = scm_call2(smc_id, &desc);
+			ret = __qseecom_scm_call2_locked(smc_id, &desc);
 			break;
 		}
 		default: {
@@ -1134,9 +1158,9 @@ static int qseecom_dmabuf_cache_operations(struct dma_buf *dmabuf,
 		goto exit;
 
 	switch (cache_op) {
-	case QSEECOM_CACHE_CLEAN:
-		dma_buf_begin_cpu_access(dmabuf, DMA_TO_DEVICE);
-		dma_buf_end_cpu_access(dmabuf, DMA_TO_DEVICE);
+	case QSEECOM_CACHE_CLEAN: /* Doing CLEAN and INVALIDATE */
+		dma_buf_begin_cpu_access(dmabuf, DMA_BIDIRECTIONAL);
+		dma_buf_end_cpu_access(dmabuf, DMA_BIDIRECTIONAL);
 		break;
 	case QSEECOM_CACHE_INVALIDATE:
 		dma_buf_begin_cpu_access(dmabuf, DMA_TO_DEVICE);
@@ -2088,6 +2112,7 @@ static int __qseecom_process_reentrancy_blocked_on_listener(
 	sigset_t old_sigset;
 	unsigned long flags;
 	bool found_app = false;
+	struct qseecom_registered_app_list dummy_app_entry = { {NULL} };
 
 	if (!resp || !data) {
 		pr_err("invalid resp or data pointer\n");
@@ -2097,24 +2122,31 @@ static int __qseecom_process_reentrancy_blocked_on_listener(
 
 	/* find app_id & img_name from list */
 	if (!ptr_app) {
-		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
-		list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
-							list) {
-			if ((ptr_app->app_id == data->client.app_id) &&
-				(!strcmp(ptr_app->app_name,
+		if (data->client.from_smcinvoke) {
+			pr_debug("This request is from smcinvoke\n");
+			ptr_app = &dummy_app_entry;
+			ptr_app->app_id = data->client.app_id;
+		} else {
+			spin_lock_irqsave(&qseecom.registered_app_list_lock,
+						flags);
+			list_for_each_entry(ptr_app,
+				&qseecom.registered_app_list_head, list) {
+				if ((ptr_app->app_id == data->client.app_id) &&
+					(!strcmp(ptr_app->app_name,
 						data->client.app_name))) {
-				found_app = true;
-				break;
+					found_app = true;
+					break;
+				}
 			}
-		}
-		spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
-					flags);
-		if (!found_app) {
-			pr_err("app_id %d (%s) is not found\n",
-				data->client.app_id,
-				(char *)data->client.app_name);
-			ret = -ENOENT;
-			goto exit;
+			spin_unlock_irqrestore(
+				&qseecom.registered_app_list_lock, flags);
+			if (!found_app) {
+				pr_err("app_id %d (%s) is not found\n",
+					data->client.app_id,
+					(char *)data->client.app_name);
+				ret = -ENOENT;
+				goto exit;
+			}
 		}
 	}
 
@@ -2821,6 +2853,7 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
 	bool unload = false;
 	bool found_app = false;
 	bool found_dead_app = false;
+	bool scm_called = false;
 
 	if (!data) {
 		pr_err("Invalid/uninitialized device handle\n");
@@ -2879,11 +2912,12 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
 		ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
 				sizeof(struct qseecom_unload_app_ireq),
 				&resp, sizeof(resp));
+		scm_called = true;
 		if (ret) {
 			pr_err("scm_call to unload app (id = %d) failed\n",
 								req.app_id);
 			ret = -EFAULT;
-			goto unload_exit;
+			goto scm_exit;
 		} else {
 			pr_warn("App id %d now unloaded\n", req.app_id);
 		}
@@ -2891,7 +2925,7 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
 			pr_err("app (%d) unload_failed!!\n",
 					data->client.app_id);
 			ret = -EFAULT;
-			goto unload_exit;
+			goto scm_exit;
 		}
 		if (resp.result == QSEOS_RESULT_SUCCESS)
 			pr_debug("App (%d) is unloaded!!\n",
@@ -2901,11 +2935,35 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
 			if (ret) {
 				pr_err("process_incomplete_cmd fail err: %d\n",
 									ret);
-				goto unload_exit;
+				goto scm_exit;
 			}
 		}
 	}
 
+scm_exit:
+	if (scm_called) {
+		/* double check if this app_entry still exists */
+		bool doublecheck = false;
+
+		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags1);
+		list_for_each_entry(ptr_app,
+			&qseecom.registered_app_list_head, list) {
+			if ((ptr_app->app_id == data->client.app_id) &&
+				(!strcmp((void *)ptr_app->app_name,
+				(void *)data->client.app_name))) {
+				doublecheck = true;
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
+								flags1);
+		if (!doublecheck) {
+			pr_warn("app %d(%s) entry is already removed\n",
+				data->client.app_id,
+				(char *)data->client.app_name);
+			found_app = false;
+		}
+	}
 unload_exit:
 	if (found_app) {
 		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags1);
@@ -4975,6 +5033,7 @@ int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc)
 	resp.data = desc->ret[2];	/*listener_id*/
 
 	dummy_private_data.client.app_id = desc->ret[1];
+	dummy_private_data.client.from_smcinvoke = true;
 	dummy_app_entry.app_id = desc->ret[1];
 
 	mutex_lock(&app_access_lock);
@@ -6527,7 +6586,7 @@ static int qseecom_mdtp_cipher_dip(void __user *argp)
 		if (ret)
 			break;
 
-		ret = scm_call2(TZ_MDTP_CIPHER_DIP_ID, &desc);
+		ret = __qseecom_scm_call2_locked(TZ_MDTP_CIPHER_DIP_ID, &desc);
 
 		__qseecom_disable_clk(CLK_QSEE);
 
@@ -8730,8 +8789,10 @@ static int qseecom_check_whitelist_feature(void)
 
 	desc.args[0] = FEATURE_ID_WHITELIST;
 	desc.arginfo = SCM_ARGS(1);
-	ret = scm_call2(SCM_SIP_FNID(SCM_SVC_INFO,
+	mutex_lock(&app_access_lock);
+	ret = __qseecom_scm_call2_locked(SCM_SIP_FNID(SCM_SVC_INFO,
 		GET_FEAT_VERSION_CMD), &desc);
+	mutex_unlock(&app_access_lock);
 	if (!ret)
 		version = desc.ret[0];
 
@@ -8814,8 +8875,10 @@ static int qseecom_probe(struct platform_device *pdev)
 	qseecom.send_resp_flag = 0;
 
 	qseecom.qsee_version = QSEEE_VERSION_00;
+	mutex_lock(&app_access_lock);
 	rc = qseecom_scm_call(6, 3, &feature, sizeof(feature),
 		&resp, sizeof(resp));
+	mutex_unlock(&app_access_lock);
 	pr_info("qseecom.qsee_version = 0x%x\n", resp.result);
 	if (rc) {
 		pr_err("Failed to get QSEE version info %d\n", rc);
@@ -8968,9 +9031,11 @@ static int qseecom_probe(struct platform_device *pdev)
 				rc = -EIO;
 				goto exit_deinit_clock;
 			}
+			mutex_lock(&app_access_lock);
 			rc = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
 					cmd_buf, cmd_len,
 					&resp, sizeof(resp));
+			mutex_unlock(&app_access_lock);
 			__qseecom_disable_clk(CLK_QSEE);
 			if (rc || (resp.result != QSEOS_RESULT_SUCCESS)) {
 				pr_err("send secapp reg fail %d resp.res %d\n",
diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c
index 2cde80c..9b4eba4 100644
--- a/drivers/misc/vexpress-syscfg.c
+++ b/drivers/misc/vexpress-syscfg.c
@@ -61,7 +61,7 @@ static int vexpress_syscfg_exec(struct vexpress_syscfg_func *func,
 	int tries;
 	long timeout;
 
-	if (WARN_ON(index > func->num_templates))
+	if (WARN_ON(index >= func->num_templates))
 		return -EINVAL;
 
 	command = readl(syscfg->base + SYS_CFGCTRL);
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 294f676..80d03ed 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -1066,21 +1066,6 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
 		goto cmd_done;
 	}
 
-	mmc_get_card(card);
-
-	if (mmc_card_cmdq(card)) {
-		err = mmc_cmdq_halt_on_empty_queue(card->host);
-		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;
-		}
-	}
-
-	mmc_put_card(card);
-
 	/*
 	 * Dispatch the ioctl() into the block request queue.
 	 */
@@ -1101,11 +1086,6 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
 	err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
 	blk_put_request(req);
 
-	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__);
-	}
 cmd_done:
 	kfree(idata->buf);
 	kfree(idata);
@@ -3186,6 +3166,7 @@ void mmc_blk_cmdq_complete_rq(struct request *rq)
 	if (err_rwsem && !(err || err_resp)) {
 		mmc_host_clk_release(host);
 		wake_up(&ctx_info->wait);
+		host->last_completed_rq_time = ktime_get();
 		mmc_put_card(host->card);
 	}
 
@@ -3488,6 +3469,7 @@ static inline int mmc_blk_cmdq_part_switch(struct mmc_card *card,
 		pr_err("%s: %s: mmc_blk_cmdq_switch failed: %d\n",
 			mmc_hostname(host), __func__,  err);
 		ret = err;
+		goto out;
 	}
 cmdq_unhalt:
 	err = mmc_cmdq_halt(host, false);
@@ -3534,16 +3516,11 @@ static int  mmc_cmdq_wait_for_small_sector_read(struct mmc_card *card,
 	return ret;
 }
 
-static int mmc_blk_cmdq_issue_drv_op(struct mmc_card *card, struct request *req)
+static int mmc_blk_cmdq_issue_drv_op(struct mmc_card *card,
+				struct mmc_queue *mq, struct request *req)
 {
-	struct mmc_queue_req *mq_rq;
-	u8 **ext_csd;
-	u32 status;
 	int ret;
 
-	mq_rq = req_to_mmc_queue_req(req);
-	ext_csd = mq_rq->drv_op_data;
-
 	ret = mmc_cmdq_halt_on_empty_queue(card->host);
 	if (ret) {
 		pr_err("%s: failed to halt on empty queue\n",
@@ -3553,35 +3530,8 @@ static int mmc_blk_cmdq_issue_drv_op(struct mmc_card *card, struct request *req)
 		return ret;
 	}
 
-	switch (mq_rq->drv_op) {
-	case MMC_DRV_OP_GET_EXT_CSD:
-		ret = mmc_get_ext_csd(card, ext_csd);
-		if (ret) {
-			pr_err("%s: failed to get ext_csd\n",
-						mmc_hostname(card->host));
-			goto out_unhalt;
-		}
-		break;
-	case MMC_DRV_OP_GET_CARD_STATUS:
-		ret = mmc_send_status(card, &status);
-		if (ret) {
-			pr_err("%s: failed to get status\n",
-						mmc_hostname(card->host));
-			goto out_unhalt;
-		}
-		ret = status;
-		break;
-	default:
-		pr_err("%s: unknown driver specific operation\n",
-					mmc_hostname(card->host));
-		ret = -EINVAL;
-		break;
-	}
-	mq_rq->drv_op_result = ret;
-	ret = ret ? BLK_STS_IOERR : BLK_STS_OK;
+	mmc_blk_issue_drv_op(mq, req);
 
-out_unhalt:
-	blk_end_request_all(req, ret);
 	ret = mmc_cmdq_halt(card->host, false);
 	if (ret)
 		pr_err("%s: %s: failed to unhalt\n",
@@ -3656,7 +3606,7 @@ static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req)
 			break;
 		case REQ_OP_DRV_IN:
 		case REQ_OP_DRV_OUT:
-			ret = mmc_blk_cmdq_issue_drv_op(card, req);
+			ret = mmc_blk_cmdq_issue_drv_op(card, mq, req);
 			break;
 		default:
 			ret = mmc_blk_cmdq_issue_rw_rq(mq, req);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index e9b5647..c95f8c3 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -455,12 +455,16 @@ int mmc_clk_update_freq(struct mmc_host *host,
 		goto invalid_state;
 	}
 
+	MMC_TRACE(host, "clock scale state %d freq %lu\n",
+			state, freq);
 	err = host->bus_ops->change_bus_speed(host, &freq);
 	if (!err)
 		host->clk_scaling.curr_freq = freq;
 	else
 		pr_err("%s: %s: failed (%d) at freq=%lu\n",
 			mmc_hostname(host), __func__, err, freq);
+	MMC_TRACE(host, "clock scale state %d freq %lu done with err %d\n",
+			state, freq, err);
 
 invalid_state:
 	if (cmdq_mode) {
@@ -704,6 +708,7 @@ static int mmc_devfreq_create_freq_table(struct mmc_host *host)
 int mmc_init_clk_scaling(struct mmc_host *host)
 {
 	int err;
+	struct devfreq *devfreq;
 
 	if (!host || !host->card) {
 		pr_err("%s: unexpected host/card parameters\n",
@@ -759,17 +764,20 @@ int mmc_init_clk_scaling(struct mmc_host *host)
 		host->clk_scaling.ondemand_gov_data.upthreshold,
 		host->clk_scaling.ondemand_gov_data.downdifferential,
 		host->clk_scaling.devfreq_profile.polling_ms);
-	host->clk_scaling.devfreq = devfreq_add_device(
+
+	devfreq = devfreq_add_device(
 		mmc_classdev(host),
 		&host->clk_scaling.devfreq_profile,
 		"simple_ondemand",
 		&host->clk_scaling.ondemand_gov_data);
-	if (!host->clk_scaling.devfreq) {
+
+	if (IS_ERR(devfreq)) {
 		pr_err("%s: unable to register with devfreq\n",
 			mmc_hostname(host));
-		return -EPERM;
+		return PTR_ERR(devfreq);
 	}
 
+	host->clk_scaling.devfreq = devfreq;
 	pr_debug("%s: clk scaling is enabled for device %s (%p) with devfreq %p (clock = %uHz)\n",
 		mmc_hostname(host),
 		dev_name(mmc_classdev(host)),
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 999b097..dc92d0b 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -153,6 +153,7 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host)
 		mmc_gate_clock(host);
 		spin_lock_irqsave(&host->clk_lock, flags);
 		pr_debug("%s: gated MCI clock\n", mmc_hostname(host));
+		MMC_TRACE(host, "clocks are gated\n");
 	}
 	spin_unlock_irqrestore(&host->clk_lock, flags);
 	mutex_unlock(&host->clk_gate_mutex);
@@ -191,6 +192,7 @@ void mmc_host_clk_hold(struct mmc_host *host)
 
 		spin_lock_irqsave(&host->clk_lock, flags);
 		pr_debug("%s: ungated MCI clock\n", mmc_hostname(host));
+		MMC_TRACE(host, "clocks are ungated\n");
 	}
 	host->clk_requests++;
 	spin_unlock_irqrestore(&host->clk_lock, flags);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index fd62ca0..c40ebff 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -673,9 +673,6 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
 				mmc_hostname(card->host),
 				card->ext_csd.cmdq_depth);
 		}
-		card->ext_csd.enhanced_rpmb_supported =
-			(card->ext_csd.rel_param &
-			 EXT_CSD_WR_REL_PARAM_EN_RPMB_REL_WR);
 	} else {
 		card->ext_csd.cmdq_support = 0;
 		card->ext_csd.cmdq_depth = 0;
@@ -714,6 +711,9 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
 				 mmc_hostname(card->host),
 				 card->ext_csd.cmdq_depth);
 		}
+		card->ext_csd.enhanced_rpmb_supported =
+			(card->ext_csd.rel_param &
+			 EXT_CSD_WR_REL_PARAM_EN_RPMB_REL_WR);
 	}
 out:
 	return err;
@@ -2976,6 +2976,9 @@ static int mmc_reset(struct mmc_host *host)
 		mmc_pwrseq_reset(host);
 	}
 
+	if (host->inlinecrypt_support)
+		host->inlinecrypt_reset_needed = true;
+
 	ret = mmc_init_card(host, host->card->ocr, host->card);
 	if (ret) {
 		pr_err("%s: %s: mmc_init_card failed (%d)\n",
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 4b1df1c..73e4344 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -429,6 +429,7 @@
 	tristate "Qualcomm Technologies, Inc. SDHCI Controller Support"
 	depends on ARCH_QCOM || ARCH_MSM || (ARM && COMPILE_TEST)
 	depends on MMC_SDHCI_PLTFM
+	select MMC_SDHCI_IO_ACCESSORS
 	help
 	  This selects the Secure Digital Host Controller Interface (SDHCI)
 	  support present in Qualcomm Technologies, Inc. SOCs. The controller
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 0a0ebf3..c8a591d 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -1954,13 +1954,14 @@ static void atmci_tasklet_func(unsigned long priv)
 			}
 
 			atmci_request_end(host, host->mrq);
-			state = STATE_IDLE;
+			goto unlock; /* atmci_request_end() sets host->state */
 			break;
 		}
 	} while (state != prev_state);
 
 	host->state = state;
 
+unlock:
 	spin_unlock(&host->lock);
 }
 
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 768972a..5301302 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -286,6 +286,7 @@ static void bcm2835_reset(struct mmc_host *mmc)
 
 	if (host->dma_chan)
 		dmaengine_terminate_sync(host->dma_chan);
+	host->dma_chan = NULL;
 	bcm2835_reset_internal(host);
 }
 
@@ -772,6 +773,8 @@ static void bcm2835_finish_command(struct bcm2835_host *host)
 
 		if (!(sdhsts & SDHSTS_CRC7_ERROR) ||
 		    (host->cmd->opcode != MMC_SEND_OP_COND)) {
+			u32 edm, fsm;
+
 			if (sdhsts & SDHSTS_CMD_TIME_OUT) {
 				host->cmd->error = -ETIMEDOUT;
 			} else {
@@ -780,6 +783,13 @@ static void bcm2835_finish_command(struct bcm2835_host *host)
 				bcm2835_dumpregs(host);
 				host->cmd->error = -EILSEQ;
 			}
+			edm = readl(host->ioaddr + SDEDM);
+			fsm = edm & SDEDM_FSM_MASK;
+			if (fsm == SDEDM_FSM_READWAIT ||
+			    fsm == SDEDM_FSM_WRITESTART1)
+				/* Kick the FSM out of its wait */
+				writel(edm | SDEDM_FORCE_DATA_MODE,
+				       host->ioaddr + SDEDM);
 			bcm2835_finish_request(host);
 			return;
 		}
@@ -837,6 +847,8 @@ static void bcm2835_timeout(struct work_struct *work)
 		dev_err(dev, "timeout waiting for hardware interrupt.\n");
 		bcm2835_dumpregs(host);
 
+		bcm2835_reset(host->mmc);
+
 		if (host->data) {
 			host->data->error = -ETIMEDOUT;
 			bcm2835_finish_data(host);
@@ -1427,6 +1439,8 @@ static int bcm2835_probe(struct platform_device *pdev)
 
 err:
 	dev_dbg(dev, "%s -> err %d\n", __func__, ret);
+	if (host->dma_chan_rxtx)
+		dma_release_channel(host->dma_chan_rxtx);
 	mmc_free_host(mmc);
 
 	return ret;
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 476e53d..67f6bd2 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1447,6 +1447,7 @@ static int mmc_spi_probe(struct spi_device *spi)
 		mmc->caps &= ~MMC_CAP_NEEDS_POLL;
 		mmc_gpiod_request_cd_irq(mmc);
 	}
+	mmc_detect_change(mmc, 0);
 
 	if (host->pdata && host->pdata->flags & MMC_SPI_USE_RO_GPIO) {
 		has_ro = true;
diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
index df44654..5dd31a2 100644
--- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
@@ -68,6 +68,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = {
 	.scc_offset	= 0x0300,
 	.taps		= rcar_gen2_scc_taps,
 	.taps_num	= ARRAY_SIZE(rcar_gen2_scc_taps),
+	.max_blk_count  = 0xffffffff,
 };
 
 /* Definitions for sampling clocks */
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index c81de2f..59041f0 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1077,11 +1077,12 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
 			| ESDHC_BURST_LEN_EN_INCR,
 			host->ioaddr + SDHCI_HOST_CONTROL);
+
 		/*
-		* erratum ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
-		* TO1.1, it's harmless for MX6SL
-		*/
-		writel(readl(host->ioaddr + 0x6c) | BIT(7),
+		 * erratum ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
+		 * TO1.1, it's harmless for MX6SL
+		 */
+		writel(readl(host->ioaddr + 0x6c) & ~BIT(7),
 			host->ioaddr + 0x6c);
 
 		/* disable DLL_CTRL delay line settings */
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c
index 0cfbdb3..cecffcb 100644
--- a/drivers/mmc/host/sdhci-iproc.c
+++ b/drivers/mmc/host/sdhci-iproc.c
@@ -278,7 +278,10 @@ static int sdhci_iproc_probe(struct platform_device *pdev)
 
 	iproc_host->data = iproc_data;
 
-	mmc_of_parse(host->mmc);
+	ret = mmc_of_parse(host->mmc);
+	if (ret)
+		goto err;
+
 	sdhci_get_of_property(pdev);
 
 	host->mmc->caps |= iproc_host->data->mmc_caps;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 02e5b8e..959ca0a 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1971,8 +1971,6 @@ static int sdhci_msm_dt_parse_hsr_info(struct device *dev,
 skip_hsr:
 	if (!msm_host->dll_hsr)
 		dev_info(dev, "Failed to get dll hsr settings from dt\n");
-	if (dll_hsr_table)
-		devm_kfree(dev, dll_hsr_table);
 	return ret;
 }
 
@@ -3544,9 +3542,9 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 			 * DLL input clock
 			 */
 			writel_relaxed(((readl_relaxed(host->ioaddr +
-				msm_host_offset->CORE_DDR_CONFIG))
+				msm_host_offset->CORE_DLL_CONFIG_3))
 				| RCLK_TOGGLE), host->ioaddr +
-				msm_host_offset->CORE_DDR_CONFIG);
+				msm_host_offset->CORE_DLL_CONFIG_3);
 			/* ensure above write as toggling same bit quickly */
 			wmb();
 			udelay(2);
@@ -3555,9 +3553,9 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
 			 * DLL input clock
 			 */
 			writel_relaxed(((readl_relaxed(host->ioaddr +
-				msm_host_offset->CORE_DDR_CONFIG))
+				msm_host_offset->CORE_DLL_CONFIG_3))
 				& ~RCLK_TOGGLE), host->ioaddr +
-				msm_host_offset->CORE_DDR_CONFIG);
+				msm_host_offset->CORE_DLL_CONFIG_3);
 		}
 		if (!host->mmc->ios.old_rate && !msm_host->use_cdclp533) {
 			/*
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 8332f56..7b7d077 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -481,8 +481,12 @@ static void esdhc_clock_enable(struct sdhci_host *host, bool enable)
 	/* Wait max 20 ms */
 	timeout = ktime_add_ms(ktime_get(), 20);
 	val = ESDHC_CLOCK_STABLE;
-	while (!(sdhci_readl(host, ESDHC_PRSSTAT) & val)) {
-		if (ktime_after(ktime_get(), timeout)) {
+	while  (1) {
+		bool timedout = ktime_after(ktime_get(), timeout);
+
+		if (sdhci_readl(host, ESDHC_PRSSTAT) & val)
+			break;
+		if (timedout) {
 			pr_err("%s: Internal clock never stabilised.\n",
 				mmc_hostname(host->mmc));
 			break;
@@ -558,8 +562,12 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 
 	/* Wait max 20 ms */
 	timeout = ktime_add_ms(ktime_get(), 20);
-	while (!(sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE)) {
-		if (ktime_after(ktime_get(), timeout)) {
+	while (1) {
+		bool timedout = ktime_after(ktime_get(), timeout);
+
+		if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE)
+			break;
+		if (timedout) {
 			pr_err("%s: Internal clock never stabilised.\n",
 				mmc_hostname(host->mmc));
 			return;
diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c
index ec87943..82051f2 100644
--- a/drivers/mmc/host/sdhci-xenon-phy.c
+++ b/drivers/mmc/host/sdhci-xenon-phy.c
@@ -357,9 +357,13 @@ static int xenon_emmc_phy_enable_dll(struct sdhci_host *host)
 
 	/* Wait max 32 ms */
 	timeout = ktime_add_ms(ktime_get(), 32);
-	while (!(sdhci_readw(host, XENON_SLOT_EXT_PRESENT_STATE) &
-		XENON_DLL_LOCK_STATE)) {
-		if (ktime_after(ktime_get(), timeout)) {
+	while (1) {
+		bool timedout = ktime_after(ktime_get(), timeout);
+
+		if (sdhci_readw(host, XENON_SLOT_EXT_PRESENT_STATE) &
+		    XENON_DLL_LOCK_STATE)
+			break;
+		if (timedout) {
 			dev_err(mmc_dev(host->mmc), "Wait for DLL Lock time-out\n");
 			return -ETIMEDOUT;
 		}
diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c
index 4d0791f..a0b5089 100644
--- a/drivers/mmc/host/sdhci-xenon.c
+++ b/drivers/mmc/host/sdhci-xenon.c
@@ -34,9 +34,13 @@ static int xenon_enable_internal_clk(struct sdhci_host *host)
 	sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL);
 	/* Wait max 20 ms */
 	timeout = ktime_add_ms(ktime_get(), 20);
-	while (!((reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
-			& SDHCI_CLOCK_INT_STABLE)) {
-		if (ktime_after(ktime_get(), timeout)) {
+	while (1) {
+		bool timedout = ktime_after(ktime_get(), timeout);
+
+		reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+		if (reg & SDHCI_CLOCK_INT_STABLE)
+			break;
+		if (timedout) {
 			dev_err(mmc_dev(host->mmc), "Internal clock never stabilised.\n");
 			return -ETIMEDOUT;
 		}
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index e4c2a4f..a986da5 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -152,6 +152,7 @@ void sdhci_dumpregs(struct sdhci_host *host)
 	}
 
 	host->mmc->err_occurred = true;
+	host->mmc->last_failed_rq_time = ktime_get();
 
 	if (host->ops->dump_vendor_regs)
 		host->ops->dump_vendor_regs(host);
@@ -316,8 +317,6 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
 		/* Resetting the controller clears many */
 		host->preset_enabled = false;
 	}
-	if (host->is_crypto_en)
-		host->crypto_reset_reqd = true;
 }
 
 static void sdhci_set_default_irqs(struct sdhci_host *host)
@@ -1837,14 +1836,15 @@ static int sdhci_crypto_cfg(struct sdhci_host *host, struct mmc_request *mrq,
 {
 	int err = 0;
 
-	if (host->crypto_reset_reqd && host->ops->crypto_engine_reset) {
+	if (host->mmc->inlinecrypt_reset_needed &&
+			host->ops->crypto_engine_reset) {
 		err = host->ops->crypto_engine_reset(host);
 		if (err) {
 			pr_err("%s: crypto reset failed\n",
 					mmc_hostname(host->mmc));
 			goto out;
 		}
-		host->crypto_reset_reqd = false;
+		host->mmc->inlinecrypt_reset_needed = false;
 	}
 
 	if (host->ops->crypto_engine_cfg) {
@@ -3586,7 +3586,11 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 			   mmc_hostname(host->mmc), unexpected);
 		MMC_TRACE(host->mmc, "Unexpected interrupt 0x%08x.\n",
 				unexpected);
-		sdhci_dumpregs(host);
+		if (host->mmc->cmdq_ops && host->mmc->cmdq_ops->dumpstate)
+			host->mmc->cmdq_ops->dumpstate(host->mmc);
+		else
+			sdhci_dumpregs(host);
+		BUG_ON(1);
 	}
 
 	return result;
@@ -4061,14 +4065,14 @@ static int sdhci_cmdq_crypto_cfg(struct mmc_host *mmc,
 	if (!host->is_crypto_en)
 		return 0;
 
-	if (host->crypto_reset_reqd && host->ops->crypto_engine_reset) {
+	if (mmc->inlinecrypt_reset_needed && host->ops->crypto_engine_reset) {
 		err = host->ops->crypto_engine_reset(host);
 		if (err) {
 			pr_err("%s: crypto reset failed\n",
 					mmc_hostname(host->mmc));
 			goto out;
 		}
-		host->crypto_reset_reqd = false;
+		mmc->inlinecrypt_reset_needed = false;
 	}
 
 	if (host->ops->crypto_engine_cmdq_cfg) {
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 76ecc0a..85b59bd 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -654,7 +654,6 @@ struct sdhci_host {
 
 	bool sdio_irq_async_status;
 	bool is_crypto_en;
-	bool crypto_reset_reqd;
 
 	u32 auto_cmd_err_sts;
 	struct ratelimit_state dbg_dump_rs;
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 3e6ff89..fe10de3 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -286,6 +286,11 @@ static inline void sd_ctrl_write32_as_16_and_16(struct tmio_mmc_host *host,
 	writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
 }
 
+static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
+{
+	iowrite32(val, host->ctl + (addr << host->bus_shift));
+}
+
 static inline void sd_ctrl_write32_rep(struct tmio_mmc_host *host, int addr,
 				       const u32 *buf, int count)
 {
diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c
index de1562f..2437fcd 100644
--- a/drivers/mmc/host/tmio_mmc_core.c
+++ b/drivers/mmc/host/tmio_mmc_core.c
@@ -46,6 +46,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/mmc/sdio.h>
 #include <linux/scatterlist.h>
+#include <linux/sizes.h>
 #include <linux/spinlock.h>
 #include <linux/swiotlb.h>
 #include <linux/workqueue.h>
@@ -688,7 +689,7 @@ static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host, int ireg,
 	return false;
 }
 
-static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host)
+static bool __tmio_mmc_sdio_irq(struct tmio_mmc_host *host)
 {
 	struct mmc_host *mmc = host->mmc;
 	struct tmio_mmc_data *pdata = host->pdata;
@@ -696,7 +697,7 @@ static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host)
 	unsigned int sdio_status;
 
 	if (!(pdata->flags & TMIO_MMC_SDIO_IRQ))
-		return;
+		return false;
 
 	status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
 	ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdio_irq_mask;
@@ -709,6 +710,8 @@ static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host)
 
 	if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ)
 		mmc_signal_sdio_irq(mmc);
+
+	return ireg;
 }
 
 irqreturn_t tmio_mmc_irq(int irq, void *devid)
@@ -727,9 +730,10 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
 	if (__tmio_mmc_sdcard_irq(host, ireg, status))
 		return IRQ_HANDLED;
 
-	__tmio_mmc_sdio_irq(host);
+	if (__tmio_mmc_sdio_irq(host))
+		return IRQ_HANDLED;
 
-	return IRQ_HANDLED;
+	return IRQ_NONE;
 }
 EXPORT_SYMBOL_GPL(tmio_mmc_irq);
 
@@ -758,7 +762,10 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host,
 
 	/* Set transfer length / blocksize */
 	sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz);
-	sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
+	if (host->mmc->max_blk_count >= SZ_64K)
+		sd_ctrl_write32(host, CTL_XFER_BLK_COUNT, data->blocks);
+	else
+		sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
 
 	tmio_mmc_start_dma(host, data);
 
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index 9778724..55e369b 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -168,9 +168,10 @@ int gpmi_init(struct gpmi_nand_data *this)
 
 	/*
 	 * Reset BCH here, too. We got failures otherwise :(
-	 * See later BCH reset for explanation of MX23 handling
+	 * See later BCH reset for explanation of MX23 and MX28 handling
 	 */
-	ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
+	ret = gpmi_reset_block(r->bch_regs,
+			       GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
 	if (ret)
 		goto err_out;
 
@@ -275,13 +276,11 @@ int bch_set_geometry(struct gpmi_nand_data *this)
 
 	/*
 	* Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
-	* chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
-	* On the other hand, the MX28 needs the reset, because one case has been
-	* seen where the BCH produced ECC errors constantly after 10000
-	* consecutive reboots. The latter case has not been seen on the MX23
-	* yet, still we don't know if it could happen there as well.
+	* chip, otherwise it will lock up. So we skip resetting BCH on the MX23
+	* and MX28.
 	*/
-	ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
+	ret = gpmi_reset_block(r->bch_regs,
+			       GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
 	if (ret)
 		goto err_out;
 
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index cf64a36..65c5a65 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1928,6 +1928,9 @@ static int __bond_release_one(struct net_device *bond_dev,
 	if (!bond_has_slaves(bond)) {
 		bond_set_carrier(bond);
 		eth_hw_addr_random(bond_dev);
+		bond->nest_level = SINGLE_DEPTH_NESTING;
+	} else {
+		bond->nest_level = dev_get_nest_level(bond_dev) + 1;
 	}
 
 	unblock_netpoll_tx();
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 035daca..7d61d88 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -479,8 +479,6 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);
 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
 {
 	struct can_priv *priv = netdev_priv(dev);
-	struct sk_buff *skb = priv->echo_skb[idx];
-	struct canfd_frame *cf;
 
 	if (idx >= priv->echo_skb_max) {
 		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
@@ -488,20 +486,21 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
 		return NULL;
 	}
 
-	if (!skb) {
-		netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n",
-			   __func__, idx);
-		return NULL;
+	if (priv->echo_skb[idx]) {
+		/* Using "struct canfd_frame::len" for the frame
+		 * length is supported on both CAN and CANFD frames.
+		 */
+		struct sk_buff *skb = priv->echo_skb[idx];
+		struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+		u8 len = cf->len;
+
+		*len_ptr = len;
+		priv->echo_skb[idx] = NULL;
+
+		return skb;
 	}
 
-	/* Using "struct canfd_frame::len" for the frame
-	 * length is supported on both CAN and CANFD frames.
-	 */
-	cf = (struct canfd_frame *)skb->data;
-	*len_ptr = cf->len;
-	priv->echo_skb[idx] = NULL;
-
-	return skb;
+	return NULL;
 }
 
 /*
diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c
index 86c56b6..502278c 100644
--- a/drivers/net/can/spi/qti-can.c
+++ b/drivers/net/can/spi/qti-can.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
@@ -45,6 +45,7 @@
 #define DRIVER_MODE_PROPERTIES		1
 #define DRIVER_MODE_AMB			2
 #define QUERY_FIRMWARE_TIMEOUT_MS	100
+#define EUPGRADE			140
 
 struct qti_can {
 	struct net_device	**netdev;
@@ -70,6 +71,7 @@ struct qti_can {
 	bool can_fw_cmd_timeout_req;
 	u32 rem_all_buffering_timeout_ms;
 	u32 can_fw_cmd_timeout_ms;
+	s64 time_diff;
 };
 
 struct qti_can_netdev_privdata {
@@ -119,6 +121,7 @@ struct spi_miso { /* TLV for MISO line */
 #define CMD_BOOT_ROM_UPGRADE_DATA	0x9A
 #define CMD_END_BOOT_ROM_UPGRADE	0x9B
 #define CMD_END_FW_UPDATE_FILE		0x9C
+#define CMD_UPDATE_TIME_INFO		0x9D
 
 #define IOCTL_RELEASE_CAN_BUFFER	(SIOCDEVPRIVATE + 0)
 #define IOCTL_ENABLE_BUFFERING		(SIOCDEVPRIVATE + 1)
@@ -165,7 +168,7 @@ struct can_add_filter_resp {
 
 struct can_receive_frame {
 	u8 can_if;
-	u32 ts;
+	u64 ts;
 	u32 mid;
 	u8 dlc;
 	u8 data[8];
@@ -180,6 +183,10 @@ struct can_config_bit_timing {
 	u32 brp;
 } __packed;
 
+struct can_time_info {
+	u64 time;
+} __packed;
+
 static struct can_bittiming_const rh850_bittiming_const = {
 	.name = "qti_can",
 	.tseg1_min = 1,
@@ -293,7 +300,7 @@ static void qti_can_receive_frame(struct qti_can *priv_data,
 		return;
 	}
 
-	LOGDI("rcv frame %d %d %x %d %x %x %x %x %x %x %x %x\n",
+	LOGDI("rcv frame %d %llu %x %d %x %x %x %x %x %x %x %x\n",
 	      frame->can_if, frame->ts, frame->mid, frame->dlc,
 	      frame->data[0], frame->data[1], frame->data[2], frame->data[3],
 	      frame->data[4], frame->data[5], frame->data[6], frame->data[7]);
@@ -303,12 +310,12 @@ static void qti_can_receive_frame(struct qti_can *priv_data,
 	for (i = 0; i < cf->can_dlc; i++)
 		cf->data[i] = frame->data[i];
 
-	nsec = ms_to_ktime(le32_to_cpu(frame->ts));
+	nsec = ms_to_ktime(le64_to_cpu(frame->ts) + priv_data->time_diff);
 	skt = skb_hwtstamps(skb);
 	skt->hwtstamp = nsec;
-	LOGDI("  hwtstamp %lld\n", ktime_to_ms(skt->hwtstamp));
 	skb->tstamp = nsec;
 	netif_rx(skb);
+	LOGDI("hwtstamp: %lld\n", ktime_to_ms(skt->hwtstamp));
 	netdev->stats.rx_packets++;
 }
 
@@ -356,11 +363,21 @@ static int qti_can_process_response(struct qti_can *priv_data,
 				    struct spi_miso *resp, int length)
 {
 	int ret = 0;
+	u64 mstime;
+	ktime_t ktime_now;
 
 	LOGDI("<%x %2d [%d]\n", resp->cmd, resp->len, resp->seq);
 	if (resp->cmd == CMD_CAN_RECEIVE_FRAME) {
 		struct can_receive_frame *frame =
 				(struct can_receive_frame *)&resp->data;
+		if ((resp->len - (frame->dlc + sizeof(frame->dlc))) <
+			(sizeof(*frame) - (sizeof(frame->dlc)
+			+ sizeof(frame->data)))) {
+			LOGDE("len:%d, size:%d\n", resp->len, sizeof(*frame));
+			LOGDE("Check the f/w version & upgrade to latest!!\n");
+			ret = -EUPGRADE;
+			goto exit;
+		}
 		if (resp->len > length) {
 			/* Error. This should never happen */
 			LOGDE("%s error: Saving %d bytes\n", __func__, length);
@@ -373,6 +390,7 @@ static int qti_can_process_response(struct qti_can *priv_data,
 	} else if (resp->cmd == CMD_PROPERTY_READ) {
 		struct vehicle_property *property =
 				(struct vehicle_property *)&resp->data;
+
 		if (resp->len > length) {
 			/* Error. This should never happen */
 			LOGDE("%s error: Saving %d bytes\n", __func__, length);
@@ -392,6 +410,7 @@ static int qti_can_process_response(struct qti_can *priv_data,
 	} else if (resp->cmd  == CMD_GET_FW_BR_VERSION) {
 		struct can_fw_br_resp *fw_resp =
 				(struct can_fw_br_resp *)resp->data;
+
 		dev_info(&priv_data->spidev->dev, "fw_can %d.%d",
 			 fw_resp->maj, fw_resp->min);
 		dev_info(&priv_data->spidev->dev, "fw string %s",
@@ -404,8 +423,16 @@ static int qti_can_process_response(struct qti_can *priv_data,
 		ret |= (fw_resp->br_min & 0xFF) << 16;
 		ret |= (fw_resp->maj & 0xF) << 8;
 		ret |= (fw_resp->min & 0xFF);
+	} else if (resp->cmd == CMD_UPDATE_TIME_INFO) {
+		struct can_time_info *time_data =
+			(struct can_time_info *)resp->data;
+
+		ktime_now = ktime_get_boottime();
+		mstime = ktime_to_ms(ktime_now);
+		priv_data->time_diff = mstime - (le64_to_cpu(time_data->time));
 	}
 
+exit:
 	if (resp->cmd == priv_data->wait_cmd) {
 		priv_data->cmd_result = ret;
 		complete(&priv_data->response_completion);
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index eebda5e..a3543d6 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -258,6 +258,7 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)
 	unsigned int sub_irq;
 	unsigned int n;
 	u16 reg;
+	u16 ctl1;
 	int err;
 
 	mutex_lock(&chip->reg_lock);
@@ -267,13 +268,28 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)
 	if (err)
 		goto out;
 
-	for (n = 0; n < chip->g1_irq.nirqs; ++n) {
-		if (reg & (1 << n)) {
-			sub_irq = irq_find_mapping(chip->g1_irq.domain, n);
-			handle_nested_irq(sub_irq);
-			++nhandled;
+	do {
+		for (n = 0; n < chip->g1_irq.nirqs; ++n) {
+			if (reg & (1 << n)) {
+				sub_irq = irq_find_mapping(chip->g1_irq.domain,
+							   n);
+				handle_nested_irq(sub_irq);
+				++nhandled;
+			}
 		}
-	}
+
+		mutex_lock(&chip->reg_lock);
+		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1);
+		if (err)
+			goto unlock;
+		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
+unlock:
+		mutex_unlock(&chip->reg_lock);
+		if (err)
+			goto out;
+		ctl1 &= GENMASK(chip->g1_irq.nirqs, 0);
+	} while (reg & ctl1);
+
 out:
 	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
 }
@@ -1979,6 +1995,107 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
 	return 0;
 }
 
+/* The mv88e6390 has some hidden registers used for debug and
+ * development. The errata also makes use of them.
+ */
+static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
+				  int reg, u16 val)
+{
+	u16 ctrl;
+	int err;
+
+	err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT,
+				   PORT_RESERVED_1A, val);
+	if (err)
+		return err;
+
+	ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE |
+	       PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
+	       reg;
+
+	return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
+				    PORT_RESERVED_1A, ctrl);
+}
+
+static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
+{
+	return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT,
+			      PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY);
+}
+
+
+static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port,
+				  int reg, u16 *val)
+{
+	u16 ctrl;
+	int err;
+
+	ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ |
+	       PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
+	       reg;
+
+	err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
+				   PORT_RESERVED_1A, ctrl);
+	if (err)
+		return err;
+
+	err = mv88e6390_hidden_wait(chip);
+	if (err)
+		return err;
+
+	return 	mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT,
+				    PORT_RESERVED_1A, val);
+}
+
+/* Check if the errata has already been applied. */
+static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
+{
+	int port;
+	int err;
+	u16 val;
+
+	for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+		err = mv88e6390_hidden_read(chip, port, 0, &val);
+		if (err) {
+			dev_err(chip->dev,
+				"Error reading hidden register: %d\n", err);
+			return false;
+		}
+		if (val != 0x01c0)
+			return false;
+	}
+
+	return true;
+}
+
+/* The 6390 copper ports have an errata which require poking magic
+ * values into undocumented hidden registers and then performing a
+ * software reset.
+ */
+static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
+{
+	int port;
+	int err;
+
+	if (mv88e6390_setup_errata_applied(chip))
+		return 0;
+
+	/* Set the ports into blocking mode */
+	for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+		err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED);
+		if (err)
+			return err;
+	}
+
+	for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+		err = mv88e6390_hidden_write(chip, port, 0, 0x01c0);
+		if (err)
+			return err;
+	}
+
+	return mv88e6xxx_software_reset(chip);
+}
+
 static int mv88e6xxx_setup(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_chip *chip = ds->priv;
@@ -1990,6 +2107,12 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
 
 	mutex_lock(&chip->reg_lock);
 
+	if (chip->info->ops->setup_errata) {
+		err = chip->info->ops->setup_errata(chip);
+		if (err)
+			goto unlock;
+	}
+
 	/* Setup Switch Port Registers */
 	for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
 		err = mv88e6xxx_setup_port(chip, i);
@@ -2652,6 +2775,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
 
 static const struct mv88e6xxx_ops mv88e6190_ops = {
 	/* MV88E6XXX_FAMILY_6390 */
+	.setup_errata = mv88e6390_setup_errata,
 	.irl_init_all = mv88e6390_g2_irl_init_all,
 	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -2687,6 +2811,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
 
 static const struct mv88e6xxx_ops mv88e6190x_ops = {
 	/* MV88E6XXX_FAMILY_6390 */
+	.setup_errata = mv88e6390_setup_errata,
 	.irl_init_all = mv88e6390_g2_irl_init_all,
 	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -2722,6 +2847,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
 
 static const struct mv88e6xxx_ops mv88e6191_ops = {
 	/* MV88E6XXX_FAMILY_6390 */
+	.setup_errata = mv88e6390_setup_errata,
 	.irl_init_all = mv88e6390_g2_irl_init_all,
 	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -2793,6 +2919,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
 
 static const struct mv88e6xxx_ops mv88e6290_ops = {
 	/* MV88E6XXX_FAMILY_6390 */
+	.setup_errata = mv88e6390_setup_errata,
 	.irl_init_all = mv88e6390_g2_irl_init_all,
 	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3030,6 +3157,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
 
 static const struct mv88e6xxx_ops mv88e6390_ops = {
 	/* MV88E6XXX_FAMILY_6390 */
+	.setup_errata = mv88e6390_setup_errata,
 	.irl_init_all = mv88e6390_g2_irl_init_all,
 	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3068,6 +3196,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
 
 static const struct mv88e6xxx_ops mv88e6390x_ops = {
 	/* MV88E6XXX_FAMILY_6390 */
+	.setup_errata = mv88e6390_setup_errata,
 	.irl_init_all = mv88e6390_g2_irl_init_all,
 	.get_eeprom = mv88e6xxx_g2_get_eeprom8,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom8,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 334f6f7..0913eec 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -222,6 +222,11 @@ struct mv88e6xxx_mdio_bus {
 };
 
 struct mv88e6xxx_ops {
+	/* Switch Setup Errata, called early in the switch setup to
+	 * allow any errata actions to be performed
+	 */
+	int (*setup_errata)(struct mv88e6xxx_chip *chip);
+
 	/* Ingress Rate Limit unit (IRL) operations */
 	int (*irl_init_all)(struct mv88e6xxx_chip *chip, int port);
 
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index b16d5f0..ccdc67f 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -236,6 +236,16 @@
 /* Offset 0x19: Port IEEE Priority Remapping Registers (4-7) */
 #define MV88E6095_PORT_IEEE_PRIO_REMAP_4567	0x19
 
+/* Offset 0x1a: Magic undocumented errata register */
+#define PORT_RESERVED_1A			0x1a
+#define PORT_RESERVED_1A_BUSY			BIT(15)
+#define PORT_RESERVED_1A_WRITE			BIT(14)
+#define PORT_RESERVED_1A_READ			0
+#define PORT_RESERVED_1A_PORT_SHIFT		5
+#define PORT_RESERVED_1A_BLOCK			(0xf << 10)
+#define PORT_RESERVED_1A_CTRL_PORT		4
+#define PORT_RESERVED_1A_DATA_PORT		5
+
 int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
 			u16 *val);
 int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 527908c..84def1f 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -714,8 +714,10 @@ static struct phy_device *connect_local_phy(struct net_device *dev)
 
 		phydev = phy_connect(dev, phy_id_fmt, &altera_tse_adjust_link,
 				     priv->phy_iface);
-		if (IS_ERR(phydev))
+		if (IS_ERR(phydev)) {
 			netdev_err(dev, "Could not attach to PHY\n");
+			phydev = NULL;
+		}
 
 	} else {
 		int ret;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index d272dc6..b40d437 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -431,8 +431,6 @@
 #define MAC_MDIOSCAR_PA_WIDTH		5
 #define MAC_MDIOSCAR_RA_INDEX		0
 #define MAC_MDIOSCAR_RA_WIDTH		16
-#define MAC_MDIOSCAR_REG_INDEX		0
-#define MAC_MDIOSCAR_REG_WIDTH		21
 #define MAC_MDIOSCCDR_BUSY_INDEX	22
 #define MAC_MDIOSCCDR_BUSY_WIDTH	1
 #define MAC_MDIOSCCDR_CMD_INDEX		16
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index e107e18..1e4bb33 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1284,6 +1284,20 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
 	}
 }
 
+static unsigned int xgbe_create_mdio_sca(int port, int reg)
+{
+	unsigned int mdio_sca, da;
+
+	da = (reg & MII_ADDR_C45) ? reg >> 16 : 0;
+
+	mdio_sca = 0;
+	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg);
+	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, PA, port);
+	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, da);
+
+	return mdio_sca;
+}
+
 static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
 				   int reg, u16 val)
 {
@@ -1291,9 +1305,7 @@ static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
 
 	reinit_completion(&pdata->mdio_complete);
 
-	mdio_sca = 0;
-	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
-	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+	mdio_sca = xgbe_create_mdio_sca(addr, reg);
 	XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
 
 	mdio_sccd = 0;
@@ -1317,9 +1329,7 @@ static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
 
 	reinit_completion(&pdata->mdio_complete);
 
-	mdio_sca = 0;
-	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
-	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+	mdio_sca = xgbe_create_mdio_sca(addr, reg);
 	XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
 
 	mdio_sccd = 0;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 3b889ef..50dd6bf 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -29,9 +29,6 @@
 #define RES_RING_CSR	1
 #define RES_RING_CMD	2
 
-static const struct of_device_id xgene_enet_of_match[];
-static const struct acpi_device_id xgene_enet_acpi_match[];
-
 static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
 {
 	struct xgene_enet_raw_desc16 *raw_desc;
diff --git a/drivers/net/ethernet/aquantia/Kconfig b/drivers/net/ethernet/aquantia/Kconfig
index ad7b137..1b35d4e 100644
--- a/drivers/net/ethernet/aquantia/Kconfig
+++ b/drivers/net/ethernet/aquantia/Kconfig
@@ -36,4 +36,13 @@
 	help
 	  Enable support for integration with Qualcomm Technologies, Inc. chipsets.
 
+config AQFWD_QCOM_IPA
+	bool "QTI IPA offload support"
+	depends on IPA_ETH
+	select AQFWD_QCOM
+	select ATLFWD_FWD
+	help
+	  Enable support for Qualcomm Technologies, Inc. IPA (Internet Protocol Accelerator).
+	  If unsure, say N.
+
 endif # NET_VENDOR_AQUANTIA
diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/Makefile b/drivers/net/ethernet/aquantia/atlantic-fwd/Makefile
index c25bf1f..52d9467 100644
--- a/drivers/net/ethernet/aquantia/atlantic-fwd/Makefile
+++ b/drivers/net/ethernet/aquantia/atlantic-fwd/Makefile
@@ -43,5 +43,6 @@
 atlantic-fwd-$(CONFIG_OF) += atl_of.o
 
 atlantic-fwd-$(CONFIG_AQFWD_QCOM) += atl_qcom.o
+atlantic-fwd-$(CONFIG_AQFWD_QCOM_IPA) += atl_qcom_ipa.o
 
 CFLAGS_atl_trace.o := -I$(src)
diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_main.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_main.c
index 16cd696..9da8923 100644
--- a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_main.c
+++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_main.c
@@ -13,6 +13,8 @@
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 
+#include "atl_qcom_ipa.h"
+
 #include "atl_of.h"
 
 const char atl_driver_name[] = "atlantic-fwd";
@@ -595,8 +597,17 @@ static int __init atl_module_init(void)
 		return -ENOMEM;
 	}
 
+	ret = atl_qcom_ipa_register(&atl_pci_ops);
+	if (ret) {
+		pr_err("%s: Failed to register driver with IPA\n",
+		       atl_driver_name);
+		destroy_workqueue(atl_wq);
+		return ret;
+	}
+
 	ret = pci_register_driver(&atl_pci_ops);
 	if (ret) {
+		atl_qcom_ipa_unregister(&atl_pci_ops);
 		destroy_workqueue(atl_wq);
 		return ret;
 	}
@@ -609,6 +620,8 @@ static void __exit atl_module_exit(void)
 {
 	pci_unregister_driver(&atl_pci_ops);
 
+	atl_qcom_ipa_unregister(&atl_pci_ops);
+
 	if (atl_wq) {
 		destroy_workqueue(atl_wq);
 		atl_wq = NULL;
diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_qcom_ipa.c b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_qcom_ipa.c
new file mode 100644
index 0000000..2c55f64
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_qcom_ipa.c
@@ -0,0 +1,322 @@
+/* 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/pci.h>
+
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/ipa_eth.h>
+
+#include "atl_fwd.h"
+#include "atl_qcom_ipa.h"
+
+#define ATL_IPA_DEFAULT_RING_SZ 256
+#define ATL_IPA_DEFAULT_BUFF_SZ 2048
+
+static inline struct atl_fwd_ring *CH_RING(struct ipa_eth_channel *ch)
+{
+	return (struct atl_fwd_ring *)(ch->nd_priv);
+}
+
+static int atl_ipa_open_device(struct ipa_eth_device *eth_dev)
+{
+	struct atl_nic *nic = (struct atl_nic *)dev_get_drvdata(eth_dev->dev);
+
+	if (!nic || !nic->ndev) {
+		dev_err(eth_dev->dev, "Invalid atl_nic");
+		return -ENODEV;
+	}
+
+	/* atl specific init, ref counting go here */
+
+	eth_dev->nd_priv = nic;
+	eth_dev->net_dev = nic->ndev;
+
+	return 0;
+}
+
+static void atl_ipa_close_device(struct ipa_eth_device *eth_dev)
+{
+	eth_dev->nd_priv = NULL;
+	eth_dev->net_dev = NULL;
+}
+
+static struct ipa_eth_channel *atl_ipa_request_channel(
+	struct ipa_eth_device *eth_dev, enum ipa_eth_channel_dir dir,
+	unsigned long features, unsigned long events)
+{
+	struct atl_fwd_ring *ring = NULL;
+	enum atl_fwd_ring_flags ring_flags = 0;
+	struct ipa_eth_channel *channel = NULL;
+
+	switch (dir) {
+	case IPA_ETH_DIR_RX:
+		break;
+	case IPA_ETH_DIR_TX:
+		ring_flags |= ATL_FWR_TX;
+		break;
+	default:
+		dev_err(eth_dev->dev, "Unsupported direction %d", dir);
+		return NULL;
+	}
+
+	ring_flags |= ATL_FWR_ALLOC_BUFS;
+	ring_flags |= ATL_FWR_CONTIG_BUFS;
+
+	ring = atl_fwd_request_ring(eth_dev->net_dev, ring_flags,
+				    ATL_IPA_DEFAULT_RING_SZ,
+				    ATL_IPA_DEFAULT_BUFF_SZ, 1);
+	if (IS_ERR_OR_NULL(ring)) {
+		dev_err(eth_dev->dev, "Request ring failed");
+		goto err_exit;
+	}
+
+	channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+	if (!channel)
+		goto err_exit;
+
+	channel->events = 0;
+	channel->features = 0;
+	channel->direction = dir;
+	channel->queue = ring->idx;
+
+	channel->desc_size = 16;
+	channel->desc_count = ring->hw.size;
+	channel->desc_mem.size = channel->desc_size * channel->desc_count;
+
+	channel->desc_mem.vaddr = ring->hw.descs;
+	channel->desc_mem.daddr = ring->hw.daddr;
+	channel->desc_mem.paddr =
+		page_to_phys(vmalloc_to_page(channel->desc_mem.vaddr));
+
+	channel->buff_size = ATL_IPA_DEFAULT_BUFF_SZ;
+	channel->buff_count = channel->desc_count;
+	channel->buff_mem.size = channel->buff_size * channel->buff_count;
+
+	channel->buff_mem.vaddr = (void *)ring->bufs->vaddr_vec;
+	channel->buff_mem.daddr = ring->bufs->daddr_vec_base;
+	channel->buff_mem.paddr = virt_to_phys((void *)ring->bufs->vaddr_vec);
+
+	channel->eth_dev = eth_dev;
+	channel->nd_priv = ring;
+
+	return channel;
+
+err_exit:
+	kzfree(channel);
+
+	if (!IS_ERR_OR_NULL(ring)) {
+		atl_fwd_release_ring(ring);
+		ring = NULL;
+	}
+
+	return NULL;
+}
+
+static void atl_ipa_release_channel(struct ipa_eth_channel *ch)
+{
+	atl_fwd_release_ring(CH_RING(ch));
+	kzfree(ch);
+}
+
+static int atl_ipa_enable_channel(struct ipa_eth_channel *ch)
+{
+	return atl_fwd_enable_ring(CH_RING(ch));
+}
+
+static int atl_ipa_disable_channel(struct ipa_eth_channel *ch)
+{
+	atl_fwd_disable_ring(CH_RING(ch));
+
+	return 0;
+}
+
+static int atl_ipa_request_event(struct ipa_eth_channel *ch,
+				 unsigned long ipa_event,
+				 phys_addr_t addr, u64 data)
+{
+	int rc = 0;
+	struct atl_fwd_event *event = NULL;
+	struct atl_fwd_event atl_event = {0};
+	struct ipa_eth_device *eth_dev = ch->eth_dev;
+
+	switch (ipa_event) {
+	case IPA_ETH_DEV_EV_RX_INT:
+		if (ch->direction != IPA_ETH_DIR_RX) {
+			dev_err(eth_dev->dev,
+				"Rx interrupt requested on incorrect channel");
+			return -EFAULT;
+		}
+
+		atl_event.msi_addr = dma_map_resource(eth_dev->dev,
+						      addr, sizeof(u32),
+						      DMA_FROM_DEVICE, 0);
+		atl_event.msi_data = (u32)data;
+		break;
+
+	case IPA_ETH_DEV_EV_TX_INT:
+		if (ch->direction != IPA_ETH_DIR_TX) {
+			dev_err(eth_dev->dev,
+				"Tx interrupt requested on incorrect channel");
+			return -EFAULT;
+		}
+
+		atl_event.msi_addr = dma_map_resource(eth_dev->dev,
+						      addr, sizeof(u32),
+						      DMA_FROM_DEVICE, 0);
+		atl_event.msi_data = (u32)data;
+		break;
+
+	case IPA_ETH_DEV_EV_TX_PTR:
+		if (ch->direction != IPA_ETH_DIR_TX) {
+			dev_err(eth_dev->dev,
+				"Tx ptr wrb requested on incorrect channel");
+			return -EFAULT;
+		}
+
+		atl_event.flags = ATL_FWD_EVT_TXWB;
+		atl_event.tx_head_wrb = dma_map_resource(eth_dev->dev,
+							 addr, sizeof(u32),
+							 DMA_FROM_DEVICE, 0);
+		break;
+
+	default:
+		dev_err(eth_dev->dev, "Unsupported event requested");
+		return -ENODEV;
+	}
+
+	event = kzalloc(sizeof(*event), GFP_KERNEL);
+	if (!event)
+		return -ENOMEM;
+
+	*event = atl_event;
+	event->ring = CH_RING(ch);
+
+	rc = atl_fwd_request_event(event);
+	if (rc)
+		kfree(event);
+
+	return rc;
+}
+
+static void atl_ipa_release_event(struct ipa_eth_channel *ch,
+				  unsigned long ipa_event)
+{
+	dma_addr_t daddr;
+	struct atl_fwd_event *event = CH_RING(ch)->evt;
+	struct ipa_eth_device *eth_dev = ch->eth_dev;
+
+	switch (ipa_event) {
+	case IPA_ETH_DEV_EV_RX_INT:
+	case IPA_ETH_DEV_EV_TX_INT:
+		daddr = event->msi_addr;
+		break;
+
+	case IPA_ETH_DEV_EV_TX_PTR:
+		daddr = event->tx_head_wrb;
+		break;
+
+	default:
+		dev_err(eth_dev->dev, "Unsupported event for release");
+		return;
+	}
+
+	/* An atl ring can have only one associated event */
+	atl_fwd_release_event(event);
+
+	dma_unmap_resource(eth_dev->dev,
+			   daddr, sizeof(u32), DMA_FROM_DEVICE, 0);
+}
+
+static int atl_ipa_enable_event(struct ipa_eth_channel *ch,
+				unsigned long event)
+{
+	/* An atl ring can have only one associated event */
+	return atl_fwd_enable_event(CH_RING(ch)->evt);
+}
+
+static int atl_ipa_disable_event(struct ipa_eth_channel *ch,
+				 unsigned long event)
+{
+	/* An atl ring can have only one associated event */
+	return atl_fwd_disable_event(CH_RING(ch)->evt);
+}
+
+int atl_ipa_moderate_event(struct ipa_eth_channel *ch, unsigned long event,
+			   u64 min_count, u64 max_count,
+			   u64 min_usecs, u64 max_usecs)
+{
+	return atl_fwd_set_ring_intr_mod(CH_RING(ch), min_usecs, max_usecs);
+}
+
+static int atl_ipa_receive_skb(struct ipa_eth_device *eth_dev,
+			       struct sk_buff *skb)
+{
+	return atl_fwd_receive_skb(eth_dev->net_dev, skb);
+}
+
+static int atl_ipa_transmit_skb(struct ipa_eth_device *eth_dev,
+				struct sk_buff *skb)
+{
+	return atl_fwd_transmit_skb(eth_dev->net_dev, skb);
+}
+
+struct ipa_eth_net_ops atl_net_ops = {
+	.open_device = atl_ipa_open_device,
+	.close_device = atl_ipa_close_device,
+	.request_channel = atl_ipa_request_channel,
+	.release_channel = atl_ipa_release_channel,
+	.enable_channel = atl_ipa_enable_channel,
+	.disable_channel = atl_ipa_disable_channel,
+	.request_event = atl_ipa_request_event,
+	.release_event = atl_ipa_release_event,
+	.enable_event = atl_ipa_enable_event,
+	.disable_event = atl_ipa_disable_event,
+	.moderate_event = atl_ipa_moderate_event,
+	.receive_skb = atl_ipa_receive_skb,
+	.transmit_skb = atl_ipa_transmit_skb,
+};
+
+static struct ipa_eth_net_driver atl_net_driver = {
+	.events =
+		IPA_ETH_DEV_EV_RX_INT |
+		IPA_ETH_DEV_EV_TX_INT |
+		IPA_ETH_DEV_EV_TX_PTR,
+	.features =
+		IPA_ETH_DEV_F_L2_CSUM |
+		IPA_ETH_DEV_F_L3_CSUM |
+		IPA_ETH_DEV_F_TCP_CSUM |
+		IPA_ETH_DEV_F_UDP_CSUM |
+		IPA_ETH_DEV_F_LSO |
+		IPA_ETH_DEV_F_LRO |
+		IPA_ETH_DEV_F_VLAN |
+		IPA_ETH_DEV_F_MODC |
+		IPA_ETH_DEV_F_MODT,
+	.bus = &pci_bus_type,
+	.ops = &atl_net_ops,
+};
+
+int atl_qcom_ipa_register(struct pci_driver *pdrv)
+{
+	if (!atl_net_driver.name)
+		atl_net_driver.name = pdrv->name;
+
+	if (!atl_net_driver.driver)
+		atl_net_driver.driver = &pdrv->driver;
+
+	return ipa_eth_register_net_driver(&atl_net_driver);
+}
+
+void atl_qcom_ipa_unregister(struct pci_driver *pdrv)
+{
+	ipa_eth_unregister_net_driver(&atl_net_driver);
+}
diff --git a/drivers/net/ethernet/aquantia/atlantic-fwd/atl_qcom_ipa.h b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_qcom_ipa.h
new file mode 100644
index 0000000..55d5b9b
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic-fwd/atl_qcom_ipa.h
@@ -0,0 +1,35 @@
+/* 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 _ATL_QCOM_IPA_H_
+#define _ATL_QCOM_IPA_H_
+
+#include <linux/pci.h>
+
+#ifdef CONFIG_AQFWD_QCOM_IPA
+
+int atl_qcom_ipa_register(struct pci_driver *drv);
+void atl_qcom_ipa_unregister(struct pci_driver *drv);
+
+#else
+
+static inline int atl_qcom_ipa_register(struct pci_driver *drv)
+{
+	return 0;
+}
+
+static inline void atl_qcom_ipa_unregister(struct pci_driver *drv)
+{ }
+
+#endif /* CONFIG_AQFWD_QCOM_IPA */
+
+#endif /* _ATL_QCOM_IPA_H_ */
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 4546255..ed3edb1 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -519,7 +519,6 @@ static void bcm_sysport_get_wol(struct net_device *dev,
 				struct ethtool_wolinfo *wol)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
-	u32 reg;
 
 	wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE;
 	wol->wolopts = priv->wolopts;
@@ -527,11 +526,7 @@ static void bcm_sysport_get_wol(struct net_device *dev,
 	if (!(priv->wolopts & WAKE_MAGICSECURE))
 		return;
 
-	/* Return the programmed SecureOn password */
-	reg = umac_readl(priv, UMAC_PSW_MS);
-	put_unaligned_be16(reg, &wol->sopass[0]);
-	reg = umac_readl(priv, UMAC_PSW_LS);
-	put_unaligned_be32(reg, &wol->sopass[2]);
+	memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
 }
 
 static int bcm_sysport_set_wol(struct net_device *dev,
@@ -547,13 +542,8 @@ static int bcm_sysport_set_wol(struct net_device *dev,
 	if (wol->wolopts & ~supported)
 		return -EINVAL;
 
-	/* Program the SecureOn password */
-	if (wol->wolopts & WAKE_MAGICSECURE) {
-		umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
-			    UMAC_PSW_MS);
-		umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
-			    UMAC_PSW_LS);
-	}
+	if (wol->wolopts & WAKE_MAGICSECURE)
+		memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
 
 	/* Flag the device and relevant IRQ as wakeup capable */
 	if (wol->wolopts) {
@@ -2221,12 +2211,17 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
 	unsigned int timeout = 1000;
 	u32 reg;
 
-	/* Password has already been programmed */
 	reg = umac_readl(priv, UMAC_MPD_CTRL);
 	reg |= MPD_EN;
 	reg &= ~PSW_EN;
-	if (priv->wolopts & WAKE_MAGICSECURE)
+	if (priv->wolopts & WAKE_MAGICSECURE) {
+		/* Program the SecureOn password */
+		umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
+			    UMAC_PSW_MS);
+		umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
+			    UMAC_PSW_LS);
 		reg |= PSW_EN;
+	}
 	umac_writel(priv, reg, UMAC_MPD_CTRL);
 
 	/* Make sure RBUF entered WoL mode as result */
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
index 86ae751..3df4a48b8 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.h
+++ b/drivers/net/ethernet/broadcom/bcmsysport.h
@@ -11,6 +11,7 @@
 #ifndef __BCM_SYSPORT_H
 #define __BCM_SYSPORT_H
 
+#include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 
 /* Receive/transmit descriptor format */
@@ -754,6 +755,7 @@ struct bcm_sysport_priv {
 	unsigned int		crc_fwd:1;
 	u16			rev;
 	u32			wolopts;
+	u8			sopass[SOPASS_MAX];
 	unsigned int		wol_irq_disabled:1;
 
 	/* MIB related fields */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 1b7f434..d17a5c9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1278,6 +1278,7 @@ enum sp_rtnl_flag {
 	BNX2X_SP_RTNL_TX_STOP,
 	BNX2X_SP_RTNL_GET_DRV_VERSION,
 	BNX2X_SP_RTNL_CHANGE_UDP_PORT,
+	BNX2X_SP_RTNL_UPDATE_SVID,
 };
 
 enum bnx2x_iov_flag {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index bd3e3f08..41ac9a2 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -2925,6 +2925,10 @@ static void bnx2x_handle_update_svid_cmd(struct bnx2x *bp)
 	func_params.f_obj = &bp->func_obj;
 	func_params.cmd = BNX2X_F_CMD_SWITCH_UPDATE;
 
+	/* Prepare parameters for function state transitions */
+	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+	__set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
+
 	if (IS_MF_UFP(bp) || IS_MF_BD(bp)) {
 		int func = BP_ABS_FUNC(bp);
 		u32 val;
@@ -4301,7 +4305,8 @@ static void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
 				bnx2x_handle_eee_event(bp);
 
 			if (val & DRV_STATUS_OEM_UPDATE_SVID)
-				bnx2x_handle_update_svid_cmd(bp);
+				bnx2x_schedule_sp_rtnl(bp,
+					BNX2X_SP_RTNL_UPDATE_SVID, 0);
 
 			if (bp->link_vars.periodic_flags &
 			    PERIODIC_FLAGS_LINK_EVENT) {
@@ -8462,6 +8467,7 @@ int bnx2x_set_vlan_one(struct bnx2x *bp, u16 vlan,
 	/* Fill a user request section if needed */
 	if (!test_bit(RAMROD_CONT, ramrod_flags)) {
 		ramrod_param.user_req.u.vlan.vlan = vlan;
+		__set_bit(BNX2X_VLAN, &ramrod_param.user_req.vlan_mac_flags);
 		/* Set the command: ADD or DEL */
 		if (set)
 			ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
@@ -8482,6 +8488,27 @@ int bnx2x_set_vlan_one(struct bnx2x *bp, u16 vlan,
 	return rc;
 }
 
+static int bnx2x_del_all_vlans(struct bnx2x *bp)
+{
+	struct bnx2x_vlan_mac_obj *vlan_obj = &bp->sp_objs[0].vlan_obj;
+	unsigned long ramrod_flags = 0, vlan_flags = 0;
+	struct bnx2x_vlan_entry *vlan;
+	int rc;
+
+	__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+	__set_bit(BNX2X_VLAN, &vlan_flags);
+	rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_flags, &ramrod_flags);
+	if (rc)
+		return rc;
+
+	/* Mark that hw forgot all entries */
+	list_for_each_entry(vlan, &bp->vlan_reg, link)
+		vlan->hw = false;
+	bp->vlan_cnt = 0;
+
+	return 0;
+}
+
 int bnx2x_del_all_macs(struct bnx2x *bp,
 		       struct bnx2x_vlan_mac_obj *mac_obj,
 		       int mac_type, bool wait_for_comp)
@@ -9320,6 +9347,17 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link)
 		BNX2X_ERR("Failed to schedule DEL commands for UC MACs list: %d\n",
 			  rc);
 
+	/* The whole *vlan_obj structure may be not initialized if VLAN
+	 * filtering offload is not supported by hardware. Currently this is
+	 * true for all hardware covered by CHIP_IS_E1x().
+	 */
+	if (!CHIP_IS_E1x(bp)) {
+		/* Remove all currently configured VLANs */
+		rc = bnx2x_del_all_vlans(bp);
+		if (rc < 0)
+			BNX2X_ERR("Failed to delete all VLANs\n");
+	}
+
 	/* Disable LLH */
 	if (!CHIP_IS_E1(bp))
 		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
@@ -10342,6 +10380,9 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work)
 			       &bp->sp_rtnl_state))
 		bnx2x_update_mng_version(bp);
 
+	if (test_and_clear_bit(BNX2X_SP_RTNL_UPDATE_SVID, &bp->sp_rtnl_state))
+		bnx2x_handle_update_svid_cmd(bp);
+
 	if (test_and_clear_bit(BNX2X_SP_RTNL_CHANGE_UDP_PORT,
 			       &bp->sp_rtnl_state)) {
 		if (bnx2x_udp_port_update(bp)) {
@@ -11733,8 +11774,10 @@ static void bnx2x_get_fcoe_info(struct bnx2x *bp)
 	 * If maximum allowed number of connections is zero -
 	 * disable the feature.
 	 */
-	if (!bp->cnic_eth_dev.max_fcoe_conn)
+	if (!bp->cnic_eth_dev.max_fcoe_conn) {
 		bp->flags |= NO_FCOE_FLAG;
+		eth_zero_addr(bp->fip_mac);
+	}
 }
 
 static void bnx2x_get_cnic_info(struct bnx2x *bp)
@@ -12935,6 +12978,24 @@ static netdev_features_t bnx2x_features_check(struct sk_buff *skb,
 					      struct net_device *dev,
 					      netdev_features_t features)
 {
+	/*
+	 * A skb with gso_size + header length > 9700 will cause a
+	 * firmware panic. Drop GSO support.
+	 *
+	 * Eventually the upper layer should not pass these packets down.
+	 *
+	 * For speed, if the gso_size is <= 9000, assume there will
+	 * not be 700 bytes of headers and pass it through. Only do a
+	 * full (slow) validation if the gso_size is > 9000.
+	 *
+	 * (Due to the way SKB_BY_FRAGS works this will also do a full
+	 * validation in that case.)
+	 */
+	if (unlikely(skb_is_gso(skb) &&
+		     (skb_shinfo(skb)->gso_size > 9000) &&
+		     !skb_gso_validate_mac_len(skb, 9700)))
+		features &= ~NETIF_F_GSO_MASK;
+
 	features = vlan_features_check(skb, features);
 	return vxlan_features_check(skb, features);
 }
@@ -13004,13 +13065,6 @@ static void bnx2x_vlan_configure(struct bnx2x *bp, bool set_rx_mode)
 
 int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp)
 {
-	struct bnx2x_vlan_entry *vlan;
-
-	/* The hw forgot all entries after reload */
-	list_for_each_entry(vlan, &bp->vlan_reg, link)
-		vlan->hw = false;
-	bp->vlan_cnt = 0;
-
 	/* Don't set rx mode here. Our caller will do it. */
 	bnx2x_vlan_configure(bp, false);
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index 0bf2fd4..7a6e82d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -265,6 +265,7 @@ enum {
 	BNX2X_ETH_MAC,
 	BNX2X_ISCSI_ETH_MAC,
 	BNX2X_NETQ_ETH_MAC,
+	BNX2X_VLAN,
 	BNX2X_DONT_CONSUME_CAM_CREDIT,
 	BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
 };
@@ -272,7 +273,8 @@ enum {
 #define BNX2X_VLAN_MAC_CMP_MASK	(1 << BNX2X_UC_LIST_MAC | \
 				 1 << BNX2X_ETH_MAC | \
 				 1 << BNX2X_ISCSI_ETH_MAC | \
-				 1 << BNX2X_NETQ_ETH_MAC)
+				 1 << BNX2X_NETQ_ETH_MAC | \
+				 1 << BNX2X_VLAN)
 #define BNX2X_VLAN_MAC_CMP_FLAGS(flags) \
 	((flags) & BNX2X_VLAN_MAC_CMP_MASK)
 
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 0b2f9dd..9046993 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -675,6 +675,11 @@ static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_
 	if (bp->hw_dma_cap & HW_DMA_CAP_64B) {
 		desc_64 = macb_64b_desc(bp, desc);
 		desc_64->addrh = upper_32_bits(addr);
+		/* The low bits of RX address contain the RX_USED bit, clearing
+		 * of which allows packet RX. Make sure the high bits are also
+		 * visible to HW at that point.
+		 */
+		dma_wmb();
 	}
 #endif
 	desc->addr = lower_32_bits(addr);
@@ -918,14 +923,19 @@ static void gem_rx_refill(struct macb *bp)
 
 			if (entry == bp->rx_ring_size - 1)
 				paddr |= MACB_BIT(RX_WRAP);
-			macb_set_addr(bp, desc, paddr);
 			desc->ctrl = 0;
+			/* Setting addr clears RX_USED and allows reception,
+			 * make sure ctrl is cleared first to avoid a race.
+			 */
+			dma_wmb();
+			macb_set_addr(bp, desc, paddr);
 
 			/* properly align Ethernet header */
 			skb_reserve(skb, NET_IP_ALIGN);
 		} else {
-			desc->addr &= ~MACB_BIT(RX_USED);
 			desc->ctrl = 0;
+			dma_wmb();
+			desc->addr &= ~MACB_BIT(RX_USED);
 		}
 	}
 
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 03f4fee..ced348e 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1393,7 +1393,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
 		 * csum is correct or is zero.
 		 */
 		if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc &&
-		    tcp_udp_csum_ok && ipv4_csum_ok && outer_csum_ok) {
+		    tcp_udp_csum_ok && outer_csum_ok &&
+		    (ipv4_csum_ok || ipv6)) {
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			skb->csum_level = encap;
 		}
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index c029688..75ce773 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -927,7 +927,7 @@ int memac_add_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr)
 	hash = get_mac_addr_hash_code(addr) & HASH_CTRL_ADDR_MASK;
 
 	/* Create element to be added to the driver hash table */
-	hash_entry = kmalloc(sizeof(*hash_entry), GFP_KERNEL);
+	hash_entry = kmalloc(sizeof(*hash_entry), GFP_ATOMIC);
 	if (!hash_entry)
 		return -ENOMEM;
 	hash_entry->addr = addr;
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index 4b0f3a5..e575259 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -551,7 +551,7 @@ int tgec_add_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr)
 	hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK;
 
 	/* Create element to be added to the driver hash table */
-	hash_entry = kmalloc(sizeof(*hash_entry), GFP_KERNEL);
+	hash_entry = kmalloc(sizeof(*hash_entry), GFP_ATOMIC);
 	if (!hash_entry)
 		return -ENOMEM;
 	hash_entry->addr = addr;
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index f77ba9f..94df1dd 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -1888,6 +1888,8 @@ static void ucc_geth_free_tx(struct ucc_geth_private *ugeth)
 	u16 i, j;
 	u8 __iomem *bd;
 
+	netdev_reset_queue(ugeth->ndev);
+
 	ug_info = ugeth->ug_info;
 	uf_info = &ug_info->uf_info;
 
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index bf930ab..53904f2 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -147,12 +147,10 @@ static void hns_ae_put_handle(struct hnae_handle *handle)
 	struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
 	int i;
 
-	vf_cb->mac_cb	 = NULL;
-
-	kfree(vf_cb);
-
 	for (i = 0; i < handle->q_num; i++)
 		hns_ae_get_ring_pair(handle->qs[i])->used_by_vf = 0;
+
+	kfree(vf_cb);
 }
 
 static int hns_ae_wait_flow_down(struct hnae_handle *handle)
@@ -379,6 +377,9 @@ void hns_ae_stop(struct hnae_handle *handle)
 
 	hns_ae_ring_enable_all(handle, 0);
 
+	/* clean rx fbd. */
+	hns_rcb_wait_fbd_clean(handle->qs, handle->q_num, RCB_INT_FLAG_RX);
+
 	(void)hns_mac_vm_config_bc_en(mac_cb, 0, false);
 }
 
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
index 8c7bc5c..5e8930d0 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
@@ -67,11 +67,14 @@ static void hns_gmac_enable(void *mac_drv, enum mac_commom_mode mode)
 	struct mac_driver *drv = (struct mac_driver *)mac_drv;
 
 	/*enable GE rX/tX */
-	if ((mode == MAC_COMM_MODE_TX) || (mode == MAC_COMM_MODE_RX_AND_TX))
+	if (mode == MAC_COMM_MODE_TX || mode == MAC_COMM_MODE_RX_AND_TX)
 		dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_TX_EN_B, 1);
 
-	if ((mode == MAC_COMM_MODE_RX) || (mode == MAC_COMM_MODE_RX_AND_TX))
+	if (mode == MAC_COMM_MODE_RX || mode == MAC_COMM_MODE_RX_AND_TX) {
+		/* enable rx pcs */
+		dsaf_set_dev_bit(drv, GMAC_PCS_RX_EN_REG, 0, 0);
 		dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_RX_EN_B, 1);
+	}
 }
 
 static void hns_gmac_disable(void *mac_drv, enum mac_commom_mode mode)
@@ -79,11 +82,14 @@ static void hns_gmac_disable(void *mac_drv, enum mac_commom_mode mode)
 	struct mac_driver *drv = (struct mac_driver *)mac_drv;
 
 	/*disable GE rX/tX */
-	if ((mode == MAC_COMM_MODE_TX) || (mode == MAC_COMM_MODE_RX_AND_TX))
+	if (mode == MAC_COMM_MODE_TX || mode == MAC_COMM_MODE_RX_AND_TX)
 		dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_TX_EN_B, 0);
 
-	if ((mode == MAC_COMM_MODE_RX) || (mode == MAC_COMM_MODE_RX_AND_TX))
+	if (mode == MAC_COMM_MODE_RX || mode == MAC_COMM_MODE_RX_AND_TX) {
+		/* disable rx pcs */
+		dsaf_set_dev_bit(drv, GMAC_PCS_RX_EN_REG, 0, 1);
 		dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_RX_EN_B, 0);
+	}
 }
 
 /* hns_gmac_get_en - get port enable
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
index 5a8dbd7..07e117d 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
@@ -783,6 +783,17 @@ static int hns_mac_register_phy(struct hns_mac_cb *mac_cb)
 	return rc;
 }
 
+static void hns_mac_remove_phydev(struct hns_mac_cb *mac_cb)
+{
+	if (!to_acpi_device_node(mac_cb->fw_port) || !mac_cb->phy_dev)
+		return;
+
+	phy_device_remove(mac_cb->phy_dev);
+	phy_device_free(mac_cb->phy_dev);
+
+	mac_cb->phy_dev = NULL;
+}
+
 #define MAC_MEDIA_TYPE_MAX_LEN		16
 
 static const struct {
@@ -1120,7 +1131,11 @@ void hns_mac_uninit(struct dsaf_device *dsaf_dev)
 	int max_port_num = hns_mac_get_max_port_num(dsaf_dev);
 
 	for (i = 0; i < max_port_num; i++) {
+		if (!dsaf_dev->mac_cb[i])
+			continue;
+
 		dsaf_dev->misc_op->cpld_reset_led(dsaf_dev->mac_cb[i]);
+		hns_mac_remove_phydev(dsaf_dev->mac_cb[i]);
 		dsaf_dev->mac_cb[i] = NULL;
 	}
 }
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 1f056a6..51d42d7 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -935,6 +935,62 @@ static void hns_dsaf_tcam_mc_cfg(
 }
 
 /**
+ * hns_dsaf_tcam_uc_cfg_vague - INT
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @address,
+ * @ptbl_tcam_data,
+ */
+static void hns_dsaf_tcam_uc_cfg_vague(struct dsaf_device *dsaf_dev,
+				       u32 address,
+				       struct dsaf_tbl_tcam_data *tcam_data,
+				       struct dsaf_tbl_tcam_data *tcam_mask,
+				       struct dsaf_tbl_tcam_ucast_cfg *tcam_uc)
+{
+	spin_lock_bh(&dsaf_dev->tcam_lock);
+	hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
+	hns_dsaf_tbl_tcam_data_cfg(dsaf_dev, tcam_data);
+	hns_dsaf_tbl_tcam_ucast_cfg(dsaf_dev, tcam_uc);
+	hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, tcam_mask);
+	hns_dsaf_tbl_tcam_data_ucast_pul(dsaf_dev);
+
+	/*Restore Match Data*/
+	tcam_mask->tbl_tcam_data_high = 0xffffffff;
+	tcam_mask->tbl_tcam_data_low = 0xffffffff;
+	hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, tcam_mask);
+
+	spin_unlock_bh(&dsaf_dev->tcam_lock);
+}
+
+/**
+ * hns_dsaf_tcam_mc_cfg_vague - INT
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @address,
+ * @ptbl_tcam_data,
+ * @ptbl_tcam_mask
+ * @ptbl_tcam_mcast
+ */
+static void hns_dsaf_tcam_mc_cfg_vague(struct dsaf_device *dsaf_dev,
+				       u32 address,
+				       struct dsaf_tbl_tcam_data *tcam_data,
+				       struct dsaf_tbl_tcam_data *tcam_mask,
+				       struct dsaf_tbl_tcam_mcast_cfg *tcam_mc)
+{
+	spin_lock_bh(&dsaf_dev->tcam_lock);
+	hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
+	hns_dsaf_tbl_tcam_data_cfg(dsaf_dev, tcam_data);
+	hns_dsaf_tbl_tcam_mcast_cfg(dsaf_dev, tcam_mc);
+	hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, tcam_mask);
+	hns_dsaf_tbl_tcam_data_mcast_pul(dsaf_dev);
+
+	/*Restore Match Data*/
+	tcam_mask->tbl_tcam_data_high = 0xffffffff;
+	tcam_mask->tbl_tcam_data_low = 0xffffffff;
+	hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, tcam_mask);
+
+	spin_unlock_bh(&dsaf_dev->tcam_lock);
+}
+
+/**
  * hns_dsaf_tcam_mc_invld - INT
  * @dsaf_id: dsa fabric id
  * @address
@@ -1492,6 +1548,27 @@ static u16 hns_dsaf_find_empty_mac_entry(struct dsaf_device *dsaf_dev)
 }
 
 /**
+ * hns_dsaf_find_empty_mac_entry_reverse
+ * search dsa fabric soft empty-entry from the end
+ * @dsaf_dev: dsa fabric device struct pointer
+ */
+static u16 hns_dsaf_find_empty_mac_entry_reverse(struct dsaf_device *dsaf_dev)
+{
+	struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
+	struct dsaf_drv_soft_mac_tbl *soft_mac_entry;
+	int i;
+
+	soft_mac_entry = priv->soft_mac_tbl + (DSAF_TCAM_SUM - 1);
+	for (i = (DSAF_TCAM_SUM - 1); i > 0; i--) {
+		/* search all entry from end to start.*/
+		if (soft_mac_entry->index == DSAF_INVALID_ENTRY_IDX)
+			return i;
+		soft_mac_entry--;
+	}
+	return DSAF_INVALID_ENTRY_IDX;
+}
+
+/**
  * hns_dsaf_set_mac_key - set mac key
  * @dsaf_dev: dsa fabric device struct pointer
  * @mac_key: tcam key pointer
@@ -2159,9 +2236,9 @@ void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 node_num)
 		DSAF_INODE_LOCAL_ADDR_FALSE_NUM_0_REG + 0x80 * (u64)node_num);
 
 	hw_stats->vlan_drop += dsaf_read_dev(dsaf_dev,
-		DSAF_INODE_SW_VLAN_TAG_DISC_0_REG + 0x80 * (u64)node_num);
+		DSAF_INODE_SW_VLAN_TAG_DISC_0_REG + 4 * (u64)node_num);
 	hw_stats->stp_drop += dsaf_read_dev(dsaf_dev,
-		DSAF_INODE_IN_DATA_STP_DISC_0_REG + 0x80 * (u64)node_num);
+		DSAF_INODE_IN_DATA_STP_DISC_0_REG + 4 * (u64)node_num);
 
 	/* pfc pause frame statistics stored in dsaf inode*/
 	if ((node_num < DSAF_SERVICE_NW_NUM) && !is_ver1) {
@@ -2278,237 +2355,237 @@ void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data)
 				DSAF_INODE_BD_ORDER_STATUS_0_REG + j * 4);
 		p[223 + i] = dsaf_read_dev(ddev,
 				DSAF_INODE_SW_VLAN_TAG_DISC_0_REG + j * 4);
-		p[224 + i] = dsaf_read_dev(ddev,
+		p[226 + i] = dsaf_read_dev(ddev,
 				DSAF_INODE_IN_DATA_STP_DISC_0_REG + j * 4);
 	}
 
-	p[227] = dsaf_read_dev(ddev, DSAF_INODE_GE_FC_EN_0_REG + port * 4);
+	p[229] = dsaf_read_dev(ddev, DSAF_INODE_GE_FC_EN_0_REG + port * 4);
 
 	for (i = 0; i < DSAF_INODE_NUM / DSAF_COMM_CHN; i++) {
 		j = i * DSAF_COMM_CHN + port;
-		p[228 + i] = dsaf_read_dev(ddev,
+		p[230 + i] = dsaf_read_dev(ddev,
 				DSAF_INODE_VC0_IN_PKT_NUM_0_REG + j * 4);
 	}
 
-	p[231] = dsaf_read_dev(ddev,
-		DSAF_INODE_VC1_IN_PKT_NUM_0_REG + port * 4);
+	p[233] = dsaf_read_dev(ddev,
+		DSAF_INODE_VC1_IN_PKT_NUM_0_REG + port * 0x80);
 
 	/* dsaf inode registers */
 	for (i = 0; i < HNS_DSAF_SBM_NUM(ddev) / DSAF_COMM_CHN; i++) {
 		j = i * DSAF_COMM_CHN + port;
-		p[232 + i] = dsaf_read_dev(ddev,
+		p[234 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_CFG_REG_0_REG + j * 0x80);
-		p[235 + i] = dsaf_read_dev(ddev,
+		p[237 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_BP_CFG_0_XGE_REG_0_REG + j * 0x80);
-		p[238 + i] = dsaf_read_dev(ddev,
+		p[240 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_BP_CFG_1_REG_0_REG + j * 0x80);
-		p[241 + i] = dsaf_read_dev(ddev,
+		p[243 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_BP_CFG_2_XGE_REG_0_REG + j * 0x80);
-		p[244 + i] = dsaf_read_dev(ddev,
+		p[246 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_FREE_CNT_0_0_REG + j * 0x80);
-		p[245 + i] = dsaf_read_dev(ddev,
+		p[249 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_FREE_CNT_1_0_REG + j * 0x80);
-		p[248 + i] = dsaf_read_dev(ddev,
+		p[252 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_BP_CNT_0_0_REG + j * 0x80);
-		p[251 + i] = dsaf_read_dev(ddev,
+		p[255 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_BP_CNT_1_0_REG + j * 0x80);
-		p[254 + i] = dsaf_read_dev(ddev,
+		p[258 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_BP_CNT_2_0_REG + j * 0x80);
-		p[257 + i] = dsaf_read_dev(ddev,
+		p[261 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_BP_CNT_3_0_REG + j * 0x80);
-		p[260 + i] = dsaf_read_dev(ddev,
+		p[264 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_INER_ST_0_REG + j * 0x80);
-		p[263 + i] = dsaf_read_dev(ddev,
+		p[267 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_MIB_REQ_FAILED_TC_0_REG + j * 0x80);
-		p[266 + i] = dsaf_read_dev(ddev,
+		p[270 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_INPORT_CNT_0_REG + j * 0x80);
-		p[269 + i] = dsaf_read_dev(ddev,
+		p[273 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_DROP_CNT_0_REG + j * 0x80);
-		p[272 + i] = dsaf_read_dev(ddev,
+		p[276 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_INF_OUTPORT_CNT_0_REG + j * 0x80);
-		p[275 + i] = dsaf_read_dev(ddev,
+		p[279 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_INPORT_TC0_CNT_0_REG + j * 0x80);
-		p[278 + i] = dsaf_read_dev(ddev,
+		p[282 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_INPORT_TC1_CNT_0_REG + j * 0x80);
-		p[281 + i] = dsaf_read_dev(ddev,
+		p[285 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_INPORT_TC2_CNT_0_REG + j * 0x80);
-		p[284 + i] = dsaf_read_dev(ddev,
+		p[288 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_INPORT_TC3_CNT_0_REG + j * 0x80);
-		p[287 + i] = dsaf_read_dev(ddev,
+		p[291 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_INPORT_TC4_CNT_0_REG + j * 0x80);
-		p[290 + i] = dsaf_read_dev(ddev,
+		p[294 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_INPORT_TC5_CNT_0_REG + j * 0x80);
-		p[293 + i] = dsaf_read_dev(ddev,
+		p[297 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_INPORT_TC6_CNT_0_REG + j * 0x80);
-		p[296 + i] = dsaf_read_dev(ddev,
+		p[300 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_INPORT_TC7_CNT_0_REG + j * 0x80);
-		p[299 + i] = dsaf_read_dev(ddev,
+		p[303 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_REQ_CNT_0_REG + j * 0x80);
-		p[302 + i] = dsaf_read_dev(ddev,
+		p[306 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_LNK_RELS_CNT_0_REG + j * 0x80);
-		p[305 + i] = dsaf_read_dev(ddev,
+		p[309 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_BP_CFG_3_REG_0_REG + j * 0x80);
-		p[308 + i] = dsaf_read_dev(ddev,
+		p[312 + i] = dsaf_read_dev(ddev,
 				DSAF_SBM_BP_CFG_4_REG_0_REG + j * 0x80);
 	}
 
 	/* dsaf onode registers */
 	for (i = 0; i < DSAF_XOD_NUM; i++) {
-		p[311 + i] = dsaf_read_dev(ddev,
+		p[315 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_ETS_TSA_TC0_TC3_CFG_0_REG + i * 0x90);
-		p[319 + i] = dsaf_read_dev(ddev,
+		p[323 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_ETS_TSA_TC4_TC7_CFG_0_REG + i * 0x90);
-		p[327 + i] = dsaf_read_dev(ddev,
+		p[331 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_ETS_BW_TC0_TC3_CFG_0_REG + i * 0x90);
-		p[335 + i] = dsaf_read_dev(ddev,
+		p[339 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_ETS_BW_TC4_TC7_CFG_0_REG + i * 0x90);
-		p[343 + i] = dsaf_read_dev(ddev,
+		p[347 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_ETS_BW_OFFSET_CFG_0_REG + i * 0x90);
-		p[351 + i] = dsaf_read_dev(ddev,
+		p[355 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_ETS_TOKEN_CFG_0_REG + i * 0x90);
 	}
 
-	p[359] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_0_0_REG + port * 0x90);
-	p[360] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_1_0_REG + port * 0x90);
-	p[361] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_2_0_REG + port * 0x90);
+	p[363] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_0_0_REG + port * 0x90);
+	p[364] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_1_0_REG + port * 0x90);
+	p[365] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_2_0_REG + port * 0x90);
 
 	for (i = 0; i < DSAF_XOD_BIG_NUM / DSAF_COMM_CHN; i++) {
 		j = i * DSAF_COMM_CHN + port;
-		p[362 + i] = dsaf_read_dev(ddev,
+		p[366 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_GNT_L_0_REG + j * 0x90);
-		p[365 + i] = dsaf_read_dev(ddev,
+		p[369 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_GNT_H_0_REG + j * 0x90);
-		p[368 + i] = dsaf_read_dev(ddev,
+		p[372 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_CONNECT_STATE_0_REG + j * 0x90);
-		p[371 + i] = dsaf_read_dev(ddev,
+		p[375 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_RCVPKT_CNT_0_REG + j * 0x90);
-		p[374 + i] = dsaf_read_dev(ddev,
+		p[378 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_RCVTC0_CNT_0_REG + j * 0x90);
-		p[377 + i] = dsaf_read_dev(ddev,
+		p[381 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_RCVTC1_CNT_0_REG + j * 0x90);
-		p[380 + i] = dsaf_read_dev(ddev,
+		p[384 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_RCVTC2_CNT_0_REG + j * 0x90);
-		p[383 + i] = dsaf_read_dev(ddev,
+		p[387 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_RCVTC3_CNT_0_REG + j * 0x90);
-		p[386 + i] = dsaf_read_dev(ddev,
+		p[390 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_RCVVC0_CNT_0_REG + j * 0x90);
-		p[389 + i] = dsaf_read_dev(ddev,
+		p[393 + i] = dsaf_read_dev(ddev,
 				DSAF_XOD_RCVVC1_CNT_0_REG + j * 0x90);
 	}
 
-	p[392] = dsaf_read_dev(ddev,
-		DSAF_XOD_XGE_RCVIN0_CNT_0_REG + port * 0x90);
-	p[393] = dsaf_read_dev(ddev,
-		DSAF_XOD_XGE_RCVIN1_CNT_0_REG + port * 0x90);
-	p[394] = dsaf_read_dev(ddev,
-		DSAF_XOD_XGE_RCVIN2_CNT_0_REG + port * 0x90);
-	p[395] = dsaf_read_dev(ddev,
-		DSAF_XOD_XGE_RCVIN3_CNT_0_REG + port * 0x90);
 	p[396] = dsaf_read_dev(ddev,
-		DSAF_XOD_XGE_RCVIN4_CNT_0_REG + port * 0x90);
+		DSAF_XOD_XGE_RCVIN0_CNT_0_REG + port * 0x90);
 	p[397] = dsaf_read_dev(ddev,
-		DSAF_XOD_XGE_RCVIN5_CNT_0_REG + port * 0x90);
+		DSAF_XOD_XGE_RCVIN1_CNT_0_REG + port * 0x90);
 	p[398] = dsaf_read_dev(ddev,
-		DSAF_XOD_XGE_RCVIN6_CNT_0_REG + port * 0x90);
+		DSAF_XOD_XGE_RCVIN2_CNT_0_REG + port * 0x90);
 	p[399] = dsaf_read_dev(ddev,
-		DSAF_XOD_XGE_RCVIN7_CNT_0_REG + port * 0x90);
+		DSAF_XOD_XGE_RCVIN3_CNT_0_REG + port * 0x90);
 	p[400] = dsaf_read_dev(ddev,
-		DSAF_XOD_PPE_RCVIN0_CNT_0_REG + port * 0x90);
+		DSAF_XOD_XGE_RCVIN4_CNT_0_REG + port * 0x90);
 	p[401] = dsaf_read_dev(ddev,
-		DSAF_XOD_PPE_RCVIN1_CNT_0_REG + port * 0x90);
+		DSAF_XOD_XGE_RCVIN5_CNT_0_REG + port * 0x90);
 	p[402] = dsaf_read_dev(ddev,
-		DSAF_XOD_ROCEE_RCVIN0_CNT_0_REG + port * 0x90);
+		DSAF_XOD_XGE_RCVIN6_CNT_0_REG + port * 0x90);
 	p[403] = dsaf_read_dev(ddev,
-		DSAF_XOD_ROCEE_RCVIN1_CNT_0_REG + port * 0x90);
+		DSAF_XOD_XGE_RCVIN7_CNT_0_REG + port * 0x90);
 	p[404] = dsaf_read_dev(ddev,
+		DSAF_XOD_PPE_RCVIN0_CNT_0_REG + port * 0x90);
+	p[405] = dsaf_read_dev(ddev,
+		DSAF_XOD_PPE_RCVIN1_CNT_0_REG + port * 0x90);
+	p[406] = dsaf_read_dev(ddev,
+		DSAF_XOD_ROCEE_RCVIN0_CNT_0_REG + port * 0x90);
+	p[407] = dsaf_read_dev(ddev,
+		DSAF_XOD_ROCEE_RCVIN1_CNT_0_REG + port * 0x90);
+	p[408] = dsaf_read_dev(ddev,
 		DSAF_XOD_FIFO_STATUS_0_REG + port * 0x90);
 
 	/* dsaf voq registers */
 	for (i = 0; i < DSAF_VOQ_NUM / DSAF_COMM_CHN; i++) {
 		j = (i * DSAF_COMM_CHN + port) * 0x90;
-		p[405 + i] = dsaf_read_dev(ddev,
+		p[409 + i] = dsaf_read_dev(ddev,
 			DSAF_VOQ_ECC_INVERT_EN_0_REG + j);
-		p[408 + i] = dsaf_read_dev(ddev,
+		p[412 + i] = dsaf_read_dev(ddev,
 			DSAF_VOQ_SRAM_PKT_NUM_0_REG + j);
-		p[411 + i] = dsaf_read_dev(ddev, DSAF_VOQ_IN_PKT_NUM_0_REG + j);
-		p[414 + i] = dsaf_read_dev(ddev,
+		p[415 + i] = dsaf_read_dev(ddev, DSAF_VOQ_IN_PKT_NUM_0_REG + j);
+		p[418 + i] = dsaf_read_dev(ddev,
 			DSAF_VOQ_OUT_PKT_NUM_0_REG + j);
-		p[417 + i] = dsaf_read_dev(ddev,
+		p[421 + i] = dsaf_read_dev(ddev,
 			DSAF_VOQ_ECC_ERR_ADDR_0_REG + j);
-		p[420 + i] = dsaf_read_dev(ddev, DSAF_VOQ_BP_STATUS_0_REG + j);
-		p[423 + i] = dsaf_read_dev(ddev, DSAF_VOQ_SPUP_IDLE_0_REG + j);
-		p[426 + i] = dsaf_read_dev(ddev,
+		p[424 + i] = dsaf_read_dev(ddev, DSAF_VOQ_BP_STATUS_0_REG + j);
+		p[427 + i] = dsaf_read_dev(ddev, DSAF_VOQ_SPUP_IDLE_0_REG + j);
+		p[430 + i] = dsaf_read_dev(ddev,
 			DSAF_VOQ_XGE_XOD_REQ_0_0_REG + j);
-		p[429 + i] = dsaf_read_dev(ddev,
+		p[433 + i] = dsaf_read_dev(ddev,
 			DSAF_VOQ_XGE_XOD_REQ_1_0_REG + j);
-		p[432 + i] = dsaf_read_dev(ddev,
+		p[436 + i] = dsaf_read_dev(ddev,
 			DSAF_VOQ_PPE_XOD_REQ_0_REG + j);
-		p[435 + i] = dsaf_read_dev(ddev,
+		p[439 + i] = dsaf_read_dev(ddev,
 			DSAF_VOQ_ROCEE_XOD_REQ_0_REG + j);
-		p[438 + i] = dsaf_read_dev(ddev,
+		p[442 + i] = dsaf_read_dev(ddev,
 			DSAF_VOQ_BP_ALL_THRD_0_REG + j);
 	}
 
 	/* dsaf tbl registers */
-	p[441] = dsaf_read_dev(ddev, DSAF_TBL_CTRL_0_REG);
-	p[442] = dsaf_read_dev(ddev, DSAF_TBL_INT_MSK_0_REG);
-	p[443] = dsaf_read_dev(ddev, DSAF_TBL_INT_SRC_0_REG);
-	p[444] = dsaf_read_dev(ddev, DSAF_TBL_INT_STS_0_REG);
-	p[445] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_ADDR_0_REG);
-	p[446] = dsaf_read_dev(ddev, DSAF_TBL_LINE_ADDR_0_REG);
-	p[447] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_HIGH_0_REG);
-	p[448] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_LOW_0_REG);
-	p[449] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_4_0_REG);
-	p[450] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_3_0_REG);
-	p[451] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_2_0_REG);
-	p[452] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_1_0_REG);
-	p[453] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_0_0_REG);
-	p[454] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_UCAST_CFG_0_REG);
-	p[455] = dsaf_read_dev(ddev, DSAF_TBL_LIN_CFG_0_REG);
-	p[456] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RDATA_HIGH_0_REG);
-	p[457] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RDATA_LOW_0_REG);
-	p[458] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA4_0_REG);
-	p[459] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA3_0_REG);
-	p[460] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA2_0_REG);
-	p[461] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA1_0_REG);
-	p[462] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA0_0_REG);
-	p[463] = dsaf_read_dev(ddev, DSAF_TBL_LIN_RDATA_0_REG);
+	p[445] = dsaf_read_dev(ddev, DSAF_TBL_CTRL_0_REG);
+	p[446] = dsaf_read_dev(ddev, DSAF_TBL_INT_MSK_0_REG);
+	p[447] = dsaf_read_dev(ddev, DSAF_TBL_INT_SRC_0_REG);
+	p[448] = dsaf_read_dev(ddev, DSAF_TBL_INT_STS_0_REG);
+	p[449] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_ADDR_0_REG);
+	p[450] = dsaf_read_dev(ddev, DSAF_TBL_LINE_ADDR_0_REG);
+	p[451] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_HIGH_0_REG);
+	p[452] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_LOW_0_REG);
+	p[453] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_4_0_REG);
+	p[454] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_3_0_REG);
+	p[455] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_2_0_REG);
+	p[456] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_1_0_REG);
+	p[457] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_0_0_REG);
+	p[458] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_UCAST_CFG_0_REG);
+	p[459] = dsaf_read_dev(ddev, DSAF_TBL_LIN_CFG_0_REG);
+	p[460] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RDATA_HIGH_0_REG);
+	p[461] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RDATA_LOW_0_REG);
+	p[462] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA4_0_REG);
+	p[463] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA3_0_REG);
+	p[464] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA2_0_REG);
+	p[465] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA1_0_REG);
+	p[466] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA0_0_REG);
+	p[467] = dsaf_read_dev(ddev, DSAF_TBL_LIN_RDATA_0_REG);
 
 	for (i = 0; i < DSAF_SW_PORT_NUM; i++) {
 		j = i * 0x8;
-		p[464 + 2 * i] = dsaf_read_dev(ddev,
+		p[468 + 2 * i] = dsaf_read_dev(ddev,
 			DSAF_TBL_DA0_MIS_INFO1_0_REG + j);
-		p[465 + 2 * i] = dsaf_read_dev(ddev,
+		p[469 + 2 * i] = dsaf_read_dev(ddev,
 			DSAF_TBL_DA0_MIS_INFO0_0_REG + j);
 	}
 
-	p[480] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO2_0_REG);
-	p[481] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO1_0_REG);
-	p[482] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO0_0_REG);
-	p[483] = dsaf_read_dev(ddev, DSAF_TBL_PUL_0_REG);
-	p[484] = dsaf_read_dev(ddev, DSAF_TBL_OLD_RSLT_0_REG);
-	p[485] = dsaf_read_dev(ddev, DSAF_TBL_OLD_SCAN_VAL_0_REG);
-	p[486] = dsaf_read_dev(ddev, DSAF_TBL_DFX_CTRL_0_REG);
-	p[487] = dsaf_read_dev(ddev, DSAF_TBL_DFX_STAT_0_REG);
-	p[488] = dsaf_read_dev(ddev, DSAF_TBL_DFX_STAT_2_0_REG);
-	p[489] = dsaf_read_dev(ddev, DSAF_TBL_LKUP_NUM_I_0_REG);
-	p[490] = dsaf_read_dev(ddev, DSAF_TBL_LKUP_NUM_O_0_REG);
-	p[491] = dsaf_read_dev(ddev, DSAF_TBL_UCAST_BCAST_MIS_INFO_0_0_REG);
+	p[484] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO2_0_REG);
+	p[485] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO1_0_REG);
+	p[486] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO0_0_REG);
+	p[487] = dsaf_read_dev(ddev, DSAF_TBL_PUL_0_REG);
+	p[488] = dsaf_read_dev(ddev, DSAF_TBL_OLD_RSLT_0_REG);
+	p[489] = dsaf_read_dev(ddev, DSAF_TBL_OLD_SCAN_VAL_0_REG);
+	p[490] = dsaf_read_dev(ddev, DSAF_TBL_DFX_CTRL_0_REG);
+	p[491] = dsaf_read_dev(ddev, DSAF_TBL_DFX_STAT_0_REG);
+	p[492] = dsaf_read_dev(ddev, DSAF_TBL_DFX_STAT_2_0_REG);
+	p[493] = dsaf_read_dev(ddev, DSAF_TBL_LKUP_NUM_I_0_REG);
+	p[494] = dsaf_read_dev(ddev, DSAF_TBL_LKUP_NUM_O_0_REG);
+	p[495] = dsaf_read_dev(ddev, DSAF_TBL_UCAST_BCAST_MIS_INFO_0_0_REG);
 
 	/* dsaf other registers */
-	p[492] = dsaf_read_dev(ddev, DSAF_INODE_FIFO_WL_0_REG + port * 0x4);
-	p[493] = dsaf_read_dev(ddev, DSAF_ONODE_FIFO_WL_0_REG + port * 0x4);
-	p[494] = dsaf_read_dev(ddev, DSAF_XGE_GE_WORK_MODE_0_REG + port * 0x4);
-	p[495] = dsaf_read_dev(ddev,
+	p[496] = dsaf_read_dev(ddev, DSAF_INODE_FIFO_WL_0_REG + port * 0x4);
+	p[497] = dsaf_read_dev(ddev, DSAF_ONODE_FIFO_WL_0_REG + port * 0x4);
+	p[498] = dsaf_read_dev(ddev, DSAF_XGE_GE_WORK_MODE_0_REG + port * 0x4);
+	p[499] = dsaf_read_dev(ddev,
 		DSAF_XGE_APP_RX_LINK_UP_0_REG + port * 0x4);
-	p[496] = dsaf_read_dev(ddev, DSAF_NETPORT_CTRL_SIG_0_REG + port * 0x4);
-	p[497] = dsaf_read_dev(ddev, DSAF_XGE_CTRL_SIG_CFG_0_REG + port * 0x4);
+	p[500] = dsaf_read_dev(ddev, DSAF_NETPORT_CTRL_SIG_0_REG + port * 0x4);
+	p[501] = dsaf_read_dev(ddev, DSAF_XGE_CTRL_SIG_CFG_0_REG + port * 0x4);
 
 	if (!is_ver1)
-		p[498] = dsaf_read_dev(ddev, DSAF_PAUSE_CFG_REG + port * 0x4);
+		p[502] = dsaf_read_dev(ddev, DSAF_PAUSE_CFG_REG + port * 0x4);
 
 	/* mark end of dsaf regs */
-	for (i = 499; i < 504; i++)
+	for (i = 503; i < 504; i++)
 		p[i] = 0xdddddddd;
 }
 
@@ -2666,58 +2743,156 @@ int hns_dsaf_get_regs_count(void)
 	return DSAF_DUMP_REGS_NUM;
 }
 
+static void set_promisc_tcam_enable(struct dsaf_device *dsaf_dev, u32 port)
+{
+	struct dsaf_tbl_tcam_ucast_cfg tbl_tcam_ucast = {0, 1, 0, 0, 0x80};
+	struct dsaf_tbl_tcam_data tbl_tcam_data_mc = {0x01000000, port};
+	struct dsaf_tbl_tcam_data tbl_tcam_mask_uc = {0x01000000, 0xf};
+	struct dsaf_tbl_tcam_mcast_cfg tbl_tcam_mcast = {0, 0, {0} };
+	struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
+	struct dsaf_tbl_tcam_data tbl_tcam_data_uc = {0, port};
+	struct dsaf_drv_mac_single_dest_entry mask_entry;
+	struct dsaf_drv_tbl_tcam_key temp_key, mask_key;
+	struct dsaf_drv_soft_mac_tbl *soft_mac_entry;
+	u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+	struct dsaf_drv_tbl_tcam_key mac_key;
+	struct hns_mac_cb *mac_cb;
+	u8 addr[ETH_ALEN] = {0};
+	u8 port_num;
+	u16 mskid;
+
+	/* promisc use vague table match with vlanid = 0 & macaddr = 0 */
+	hns_dsaf_set_mac_key(dsaf_dev, &mac_key, 0x00, port, addr);
+	entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+	if (entry_index != DSAF_INVALID_ENTRY_IDX)
+		return;
+
+	/* put promisc tcam entry in the end. */
+	/* 1. set promisc unicast vague tcam entry. */
+	entry_index = hns_dsaf_find_empty_mac_entry_reverse(dsaf_dev);
+	if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+		dev_err(dsaf_dev->dev,
+			"enable uc promisc failed (port:%#x)\n",
+			port);
+		return;
+	}
+
+	mac_cb = dsaf_dev->mac_cb[port];
+	(void)hns_mac_get_inner_port_num(mac_cb, 0, &port_num);
+	tbl_tcam_ucast.tbl_ucast_out_port = port_num;
+
+	/* config uc vague table */
+	hns_dsaf_tcam_uc_cfg_vague(dsaf_dev, entry_index, &tbl_tcam_data_uc,
+				   &tbl_tcam_mask_uc, &tbl_tcam_ucast);
+
+	/* update software entry */
+	soft_mac_entry = priv->soft_mac_tbl;
+	soft_mac_entry += entry_index;
+	soft_mac_entry->index = entry_index;
+	soft_mac_entry->tcam_key.high.val = mac_key.high.val;
+	soft_mac_entry->tcam_key.low.val = mac_key.low.val;
+	/* step back to the START for mc. */
+	soft_mac_entry = priv->soft_mac_tbl;
+
+	/* 2. set promisc multicast vague tcam entry. */
+	entry_index = hns_dsaf_find_empty_mac_entry_reverse(dsaf_dev);
+	if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+		dev_err(dsaf_dev->dev,
+			"enable mc promisc failed (port:%#x)\n",
+			port);
+		return;
+	}
+
+	memset(&mask_entry, 0x0, sizeof(mask_entry));
+	memset(&mask_key, 0x0, sizeof(mask_key));
+	memset(&temp_key, 0x0, sizeof(temp_key));
+	mask_entry.addr[0] = 0x01;
+	hns_dsaf_set_mac_key(dsaf_dev, &mask_key, mask_entry.in_vlan_id,
+			     port, mask_entry.addr);
+	tbl_tcam_mcast.tbl_mcast_item_vld = 1;
+	tbl_tcam_mcast.tbl_mcast_old_en = 0;
+
+	if (port < DSAF_SERVICE_NW_NUM) {
+		mskid = port;
+	} else if (port >= DSAF_BASE_INNER_PORT_NUM) {
+		mskid = port - DSAF_BASE_INNER_PORT_NUM + DSAF_SERVICE_NW_NUM;
+	} else {
+		dev_err(dsaf_dev->dev, "%s,pnum(%d)error,key(%#x:%#x)\n",
+			dsaf_dev->ae_dev.name, port,
+			mask_key.high.val, mask_key.low.val);
+		return;
+	}
+
+	dsaf_set_bit(tbl_tcam_mcast.tbl_mcast_port_msk[mskid / 32],
+		     mskid % 32, 1);
+	memcpy(&temp_key, &mask_key, sizeof(mask_key));
+	hns_dsaf_tcam_mc_cfg_vague(dsaf_dev, entry_index, &tbl_tcam_data_mc,
+				   (struct dsaf_tbl_tcam_data *)(&mask_key),
+				   &tbl_tcam_mcast);
+
+	/* update software entry */
+	soft_mac_entry += entry_index;
+	soft_mac_entry->index = entry_index;
+	soft_mac_entry->tcam_key.high.val = temp_key.high.val;
+	soft_mac_entry->tcam_key.low.val = temp_key.low.val;
+}
+
+static void set_promisc_tcam_disable(struct dsaf_device *dsaf_dev, u32 port)
+{
+	struct dsaf_tbl_tcam_data tbl_tcam_data_mc = {0x01000000, port};
+	struct dsaf_tbl_tcam_ucast_cfg tbl_tcam_ucast = {0, 0, 0, 0, 0};
+	struct dsaf_tbl_tcam_mcast_cfg tbl_tcam_mcast = {0, 0, {0} };
+	struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
+	struct dsaf_tbl_tcam_data tbl_tcam_data_uc = {0, 0};
+	struct dsaf_tbl_tcam_data tbl_tcam_mask = {0, 0};
+	struct dsaf_drv_soft_mac_tbl *soft_mac_entry;
+	u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+	struct dsaf_drv_tbl_tcam_key mac_key;
+	u8 addr[ETH_ALEN] = {0};
+
+	/* 1. delete uc vague tcam entry. */
+	/* promisc use vague table match with vlanid = 0 & macaddr = 0 */
+	hns_dsaf_set_mac_key(dsaf_dev, &mac_key, 0x00, port, addr);
+	entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+
+	if (entry_index == DSAF_INVALID_ENTRY_IDX)
+		return;
+
+	/* config uc vague table */
+	hns_dsaf_tcam_uc_cfg_vague(dsaf_dev, entry_index, &tbl_tcam_data_uc,
+				   &tbl_tcam_mask, &tbl_tcam_ucast);
+	/* update soft management table. */
+	soft_mac_entry = priv->soft_mac_tbl;
+	soft_mac_entry += entry_index;
+	soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX;
+	/* step back to the START for mc. */
+	soft_mac_entry = priv->soft_mac_tbl;
+
+	/* 2. delete mc vague tcam entry. */
+	addr[0] = 0x01;
+	memset(&mac_key, 0x0, sizeof(mac_key));
+	hns_dsaf_set_mac_key(dsaf_dev, &mac_key, 0x00, port, addr);
+	entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+
+	if (entry_index == DSAF_INVALID_ENTRY_IDX)
+		return;
+
+	/* config mc vague table */
+	hns_dsaf_tcam_mc_cfg_vague(dsaf_dev, entry_index, &tbl_tcam_data_mc,
+				   &tbl_tcam_mask, &tbl_tcam_mcast);
+	/* update soft management table. */
+	soft_mac_entry += entry_index;
+	soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX;
+}
+
 /* Reserve the last TCAM entry for promisc support */
-#define dsaf_promisc_tcam_entry(port) \
-	(DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM + (port))
 void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev,
 			       u32 port, bool enable)
 {
-	struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
-	struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
-	u16 entry_index;
-	struct dsaf_drv_tbl_tcam_key tbl_tcam_data, tbl_tcam_mask;
-	struct dsaf_tbl_tcam_mcast_cfg mac_data = {0};
-
-	if ((AE_IS_VER1(dsaf_dev->dsaf_ver)) || HNS_DSAF_IS_DEBUG(dsaf_dev))
-		return;
-
-	/* find the tcam entry index for promisc */
-	entry_index = dsaf_promisc_tcam_entry(port);
-
-	memset(&tbl_tcam_data, 0, sizeof(tbl_tcam_data));
-	memset(&tbl_tcam_mask, 0, sizeof(tbl_tcam_mask));
-
-	/* config key mask */
-	if (enable) {
-		dsaf_set_field(tbl_tcam_data.low.bits.port_vlan,
-			       DSAF_TBL_TCAM_KEY_PORT_M,
-			       DSAF_TBL_TCAM_KEY_PORT_S, port);
-		dsaf_set_field(tbl_tcam_mask.low.bits.port_vlan,
-			       DSAF_TBL_TCAM_KEY_PORT_M,
-			       DSAF_TBL_TCAM_KEY_PORT_S, 0xf);
-
-		/* SUB_QID */
-		dsaf_set_bit(mac_data.tbl_mcast_port_msk[0],
-			     DSAF_SERVICE_NW_NUM, true);
-		mac_data.tbl_mcast_item_vld = true;	/* item_vld bit */
-	} else {
-		mac_data.tbl_mcast_item_vld = false;	/* item_vld bit */
-	}
-
-	dev_dbg(dsaf_dev->dev,
-		"set_promisc_entry, %s Mac key(%#x:%#x) entry_index%d\n",
-		dsaf_dev->ae_dev.name, tbl_tcam_data.high.val,
-		tbl_tcam_data.low.val, entry_index);
-
-	/* config promisc entry with mask */
-	hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index,
-			     (struct dsaf_tbl_tcam_data *)&tbl_tcam_data,
-			     (struct dsaf_tbl_tcam_data *)&tbl_tcam_mask,
-			     &mac_data);
-
-	/* config software entry */
-	soft_mac_entry += entry_index;
-	soft_mac_entry->index = enable ? entry_index : DSAF_INVALID_ENTRY_IDX;
+	if (enable)
+		set_promisc_tcam_enable(dsaf_dev, port);
+	else
+		set_promisc_tcam_disable(dsaf_dev, port);
 }
 
 int hns_dsaf_wait_pkt_clean(struct dsaf_device *dsaf_dev, int port)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
index 6d20e4e..ae97b20 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
@@ -176,7 +176,7 @@
 #define DSAF_INODE_IN_DATA_STP_DISC_0_REG	0x1A50
 #define DSAF_INODE_GE_FC_EN_0_REG		0x1B00
 #define DSAF_INODE_VC0_IN_PKT_NUM_0_REG		0x1B50
-#define DSAF_INODE_VC1_IN_PKT_NUM_0_REG		0x1C00
+#define DSAF_INODE_VC1_IN_PKT_NUM_0_REG		0x103C
 #define DSAF_INODE_IN_PRIO_PAUSE_BASE_REG	0x1C00
 #define DSAF_INODE_IN_PRIO_PAUSE_BASE_OFFSET	0x100
 #define DSAF_INODE_IN_PRIO_PAUSE_OFFSET		0x50
@@ -404,11 +404,11 @@
 #define RCB_ECC_ERR_ADDR4_REG			0x460
 #define RCB_ECC_ERR_ADDR5_REG			0x464
 
-#define RCB_COM_SF_CFG_INTMASK_RING		0x480
-#define RCB_COM_SF_CFG_RING_STS			0x484
-#define RCB_COM_SF_CFG_RING			0x488
-#define RCB_COM_SF_CFG_INTMASK_BD		0x48C
-#define RCB_COM_SF_CFG_BD_RINT_STS		0x470
+#define RCB_COM_SF_CFG_INTMASK_RING		0x470
+#define RCB_COM_SF_CFG_RING_STS			0x474
+#define RCB_COM_SF_CFG_RING			0x478
+#define RCB_COM_SF_CFG_INTMASK_BD		0x47C
+#define RCB_COM_SF_CFG_BD_RINT_STS		0x480
 #define RCB_COM_RCB_RD_BD_BUSY			0x490
 #define RCB_COM_RCB_FBD_CRT_EN			0x494
 #define RCB_COM_AXI_WR_ERR_INTMASK		0x498
@@ -534,6 +534,7 @@
 #define GMAC_LD_LINK_COUNTER_REG		0x01D0UL
 #define GMAC_LOOP_REG				0x01DCUL
 #define GMAC_RECV_CONTROL_REG			0x01E0UL
+#define GMAC_PCS_RX_EN_REG			0x01E4UL
 #define GMAC_VLAN_CODE_REG			0x01E8UL
 #define GMAC_RX_OVERRUN_CNT_REG			0x01ECUL
 #define GMAC_RX_LENGTHFIELD_ERR_CNT_REG		0x01F4UL
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 4faadc3..86662a1 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1286,6 +1286,9 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
 	if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
 		phy_dev->autoneg = false;
 
+	if (h->phy_if == PHY_INTERFACE_MODE_SGMII)
+		phy_stop(phy_dev);
+
 	return 0;
 }
 
@@ -1381,6 +1384,22 @@ static int hns_nic_init_affinity_mask(int q_num, int ring_idx,
 	return cpu;
 }
 
+static void hns_nic_free_irq(int q_num, struct hns_nic_priv *priv)
+{
+	int i;
+
+	for (i = 0; i < q_num * 2; i++) {
+		if (priv->ring_data[i].ring->irq_init_flag == RCB_IRQ_INITED) {
+			irq_set_affinity_hint(priv->ring_data[i].ring->irq,
+					      NULL);
+			free_irq(priv->ring_data[i].ring->irq,
+				 &priv->ring_data[i]);
+			priv->ring_data[i].ring->irq_init_flag =
+				RCB_IRQ_NOT_INITED;
+		}
+	}
+}
+
 static int hns_nic_init_irq(struct hns_nic_priv *priv)
 {
 	struct hnae_handle *h = priv->ae_handle;
@@ -1406,7 +1425,7 @@ static int hns_nic_init_irq(struct hns_nic_priv *priv)
 		if (ret) {
 			netdev_err(priv->netdev, "request irq(%d) fail\n",
 				   rd->ring->irq);
-			return ret;
+			goto out_free_irq;
 		}
 		disable_irq(rd->ring->irq);
 
@@ -1421,6 +1440,10 @@ static int hns_nic_init_irq(struct hns_nic_priv *priv)
 	}
 
 	return 0;
+
+out_free_irq:
+	hns_nic_free_irq(h->q_num, priv);
+	return ret;
 }
 
 static int hns_nic_net_up(struct net_device *ndev)
@@ -1430,6 +1453,9 @@ static int hns_nic_net_up(struct net_device *ndev)
 	int i, j;
 	int ret;
 
+	if (!test_bit(NIC_STATE_DOWN, &priv->state))
+		return 0;
+
 	ret = hns_nic_init_irq(priv);
 	if (ret != 0) {
 		netdev_err(ndev, "hns init irq failed! ret=%d\n", ret);
@@ -1465,6 +1491,7 @@ static int hns_nic_net_up(struct net_device *ndev)
 	for (j = i - 1; j >= 0; j--)
 		hns_nic_ring_close(ndev, j);
 
+	hns_nic_free_irq(h->q_num, priv);
 	set_bit(NIC_STATE_DOWN, &priv->state);
 
 	return ret;
@@ -1582,11 +1609,19 @@ static int hns_nic_net_stop(struct net_device *ndev)
 }
 
 static void hns_tx_timeout_reset(struct hns_nic_priv *priv);
+#define HNS_TX_TIMEO_LIMIT (40 * HZ)
 static void hns_nic_net_timeout(struct net_device *ndev)
 {
 	struct hns_nic_priv *priv = netdev_priv(ndev);
 
-	hns_tx_timeout_reset(priv);
+	if (ndev->watchdog_timeo < HNS_TX_TIMEO_LIMIT) {
+		ndev->watchdog_timeo *= 2;
+		netdev_info(ndev, "watchdog_timo changed to %d.\n",
+			    ndev->watchdog_timeo);
+	} else {
+		ndev->watchdog_timeo = HNS_NIC_TX_TIMEOUT;
+		hns_tx_timeout_reset(priv);
+	}
 }
 
 static int hns_nic_do_ioctl(struct net_device *netdev, struct ifreq *ifr,
@@ -2166,11 +2201,11 @@ static void hns_nic_service_task(struct work_struct *work)
 		= container_of(work, struct hns_nic_priv, service_task);
 	struct hnae_handle *h = priv->ae_handle;
 
+	hns_nic_reset_subtask(priv);
 	hns_nic_update_link_status(priv->netdev);
 	h->dev->ops->update_led_status(h);
 	hns_nic_update_stats(priv->netdev);
 
-	hns_nic_reset_subtask(priv);
 	hns_nic_service_event_complete(priv);
 }
 
@@ -2451,7 +2486,7 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
 	ndev->min_mtu = MAC_MIN_MTU;
 	switch (priv->enet_ver) {
 	case AE_VERSION_2:
-		ndev->features |= NETIF_F_TSO | NETIF_F_TSO6;
+		ndev->features |= NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_NTUPLE;
 		ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 			NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
 			NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6;
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 6c05819..754dff4 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1314,7 +1314,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
 	unsigned long lpar_rc;
 	u16 mss = 0;
 
-restart_poll:
 	while (frames_processed < budget) {
 		if (!ibmveth_rxq_pending_buffer(adapter))
 			break;
@@ -1402,7 +1401,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
 		    napi_reschedule(napi)) {
 			lpar_rc = h_vio_signal(adapter->vdev->unit_address,
 					       VIO_IRQ_DISABLE);
-			goto restart_poll;
 		}
 	}
 
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 14c53ed..c914b33 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -1596,7 +1596,7 @@ static void ibmvnic_reset(struct ibmvnic_adapter *adapter,
 		}
 	}
 
-	rwi = kzalloc(sizeof(*rwi), GFP_KERNEL);
+	rwi = kzalloc(sizeof(*rwi), GFP_ATOMIC);
 	if (!rwi) {
 		mutex_unlock(&adapter->rwi_lock);
 		ibmvnic_close(netdev);
diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c
index b366885..cd16b70 100644
--- a/drivers/net/ethernet/intel/e1000e/ptp.c
+++ b/drivers/net/ethernet/intel/e1000e/ptp.c
@@ -191,10 +191,14 @@ static int e1000e_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
 	struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter,
 						     ptp_clock_info);
 	unsigned long flags;
-	u64 ns;
+	u64 cycles, ns;
 
 	spin_lock_irqsave(&adapter->systim_lock, flags);
-	ns = timecounter_read(&adapter->tc);
+
+	/* Use timecounter_cyc2time() to allow non-monotonic SYSTIM readings */
+	cycles = adapter->cc.read(&adapter->cc);
+	ns = timecounter_cyc2time(&adapter->tc, cycles);
+
 	spin_unlock_irqrestore(&adapter->systim_lock, flags);
 
 	*ts = ns_to_timespec64(ns);
@@ -250,9 +254,12 @@ static void e1000e_systim_overflow_work(struct work_struct *work)
 						     systim_overflow_work.work);
 	struct e1000_hw *hw = &adapter->hw;
 	struct timespec64 ts;
+	u64 ns;
 
-	adapter->ptp_clock_info.gettime64(&adapter->ptp_clock_info, &ts);
+	/* Update the timecounter */
+	ns = timecounter_read(&adapter->tc);
 
+	ts = ns_to_timespec64(ns);
 	e_dbg("SYSTIM overflow check at %lld.%09lu\n",
 	      (long long) ts.tv_sec, ts.tv_nsec);
 
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 176c99b..5d47a51 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -1554,17 +1554,17 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
 		netdev_info(netdev, "set new mac address %pM\n", addr->sa_data);
 
 	/* Copy the address first, so that we avoid a possible race with
-	 * .set_rx_mode(). If we copy after changing the address in the filter
-	 * list, we might open ourselves to a narrow race window where
-	 * .set_rx_mode could delete our dev_addr filter and prevent traffic
-	 * from passing.
+	 * .set_rx_mode().
+	 * - Remove old address from MAC filter
+	 * - Copy new address
+	 * - Add new address to MAC filter
 	 */
-	ether_addr_copy(netdev->dev_addr, addr->sa_data);
-
 	spin_lock_bh(&vsi->mac_filter_hash_lock);
 	i40e_del_mac_filter(vsi, netdev->dev_addr);
-	i40e_add_mac_filter(vsi, addr->sa_data);
+	ether_addr_copy(netdev->dev_addr, addr->sa_data);
+	i40e_add_mac_filter(vsi, netdev->dev_addr);
 	spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
 	if (vsi->type == I40E_VSI_MAIN) {
 		i40e_status ret;
 
@@ -9772,6 +9772,9 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	ether_addr_copy(netdev->dev_addr, mac_addr);
 	ether_addr_copy(netdev->perm_addr, mac_addr);
 
+	/* i40iw_net_event() reads 16 bytes from neigh->primary_key */
+	netdev->neigh_priv_len = sizeof(u32) * 4;
+
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
 	/* Setup netdev TC information */
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 1c027f9..8892ea5 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -7950,9 +7950,11 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake,
 	rtnl_unlock();
 
 #ifdef CONFIG_PM
-	retval = pci_save_state(pdev);
-	if (retval)
-		return retval;
+	if (!runtime) {
+		retval = pci_save_state(pdev);
+		if (retval)
+			return retval;
+	}
 #endif
 
 	status = rd32(E1000_STATUS);
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index eef35bf..5d00be3 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -152,8 +152,10 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 	memset(p, 0, regs->len);
 	memcpy_fromio(p, io, B3_RAM_ADDR);
 
-	memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
-		      regs->len - B3_RI_WTO_R1);
+	if (regs->len > B3_RI_WTO_R1) {
+		memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
+			      regs->len - B3_RI_WTO_R1);
+	}
 }
 
 /* Wake on Lan only supported on Yukon chips with rev 1 or above */
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index b12e3a4..3954bc1 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -5087,7 +5087,7 @@ static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	INIT_WORK(&hw->restart_work, sky2_restart);
 
 	pci_set_drvdata(pdev, hw);
-	pdev->d3_delay = 200;
+	pdev->d3_delay = 300;
 
 	return 0;
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index ab2a9db..8fcf9dd 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -623,13 +623,27 @@ static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb,
 	return 0;
 }
 #endif
+
+#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN)
+
 static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va,
 		      netdev_features_t dev_features)
 {
 	__wsum hw_checksum = 0;
+	void *hdr;
 
-	void *hdr = (u8 *)va + sizeof(struct ethhdr);
+	/* CQE csum doesn't cover padding octets in short ethernet
+	 * frames. And the pad field is appended prior to calculating
+	 * and appending the FCS field.
+	 *
+	 * Detecting these padded frames requires to verify and parse
+	 * IP headers, so we simply force all those small frames to skip
+	 * checksum complete.
+	 */
+	if (short_frame(skb->len))
+		return -EINVAL;
 
+	hdr = (u8 *)va + sizeof(struct ethhdr);
 	hw_checksum = csum_unfold((__force __sum16)cqe->checksum);
 
 	if (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK) &&
@@ -817,6 +831,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 		skb_record_rx_queue(skb, cq_ring);
 
 		if (likely(dev->features & NETIF_F_RXCSUM)) {
+			/* TODO: For IP non TCP/UDP packets when csum complete is
+			 * not an option (not supported or any other reason) we can
+			 * actually check cqe IPOK status bit and report
+			 * CHECKSUM_UNNECESSARY rather than CHECKSUM_NONE
+			 */
 			if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP |
 						      MLX4_CQE_STATUS_UDP)) {
 				if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 16c0994..7440c76 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -2048,9 +2048,11 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 {
 	struct mlx4_cmd_mailbox *mailbox;
 	__be32 *outbox;
+	u64 qword_field;
 	u32 dword_field;
-	int err;
+	u16 word_field;
 	u8 byte_field;
+	int err;
 	static const u8 a0_dmfs_query_hw_steering[] =  {
 		[0] = MLX4_STEERING_DMFS_A0_DEFAULT,
 		[1] = MLX4_STEERING_DMFS_A0_DYNAMIC,
@@ -2078,19 +2080,32 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 
 	/* QPC/EEC/CQC/EQC/RDMARC attributes */
 
-	MLX4_GET(param->qpc_base,      outbox, INIT_HCA_QPC_BASE_OFFSET);
-	MLX4_GET(param->log_num_qps,   outbox, INIT_HCA_LOG_QP_OFFSET);
-	MLX4_GET(param->srqc_base,     outbox, INIT_HCA_SRQC_BASE_OFFSET);
-	MLX4_GET(param->log_num_srqs,  outbox, INIT_HCA_LOG_SRQ_OFFSET);
-	MLX4_GET(param->cqc_base,      outbox, INIT_HCA_CQC_BASE_OFFSET);
-	MLX4_GET(param->log_num_cqs,   outbox, INIT_HCA_LOG_CQ_OFFSET);
-	MLX4_GET(param->altc_base,     outbox, INIT_HCA_ALTC_BASE_OFFSET);
-	MLX4_GET(param->auxc_base,     outbox, INIT_HCA_AUXC_BASE_OFFSET);
-	MLX4_GET(param->eqc_base,      outbox, INIT_HCA_EQC_BASE_OFFSET);
-	MLX4_GET(param->log_num_eqs,   outbox, INIT_HCA_LOG_EQ_OFFSET);
-	MLX4_GET(param->num_sys_eqs,   outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
-	MLX4_GET(param->rdmarc_base,   outbox, INIT_HCA_RDMARC_BASE_OFFSET);
-	MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
+	MLX4_GET(qword_field, outbox, INIT_HCA_QPC_BASE_OFFSET);
+	param->qpc_base = qword_field & ~((u64)0x1f);
+	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_QP_OFFSET);
+	param->log_num_qps = byte_field & 0x1f;
+	MLX4_GET(qword_field, outbox, INIT_HCA_SRQC_BASE_OFFSET);
+	param->srqc_base = qword_field & ~((u64)0x1f);
+	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_SRQ_OFFSET);
+	param->log_num_srqs = byte_field & 0x1f;
+	MLX4_GET(qword_field, outbox, INIT_HCA_CQC_BASE_OFFSET);
+	param->cqc_base = qword_field & ~((u64)0x1f);
+	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_CQ_OFFSET);
+	param->log_num_cqs = byte_field & 0x1f;
+	MLX4_GET(qword_field, outbox, INIT_HCA_ALTC_BASE_OFFSET);
+	param->altc_base = qword_field;
+	MLX4_GET(qword_field, outbox, INIT_HCA_AUXC_BASE_OFFSET);
+	param->auxc_base = qword_field;
+	MLX4_GET(qword_field, outbox, INIT_HCA_EQC_BASE_OFFSET);
+	param->eqc_base = qword_field & ~((u64)0x1f);
+	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_EQ_OFFSET);
+	param->log_num_eqs = byte_field & 0x1f;
+	MLX4_GET(word_field, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
+	param->num_sys_eqs = word_field & 0xfff;
+	MLX4_GET(qword_field, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
+	param->rdmarc_base = qword_field & ~((u64)0x1f);
+	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_RD_OFFSET);
+	param->log_rd_per_qp = byte_field & 0x7;
 
 	MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
 	if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
@@ -2109,22 +2124,21 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 	/* steering attributes */
 	if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
 		MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
-		MLX4_GET(param->log_mc_entry_sz, outbox,
-			 INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
-		MLX4_GET(param->log_mc_table_sz, outbox,
-			 INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
-		MLX4_GET(byte_field, outbox,
-			 INIT_HCA_FS_A0_OFFSET);
+		MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
+		param->log_mc_entry_sz = byte_field & 0x1f;
+		MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
+		param->log_mc_table_sz = byte_field & 0x1f;
+		MLX4_GET(byte_field, outbox, INIT_HCA_FS_A0_OFFSET);
 		param->dmfs_high_steer_mode =
 			a0_dmfs_query_hw_steering[(byte_field >> 6) & 3];
 	} else {
 		MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
-		MLX4_GET(param->log_mc_entry_sz, outbox,
-			 INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
-		MLX4_GET(param->log_mc_hash_sz,  outbox,
-			 INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
-		MLX4_GET(param->log_mc_table_sz, outbox,
-			 INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
+		MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
+		param->log_mc_entry_sz = byte_field & 0x1f;
+		MLX4_GET(byte_field,  outbox, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
+		param->log_mc_hash_sz = byte_field & 0x1f;
+		MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
+		param->log_mc_table_sz = byte_field & 0x1f;
 	}
 
 	/* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
@@ -2148,15 +2162,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 	/* TPT attributes */
 
 	MLX4_GET(param->dmpt_base,  outbox, INIT_HCA_DMPT_BASE_OFFSET);
-	MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET);
-	MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
+	MLX4_GET(byte_field, outbox, INIT_HCA_TPT_MW_OFFSET);
+	param->mw_enabled = byte_field >> 7;
+	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
+	param->log_mpt_sz = byte_field & 0x3f;
 	MLX4_GET(param->mtt_base,   outbox, INIT_HCA_MTT_BASE_OFFSET);
 	MLX4_GET(param->cmpt_base,  outbox, INIT_HCA_CMPT_BASE_OFFSET);
 
 	/* UAR attributes */
 
 	MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET);
-	MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
+	MLX4_GET(byte_field, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
+	param->log_uar_sz = byte_field & 0xf;
 
 	/* phv_check enable */
 	MLX4_GET(byte_field, outbox, INIT_HCA_CACHELINE_SZ_OFFSET);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index bf34264..14bab8a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -1605,7 +1605,7 @@ static void mlx5e_close_cq(struct mlx5e_cq *cq)
 
 static int mlx5e_get_cpu(struct mlx5e_priv *priv, int ix)
 {
-	return cpumask_first(priv->mdev->priv.irq_info[ix].mask);
+	return cpumask_first(priv->mdev->priv.irq_info[ix + MLX5_EQ_VEC_COMP_BASE].mask);
 }
 
 static int mlx5e_open_tx_cqs(struct mlx5e_channel *c,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 2819116..e69674d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -125,6 +125,7 @@ static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv)
 
 			s->tx_packets		+= sq_stats->packets;
 			s->tx_bytes		+= sq_stats->bytes;
+			s->tx_queue_dropped	+= sq_stats->dropped;
 		}
 	}
 }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 8b7b52c..eec7c2e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -646,6 +646,8 @@ static u32 mlx5e_get_fcs(const struct sk_buff *skb)
 	return __get_unaligned_cpu32(fcs_bytes);
 }
 
+#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN)
+
 static inline void mlx5e_handle_csum(struct net_device *netdev,
 				     struct mlx5_cqe64 *cqe,
 				     struct mlx5e_rq *rq,
@@ -661,6 +663,17 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
 		return;
 	}
 
+	/* CQE csum doesn't cover padding octets in short ethernet
+	 * frames. And the pad field is appended prior to calculating
+	 * and appending the FCS field.
+	 *
+	 * Detecting these padded frames requires to verify and parse
+	 * IP headers, so we simply force all those small frames to be
+	 * CHECKSUM_UNNECESSARY even if they are not padded.
+	 */
+	if (short_frame(skb->len))
+		goto csum_unnecessary;
+
 	if (is_first_ethertype_ip(skb)) {
 		skb->ip_summed = CHECKSUM_COMPLETE;
 		skb->csum = csum_unfold((__force __sum16)cqe->check_sum);
@@ -672,6 +685,7 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
 		return;
 	}
 
+csum_unnecessary:
 	if (likely((cqe->hds_ip_ext & CQE_L3_OK) &&
 		   (cqe->hds_ip_ext & CQE_L4_OK))) {
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 9e0be07..47003ea 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -81,6 +81,7 @@ struct mlx5e_tc_flow_parse_attr {
 	struct ip_tunnel_info tun_info;
 	struct mlx5_flow_spec spec;
 	int num_mod_hdr_actions;
+	int max_mod_hdr_actions;
 	void *mod_hdr_actions;
 	int mirred_ifindex;
 };
@@ -1128,9 +1129,9 @@ static struct mlx5_fields fields[] = {
 	OFFLOAD(UDP_DPORT, 2, udp.dest,   0),
 };
 
-/* On input attr->num_mod_hdr_actions tells how many HW actions can be parsed at
- * max from the SW pedit action. On success, it says how many HW actions were
- * actually parsed.
+/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
+ * max from the SW pedit action. On success, attr->num_mod_hdr_actions
+ * says how many HW actions were actually parsed.
  */
 static int offload_pedit_fields(struct pedit_headers *masks,
 				struct pedit_headers *vals,
@@ -1153,9 +1154,11 @@ static int offload_pedit_fields(struct pedit_headers *masks,
 	add_vals = &vals[TCA_PEDIT_KEY_EX_CMD_ADD];
 
 	action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
-	action = parse_attr->mod_hdr_actions;
-	max_actions = parse_attr->num_mod_hdr_actions;
-	nactions = 0;
+	action = parse_attr->mod_hdr_actions +
+		 parse_attr->num_mod_hdr_actions * action_size;
+
+	max_actions = parse_attr->max_mod_hdr_actions;
+	nactions = parse_attr->num_mod_hdr_actions;
 
 	for (i = 0; i < ARRAY_SIZE(fields); i++) {
 		f = &fields[i];
@@ -1260,7 +1263,7 @@ static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
 	if (!parse_attr->mod_hdr_actions)
 		return -ENOMEM;
 
-	parse_attr->num_mod_hdr_actions = max_actions;
+	parse_attr->max_mod_hdr_actions = max_actions;
 	return 0;
 }
 
@@ -1304,9 +1307,11 @@ static int parse_tc_pedit_action(struct mlx5e_priv *priv,
 			goto out_err;
 	}
 
-	err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
-	if (err)
-		goto out_err;
+	if (!parse_attr->mod_hdr_actions) {
+		err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
+		if (err)
+			goto out_err;
+	}
 
 	err = offload_pedit_fields(masks, vals, parse_attr);
 	if (err < 0)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index 1af9894..2f93e6e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -1126,13 +1126,6 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
 	int err = 0;
 	u8 *smac_v;
 
-	if (vport->info.spoofchk && !is_valid_ether_addr(vport->info.mac)) {
-		mlx5_core_warn(esw->dev,
-			       "vport[%d] configure ingress rules failed, illegal mac with spoofchk\n",
-			       vport->vport);
-		return -EPERM;
-	}
-
 	esw_vport_cleanup_ingress_rules(esw, vport);
 
 	if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
@@ -1614,7 +1607,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
 	int vport_num;
 	int err;
 
-	if (!MLX5_ESWITCH_MANAGER(dev))
+	if (!MLX5_VPORT_MANAGER(dev))
 		return 0;
 
 	esw_info(dev,
@@ -1687,7 +1680,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
 
 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
 {
-	if (!esw || !MLX5_ESWITCH_MANAGER(esw->dev))
+	if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
 		return;
 
 	esw_info(esw->dev, "cleanup\n");
@@ -1734,13 +1727,10 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
 	mutex_lock(&esw->state_lock);
 	evport = &esw->vports[vport];
 
-	if (evport->info.spoofchk && !is_valid_ether_addr(mac)) {
+	if (evport->info.spoofchk && !is_valid_ether_addr(mac))
 		mlx5_core_warn(esw->dev,
-			       "MAC invalidation is not allowed when spoofchk is on, vport(%d)\n",
+			       "Set invalid MAC while spoofchk is on, vport(%d)\n",
 			       vport);
-		err = -EPERM;
-		goto unlock;
-	}
 
 	err = mlx5_modify_nic_vport_mac_address(esw->dev, vport, mac);
 	if (err) {
@@ -1886,6 +1876,10 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
 	evport = &esw->vports[vport];
 	pschk = evport->info.spoofchk;
 	evport->info.spoofchk = spoofchk;
+	if (pschk && !is_valid_ether_addr(evport->info.mac))
+		mlx5_core_warn(esw->dev,
+			       "Spoofchk in set while MAC is invalid, vport(%d)\n",
+			       evport->vport);
 	if (evport->enabled && esw->mode == SRIOV_LEGACY)
 		err = esw_vport_ingress_config(esw, evport);
 	if (err)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index e99f138..558fc6a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -619,18 +619,19 @@ u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev)
 static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
 {
 	struct mlx5_priv *priv  = &mdev->priv;
-	int irq = pci_irq_vector(mdev->pdev, MLX5_EQ_VEC_COMP_BASE + i);
+	int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
+	int irq = pci_irq_vector(mdev->pdev, vecidx);
 
-	if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) {
+	if (!zalloc_cpumask_var(&priv->irq_info[vecidx].mask, GFP_KERNEL)) {
 		mlx5_core_warn(mdev, "zalloc_cpumask_var failed");
 		return -ENOMEM;
 	}
 
 	cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),
-			priv->irq_info[i].mask);
+			priv->irq_info[vecidx].mask);
 
 	if (IS_ENABLED(CONFIG_SMP) &&
-	    irq_set_affinity_hint(irq, priv->irq_info[i].mask))
+	    irq_set_affinity_hint(irq, priv->irq_info[vecidx].mask))
 		mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq);
 
 	return 0;
@@ -638,11 +639,12 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
 
 static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i)
 {
+	int vecidx = MLX5_EQ_VEC_COMP_BASE + i;
 	struct mlx5_priv *priv  = &mdev->priv;
-	int irq = pci_irq_vector(mdev->pdev, MLX5_EQ_VEC_COMP_BASE + i);
+	int irq = pci_irq_vector(mdev->pdev, vecidx);
 
 	irq_set_affinity_hint(irq, NULL);
-	free_cpumask_var(priv->irq_info[i].mask);
+	free_cpumask_var(priv->irq_info[vecidx].mask);
 }
 
 static int mlx5_irq_set_affinity_hints(struct mlx5_core_dev *mdev)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 84864fd..8ff9264 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1161,8 +1161,9 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 		bool configure = false;
 		bool pfc = false;
+		u16 thres_cells;
+		u16 delay_cells;
 		bool lossy;
-		u16 thres;
 
 		for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) {
 			if (prio_tc[j] == i) {
@@ -1176,10 +1177,11 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
 			continue;
 
 		lossy = !(pfc || pause_en);
-		thres = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu);
-		delay = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay, pfc,
-						  pause_en);
-		mlxsw_sp_pg_buf_pack(pbmc_pl, i, thres + delay, thres, lossy);
+		thres_cells = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu);
+		delay_cells = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay,
+							pfc, pause_en);
+		mlxsw_sp_pg_buf_pack(pbmc_pl, i, thres_cells + delay_cells,
+				     thres_cells, lossy);
 	}
 
 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl);
@@ -3907,6 +3909,25 @@ void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port)
 	dev_put(mlxsw_sp_port->dev);
 }
 
+static void
+mlxsw_sp_port_lag_uppers_cleanup(struct mlxsw_sp_port *mlxsw_sp_port,
+				 struct net_device *lag_dev)
+{
+	struct net_device *br_dev = netdev_master_upper_dev_get(lag_dev);
+	struct net_device *upper_dev;
+	struct list_head *iter;
+
+	if (netif_is_bridge_port(lag_dev))
+		mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lag_dev, br_dev);
+
+	netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
+		if (!netif_is_bridge_port(upper_dev))
+			continue;
+		br_dev = netdev_master_upper_dev_get(upper_dev);
+		mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev, br_dev);
+	}
+}
+
 static int mlxsw_sp_lag_create(struct mlxsw_sp *mlxsw_sp, u16 lag_id)
 {
 	char sldr_pl[MLXSW_REG_SLDR_LEN];
@@ -4094,6 +4115,10 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	/* Any VLANs configured on the port are no longer valid */
 	mlxsw_sp_port_vlan_flush(mlxsw_sp_port);
+	/* Make the LAG and its directly linked uppers leave bridges they
+	 * are memeber in
+	 */
+	mlxsw_sp_port_lag_uppers_cleanup(mlxsw_sp_port, lag_dev);
 
 	if (lag->ref_count == 1)
 		mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
@@ -4276,12 +4301,15 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
 							   lower_dev,
 							   upper_dev);
 		} else if (netif_is_lag_master(upper_dev)) {
-			if (info->linking)
+			if (info->linking) {
 				err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
 							     upper_dev);
-			else
+			} else {
+				mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port,
+							    false);
 				mlxsw_sp_port_lag_leave(mlxsw_sp_port,
 							upper_dev);
+			}
 		} else if (netif_is_ovs_master(upper_dev)) {
 			if (info->linking)
 				err = mlxsw_sp_port_ovs_join(mlxsw_sp_port);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 2161161..3ba9f2c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -291,30 +291,6 @@ mlxsw_sp_bridge_port_destroy(struct mlxsw_sp_bridge_port *bridge_port)
 	kfree(bridge_port);
 }
 
-static bool
-mlxsw_sp_bridge_port_should_destroy(const struct mlxsw_sp_bridge_port *
-				    bridge_port)
-{
-	struct net_device *dev = bridge_port->dev;
-	struct mlxsw_sp *mlxsw_sp;
-
-	if (is_vlan_dev(dev))
-		mlxsw_sp = mlxsw_sp_lower_get(vlan_dev_real_dev(dev));
-	else
-		mlxsw_sp = mlxsw_sp_lower_get(dev);
-
-	/* In case ports were pulled from out of a bridged LAG, then
-	 * it's possible the reference count isn't zero, yet the bridge
-	 * port should be destroyed, as it's no longer an upper of ours.
-	 */
-	if (!mlxsw_sp && list_empty(&bridge_port->vlans_list))
-		return true;
-	else if (bridge_port->ref_count == 0)
-		return true;
-	else
-		return false;
-}
-
 static struct mlxsw_sp_bridge_port *
 mlxsw_sp_bridge_port_get(struct mlxsw_sp_bridge *bridge,
 			 struct net_device *brport_dev)
@@ -352,8 +328,7 @@ static void mlxsw_sp_bridge_port_put(struct mlxsw_sp_bridge *bridge,
 {
 	struct mlxsw_sp_bridge_device *bridge_device;
 
-	bridge_port->ref_count--;
-	if (!mlxsw_sp_bridge_port_should_destroy(bridge_port))
+	if (--bridge_port->ref_count != 0)
 		return;
 	bridge_device = bridge_port->bridge_device;
 	mlxsw_sp_bridge_port_destroy(bridge_port);
@@ -1111,7 +1086,7 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
 static enum mlxsw_reg_sfd_rec_policy mlxsw_sp_sfd_rec_policy(bool dynamic)
 {
 	return dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS :
-			 MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY;
+			 MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_MLAG;
 }
 
 static enum mlxsw_reg_sfd_op mlxsw_sp_sfd_op(bool adding)
@@ -1123,7 +1098,7 @@ static enum mlxsw_reg_sfd_op mlxsw_sp_sfd_op(bool adding)
 static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 				     const char *mac, u16 fid, bool adding,
 				     enum mlxsw_reg_sfd_rec_action action,
-				     bool dynamic)
+				     enum mlxsw_reg_sfd_rec_policy policy)
 {
 	char *sfd_pl;
 	u8 num_rec;
@@ -1134,8 +1109,7 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 		return -ENOMEM;
 
 	mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
-	mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
-			      mac, fid, action, local_port);
+	mlxsw_reg_sfd_uc_pack(sfd_pl, 0, policy, mac, fid, action, local_port);
 	num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
 	if (err)
@@ -1154,7 +1128,8 @@ static int mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
 				   bool dynamic)
 {
 	return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, adding,
-					 MLXSW_REG_SFD_REC_ACTION_NOP, dynamic);
+					 MLXSW_REG_SFD_REC_ACTION_NOP,
+					 mlxsw_sp_sfd_rec_policy(dynamic));
 }
 
 int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
@@ -1162,7 +1137,7 @@ int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
 {
 	return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, 0, mac, fid, adding,
 					 MLXSW_REG_SFD_REC_ACTION_FORWARD_IP_ROUTER,
-					 false);
+					 MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY);
 }
 
 static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
@@ -1424,7 +1399,7 @@ static void
 mlxsw_sp_bridge_port_vlan_del(struct mlxsw_sp_port *mlxsw_sp_port,
 			      struct mlxsw_sp_bridge_port *bridge_port, u16 vid)
 {
-	u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : vid;
+	u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : mlxsw_sp_port->pvid;
 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
 
 	mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c
index 6223930..6f57b0b 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-config.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c
@@ -808,7 +808,7 @@ __vxge_hw_vpath_fw_ver_get(struct __vxge_hw_virtualpath *vpath,
 	struct vxge_hw_device_date *fw_date = &hw_info->fw_date;
 	struct vxge_hw_device_version *flash_version = &hw_info->flash_version;
 	struct vxge_hw_device_date *flash_date = &hw_info->flash_date;
-	u64 data0, data1 = 0, steer_ctrl = 0;
+	u64 data0 = 0, data1 = 0, steer_ctrl = 0;
 	enum vxge_hw_status status;
 
 	status = vxge_hw_vpath_fw_api(vpath,
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
index 4a67c55..11a9add 100644
--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
+++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
@@ -912,7 +912,7 @@ static const struct net_device_ops w90p910_ether_netdev_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
-static void __init get_mac_address(struct net_device *dev)
+static void get_mac_address(struct net_device *dev)
 {
 	struct w90p910_ether *ether = netdev_priv(dev);
 	struct platform_device *pdev;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
index 3dd9734..4b44435 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
@@ -1125,7 +1125,8 @@ netxen_validate_firmware(struct netxen_adapter *adapter)
 		return -EINVAL;
 	}
 	val = nx_get_bios_version(adapter);
-	netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
+	if (netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios))
+		return -EIO;
 	if ((__force u32)val != bios) {
 		dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
 				fw_name[fw_type]);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index 5f52f14..cef619f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -1487,6 +1487,10 @@ static void qed_ll2_post_rx_buffer_notify_fw(struct qed_hwfn *p_hwfn,
 	cq_prod = qed_chain_get_prod_idx(&p_rx->rcq_chain);
 	rx_prod.bd_prod = cpu_to_le16(bd_prod);
 	rx_prod.cqe_prod = cpu_to_le16(cq_prod);
+
+	/* Make sure chain element is updated before ringing the doorbell */
+	dma_wmb();
+
 	DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod));
 }
 
@@ -2351,6 +2355,7 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb)
 		if (unlikely(dma_mapping_error(&cdev->pdev->dev, mapping))) {
 			DP_NOTICE(cdev,
 				  "Unable to map frag - dropping packet\n");
+			rc = -ENOMEM;
 			goto err;
 		}
 
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
index 596a365..cec68ef 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
@@ -46,10 +46,25 @@
 
 /* Local Definitions and Declarations */
 
-static const struct nla_policy rmnet_policy[IFLA_RMNET_MAX + 2] = {
-	[IFLA_RMNET_MUX_ID]	= { .type = NLA_U16 },
-	[IFLA_RMNET_FLAGS]	= { .len = sizeof(struct ifla_rmnet_flags) },
-	[IFLA_VLAN_EGRESS_QOS]	= { .len = sizeof(struct tcmsg) },
+enum {
+	IFLA_RMNET_DFC_QOS = __IFLA_RMNET_MAX,
+	IFLA_RMNET_UL_AGG_PARAMS,
+	__IFLA_RMNET_EXT_MAX,
+};
+
+static const struct nla_policy rmnet_policy[__IFLA_RMNET_EXT_MAX] = {
+	[IFLA_RMNET_MUX_ID] = {
+		.type = NLA_U16
+	},
+	[IFLA_RMNET_FLAGS] = {
+		.len = sizeof(struct ifla_rmnet_flags)
+	},
+	[IFLA_RMNET_DFC_QOS] = {
+		.len = sizeof(struct tcmsg)
+	},
+	[IFLA_RMNET_UL_AGG_PARAMS] = {
+		.len = sizeof(struct rmnet_egress_agg_params)
+	},
 };
 
 int rmnet_is_real_dev_registered(const struct net_device *real_dev)
@@ -190,6 +205,17 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
 	netdev_dbg(dev, "data format [0x%08X]\n", data_format);
 	port->data_format = data_format;
 
+	if (data[IFLA_RMNET_UL_AGG_PARAMS]) {
+		void *agg_params;
+		unsigned long irq_flags;
+
+		agg_params = nla_data(data[IFLA_RMNET_UL_AGG_PARAMS]);
+		spin_lock_irqsave(&port->agg_lock, irq_flags);
+		memcpy(&port->egress_agg_params, agg_params,
+		       sizeof(port->egress_agg_params));
+		spin_unlock_irqrestore(&port->agg_lock, irq_flags);
+	}
+
 	return 0;
 
 err1:
@@ -294,6 +320,7 @@ static struct notifier_block rmnet_dev_notifier __read_mostly = {
 static int rmnet_rtnl_validate(struct nlattr *tb[], struct nlattr *data[],
 			       struct netlink_ext_ack *extack)
 {
+	struct rmnet_egress_agg_params *agg_params;
 	u16 mux_id;
 
 	if (!data) {
@@ -304,6 +331,12 @@ static int rmnet_rtnl_validate(struct nlattr *tb[], struct nlattr *data[],
 			if (mux_id > (RMNET_MAX_LOGICAL_EP - 1))
 				return -ERANGE;
 		}
+
+		if (data[IFLA_RMNET_UL_AGG_PARAMS]) {
+			agg_params = nla_data(data[IFLA_RMNET_UL_AGG_PARAMS]);
+			if (agg_params->agg_time < 3000000)
+				return -EINVAL;
+		}
 	}
 
 	return 0;
@@ -347,13 +380,24 @@ static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[],
 		port->data_format = flags->flags & flags->mask;
 	}
 
-	if (data[IFLA_VLAN_EGRESS_QOS]) {
+	if (data[IFLA_RMNET_DFC_QOS]) {
 		struct tcmsg *tcm;
 
-		tcm = nla_data(data[IFLA_VLAN_EGRESS_QOS]);
+		tcm = nla_data(data[IFLA_RMNET_DFC_QOS]);
 		qmi_rmnet_change_link(dev, port, tcm);
 	}
 
+	if (data[IFLA_RMNET_UL_AGG_PARAMS]) {
+		void *agg_params;
+		unsigned long irq_flags;
+
+		agg_params = nla_data(data[IFLA_RMNET_UL_AGG_PARAMS]);
+		spin_lock_irqsave(&port->agg_lock, irq_flags);
+		memcpy(&port->egress_agg_params, agg_params,
+		       sizeof(port->egress_agg_params));
+		spin_unlock_irqrestore(&port->agg_lock, irq_flags);
+	}
+
 	return 0;
 }
 
@@ -364,7 +408,10 @@ static size_t rmnet_get_size(const struct net_device *dev)
 		nla_total_size(2) +
 		/* IFLA_RMNET_FLAGS */
 		nla_total_size(sizeof(struct ifla_rmnet_flags)) +
-		nla_total_size(sizeof(struct tcmsg));
+		/* IFLA_RMNET_DFC_QOS */
+		nla_total_size(sizeof(struct tcmsg)) +
+		/* IFLA_RMNET_UL_AGG_PARAMS */
+		nla_total_size(sizeof(struct rmnet_egress_agg_params));
 }
 
 static int rmnet_fill_info(struct sk_buff *skb, const struct net_device *dev)
@@ -372,7 +419,7 @@ static int rmnet_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	struct rmnet_priv *priv = netdev_priv(dev);
 	struct net_device *real_dev;
 	struct ifla_rmnet_flags f;
-	struct rmnet_port *port;
+	struct rmnet_port *port = NULL;
 
 	real_dev = priv->real_dev;
 
@@ -391,6 +438,13 @@ static int rmnet_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	if (nla_put(skb, IFLA_RMNET_FLAGS, sizeof(f), &f))
 		goto nla_put_failure;
 
+	if (port) {
+		if (nla_put(skb, IFLA_RMNET_UL_AGG_PARAMS,
+			    sizeof(port->egress_agg_params),
+			    &port->egress_agg_params))
+			goto nla_put_failure;
+	}
+
 	return 0;
 
 nla_put_failure:
@@ -399,7 +453,7 @@ static int rmnet_fill_info(struct sk_buff *skb, const struct net_device *dev)
 
 struct rtnl_link_ops rmnet_link_ops __read_mostly = {
 	.kind		= "rmnet",
-	.maxtype	= __IFLA_RMNET_MAX,
+	.maxtype	= __IFLA_RMNET_EXT_MAX,
 	.priv_size	= sizeof(struct rmnet_priv),
 	.setup		= rmnet_vnd_setup,
 	.validate	= rmnet_rtnl_validate,
@@ -610,6 +664,30 @@ void rmnet_enable_all_flows(void *port)
 }
 EXPORT_SYMBOL(rmnet_enable_all_flows);
 
+bool rmnet_all_flows_enabled(void *port)
+{
+	struct rmnet_endpoint *ep;
+	unsigned long bkt;
+	bool ret = true;
+
+	if (unlikely(!port))
+		return true;
+
+	rcu_read_lock();
+	hash_for_each_rcu(((struct rmnet_port *)port)->muxed_ep,
+			  bkt, ep, hlnode) {
+		if (!qmi_rmnet_all_flows_enabled(ep->egress_dev)) {
+			ret = false;
+			goto out;
+		}
+	}
+out:
+	rcu_read_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(rmnet_all_flows_enabled);
+
 int rmnet_get_powersave_notif(void *port)
 {
 	if (!port)
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
index 1658160..9d89ece 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
@@ -40,6 +40,12 @@ struct rmnet_port_priv_stats {
 	u64 dl_trl_count;
 };
 
+struct rmnet_egress_agg_params {
+	u16 agg_size;
+	u16 agg_count;
+	u32 agg_time;
+};
+
 /* One instance of this structure is instantiated for each real_dev associated
  * with rmnet.
  */
@@ -52,8 +58,7 @@ struct rmnet_port {
 	struct net_device *bridge_ep;
 	void *rmnet_perf;
 
-	u16 egress_agg_size;
-	u16 egress_agg_count;
+	struct rmnet_egress_agg_params egress_agg_params;
 
 	/* Protect aggregation related elements */
 	spinlock_t agg_lock;
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
index c55daaf..d5c5111 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
@@ -219,6 +219,7 @@ __rmnet_map_ingress_handler(struct sk_buff *skb,
 
 	qmap = (struct rmnet_map_header *)rmnet_map_data_ptr(skb);
 	if (qmap->cd_bit) {
+		qmi_rmnet_set_dl_msg_active(port);
 		if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) {
 			if (!rmnet_map_flow_command(skb, port, false))
 				return;
@@ -247,12 +248,14 @@ __rmnet_map_ingress_handler(struct sk_buff *skb,
 	if (qmap->next_hdr &&
 	    (port->data_format & (RMNET_FLAGS_INGRESS_COALESCE |
 				  RMNET_FLAGS_INGRESS_MAP_CKSUMV5))) {
-		if (rmnet_map_process_next_hdr_packet(skb, &list))
+		if (rmnet_map_process_next_hdr_packet(skb, &list, len))
 			goto free_skb;
 	} else {
 		/* We only have the main QMAP header to worry about */
 		pskb_pull(skb, sizeof(*qmap));
 
+		rmnet_set_skb_proto(skb);
+
 		if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) {
 			if (!rmnet_map_checksum_downlink_packet(skb, len + pad))
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -315,10 +318,15 @@ rmnet_map_ingress_handler(struct sk_buff *skb,
 		struct sk_buff *skb_frag = skb_shinfo(skb)->frag_list;
 
 		skb_shinfo(skb)->frag_list = NULL;
-		while ((skbn = rmnet_map_deaggregate(skb, port)) != NULL)
+		while ((skbn = rmnet_map_deaggregate(skb, port)) != NULL) {
 			__rmnet_map_ingress_handler(skbn, port);
 
+			if (skbn == skb)
+				goto next_skb;
+		}
+
 		consume_skb(skb);
+next_skb:
 		skb = skb_frag;
 	}
 }
@@ -349,9 +357,6 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
 			return -ENOMEM;
 	}
 
-	if (port->data_format & RMNET_INGRESS_FORMAT_PS)
-		qmi_rmnet_work_maybe_restart(port);
-
 	if (csum_type)
 		rmnet_map_checksum_uplink_packet(skb, orig_dev, csum_type);
 
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
index ee75da9..9adaf29 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
@@ -248,7 +248,8 @@ void rmnet_map_checksum_uplink_packet(struct sk_buff *skb,
 				      struct net_device *orig_dev,
 				      int csum_type);
 int rmnet_map_process_next_hdr_packet(struct sk_buff *skb,
-				      struct sk_buff_head *list);
+				      struct sk_buff_head *list,
+				      u16 len);
 int rmnet_map_tx_agg_skip(struct sk_buff *skb, int offset);
 void rmnet_map_tx_aggregate(struct sk_buff *skb, struct rmnet_port *port);
 void rmnet_map_tx_aggregate_init(struct rmnet_port *port);
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
index b2929f6..bf0408d 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
@@ -324,7 +324,7 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
 {
 	struct rmnet_map_header *maph;
 	struct sk_buff *skbn;
-	unsigned char *data = rmnet_map_data_ptr(skb);
+	unsigned char *data = rmnet_map_data_ptr(skb), *next_hdr = NULL;
 	u32 packet_len;
 
 	if (skb->len == 0)
@@ -335,8 +335,14 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
 
 	if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4)
 		packet_len += sizeof(struct rmnet_map_dl_csum_trailer);
-	else if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV5)
-		packet_len += sizeof(struct rmnet_map_v5_csum_header);
+	else if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV5) {
+		if (!maph->cd_bit) {
+			packet_len += sizeof(struct rmnet_map_v5_csum_header);
+
+			/* Coalescing headers require MAPv5 */
+			next_hdr = data + sizeof(*maph);
+		}
+	}
 
 	if (((int)skb->len - (int)packet_len) < 0)
 		return NULL;
@@ -345,6 +351,11 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
 	if (ntohs(maph->pkt_len) == 0)
 		return NULL;
 
+	if (next_hdr &&
+	    ((struct rmnet_map_v5_coal_header *)next_hdr)->header_type ==
+	     RMNET_MAP_HEADER_TYPE_COALESCING)
+		return skb;
+
 	if (skb_is_nonlinear(skb)) {
 		skb_frag_t *frag0 = skb_shinfo(skb)->frags;
 		struct page *page = skb_frag_page(frag0);
@@ -787,9 +798,30 @@ static void rmnet_map_segment_coal_data(struct sk_buff *coal_skb,
 	if (iph->version == 4) {
 		protocol = iph->protocol;
 		ip_len = iph->ihl * 4;
+
+		/* Don't allow coalescing of any packets with IP options */
+		if (iph->ihl != 5)
+			gro = false;
 	} else if (iph->version == 6) {
+		__be16 frag_off;
+
 		protocol = ((struct ipv6hdr *)iph)->nexthdr;
-		ip_len = sizeof(struct ipv6hdr);
+		ip_len = ipv6_skip_exthdr(coal_skb, sizeof(struct ipv6hdr),
+					  &protocol, &frag_off);
+
+		/* If we run into a problem, or this has a fragment header
+		 * (which should technically not be possible, if the HW
+		 * works as intended...), bail.
+		 */
+		if (ip_len < 0 || frag_off) {
+			priv->stats.coal.coal_ip_invalid++;
+			return;
+		} else if (ip_len > sizeof(struct ipv6hdr)) {
+			/* Don't allow coalescing of any packets with IPv6
+			 * extension headers.
+			 */
+			gro = false;
+		}
 	} else {
 		priv->stats.coal.coal_ip_invalid++;
 		return;
@@ -826,6 +858,7 @@ static void rmnet_map_segment_coal_data(struct sk_buff *coal_skb,
 						return;
 
 					__skb_queue_tail(list, new_skb);
+					start += pkt_len * gro_count;
 					gro_count = 0;
 				}
 
@@ -866,7 +899,7 @@ static void rmnet_map_segment_coal_data(struct sk_buff *coal_skb,
 
 			__skb_queue_tail(list, new_skb);
 
-			start += pkt_len;
+			start += pkt_len * gro_count;
 			start_pkt_num = total_pkt + 1;
 			gro_count = 0;
 		}
@@ -976,7 +1009,8 @@ static int rmnet_map_data_check_coal_header(struct sk_buff *skb,
 
 /* Process a QMAPv5 packet header */
 int rmnet_map_process_next_hdr_packet(struct sk_buff *skb,
-				      struct sk_buff_head *list)
+				      struct sk_buff_head *list,
+				      u16 len)
 {
 	struct rmnet_priv *priv = netdev_priv(skb->dev);
 	u64 nlo_err_mask;
@@ -1003,6 +1037,11 @@ int rmnet_map_process_next_hdr_packet(struct sk_buff *skb,
 		pskb_pull(skb,
 			  (sizeof(struct rmnet_map_header) +
 			   sizeof(struct rmnet_map_v5_csum_header)));
+
+		/* Remove padding only for csum offload packets.
+		 * Coalesced packets should never have padding.
+		 */
+		pskb_trim(skb, len);
 		__skb_queue_tail(list, skb);
 		break;
 	default:
@@ -1097,15 +1136,16 @@ void rmnet_map_tx_aggregate(struct sk_buff *skb, struct rmnet_port *port)
 		 * sparse, don't aggregate. We will need to tune this later
 		 */
 		diff = timespec_sub(port->agg_last, last);
+		size = port->egress_agg_params.agg_size - skb->len;
 
-		if (diff.tv_sec > 0 || diff.tv_nsec > rmnet_agg_bypass_time) {
+		if (diff.tv_sec > 0 || diff.tv_nsec > rmnet_agg_bypass_time ||
+		    size <= 0) {
 			spin_unlock_irqrestore(&port->agg_lock, flags);
 			skb->protocol = htons(ETH_P_MAP);
 			dev_queue_xmit(skb);
 			return;
 		}
 
-		size = port->egress_agg_size - skb->len;
 		port->agg_skb = skb_copy_expand(skb, 0, size, GFP_ATOMIC);
 		if (!port->agg_skb) {
 			port->agg_skb = 0;
@@ -1123,9 +1163,10 @@ void rmnet_map_tx_aggregate(struct sk_buff *skb, struct rmnet_port *port)
 		goto schedule;
 	}
 	diff = timespec_sub(port->agg_last, port->agg_time);
+	size = port->egress_agg_params.agg_size - port->agg_skb->len;
 
-	if (skb->len > (port->egress_agg_size - port->agg_skb->len) ||
-	    port->agg_count >= port->egress_agg_count ||
+	if (skb->len > size ||
+	    port->agg_count >= port->egress_agg_params.agg_count ||
 	    diff.tv_sec > 0 || diff.tv_nsec > rmnet_agg_time_limit) {
 		agg_skb = port->agg_skb;
 		agg_count = port->agg_count;
@@ -1147,7 +1188,8 @@ void rmnet_map_tx_aggregate(struct sk_buff *skb, struct rmnet_port *port)
 schedule:
 	if (port->agg_state != -EINPROGRESS) {
 		port->agg_state = -EINPROGRESS;
-		hrtimer_start(&port->hrtimer, ns_to_ktime(3000000),
+		hrtimer_start(&port->hrtimer,
+			      ns_to_ktime(port->egress_agg_params.agg_time),
 			      HRTIMER_MODE_REL);
 	}
 	spin_unlock_irqrestore(&port->agg_lock, flags);
@@ -1157,8 +1199,9 @@ void rmnet_map_tx_aggregate_init(struct rmnet_port *port)
 {
 	hrtimer_init(&port->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	port->hrtimer.function = rmnet_map_flush_tx_packet_queue;
-	port->egress_agg_size = 8192;
-	port->egress_agg_count = 20;
+	port->egress_agg_params.agg_size = 8192;
+	port->egress_agg_params.agg_count = 20;
+	port->egress_agg_params.agg_time = 3000000;
 	spin_lock_init(&port->agg_lock);
 
 	INIT_WORK(&port->agg_wq, rmnet_map_flush_tx_packet_work);
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
index ed8bbbb..ed41529 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
@@ -25,6 +25,7 @@
 #include "rmnet_vnd.h"
 
 #include <soc/qcom/qmi_rmnet.h>
+#include <soc/qcom/rmnet_qmi.h>
 #define CREATE_TRACE_POINTS
 #include <trace/events/rmnet.h>
 
@@ -75,6 +76,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
 		trace_rmnet_xmit_skb(skb);
 		rmnet_egress_handler(skb);
 		qmi_rmnet_burst_fc_check(dev, ip_type, mark, len);
+		qmi_rmnet_work_maybe_restart(rmnet_get_rmnet_port(dev));
 	} else {
 		this_cpu_inc(priv->pcpu_stats->stats.tx_drops);
 		kfree_skb(skb);
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 1b61ce3..c7364d9 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -324,6 +324,8 @@ enum cfg_version {
 };
 
 static const struct pci_device_id rtl8169_pci_tbl[] = {
+	{ PCI_VDEVICE(REALTEK,	0x2502), RTL_CFG_1 },
+	{ PCI_VDEVICE(REALTEK,	0x2600), RTL_CFG_1 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8129), 0, 0, RTL_CFG_0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8136), 0, 0, RTL_CFG_2 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8161), 0, 0, RTL_CFG_1 },
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 8e2a196..d824bf9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -444,7 +444,8 @@ struct stmmac_dma_ops {
 			 int rxfifosz);
 	void (*dma_rx_mode)(void __iomem *ioaddr, int mode, u32 channel,
 			    int fifosz);
-	void (*dma_tx_mode)(void __iomem *ioaddr, int mode, u32 channel);
+	void (*dma_tx_mode)(void __iomem *ioaddr, int mode, u32 channel,
+			    int fifosz);
 	/* To track extra statistic (if supported) */
 	void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x,
 				   void __iomem *ioaddr);
@@ -474,7 +475,7 @@ struct mac_device_info;
 /* Helpers to program the MAC core */
 struct stmmac_ops {
 	/* MAC core initialization */
-	void (*core_init)(struct mac_device_info *hw, int mtu);
+	void (*core_init)(struct mac_device_info *hw, struct net_device *dev);
 	/* Enable the MAC RX/TX */
 	void (*set_mac)(void __iomem *ioaddr, bool enable);
 	/* Enable and verify that the IPC module is supported */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 39c2122..14866331 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -477,7 +477,8 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv)
 	return 0;
 }
 
-static void sun8i_dwmac_core_init(struct mac_device_info *hw, int mtu)
+static void sun8i_dwmac_core_init(struct mac_device_info *hw,
+				  struct net_device *dev)
 {
 	void __iomem *ioaddr = hw->pcsr;
 	u32 v;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 8a86340..540d217 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -25,18 +25,28 @@
 #include <linux/crc32.h>
 #include <linux/slab.h>
 #include <linux/ethtool.h>
+#include <net/dsa.h>
 #include <asm/io.h>
 #include "stmmac_pcs.h"
 #include "dwmac1000.h"
 
-static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
+static void dwmac1000_core_init(struct mac_device_info *hw,
+				struct net_device *dev)
 {
 	void __iomem *ioaddr = hw->pcsr;
 	u32 value = readl(ioaddr + GMAC_CONTROL);
+	int mtu = dev->mtu;
 
 	/* Configure GMAC core */
 	value |= GMAC_CORE_INIT;
 
+	/* Clear ACS bit because Ethernet switch tagging formats such as
+	 * Broadcom tags can look like invalid LLC/SNAP packets and cause the
+	 * hardware to truncate packets on reception.
+	 */
+	if (netdev_uses_dsa(dev))
+		value &= ~GMAC_CONTROL_ACS;
+
 	if (mtu > 1500)
 		value |= GMAC_CONTROL_2K;
 	if (mtu > 2000)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 8ef5173..91b23f9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -25,15 +25,26 @@
 *******************************************************************************/
 
 #include <linux/crc32.h>
+#include <net/dsa.h>
 #include <asm/io.h>
 #include "dwmac100.h"
 
-static void dwmac100_core_init(struct mac_device_info *hw, int mtu)
+static void dwmac100_core_init(struct mac_device_info *hw,
+			       struct net_device *dev)
 {
 	void __iomem *ioaddr = hw->pcsr;
 	u32 value = readl(ioaddr + MAC_CONTROL);
 
-	writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL);
+	value |= MAC_CORE_INIT;
+
+	/* Clear ASTP bit because Ethernet switch tagging formats such as
+	 * Broadcom tags can look like invalid LLC/SNAP packets and cause the
+	 * hardware to truncate packets on reception.
+	 */
+	if (netdev_uses_dsa(dev))
+		value &= ~MAC_CONTROL_ASTP;
+
+	writel(value, ioaddr + MAC_CONTROL);
 
 #ifdef STMMAC_VLAN_TAG_USED
 	writel(ETH_P_8021Q, ioaddr + MAC_VLAN1);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
index d74cedf..db5f2ae 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
@@ -336,7 +336,7 @@ enum power_event {
 #define MTL_RX_OVERFLOW_INT		BIT(16)
 
 /* Default operating mode of the MAC */
-#define GMAC_CORE_INIT (GMAC_CONFIG_JD | GMAC_CONFIG_PS | GMAC_CONFIG_ACS | \
+#define GMAC_CORE_INIT (GMAC_CONFIG_JD | GMAC_CONFIG_PS | \
 			GMAC_CONFIG_BE | GMAC_CONFIG_DCRS)
 
 /* To dump the core regs excluding  the Address Registers */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index e1d0348..55ae14a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -17,13 +17,16 @@
 #include <linux/slab.h>
 #include <linux/ethtool.h>
 #include <linux/io.h>
+#include <net/dsa.h>
 #include "stmmac_pcs.h"
 #include "dwmac4.h"
 
-static void dwmac4_core_init(struct mac_device_info *hw, int mtu)
+static void dwmac4_core_init(struct mac_device_info *hw,
+			     struct net_device *dev)
 {
 	void __iomem *ioaddr = hw->pcsr;
 	u32 value = readl(ioaddr + GMAC_CONFIG);
+	int mtu = dev->mtu;
 
 	value |= GMAC_CORE_INIT;
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index 7e089bf..37b77e7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@ -238,15 +238,18 @@ static inline u64 dwmac4_get_timestamp(void *desc, u32 ats)
 static int dwmac4_rx_check_timestamp(void *desc)
 {
 	struct dma_desc *p = (struct dma_desc *)desc;
+	unsigned int rdes0 = le32_to_cpu(p->des0);
+	unsigned int rdes1 = le32_to_cpu(p->des1);
+	unsigned int rdes3 = le32_to_cpu(p->des3);
 	u32 own, ctxt;
 	int ret = 1;
 
-	own = p->des3 & RDES3_OWN;
-	ctxt = ((p->des3 & RDES3_CONTEXT_DESCRIPTOR)
+	own = rdes3 & RDES3_OWN;
+	ctxt = ((rdes3 & RDES3_CONTEXT_DESCRIPTOR)
 		>> RDES3_CONTEXT_DESCRIPTOR_SHIFT);
 
 	if (likely(!own && ctxt)) {
-		if ((p->des0 == 0xffffffff) && (p->des1 == 0xffffffff))
+		if ((rdes0 == 0xffffffff) && (rdes1 == 0xffffffff))
 			/* Corrupted value */
 			ret = -EINVAL;
 		else
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index e84831e..898849b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -271,9 +271,10 @@ static void dwmac4_dma_rx_chan_op_mode(void __iomem *ioaddr, int mode,
 }
 
 static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode,
-				       u32 channel)
+				       u32 channel, int fifosz)
 {
 	u32 mtl_tx_op = readl(ioaddr + MTL_CHAN_TX_OP_MODE(channel));
+	unsigned int tqs = fifosz / 256 - 1;
 
 	if (mode == SF_DMA_MODE) {
 		pr_debug("GMAC: enable TX store and forward mode\n");
@@ -306,12 +307,14 @@ static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode,
 	 * For an IP with DWC_EQOS_NUM_TXQ > 1, the fields TXQEN and TQS are R/W
 	 * with reset values: TXQEN off, TQS 256 bytes.
 	 *
-	 * Write the bits in both cases, since it will have no effect when RO.
-	 * For DWC_EQOS_NUM_TXQ > 1, the top bits in MTL_OP_MODE_TQS_MASK might
-	 * be RO, however, writing the whole TQS field will result in a value
-	 * equal to DWC_EQOS_TXFIFO_SIZE, just like for DWC_EQOS_NUM_TXQ == 1.
+	 * TXQEN must be written for multi-channel operation and TQS must
+	 * reflect the available fifo size per queue (total fifo size / number
+	 * of enabled queues).
 	 */
-	mtl_tx_op |= MTL_OP_MODE_TXQEN | MTL_OP_MODE_TQS_MASK;
+	mtl_tx_op |= MTL_OP_MODE_TXQEN;
+	mtl_tx_op &= ~MTL_OP_MODE_TQS_MASK;
+	mtl_tx_op |= tqs << MTL_OP_MODE_TQS_SHIFT;
+
 	writel(mtl_tx_op, ioaddr +  MTL_CHAN_TX_OP_MODE(channel));
 }
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index af30b48..c3c6335c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -675,25 +675,27 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
 				     struct ethtool_eee *edata)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
+	int ret;
 
-	priv->eee_enabled = edata->eee_enabled;
-
-	if (!priv->eee_enabled)
+	if (!edata->eee_enabled) {
 		stmmac_disable_eee_mode(priv);
-	else {
+	} else {
 		/* We are asking for enabling the EEE but it is safe
 		 * to verify all by invoking the eee_init function.
 		 * In case of failure it will return an error.
 		 */
-		priv->eee_enabled = stmmac_eee_init(priv);
-		if (!priv->eee_enabled)
+		edata->eee_enabled = stmmac_eee_init(priv);
+		if (!edata->eee_enabled)
 			return -EOPNOTSUPP;
-
-		/* Do not change tx_lpi_timer in case of failure */
-		priv->tx_lpi_timer = edata->tx_lpi_timer;
 	}
 
-	return phy_ethtool_set_eee(dev->phydev, edata);
+	ret = phy_ethtool_set_eee(dev->phydev, edata);
+	if (ret)
+		return ret;
+
+	priv->eee_enabled = edata->eee_enabled;
+	priv->tx_lpi_timer = edata->tx_lpi_timer;
+	return 0;
 }
 
 static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index bafbebe..0e66a50 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1765,12 +1765,19 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
 	int rxfifosz = priv->plat->rx_fifo_size;
+	int txfifosz = priv->plat->tx_fifo_size;
 	u32 txmode = 0;
 	u32 rxmode = 0;
 	u32 chan = 0;
 
 	if (rxfifosz == 0)
 		rxfifosz = priv->dma_cap.rx_fifo_size;
+	if (txfifosz == 0)
+		txfifosz = priv->dma_cap.tx_fifo_size;
+
+	/* Adjust for real per queue fifo size */
+	rxfifosz /= rx_channels_count;
+	txfifosz /= tx_channels_count;
 
 	if (priv->plat->force_thresh_dma_mode) {
 		txmode = tc;
@@ -1798,7 +1805,8 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
 						   rxfifosz);
 
 		for (chan = 0; chan < tx_channels_count; chan++)
-			priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan);
+			priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan,
+						   txfifosz);
 	} else {
 		priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode,
 					rxfifosz);
@@ -1967,15 +1975,25 @@ static void stmmac_tx_err(struct stmmac_priv *priv, u32 chan)
 static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode,
 					  u32 rxmode, u32 chan)
 {
+	u32 rx_channels_count = priv->plat->rx_queues_to_use;
+	u32 tx_channels_count = priv->plat->tx_queues_to_use;
 	int rxfifosz = priv->plat->rx_fifo_size;
+	int txfifosz = priv->plat->tx_fifo_size;
 
 	if (rxfifosz == 0)
 		rxfifosz = priv->dma_cap.rx_fifo_size;
+	if (txfifosz == 0)
+		txfifosz = priv->dma_cap.tx_fifo_size;
+
+	/* Adjust for real per queue fifo size */
+	rxfifosz /= rx_channels_count;
+	txfifosz /= tx_channels_count;
 
 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
 		priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan,
 					   rxfifosz);
-		priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan);
+		priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan,
+					   txfifosz);
 	} else {
 		priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode,
 					rxfifosz);
@@ -2479,7 +2497,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
 	}
 
 	/* Initialize the MAC Core */
-	priv->hw->mac->core_init(priv->hw, dev->mtu);
+	priv->hw->mac->core_init(priv->hw, dev);
 
 	/* Initialize MTL*/
 	if (priv->synopsys_id >= DWMAC_CORE_4_00)
@@ -3397,8 +3415,13 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
 
 			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
 			 * Type frames (LLC/LLC-SNAP)
+			 *
+			 * llc_snap is never checked in GMAC >= 4, so this ACS
+			 * feature is always disabled and packets need to be
+			 * stripped manually.
 			 */
-			if (unlikely(status != llc_snap))
+			if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00) ||
+			    unlikely(status != llc_snap))
 				frame_len -= ETH_FCS_LEN;
 
 			if (netif_msg_rx_status(priv)) {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index c54a50d..d819e8e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -299,7 +299,17 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
  */
 static void stmmac_pci_remove(struct pci_dev *pdev)
 {
+	int i;
+
 	stmmac_dvr_remove(&pdev->dev);
+
+	for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {
+		if (pci_resource_len(pdev, i) == 0)
+			continue;
+		pcim_iounmap_regions(pdev, BIT(i));
+		break;
+	}
+
 	pci_disable_device(pdev);
 }
 
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index e92f41d..411a69b 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -8119,6 +8119,8 @@ static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end)
 		start += 3;
 
 		prop_len = niu_pci_eeprom_read(np, start + 4);
+		if (prop_len < 0)
+			return prop_len;
 		err = niu_pci_vpd_get_propname(np, start + 5, namebuf, 64);
 		if (err < 0)
 			return err;
@@ -8163,8 +8165,12 @@ static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end)
 			netif_printk(np, probe, KERN_DEBUG, np->dev,
 				     "VPD_SCAN: Reading in property [%s] len[%d]\n",
 				     namebuf, prop_len);
-			for (i = 0; i < prop_len; i++)
-				*prop_buf++ = niu_pci_eeprom_read(np, off + i);
+			for (i = 0; i < prop_len; i++) {
+				err = niu_pci_eeprom_read(np, off + i);
+				if (err >= 0)
+					*prop_buf = err;
+				++prop_buf;
+			}
 		}
 
 		start += len;
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 17025d4..fc1d5e1 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -711,8 +711,8 @@ rndis_filter_set_offload_params(struct net_device *ndev,
 	return ret;
 }
 
-int rndis_filter_set_rss_param(struct rndis_device *rdev,
-			       const u8 *rss_key)
+static int rndis_set_rss_param_msg(struct rndis_device *rdev,
+				   const u8 *rss_key, u16 flag)
 {
 	struct net_device *ndev = rdev->ndev;
 	struct rndis_request *request;
@@ -741,7 +741,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
 	rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
 	rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
 	rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
-	rssp->flag = 0;
+	rssp->flag = flag;
 	rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
 			 NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
 			 NDIS_HASH_TCP_IPV6;
@@ -766,9 +766,12 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
 
 	wait_for_completion(&request->wait_event);
 	set_complete = &request->response_msg.msg.set_complete;
-	if (set_complete->status == RNDIS_STATUS_SUCCESS)
-		memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
-	else {
+	if (set_complete->status == RNDIS_STATUS_SUCCESS) {
+		if (!(flag & NDIS_RSS_PARAM_FLAG_DISABLE_RSS) &&
+		    !(flag & NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED))
+			memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
+
+	} else {
 		netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
 			   set_complete->status);
 		ret = -EINVAL;
@@ -779,6 +782,16 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
 	return ret;
 }
 
+int rndis_filter_set_rss_param(struct rndis_device *rdev,
+			       const u8 *rss_key)
+{
+	/* Disable RSS before change */
+	rndis_set_rss_param_msg(rdev, rss_key,
+				NDIS_RSS_PARAM_FLAG_DISABLE_RSS);
+
+	return rndis_set_rss_param_msg(rdev, rss_key, 0);
+}
+
 static int rndis_filter_query_device_link_status(struct rndis_device *dev,
 						 struct netvsc_device *net_device)
 {
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index 22e466e..dcd10db 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -722,7 +722,7 @@ static void ca8210_mlme_reset_worker(struct work_struct *work)
 static void ca8210_rx_done(struct cas_control *cas_ctl)
 {
 	u8 *buf;
-	u8 len;
+	unsigned int len;
 	struct work_priv_container *mlme_reset_wpc;
 	struct ca8210_priv *priv = cas_ctl->priv;
 
@@ -731,7 +731,7 @@ static void ca8210_rx_done(struct cas_control *cas_ctl)
 	if (len > CA8210_SPI_BUF_SIZE) {
 		dev_crit(
 			&priv->spi->dev,
-			"Received packet len (%d) erroneously long\n",
+			"Received packet len (%u) erroneously long\n",
 			len
 		);
 		goto finish;
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 58133c9..2222ed6 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -95,12 +95,12 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval)
 			err = ipvlan_register_nf_hook(read_pnet(&port->pnet));
 			if (!err) {
 				mdev->l3mdev_ops = &ipvl_l3mdev_ops;
-				mdev->priv_flags |= IFF_L3MDEV_MASTER;
+				mdev->priv_flags |= IFF_L3MDEV_RX_HANDLER;
 			} else
 				goto fail;
 		} else if (port->mode == IPVLAN_MODE_L3S) {
 			/* Old mode was L3S */
-			mdev->priv_flags &= ~IFF_L3MDEV_MASTER;
+			mdev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
 			ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
 			mdev->l3mdev_ops = NULL;
 		}
@@ -172,7 +172,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
 
 	dev->priv_flags &= ~IFF_IPVLAN_MASTER;
 	if (port->mode == IPVLAN_MODE_L3S) {
-		dev->priv_flags &= ~IFF_L3MDEV_MASTER;
+		dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
 		ipvlan_unregister_nf_hook(dev_net(dev));
 		dev->l3mdev_ops = NULL;
 	}
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 26fbbd3f..afebdc2 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -893,14 +893,14 @@ static void decode_txts(struct dp83640_private *dp83640,
 			struct phy_txts *phy_txts)
 {
 	struct skb_shared_hwtstamps shhwtstamps;
+	struct dp83640_skb_info *skb_info;
 	struct sk_buff *skb;
-	u64 ns;
 	u8 overflow;
+	u64 ns;
 
 	/* We must already have the skb that triggered this. */
-
+again:
 	skb = skb_dequeue(&dp83640->tx_queue);
-
 	if (!skb) {
 		pr_debug("have timestamp but tx_queue empty\n");
 		return;
@@ -915,6 +915,11 @@ static void decode_txts(struct dp83640_private *dp83640,
 		}
 		return;
 	}
+	skb_info = (struct dp83640_skb_info *)skb->cb;
+	if (time_after(jiffies, skb_info->tmo)) {
+		kfree_skb(skb);
+		goto again;
+	}
 
 	ns = phy2txts(phy_txts);
 	memset(&shhwtstamps, 0, sizeof(shhwtstamps));
@@ -1466,6 +1471,7 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
 static void dp83640_txtstamp(struct phy_device *phydev,
 			     struct sk_buff *skb, int type)
 {
+	struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb;
 	struct dp83640_private *dp83640 = phydev->priv;
 
 	switch (dp83640->hwts_tx_en) {
@@ -1478,6 +1484,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
 		/* fall through */
 	case HWTSTAMP_TX_ON:
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+		skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
 		skb_queue_tail(&dp83640->tx_queue, skb);
 		break;
 
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 2df7b62c..1ece412 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -358,6 +358,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
 	if (IS_ERR(gpiod)) {
 		dev_err(&bus->dev, "mii_bus %s couldn't get reset GPIO\n",
 			bus->id);
+		device_del(&bus->dev);
 		return PTR_ERR(gpiod);
 	} else	if (gpiod) {
 		bus->reset_gpiod = gpiod;
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 5d5acf0..83dd121 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -971,7 +971,7 @@ static struct phy_driver ksphy_driver[] = {
 	.phy_id		= PHY_ID_KSZ9031,
 	.phy_id_mask	= MICREL_PHY_ID_MASK,
 	.name		= "Micrel KSZ9031 Gigabit PHY",
-	.features	= PHY_GBIT_FEATURES,
+	.features	= (PHY_GBIT_FEATURES | SUPPORTED_Pause),
 	.flags		= PHY_HAS_INTERRUPT,
 	.driver_data	= &ksz9021_type,
 	.probe		= kszphy_probe,
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 70ce7da..afe3355 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -487,6 +487,17 @@ static void phylink_run_resolve(struct phylink *pl)
 		queue_work(system_power_efficient_wq, &pl->resolve);
 }
 
+static void phylink_run_resolve_and_disable(struct phylink *pl, int bit)
+{
+	unsigned long state = pl->phylink_disable_state;
+
+	set_bit(bit, &pl->phylink_disable_state);
+	if (state == 0) {
+		queue_work(system_power_efficient_wq, &pl->resolve);
+		flush_work(&pl->resolve);
+	}
+}
+
 static const struct sfp_upstream_ops sfp_phylink_ops;
 
 static int phylink_register_sfp(struct phylink *pl, struct device_node *np)
@@ -776,9 +787,7 @@ void phylink_stop(struct phylink *pl)
 	if (pl->sfp_bus)
 		sfp_upstream_stop(pl->sfp_bus);
 
-	set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
-	queue_work(system_power_efficient_wq, &pl->resolve);
-	flush_work(&pl->resolve);
+	phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
 }
 EXPORT_SYMBOL_GPL(phylink_stop);
 
@@ -1433,9 +1442,7 @@ static void phylink_sfp_link_down(void *upstream)
 
 	WARN_ON(!lockdep_rtnl_is_held());
 
-	set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
-	queue_work(system_power_efficient_wq, &pl->resolve);
-	flush_work(&pl->resolve);
+	phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_LINK);
 }
 
 static void phylink_sfp_link_up(void *upstream)
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 7ae815b..be6016e2 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -276,6 +276,7 @@ static int sfp_register_bus(struct sfp_bus *bus)
 				return ret;
 		}
 	}
+	bus->socket_ops->attach(bus->sfp);
 	if (bus->started)
 		bus->socket_ops->start(bus->sfp);
 	bus->registered = true;
@@ -289,6 +290,7 @@ static void sfp_unregister_bus(struct sfp_bus *bus)
 	if (bus->registered) {
 		if (bus->started)
 			bus->socket_ops->stop(bus->sfp);
+		bus->socket_ops->detach(bus->sfp);
 		if (bus->phydev && ops && ops->disconnect_phy)
 			ops->disconnect_phy(bus->upstream);
 	}
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 3165bc7..a1b68b1 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -114,6 +114,7 @@ struct sfp {
 
 	struct gpio_desc *gpio[GPIO_MAX];
 
+	bool attached;
 	unsigned int state;
 	struct delayed_work poll;
 	struct delayed_work timeout;
@@ -500,7 +501,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
 	 */
 	switch (sfp->sm_mod_state) {
 	default:
-		if (event == SFP_E_INSERT) {
+		if (event == SFP_E_INSERT && sfp->attached) {
 			sfp_module_tx_disable(sfp);
 			sfp_sm_ins_next(sfp, SFP_MOD_PROBE, T_PROBE_INIT);
 		}
@@ -628,6 +629,19 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
 	mutex_unlock(&sfp->sm_mutex);
 }
 
+static void sfp_attach(struct sfp *sfp)
+{
+	sfp->attached = true;
+	if (sfp->state & SFP_F_PRESENT)
+		sfp_sm_event(sfp, SFP_E_INSERT);
+}
+
+static void sfp_detach(struct sfp *sfp)
+{
+	sfp->attached = false;
+	sfp_sm_event(sfp, SFP_E_REMOVE);
+}
+
 static void sfp_start(struct sfp *sfp)
 {
 	sfp_sm_event(sfp, SFP_E_DEV_UP);
@@ -687,6 +701,8 @@ static int sfp_module_eeprom(struct sfp *sfp, struct ethtool_eeprom *ee,
 }
 
 static const struct sfp_socket_ops sfp_module_ops = {
+	.attach = sfp_attach,
+	.detach = sfp_detach,
 	.start = sfp_start,
 	.stop = sfp_stop,
 	.module_info = sfp_module_info,
@@ -829,10 +845,6 @@ static int sfp_probe(struct platform_device *pdev)
 		sfp->set_state = sfp_gpio_set_state;
 	}
 
-	sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
-	if (!sfp->sfp_bus)
-		return -ENOMEM;
-
 	/* Get the initial state, and always signal TX disable,
 	 * since the network interface will not be up.
 	 */
@@ -843,10 +855,6 @@ static int sfp_probe(struct platform_device *pdev)
 		sfp->state |= SFP_F_RATE_SELECT;
 	sfp_set_state(sfp, sfp->state);
 	sfp_module_tx_disable(sfp);
-	rtnl_lock();
-	if (sfp->state & SFP_F_PRESENT)
-		sfp_sm_event(sfp, SFP_E_INSERT);
-	rtnl_unlock();
 
 	for (i = 0; i < GPIO_MAX; i++) {
 		if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i])
@@ -879,6 +887,10 @@ static int sfp_remove(struct platform_device *pdev)
 
 	sfp_unregister_socket(sfp->sfp_bus);
 
+	sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
+	if (!sfp->sfp_bus)
+		return -ENOMEM;
+
 	return 0;
 }
 
diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h
index 31b0acf..64f54b0 100644
--- a/drivers/net/phy/sfp.h
+++ b/drivers/net/phy/sfp.h
@@ -7,6 +7,8 @@
 struct sfp;
 
 struct sfp_socket_ops {
+	void (*attach)(struct sfp *sfp);
+	void (*detach)(struct sfp *sfp);
 	void (*start)(struct sfp *sfp);
 	void (*stop)(struct sfp *sfp);
 	int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo);
diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c
index 7a14e81..aef5254 100644
--- a/drivers/net/phy/xilinx_gmii2rgmii.c
+++ b/drivers/net/phy/xilinx_gmii2rgmii.c
@@ -42,7 +42,10 @@ static int xgmiitorgmii_read_status(struct phy_device *phydev)
 	u16 val = 0;
 	int err;
 
-	err = priv->phy_drv->read_status(phydev);
+	if (priv->phy_drv->read_status)
+		err = priv->phy_drv->read_status(phydev);
+	else
+		err = genphy_read_status(phydev);
 	if (err < 0)
 		return err;
 
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 951892d..c37ef52 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -445,6 +445,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (pskb_trim_rcsum(skb, len))
 		goto drop;
 
+	ph = pppoe_hdr(skb);
 	pn = pppoe_pernet(dev_net(dev));
 
 	/* Note that get_item does a sock_hold(), so sk_pppox(po)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index bd455a6..bb96153 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -261,17 +261,6 @@ static void __team_option_inst_mark_removed_port(struct team *team,
 	}
 }
 
-static bool __team_option_inst_tmp_find(const struct list_head *opts,
-					const struct team_option_inst *needle)
-{
-	struct team_option_inst *opt_inst;
-
-	list_for_each_entry(opt_inst, opts, tmp_list)
-		if (opt_inst == needle)
-			return true;
-	return false;
-}
-
 static int __team_options_register(struct team *team,
 				   const struct team_option *option,
 				   size_t option_count)
@@ -2457,7 +2446,6 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
 	int err = 0;
 	int i;
 	struct nlattr *nl_option;
-	LIST_HEAD(opt_inst_list);
 
 	rtnl_lock();
 
@@ -2477,6 +2465,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
 		struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1];
 		struct nlattr *attr;
 		struct nlattr *attr_data;
+		LIST_HEAD(opt_inst_list);
 		enum team_option_type opt_type;
 		int opt_port_ifindex = 0; /* != 0 for per-port options */
 		u32 opt_array_index = 0;
@@ -2581,23 +2570,17 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
 			if (err)
 				goto team_put;
 			opt_inst->changed = true;
-
-			/* dumb/evil user-space can send us duplicate opt,
-			 * keep only the last one
-			 */
-			if (__team_option_inst_tmp_find(&opt_inst_list,
-							opt_inst))
-				continue;
-
 			list_add(&opt_inst->tmp_list, &opt_inst_list);
 		}
 		if (!opt_found) {
 			err = -ENOENT;
 			goto team_put;
 		}
-	}
 
-	err = team_nl_send_event_options_get(team, &opt_inst_list);
+		err = team_nl_send_event_options_get(team, &opt_inst_list);
+		if (err)
+			break;
+	}
 
 team_put:
 	team_nl_team_put(team);
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index b1b3d8f..d0c0ac0 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -731,8 +731,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 	asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
 	chipcode &= AX_CHIPCODE_MASK;
 
-	(chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
-					    ax88772a_hw_reset(dev, 0);
+	ret = (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
+						  ax88772a_hw_reset(dev, 0);
+
+	if (ret < 0) {
+		netdev_dbg(dev->net, "Failed to reset AX88772: %d\n", ret);
+		return ret;
+	}
 
 	/* Read PHYID register *AFTER* the PHY was reset properly */
 	phyid = asix_get_phyid(dev);
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 969474c..25204d2 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -123,6 +123,7 @@ static void qmimux_setup(struct net_device *dev)
 	dev->addr_len        = 0;
 	dev->flags           = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
 	dev->netdev_ops      = &qmimux_netdev_ops;
+	dev->mtu             = 1500;
 	dev->needs_free_netdev = true;
 }
 
@@ -151,17 +152,18 @@ static bool qmimux_has_slaves(struct usbnet *dev)
 
 static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
-	unsigned int len, offset = sizeof(struct qmimux_hdr);
+	unsigned int len, offset = 0;
 	struct qmimux_hdr *hdr;
 	struct net_device *net;
 	struct sk_buff *skbn;
+	u8 qmimux_hdr_sz = sizeof(*hdr);
 
-	while (offset < skb->len) {
-		hdr = (struct qmimux_hdr *)skb->data;
+	while (offset + qmimux_hdr_sz < skb->len) {
+		hdr = (struct qmimux_hdr *)(skb->data + offset);
 		len = be16_to_cpu(hdr->pkt_len);
 
 		/* drop the packet, bogus length */
-		if (offset + len > skb->len)
+		if (offset + len + qmimux_hdr_sz > skb->len)
 			return 0;
 
 		/* control packet, we do not know what to do */
@@ -176,7 +178,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 			return 0;
 		skbn->dev = net;
 
-		switch (skb->data[offset] & 0xf0) {
+		switch (skb->data[offset + qmimux_hdr_sz] & 0xf0) {
 		case 0x40:
 			skbn->protocol = htons(ETH_P_IP);
 			break;
@@ -188,12 +190,12 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 			goto skip;
 		}
 
-		skb_put_data(skbn, skb->data + offset, len);
+		skb_put_data(skbn, skb->data + offset + qmimux_hdr_sz, len);
 		if (netif_rx(skbn) != NET_RX_SUCCESS)
 			return 0;
 
 skip:
-		offset += len + sizeof(struct qmimux_hdr);
+		offset += len + qmimux_hdr_sz;
 	}
 	return 1;
 }
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 2f65975..fc48da1 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1295,6 +1295,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
 		dev->net->features |= NETIF_F_RXCSUM;
 
 	dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+	set_bit(EVENT_NO_IP_ALIGN, &dev->flags);
 
 	smsc95xx_init_mac_address(dev);
 
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 32fc695..e35903c 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -329,7 +329,9 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
 
 	flags = u64_stats_update_begin_irqsave(&stats64->syncp);
 	stats64->rx_packets++;
+	dev->net->stats.rx_packets++;
 	stats64->rx_bytes += skb->len;
+	dev->net->stats.rx_bytes += skb->len;
 	u64_stats_update_end_irqrestore(&stats64->syncp, flags);
 
 	netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n",
@@ -1255,7 +1257,9 @@ static void tx_complete (struct urb *urb)
 
 		flags = u64_stats_update_begin_irqsave(&stats64->syncp);
 		stats64->tx_packets += entry->packets;
+		dev->net->stats.tx_packets += entry->packets;
 		stats64->tx_bytes += entry->length;
+		dev->net->stats.tx_bytes += entry->length;
 		u64_stats_update_end_irqrestore(&stats64->syncp, flags);
 	} else {
 		dev->net->stats.tx_errors++;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 215696f..0b457c8 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1149,6 +1149,16 @@ static void free_old_xmit_skbs(struct send_queue *sq)
 	u64_stats_update_end(&stats->tx_syncp);
 }
 
+static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
+{
+	if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
+		return false;
+	else if (q < vi->curr_queue_pairs)
+		return true;
+	else
+		return false;
+}
+
 static void virtnet_poll_cleantx(struct receive_queue *rq)
 {
 	struct virtnet_info *vi = rq->vq->vdev->priv;
@@ -1156,7 +1166,7 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
 	struct send_queue *sq = &vi->sq[index];
 	struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, index);
 
-	if (!sq->napi.weight)
+	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
 		return;
 
 	if (__netif_tx_trylock(txq)) {
@@ -1206,8 +1216,16 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
 {
 	struct send_queue *sq = container_of(napi, struct send_queue, napi);
 	struct virtnet_info *vi = sq->vq->vdev->priv;
-	struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, vq2txq(sq->vq));
+	unsigned int index = vq2txq(sq->vq);
+	struct netdev_queue *txq;
 
+	if (unlikely(is_xdp_raw_buffer_queue(vi, index))) {
+		/* We don't need to enable cb for XDP */
+		napi_complete_done(napi, 0);
+		return 0;
+	}
+
+	txq = netdev_get_tx_queue(vi->dev, index);
 	__netif_tx_lock(txq, raw_smp_processor_id());
 	free_old_xmit_skbs(sq);
 	__netif_tx_unlock(txq);
@@ -2006,14 +2024,17 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
 	}
 
 	/* Make sure NAPI is not using any XDP TX queues for RX. */
-	if (netif_running(dev))
-		for (i = 0; i < vi->max_queue_pairs; i++)
+	if (netif_running(dev)) {
+		for (i = 0; i < vi->max_queue_pairs; i++) {
 			napi_disable(&vi->rq[i].napi);
+			virtnet_napi_tx_disable(&vi->sq[i].napi);
+		}
+	}
 
-	netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
 	err = _virtnet_set_queues(vi, curr_qp + xdp_qp);
 	if (err)
 		goto err;
+	netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
 	vi->xdp_queue_pairs = xdp_qp;
 
 	for (i = 0; i < vi->max_queue_pairs; i++) {
@@ -2027,15 +2048,23 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
 		}
 		if (old_prog)
 			bpf_prog_put(old_prog);
-		if (netif_running(dev))
+		if (netif_running(dev)) {
 			virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+			virtnet_napi_tx_enable(vi, vi->sq[i].vq,
+					       &vi->sq[i].napi);
+		}
 	}
 
 	return 0;
 
 err:
-	for (i = 0; i < vi->max_queue_pairs; i++)
-		virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+	if (netif_running(dev)) {
+		for (i = 0; i < vi->max_queue_pairs; i++) {
+			virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+			virtnet_napi_tx_enable(vi, vi->sq[i].vq,
+					       &vi->sq[i].napi);
+		}
+	}
 	if (prog)
 		bpf_prog_sub(prog, vi->max_queue_pairs - 1);
 	return err;
@@ -2176,16 +2205,6 @@ static void free_receive_page_frags(struct virtnet_info *vi)
 			put_page(vi->rq[i].alloc_frag.page);
 }
 
-static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
-{
-	if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
-		return false;
-	else if (q < vi->curr_queue_pairs)
-		return true;
-	else
-		return false;
-}
-
 static void free_unused_bufs(struct virtnet_info *vi)
 {
 	void *buf;
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 13d39a7..a1b40b9 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2002,7 +2002,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
 	struct pcpu_sw_netstats *tx_stats, *rx_stats;
 	union vxlan_addr loopback;
 	union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip;
-	struct net_device *dev = skb->dev;
+	struct net_device *dev;
 	int len = skb->len;
 
 	tx_stats = this_cpu_ptr(src_vxlan->dev->tstats);
@@ -2022,9 +2022,15 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
 #endif
 	}
 
+	rcu_read_lock();
+	dev = skb->dev;
+	if (unlikely(!(dev->flags & IFF_UP))) {
+		kfree_skb(skb);
+		goto drop;
+	}
+
 	if (dst_vxlan->cfg.flags & VXLAN_F_LEARN)
-		vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, 0,
-			    vni);
+		vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni);
 
 	u64_stats_update_begin(&tx_stats->syncp);
 	tx_stats->tx_packets++;
@@ -2037,8 +2043,10 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
 		rx_stats->rx_bytes += len;
 		u64_stats_update_end(&rx_stats->syncp);
 	} else {
+drop:
 		dev->stats.rx_dropped++;
 	}
+	rcu_read_unlock();
 }
 
 static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index cf07671..f9339b5 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -272,7 +272,7 @@ struct ath_node {
 #endif
 	u8 key_idx[4];
 
-	u32 ackto;
+	int ackto;
 	struct list_head list;
 };
 
diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c
index 7334c9b0..6e236a4 100644
--- a/drivers/net/wireless/ath/ath9k/dynack.c
+++ b/drivers/net/wireless/ath/ath9k/dynack.c
@@ -29,9 +29,13 @@
  * ath_dynack_ewma - EWMA (Exponentially Weighted Moving Average) calculation
  *
  */
-static inline u32 ath_dynack_ewma(u32 old, u32 new)
+static inline int ath_dynack_ewma(int old, int new)
 {
-	return (new * (EWMA_DIV - EWMA_LEVEL) + old * EWMA_LEVEL) / EWMA_DIV;
+	if (old > 0)
+		return (new * (EWMA_DIV - EWMA_LEVEL) +
+			old * EWMA_LEVEL) / EWMA_DIV;
+	else
+		return new;
 }
 
 /**
@@ -82,10 +86,10 @@ static inline bool ath_dynack_bssidmask(struct ath_hw *ah, const u8 *mac)
  */
 static void ath_dynack_compute_ackto(struct ath_hw *ah)
 {
-	struct ath_node *an;
-	u32 to = 0;
-	struct ath_dynack *da = &ah->dynack;
 	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath_dynack *da = &ah->dynack;
+	struct ath_node *an;
+	int to = 0;
 
 	list_for_each_entry(an, &da->nodes, list)
 		if (an->ackto > to)
@@ -144,7 +148,8 @@ static void ath_dynack_compute_to(struct ath_hw *ah)
 					an->ackto = ath_dynack_ewma(an->ackto,
 								    ackto);
 					ath_dbg(ath9k_hw_common(ah), DYNACK,
-						"%pM to %u\n", dst, an->ackto);
+						"%pM to %d [%u]\n", dst,
+						an->ackto, ackto);
 					if (time_is_before_jiffies(da->lto)) {
 						ath_dynack_compute_ackto(ah);
 						da->lto = jiffies + COMPUTE_TO;
@@ -166,10 +171,12 @@ static void ath_dynack_compute_to(struct ath_hw *ah)
  * @ah: ath hw
  * @skb: socket buffer
  * @ts: tx status info
+ * @sta: station pointer
  *
  */
 void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
-			     struct ath_tx_status *ts)
+			     struct ath_tx_status *ts,
+			     struct ieee80211_sta *sta)
 {
 	u8 ridx;
 	struct ieee80211_hdr *hdr;
@@ -177,7 +184,7 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
-	if ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !da->enabled)
+	if (!da->enabled || (info->flags & IEEE80211_TX_CTL_NO_ACK))
 		return;
 
 	spin_lock_bh(&da->qlock);
@@ -187,11 +194,19 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
 	/* late ACK */
 	if (ts->ts_status & ATH9K_TXERR_XRETRY) {
 		if (ieee80211_is_assoc_req(hdr->frame_control) ||
-		    ieee80211_is_assoc_resp(hdr->frame_control)) {
+		    ieee80211_is_assoc_resp(hdr->frame_control) ||
+		    ieee80211_is_auth(hdr->frame_control)) {
 			ath_dbg(common, DYNACK, "late ack\n");
+
 			ath9k_hw_setslottime(ah, (LATEACK_TO - 3) / 2);
 			ath9k_hw_set_ack_timeout(ah, LATEACK_TO);
 			ath9k_hw_set_cts_timeout(ah, LATEACK_TO);
+			if (sta) {
+				struct ath_node *an;
+
+				an = (struct ath_node *)sta->drv_priv;
+				an->ackto = -1;
+			}
 			da->lto = jiffies + LATEACK_DELAY;
 		}
 
@@ -251,7 +266,7 @@ void ath_dynack_sample_ack_ts(struct ath_hw *ah, struct sk_buff *skb,
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
-	if (!ath_dynack_bssidmask(ah, hdr->addr1) || !da->enabled)
+	if (!da->enabled || !ath_dynack_bssidmask(ah, hdr->addr1))
 		return;
 
 	spin_lock_bh(&da->qlock);
diff --git a/drivers/net/wireless/ath/ath9k/dynack.h b/drivers/net/wireless/ath/ath9k/dynack.h
index 6d7bef9..cf60224 100644
--- a/drivers/net/wireless/ath/ath9k/dynack.h
+++ b/drivers/net/wireless/ath/ath9k/dynack.h
@@ -86,7 +86,8 @@ void ath_dynack_node_deinit(struct ath_hw *ah, struct ath_node *an);
 void ath_dynack_init(struct ath_hw *ah);
 void ath_dynack_sample_ack_ts(struct ath_hw *ah, struct sk_buff *skb, u32 ts);
 void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
-			     struct ath_tx_status *ts);
+			     struct ath_tx_status *ts,
+			     struct ieee80211_sta *sta);
 #else
 static inline void ath_dynack_init(struct ath_hw *ah) {}
 static inline void ath_dynack_node_init(struct ath_hw *ah,
@@ -97,7 +98,8 @@ static inline void ath_dynack_sample_ack_ts(struct ath_hw *ah,
 					    struct sk_buff *skb, u32 ts) {}
 static inline void ath_dynack_sample_tx_ts(struct ath_hw *ah,
 					   struct sk_buff *skb,
-					   struct ath_tx_status *ts) {}
+					   struct ath_tx_status *ts,
+					   struct ieee80211_sta *sta) {}
 #endif
 
 #endif /* DYNACK_H */
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index fa64c1c..458c4f5 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -621,7 +621,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 				if (bf == bf->bf_lastbf)
 					ath_dynack_sample_tx_ts(sc->sc_ah,
 								bf->bf_mpdu,
-								ts);
+								ts, sta);
 			}
 
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, sta, ts,
@@ -765,7 +765,8 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
 			memcpy(info->control.rates, bf->rates,
 			       sizeof(info->control.rates));
 			ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
-			ath_dynack_sample_tx_ts(sc->sc_ah, bf->bf_mpdu, ts);
+			ath_dynack_sample_tx_ts(sc->sc_ah, bf->bf_mpdu, ts,
+						sta);
 		}
 		ath_tx_complete_buf(sc, bf, txq, bf_head, sta, ts, txok);
 	} else
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index a58fccb..86bc999 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -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
@@ -296,21 +296,24 @@ void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
 static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
 {
 	struct wil6210_priv *wil = cookie;
-	u32 isr = wil_ioread32_and_clear(wil->csr +
-					 HOSTADDR(RGF_DMA_EP_RX_ICR) +
-					 offsetof(struct RGF_ICR, ICR));
+	u32 isr;
 	bool need_unmask = true;
 
+	wil6210_mask_irq_rx(wil);
+
+	isr = wil_ioread32_and_clear(wil->csr +
+				     HOSTADDR(RGF_DMA_EP_RX_ICR) +
+				     offsetof(struct RGF_ICR, ICR));
+
 	trace_wil6210_irq_rx(isr);
 	wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
 
 	if (unlikely(!isr)) {
 		wil_err_ratelimited(wil, "spurious IRQ: RX\n");
+		wil6210_unmask_irq_rx(wil);
 		return IRQ_NONE;
 	}
 
-	wil6210_mask_irq_rx(wil);
-
 	/* RX_DONE and RX_HTRSH interrupts are the same if interrupt
 	 * moderation is not used. Interrupt moderation may cause RX
 	 * buffer overflow while RX_DONE is delayed. The required
@@ -355,21 +358,24 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
 static irqreturn_t wil6210_irq_rx_edma(int irq, void *cookie)
 {
 	struct wil6210_priv *wil = cookie;
-	u32 isr = wil_ioread32_and_clear(wil->csr +
-					 HOSTADDR(RGF_INT_GEN_RX_ICR) +
-					 offsetof(struct RGF_ICR, ICR));
+	u32 isr;
 	bool need_unmask = true;
 
+	wil6210_mask_irq_rx_edma(wil);
+
+	isr = wil_ioread32_and_clear(wil->csr +
+				     HOSTADDR(RGF_INT_GEN_RX_ICR) +
+				     offsetof(struct RGF_ICR, ICR));
+
 	trace_wil6210_irq_rx(isr);
 	wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
 
 	if (unlikely(!isr)) {
 		wil_err(wil, "spurious IRQ: RX\n");
+		wil6210_unmask_irq_rx_edma(wil);
 		return IRQ_NONE;
 	}
 
-	wil6210_mask_irq_rx_edma(wil);
-
 	if (likely(isr & BIT_RX_STATUS_IRQ)) {
 		wil_dbg_irq(wil, "RX status ring\n");
 		isr &= ~BIT_RX_STATUS_IRQ;
@@ -403,21 +409,24 @@ static irqreturn_t wil6210_irq_rx_edma(int irq, void *cookie)
 static irqreturn_t wil6210_irq_tx_edma(int irq, void *cookie)
 {
 	struct wil6210_priv *wil = cookie;
-	u32 isr = wil_ioread32_and_clear(wil->csr +
-					 HOSTADDR(RGF_INT_GEN_TX_ICR) +
-					 offsetof(struct RGF_ICR, ICR));
+	u32 isr;
 	bool need_unmask = true;
 
+	wil6210_mask_irq_tx_edma(wil);
+
+	isr = wil_ioread32_and_clear(wil->csr +
+				     HOSTADDR(RGF_INT_GEN_TX_ICR) +
+				     offsetof(struct RGF_ICR, ICR));
+
 	trace_wil6210_irq_tx(isr);
 	wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
 
 	if (unlikely(!isr)) {
 		wil_err(wil, "spurious IRQ: TX\n");
+		wil6210_unmask_irq_tx_edma(wil);
 		return IRQ_NONE;
 	}
 
-	wil6210_mask_irq_tx_edma(wil);
-
 	if (likely(isr & BIT_TX_STATUS_IRQ)) {
 		wil_dbg_irq(wil, "TX status ring\n");
 		isr &= ~BIT_TX_STATUS_IRQ;
@@ -446,21 +455,24 @@ static irqreturn_t wil6210_irq_tx_edma(int irq, void *cookie)
 static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
 {
 	struct wil6210_priv *wil = cookie;
-	u32 isr = wil_ioread32_and_clear(wil->csr +
-					 HOSTADDR(RGF_DMA_EP_TX_ICR) +
-					 offsetof(struct RGF_ICR, ICR));
+	u32 isr;
 	bool need_unmask = true;
 
+	wil6210_mask_irq_tx(wil);
+
+	isr = wil_ioread32_and_clear(wil->csr +
+				     HOSTADDR(RGF_DMA_EP_TX_ICR) +
+				     offsetof(struct RGF_ICR, ICR));
+
 	trace_wil6210_irq_tx(isr);
 	wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
 
 	if (unlikely(!isr)) {
 		wil_err_ratelimited(wil, "spurious IRQ: TX\n");
+		wil6210_unmask_irq_tx(wil);
 		return IRQ_NONE;
 	}
 
-	wil6210_mask_irq_tx(wil);
-
 	if (likely(isr & BIT_DMA_EP_TX_ICR_TX_DONE)) {
 		wil_dbg_irq(wil, "TX done\n");
 		isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
@@ -532,20 +544,23 @@ static bool wil_validate_mbox_regs(struct wil6210_priv *wil)
 static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
 {
 	struct wil6210_priv *wil = cookie;
-	u32 isr = wil_ioread32_and_clear(wil->csr +
-					 HOSTADDR(RGF_DMA_EP_MISC_ICR) +
-					 offsetof(struct RGF_ICR, ICR));
+	u32 isr;
+
+	wil6210_mask_irq_misc(wil, false);
+
+	isr = wil_ioread32_and_clear(wil->csr +
+				     HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+				     offsetof(struct RGF_ICR, ICR));
 
 	trace_wil6210_irq_misc(isr);
 	wil_dbg_irq(wil, "ISR MISC 0x%08x\n", isr);
 
 	if (!isr) {
 		wil_err(wil, "spurious IRQ: MISC\n");
+		wil6210_unmask_irq_misc(wil, false);
 		return IRQ_NONE;
 	}
 
-	wil6210_mask_irq_misc(wil, false);
-
 	if (isr & ISR_MISC_FW_ERROR) {
 		u32 fw_assert_code = wil_r(wil, wil->rgf_fw_assert_code_addr);
 		u32 ucode_assert_code =
@@ -580,7 +595,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
 			/* no need to handle HALP ICRs until next vote */
 			atomic_set(&wil->halp.handle_icr, 0);
 			wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
-			wil6210_mask_halp(wil);
+			wil6210_mask_irq_misc(wil, true);
 			complete(&wil->halp.comp);
 		}
 	}
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c
index 91d86f8..1125598 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.c
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c
@@ -270,6 +270,9 @@ static void wil_move_all_rx_buff_to_free_list(struct wil6210_priv *wil,
 	struct list_head *active = &wil->rx_buff_mgmt.active;
 	dma_addr_t pa;
 
+	if (!wil->rx_buff_mgmt.buff_arr)
+		return;
+
 	while (!list_empty(active)) {
 		struct wil_rx_buff *rx_buff =
 			list_first_entry(active, struct wil_rx_buff, list);
diff --git a/drivers/net/wireless/broadcom/b43/phy_common.c b/drivers/net/wireless/broadcom/b43/phy_common.c
index 85f2ca9..ef3ffa5 100644
--- a/drivers/net/wireless/broadcom/b43/phy_common.c
+++ b/drivers/net/wireless/broadcom/b43/phy_common.c
@@ -616,7 +616,7 @@ struct b43_c32 b43_cordic(int theta)
 	u8 i;
 	s32 tmp;
 	s8 signx = 1;
-	u32 angle = 0;
+	s32 angle = 0;
 	struct b43_c32 ret = { .i = 39797, .q = 0, };
 
 	while (theta > (180 << 16))
diff --git a/drivers/net/wireless/cnss2/Makefile b/drivers/net/wireless/cnss2/Makefile
index fe0f595..52d0aa0 100644
--- a/drivers/net/wireless/cnss2/Makefile
+++ b/drivers/net/wireless/cnss2/Makefile
@@ -4,5 +4,7 @@
 cnss2-y += bus.o
 cnss2-y += debug.o
 cnss2-y += pci.o
+cnss2-y += usb.o
 cnss2-y += power.o
+cnss2-$(CONFIG_CNSS2_DEBUG) += genl.o
 cnss2-$(CONFIG_CNSS2_QMI) += qmi.o wlan_firmware_service_v01.o
diff --git a/drivers/net/wireless/cnss2/bus.c b/drivers/net/wireless/cnss2/bus.c
index da06a9c..7453d42 100644
--- a/drivers/net/wireless/cnss2/bus.c
+++ b/drivers/net/wireless/cnss2/bus.c
@@ -13,6 +13,7 @@
 #include "bus.h"
 #include "debug.h"
 #include "pci.h"
+#include "usb.h"
 
 enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev)
 {
@@ -53,6 +54,10 @@ enum cnss_dev_bus_type cnss_get_bus_type(struct cnss_plat_data *plat_priv)
 	case QCA6390_DEVICE_ID:
 		bus_type = CNSS_BUS_PCI;
 		break;
+	case QCN7605_COMPOSITE_DEVICE_ID:
+	case QCN7605_STANDALONE_DEVICE_ID:
+		bus_type = CNSS_BUS_USB;
+		break;
 	default:
 		cnss_pr_err("Unknown device: 0x%lx\n", plat_priv->device_id);
 		break;
@@ -61,6 +66,14 @@ enum cnss_dev_bus_type cnss_get_bus_type(struct cnss_plat_data *plat_priv)
 	return bus_type;
 }
 
+bool cnss_bus_req_mem_ind_valid(struct cnss_plat_data *plat_priv)
+{
+	if (cnss_get_bus_type(plat_priv) == CNSS_BUS_USB)
+		return false;
+	else
+		return true;
+}
+
 void *cnss_bus_dev_to_bus_priv(struct device *dev)
 {
 	if (!dev)
@@ -88,6 +101,8 @@ struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev)
 	switch (cnss_get_dev_bus_type(dev)) {
 	case CNSS_BUS_PCI:
 		return cnss_pci_priv_to_plat_priv(bus_priv);
+	case CNSS_BUS_USB:
+		return cnss_usb_priv_to_plat_priv(bus_priv);
 	default:
 		return NULL;
 	}
@@ -101,6 +116,8 @@ int cnss_bus_init(struct cnss_plat_data *plat_priv)
 	switch (plat_priv->bus_type) {
 	case CNSS_BUS_PCI:
 		return cnss_pci_init(plat_priv);
+	case CNSS_BUS_USB:
+		return cnss_usb_init(plat_priv);
 	default:
 		cnss_pr_err("Unsupported bus type: %d\n",
 			    plat_priv->bus_type);
@@ -116,6 +133,8 @@ void cnss_bus_deinit(struct cnss_plat_data *plat_priv)
 	switch (plat_priv->bus_type) {
 	case CNSS_BUS_PCI:
 		cnss_pci_deinit(plat_priv);
+	case CNSS_BUS_USB:
+		cnss_usb_deinit(plat_priv);
 	default:
 		cnss_pr_err("Unsupported bus type: %d\n",
 			    plat_priv->bus_type);
@@ -153,6 +172,37 @@ int cnss_bus_alloc_fw_mem(struct cnss_plat_data *plat_priv)
 	}
 }
 
+int cnss_bus_alloc_qdss_mem(struct cnss_plat_data *plat_priv)
+{
+	if (!plat_priv)
+		return -ENODEV;
+
+	switch (plat_priv->bus_type) {
+	case CNSS_BUS_PCI:
+		return cnss_pci_alloc_qdss_mem(plat_priv->bus_priv);
+	default:
+		cnss_pr_err("Unsupported bus type: %d\n",
+			    plat_priv->bus_type);
+		return -EINVAL;
+	}
+}
+
+void cnss_bus_free_qdss_mem(struct cnss_plat_data *plat_priv)
+{
+	if (!plat_priv)
+		return;
+
+	switch (plat_priv->bus_type) {
+	case CNSS_BUS_PCI:
+		cnss_pci_free_qdss_mem(plat_priv->bus_priv);
+		return;
+	default:
+		cnss_pr_err("Unsupported bus type: %d\n",
+			    plat_priv->bus_type);
+		return;
+	}
+}
+
 u32 cnss_bus_get_wake_irq(struct cnss_plat_data *plat_priv)
 {
 	if (!plat_priv)
@@ -224,6 +274,8 @@ int cnss_bus_call_driver_probe(struct cnss_plat_data *plat_priv)
 	switch (plat_priv->bus_type) {
 	case CNSS_BUS_PCI:
 		return cnss_pci_call_driver_probe(plat_priv->bus_priv);
+	case CNSS_BUS_USB:
+		return cnss_usb_call_driver_probe(plat_priv->bus_priv);
 	default:
 		cnss_pr_err("Unsupported bus type: %d\n",
 			    plat_priv->bus_type);
@@ -239,6 +291,8 @@ int cnss_bus_call_driver_remove(struct cnss_plat_data *plat_priv)
 	switch (plat_priv->bus_type) {
 	case CNSS_BUS_PCI:
 		return cnss_pci_call_driver_remove(plat_priv->bus_priv);
+	case CNSS_BUS_USB:
+		return cnss_usb_call_driver_remove(plat_priv->bus_priv);
 	default:
 		cnss_pr_err("Unsupported bus type: %d\n",
 			    plat_priv->bus_type);
@@ -254,6 +308,8 @@ int cnss_bus_dev_powerup(struct cnss_plat_data *plat_priv)
 	switch (plat_priv->bus_type) {
 	case CNSS_BUS_PCI:
 		return cnss_pci_dev_powerup(plat_priv->bus_priv);
+	case CNSS_BUS_USB:
+		return 0;
 	default:
 		cnss_pr_err("Unsupported bus type: %d\n",
 			    plat_priv->bus_type);
@@ -269,6 +325,8 @@ int cnss_bus_dev_shutdown(struct cnss_plat_data *plat_priv)
 	switch (plat_priv->bus_type) {
 	case CNSS_BUS_PCI:
 		return cnss_pci_dev_shutdown(plat_priv->bus_priv);
+	case CNSS_BUS_USB:
+		return 0;
 	default:
 		cnss_pr_err("Unsupported bus type: %d\n",
 			    plat_priv->bus_type);
@@ -314,6 +372,8 @@ int cnss_bus_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data)
 	switch (plat_priv->bus_type) {
 	case CNSS_BUS_PCI:
 		return cnss_pci_register_driver_hdlr(plat_priv->bus_priv, data);
+	case CNSS_BUS_USB:
+		return cnss_usb_register_driver_hdlr(plat_priv->bus_priv, data);
 	default:
 		cnss_pr_err("Unsupported bus type: %d\n",
 			    plat_priv->bus_type);
@@ -329,6 +389,8 @@ int cnss_bus_unregister_driver_hdlr(struct cnss_plat_data *plat_priv)
 	switch (plat_priv->bus_type) {
 	case CNSS_BUS_PCI:
 		return cnss_pci_unregister_driver_hdlr(plat_priv->bus_priv);
+	case CNSS_BUS_USB:
+		return cnss_usb_unregister_driver_hdlr(plat_priv->bus_priv);
 	default:
 		cnss_pr_err("Unsupported bus type: %d\n",
 			    plat_priv->bus_type);
diff --git a/drivers/net/wireless/cnss2/bus.h b/drivers/net/wireless/cnss2/bus.h
index 81627be..a812672 100644
--- a/drivers/net/wireless/cnss2/bus.h
+++ b/drivers/net/wireless/cnss2/bus.h
@@ -24,6 +24,15 @@
 #define QCA6290_DEVICE_ID		0x1100
 #define QCA6390_VENDOR_ID		0x17CB
 #define QCA6390_DEVICE_ID		0x1101
+#define QCN7605_VENDOR_ID               0x17CB
+#define QCN7605_DEVICE_ID               0x1102
+
+#define QCN7605_USB_VENDOR_ID             0x05C6
+#define QCN7605_STANDALONE_PRODUCT_ID    0x9900
+#define QCN7605_COMPOSITE_PRODUCT_ID     0x9901
+
+#define QCN7605_COMPOSITE_DEVICE_ID     QCN7605_COMPOSITE_PRODUCT_ID
+#define QCN7605_STANDALONE_DEVICE_ID    QCN7605_STANDALONE_PRODUCT_ID
 
 enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
 enum cnss_dev_bus_type cnss_get_bus_type(struct cnss_plat_data *plat_priv);
@@ -33,6 +42,8 @@ int cnss_bus_init(struct cnss_plat_data *plat_priv);
 void cnss_bus_deinit(struct cnss_plat_data *plat_priv);
 int cnss_bus_load_m3(struct cnss_plat_data *plat_priv);
 int cnss_bus_alloc_fw_mem(struct cnss_plat_data *plat_priv);
+int cnss_bus_alloc_qdss_mem(struct cnss_plat_data *plat_priv);
+void cnss_bus_free_qdss_mem(struct cnss_plat_data *plat_priv);
 u32 cnss_bus_get_wake_irq(struct cnss_plat_data *plat_priv);
 int cnss_bus_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv);
 void cnss_bus_fw_boot_timeout_hdlr(unsigned long data);
@@ -50,5 +61,5 @@ int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv,
 				      int modem_current_status);
 int cnss_bus_update_status(struct cnss_plat_data *plat_priv,
 			   enum cnss_driver_status status);
-
+bool cnss_bus_req_mem_ind_valid(struct cnss_plat_data *plat_priv);
 #endif /* _CNSS_BUS_H */
diff --git a/drivers/net/wireless/cnss2/debug.h b/drivers/net/wireless/cnss2/debug.h
index 33095af..f0bf270 100644
--- a/drivers/net/wireless/cnss2/debug.h
+++ b/drivers/net/wireless/cnss2/debug.h
@@ -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
@@ -63,6 +63,9 @@ extern void *cnss_ipc_log_context;
 	} while (0)
 #endif
 
+#define cnss_fatal_err(_fmt, ...)					\
+	cnss_pr_err("fatal: " _fmt, ##__VA_ARGS__)
+
 int cnss_debug_init(void);
 void cnss_debug_deinit(void);
 int cnss_debugfs_create(struct cnss_plat_data *plat_priv);
diff --git a/drivers/net/wireless/cnss2/genl.c b/drivers/net/wireless/cnss2/genl.c
new file mode 100644
index 0000000..5fb9466
--- /dev/null
+++ b/drivers/net/wireless/cnss2/genl.c
@@ -0,0 +1,212 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt) "cnss_genl: " fmt
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include "main.h"
+#include "debug.h"
+
+#define CNSS_GENL_FAMILY_NAME "cnss-genl"
+#define CNSS_GENL_MCAST_GROUP_NAME "cnss-genl-grp"
+#define CNSS_GENL_VERSION 1
+#define CNSS_GENL_DATA_LEN_MAX (15 * 1024)
+#define CNSS_GENL_STR_LEN_MAX 16
+
+enum {
+	CNSS_GENL_ATTR_MSG_UNSPEC,
+	CNSS_GENL_ATTR_MSG_TYPE,
+	CNSS_GENL_ATTR_MSG_FILE_NAME,
+	CNSS_GENL_ATTR_MSG_TOTAL_SIZE,
+	CNSS_GENL_ATTR_MSG_SEG_ID,
+	CNSS_GENL_ATTR_MSG_END,
+	CNSS_GENL_ATTR_MSG_DATA_LEN,
+	CNSS_GENL_ATTR_MSG_DATA,
+	__CNSS_GENL_ATTR_MAX,
+};
+
+#define CNSS_GENL_ATTR_MAX (__CNSS_GENL_ATTR_MAX - 1)
+
+enum {
+	CNSS_GENL_CMD_UNSPEC,
+	CNSS_GENL_CMD_MSG,
+	__CNSS_GENL_CMD_MAX,
+};
+
+#define CNSS_GENL_CMD_MAX (__CNSS_GENL_CMD_MAX - 1)
+
+static struct nla_policy cnss_genl_msg_policy[CNSS_GENL_ATTR_MAX + 1] = {
+	[CNSS_GENL_ATTR_MSG_TYPE] = { .type = NLA_U8 },
+	[CNSS_GENL_ATTR_MSG_FILE_NAME] = { .type = NLA_NUL_STRING,
+					   .len = CNSS_GENL_STR_LEN_MAX },
+	[CNSS_GENL_ATTR_MSG_TOTAL_SIZE] = { .type = NLA_U32 },
+	[CNSS_GENL_ATTR_MSG_SEG_ID] = { .type = NLA_U32 },
+	[CNSS_GENL_ATTR_MSG_END] = { .type = NLA_U8 },
+	[CNSS_GENL_ATTR_MSG_DATA_LEN] = { .type = NLA_U32 },
+	[CNSS_GENL_ATTR_MSG_DATA] = { .type = NLA_BINARY,
+				      .len = CNSS_GENL_DATA_LEN_MAX },
+};
+
+static int cnss_genl_process_msg(struct sk_buff *skb, struct genl_info *info)
+{
+	return 0;
+}
+
+static struct genl_ops cnss_genl_ops[] = {
+	{
+		.cmd = CNSS_GENL_CMD_MSG,
+		.policy = cnss_genl_msg_policy,
+		.doit = cnss_genl_process_msg,
+	},
+};
+
+static struct genl_multicast_group cnss_genl_mcast_grp[] = {
+	{
+		.name = CNSS_GENL_MCAST_GROUP_NAME,
+	},
+};
+
+static struct genl_family cnss_genl_family = {
+	.id = 0,
+	.hdrsize = 0,
+	.name = CNSS_GENL_FAMILY_NAME,
+	.version = CNSS_GENL_VERSION,
+	.maxattr = CNSS_GENL_ATTR_MAX,
+	.module = THIS_MODULE,
+	.ops = cnss_genl_ops,
+	.n_ops = ARRAY_SIZE(cnss_genl_ops),
+	.mcgrps = cnss_genl_mcast_grp,
+	.n_mcgrps = ARRAY_SIZE(cnss_genl_mcast_grp),
+};
+
+static int cnss_genl_send_data(u8 type, char *file_name, u32 total_size,
+			       u32 seg_id, u8 end, u32 data_len, u8 *msg_buff)
+{
+	struct sk_buff *skb = NULL;
+	void *msg_header = NULL;
+	int ret = 0;
+	char filename[CNSS_GENL_STR_LEN_MAX + 1];
+
+	cnss_pr_dbg("type: %u, file_name %s, total_size: %x, seg_id %u, end %u, data_len %u\n",
+		    type, file_name, total_size, seg_id, end, data_len);
+
+	if (!file_name)
+		strlcpy(filename, "default", sizeof(filename));
+	else
+		strlcpy(filename, file_name, sizeof(filename));
+
+	skb = genlmsg_new(NLMSG_HDRLEN +
+			  nla_total_size(sizeof(type)) +
+			  nla_total_size(strlen(filename) + 1) +
+			  nla_total_size(sizeof(total_size)) +
+			  nla_total_size(sizeof(seg_id)) +
+			  nla_total_size(sizeof(end)) +
+			  nla_total_size(sizeof(data_len)) +
+			  nla_total_size(data_len), GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	msg_header = genlmsg_put(skb, 0, 0,
+				 &cnss_genl_family, 0,
+				 CNSS_GENL_CMD_MSG);
+	if (!msg_header) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	ret = nla_put_u8(skb, CNSS_GENL_ATTR_MSG_TYPE, type);
+	if (ret < 0)
+		goto fail;
+	ret = nla_put_string(skb, CNSS_GENL_ATTR_MSG_FILE_NAME, filename);
+	if (ret < 0)
+		goto fail;
+	ret = nla_put_u32(skb, CNSS_GENL_ATTR_MSG_TOTAL_SIZE, total_size);
+	if (ret < 0)
+		goto fail;
+	ret = nla_put_u32(skb, CNSS_GENL_ATTR_MSG_SEG_ID, seg_id);
+	if (ret < 0)
+		goto fail;
+	ret = nla_put_u8(skb, CNSS_GENL_ATTR_MSG_END, end);
+	if (ret < 0)
+		goto fail;
+	ret = nla_put_u32(skb, CNSS_GENL_ATTR_MSG_DATA_LEN, data_len);
+	if (ret < 0)
+		goto fail;
+	ret = nla_put(skb, CNSS_GENL_ATTR_MSG_DATA, data_len, msg_buff);
+	if (ret < 0)
+		goto fail;
+
+	genlmsg_end(skb, msg_header);
+	ret = genlmsg_multicast(&cnss_genl_family, skb, 0, 0, GFP_KERNEL);
+	if (ret < 0)
+		goto fail;
+
+	return ret;
+fail:
+	cnss_pr_err("genl msg send fail: %d\n", ret);
+	if (skb)
+		nlmsg_free(skb);
+	return ret;
+}
+
+int cnss_genl_send_msg(void *buff, u8 type, char *file_name, u32 total_size)
+{
+	int ret = 0;
+	u8 *msg_buff = buff;
+	u32 remaining = total_size;
+	u32 seg_id = 0;
+	u32 data_len = 0;
+	u8 end = 0;
+
+	cnss_pr_dbg("type: %u, total_size: %x\n", type, total_size);
+
+	while (remaining) {
+		if (remaining > CNSS_GENL_DATA_LEN_MAX) {
+			data_len = CNSS_GENL_DATA_LEN_MAX;
+		} else {
+			data_len = remaining;
+			end = 1;
+		}
+		ret = cnss_genl_send_data(type, file_name, total_size,
+					  seg_id, end, data_len, msg_buff);
+		if (ret < 0) {
+			cnss_pr_err("fail to send genl data, ret %d\n", ret);
+			return ret;
+		}
+
+		remaining -= data_len;
+		msg_buff += data_len;
+		seg_id++;
+	}
+
+	return ret;
+}
+
+int cnss_genl_init(void)
+{
+	int ret = 0;
+
+	ret = genl_register_family(&cnss_genl_family);
+	if (ret != 0)
+		cnss_pr_err("genl_register_family fail: %d\n", ret);
+
+	return ret;
+}
+
+void cnss_genl_exit(void)
+{
+	genl_unregister_family(&cnss_genl_family);
+}
diff --git a/drivers/net/wireless/cnss2/genl.h b/drivers/net/wireless/cnss2/genl.h
new file mode 100644
index 0000000..31cc66e9
--- /dev/null
+++ b/drivers/net/wireless/cnss2/genl.h
@@ -0,0 +1,43 @@
+/* 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 __CNSS_GENL_H__
+#define __CNSS_GENL_H__
+
+enum cnss_genl_msg_type {
+	CNSS_GENL_MSG_TYPE_UNSPEC,
+	CNSS_GENL_MSG_TYPE_QDSS,
+};
+
+#ifdef CONFIG_CNSS2_DEBUG
+int cnss_genl_init(void);
+void cnss_genl_exit(void);
+int cnss_genl_send_msg(void *buff, u8 type,
+		       char *file_name, u32 total_size);
+#else
+static inline int cnss_genl_init(void)
+{
+	return 0;
+}
+
+static inline void cnss_genl_exit(void)
+{
+}
+
+static inline int cnss_genl_send_msg(void *buff, u8 type,
+				     char *file_name, u32 total_size)
+{
+	return 0;
+}
+#endif
+
+#endif
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index 29ca1cf..fec3bd4 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -25,6 +25,7 @@
 #include "main.h"
 #include "bus.h"
 #include "debug.h"
+#include "genl.h"
 
 #define CNSS_DUMP_FORMAT_VER		0x11
 #define CNSS_DUMP_FORMAT_VER_V2		0x22
@@ -364,7 +365,10 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
 	if (ret)
 		goto out;
 
-	ret = cnss_wlfw_bdf_dnld_send_sync(plat_priv);
+	cnss_wlfw_bdf_dnld_send_sync(plat_priv, CNSS_BDF_REGDB);
+
+	ret = cnss_wlfw_bdf_dnld_send_sync(plat_priv,
+					   plat_priv->ctrl_params.bdf_type);
 	if (ret)
 		goto out;
 
@@ -427,6 +431,15 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
 	return ret;
 }
 
+static int cnss_cal_update_hdlr(struct cnss_plat_data *plat_priv)
+{
+	/* QCN7605 store the cal data sent by FW to calDB memory area
+	 * get out of this after complete data is uploaded. FW is expected
+	 * to send cal done
+	 */
+	return 0;
+}
+
 static char *cnss_driver_event_to_str(enum cnss_driver_event_type type)
 {
 	switch (type) {
@@ -444,6 +457,10 @@ static char *cnss_driver_event_to_str(enum cnss_driver_event_type type)
 		return "COLD_BOOT_CAL_START";
 	case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE:
 		return "COLD_BOOT_CAL_DONE";
+	case CNSS_DRIVER_EVENT_CAL_UPDATE:
+		return "COLD_BOOT_CAL_DATA_UPDATE";
+	case CNSS_DRIVER_EVENT_CAL_DOWNLOAD:
+		return "COLD_BOOT_CAL_DATA_DOWNLOAD";
 	case CNSS_DRIVER_EVENT_REGISTER_DRIVER:
 		return "REGISTER_DRIVER";
 	case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER:
@@ -456,6 +473,12 @@ static char *cnss_driver_event_to_str(enum cnss_driver_event_type type)
 		return "POWER_UP";
 	case CNSS_DRIVER_EVENT_POWER_DOWN:
 		return "POWER_DOWN";
+	case CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM:
+		return "QDSS_TRACE_REQ_MEM";
+	case CNSS_DRIVER_EVENT_QDSS_TRACE_SAVE:
+		return "QDSS_TRACE_SAVE";
+	case CNSS_DRIVER_EVENT_QDSS_TRACE_FREE:
+		return "QDSS_TRACE_FREE";
 	case CNSS_DRIVER_EVENT_MAX:
 		return "EVENT_MAX";
 	}
@@ -1003,6 +1026,11 @@ int cnss_force_fw_assert(struct device *dev)
 		return -EOPNOTSUPP;
 	}
 
+	if (cnss_pci_is_device_down(dev)) {
+		cnss_pr_info("Device is already in bad state, ignore force assert\n");
+		return 0;
+	}
+
 	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
 		cnss_pr_info("Recovery is already in progress, ignore forced FW assert\n");
 		return 0;
@@ -1016,6 +1044,27 @@ int cnss_force_fw_assert(struct device *dev)
 }
 EXPORT_SYMBOL(cnss_force_fw_assert);
 
+static int cnss_wlfw_server_arrive_hdlr(struct cnss_plat_data *plat_priv,
+					void *data)
+{
+	int ret;
+	unsigned int bdf_type;
+
+	ret = cnss_wlfw_server_arrive(plat_priv, data);
+	if (ret)
+		goto out;
+
+	if (!cnss_bus_req_mem_ind_valid(plat_priv)) {
+		ret = cnss_wlfw_tgt_cap_send_sync(plat_priv);
+		if (ret)
+			goto out;
+		bdf_type = plat_priv->ctrl_params.bdf_type;
+		ret = cnss_wlfw_bdf_dnld_send_sync(plat_priv, bdf_type);
+	}
+out:
+	return ret;
+}
+
 int cnss_force_collect_rddm(struct device *dev)
 {
 	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
@@ -1031,14 +1080,19 @@ int cnss_force_collect_rddm(struct device *dev)
 		return -EOPNOTSUPP;
 	}
 
+	if (cnss_pci_is_device_down(dev)) {
+		cnss_pr_info("Device is already in bad state, ignore force collect rddm\n");
+		return 0;
+	}
+
 	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
 		cnss_pr_info("Recovery is already in progress, ignore forced collect rddm\n");
 		return 0;
 	}
 
-	cnss_driver_event_post(plat_priv,
-			       CNSS_DRIVER_EVENT_FORCE_FW_ASSERT,
-			       0, NULL);
+	ret = cnss_bus_force_fw_assert_hdlr(plat_priv);
+	if (ret)
+		return ret;
 
 	reinit_completion(&plat_priv->rddm_complete);
 	ret = wait_for_completion_timeout
@@ -1081,7 +1135,13 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv)
 
 	plat_priv->cal_done = true;
 	cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF);
+	if (plat_priv->device_id == QCN7605_DEVICE_ID ||
+	    plat_priv->device_id == QCN7605_STANDALONE_DEVICE_ID ||
+	    plat_priv->device_id == QCN7605_COMPOSITE_DEVICE_ID)
+		goto skip_shutdown;
 	cnss_bus_dev_shutdown(plat_priv);
+
+skip_shutdown:
 	complete(&plat_priv->cal_complete);
 	clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
 
@@ -1100,6 +1160,109 @@ static int cnss_power_down_hdlr(struct cnss_plat_data *plat_priv)
 	return 0;
 }
 
+static int cnss_qdss_trace_req_mem_hdlr(struct cnss_plat_data *plat_priv)
+{
+	int ret = 0;
+
+	ret = cnss_bus_alloc_qdss_mem(plat_priv);
+	if (ret < 0)
+		return ret;
+
+	return cnss_wlfw_qdss_trace_mem_info_send_sync(plat_priv);
+}
+
+static void *cnss_qdss_trace_pa_to_va(struct cnss_plat_data *plat_priv,
+				      u64 pa, u32 size, int *seg_id)
+{
+	int i = 0;
+	struct cnss_fw_mem *qdss_mem = plat_priv->qdss_mem;
+	u64 offset = 0;
+	void *va = NULL;
+	u64 local_pa;
+	u32 local_size;
+
+	for (i = 0; i < plat_priv->qdss_mem_seg_len; i++) {
+		local_pa = (u64)qdss_mem[i].pa;
+		local_size = (u32)qdss_mem[i].size;
+		if (pa == local_pa && size <= local_size) {
+			va = qdss_mem[i].va;
+			break;
+		}
+		if (pa > local_pa &&
+		    pa < local_pa + local_size &&
+		    pa + size <= local_pa + local_size) {
+			offset = pa - local_pa;
+			va = qdss_mem[i].va + offset;
+			break;
+		}
+	}
+
+	*seg_id = i;
+	return va;
+}
+
+static int cnss_qdss_trace_save_hdlr(struct cnss_plat_data *plat_priv,
+				     void *data)
+{
+	struct cnss_qmi_event_qdss_trace_save_data *event_data = data;
+	struct cnss_fw_mem *qdss_mem = plat_priv->qdss_mem;
+	int ret = 0;
+	int i;
+	void *va = NULL;
+	u64 pa;
+	u32 size;
+	int seg_id = 0;
+
+	if (!plat_priv->qdss_mem_seg_len) {
+		cnss_pr_err("Memory for QDSS trace is not available\n");
+		return -ENOMEM;
+	}
+
+	if (event_data->mem_seg_len == 0) {
+		for (i = 0; i < plat_priv->qdss_mem_seg_len; i++) {
+			ret = cnss_genl_send_msg(qdss_mem[i].va,
+						 CNSS_GENL_MSG_TYPE_QDSS,
+						 event_data->file_name,
+						 qdss_mem[i].size);
+			if (ret < 0) {
+				cnss_pr_err("Fail to save QDSS data: %d\n",
+					    ret);
+				break;
+			}
+		}
+	} else {
+		for (i = 0; i < event_data->mem_seg_len; i++) {
+			pa = event_data->mem_seg[i].addr;
+			size = event_data->mem_seg[i].size;
+			va = cnss_qdss_trace_pa_to_va(plat_priv, pa,
+						      size, &seg_id);
+			if (!va) {
+				cnss_pr_err("Fail to find matching va for pa %pa\n",
+					    pa);
+				ret = -EINVAL;
+				break;
+			}
+			ret = cnss_genl_send_msg(va, CNSS_GENL_MSG_TYPE_QDSS,
+						 event_data->file_name, size);
+			if (ret < 0) {
+				cnss_pr_err("Fail to save QDSS data: %d\n",
+					    ret);
+				break;
+			}
+		}
+	}
+
+	kfree(data);
+	return ret;
+}
+
+static int cnss_qdss_trace_free_hdlr(struct cnss_plat_data *plat_priv)
+{
+	cnss_bus_free_qdss_mem(plat_priv);
+
+	return 0;
+}
+
 static void cnss_driver_event_work(struct work_struct *work)
 {
 	struct cnss_plat_data *plat_priv =
@@ -1130,7 +1293,8 @@ static void cnss_driver_event_work(struct work_struct *work)
 
 		switch (event->type) {
 		case CNSS_DRIVER_EVENT_SERVER_ARRIVE:
-			ret = cnss_wlfw_server_arrive(plat_priv, event->data);
+			ret = cnss_wlfw_server_arrive_hdlr(plat_priv,
+							   event->data);
 			break;
 		case CNSS_DRIVER_EVENT_SERVER_EXIT:
 			ret = cnss_wlfw_server_exit(plat_priv);
@@ -1150,6 +1314,9 @@ static void cnss_driver_event_work(struct work_struct *work)
 		case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START:
 			ret = cnss_cold_boot_cal_start_hdlr(plat_priv);
 			break;
+		case CNSS_DRIVER_EVENT_CAL_UPDATE:
+			ret = cnss_cal_update_hdlr(plat_priv);
+			break;
 		case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE:
 			ret = cnss_cold_boot_cal_done_hdlr(plat_priv);
 			break;
@@ -1173,6 +1340,16 @@ static void cnss_driver_event_work(struct work_struct *work)
 		case CNSS_DRIVER_EVENT_POWER_DOWN:
 			ret = cnss_power_down_hdlr(plat_priv);
 			break;
+		case CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM:
+			ret = cnss_qdss_trace_req_mem_hdlr(plat_priv);
+			break;
+		case CNSS_DRIVER_EVENT_QDSS_TRACE_SAVE:
+			ret = cnss_qdss_trace_save_hdlr(plat_priv,
+							event->data);
+			break;
+		case CNSS_DRIVER_EVENT_QDSS_TRACE_FREE:
+			ret = cnss_qdss_trace_free_hdlr(plat_priv);
+			break;
 		default:
 			cnss_pr_err("Invalid driver event type: %d",
 				    event->type);
@@ -1420,6 +1597,9 @@ int cnss_register_ramdump(struct cnss_plat_data *plat_priv)
 	case QCA6390_DEVICE_ID:
 		ret = cnss_register_ramdump_v2(plat_priv);
 		break;
+	case QCN7605_COMPOSITE_DEVICE_ID:
+	case QCN7605_STANDALONE_DEVICE_ID:
+		break;
 	default:
 		cnss_pr_err("Unknown device ID: 0x%lx\n", plat_priv->device_id);
 		ret = -ENODEV;
@@ -1438,6 +1618,9 @@ void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv)
 	case QCA6390_DEVICE_ID:
 		cnss_unregister_ramdump_v2(plat_priv);
 		break;
+	case QCN7605_COMPOSITE_DEVICE_ID:
+	case QCN7605_STANDALONE_DEVICE_ID:
+		break;
 	default:
 		cnss_pr_err("Unknown device ID: 0x%lx\n", plat_priv->device_id);
 		break;
@@ -1582,6 +1765,7 @@ static int cnss_misc_init(struct cnss_plat_data *plat_priv)
 	init_completion(&plat_priv->power_up_complete);
 	init_completion(&plat_priv->cal_complete);
 	init_completion(&plat_priv->rddm_complete);
+	init_completion(&plat_priv->recovery_complete);
 	mutex_init(&plat_priv->dev_lock);
 
 	return 0;
@@ -1589,6 +1773,7 @@ static int cnss_misc_init(struct cnss_plat_data *plat_priv)
 
 static void cnss_misc_deinit(struct cnss_plat_data *plat_priv)
 {
+	complete_all(&plat_priv->recovery_complete);
 	complete_all(&plat_priv->rddm_complete);
 	complete_all(&plat_priv->cal_complete);
 	complete_all(&plat_priv->power_up_complete);
@@ -1759,6 +1944,10 @@ static int cnss_probe(struct platform_device *plat_dev)
 	if (ret)
 		goto destroy_debugfs;
 
+	ret = cnss_genl_init();
+	if (ret < 0)
+		cnss_pr_err("CNSS genl init failed %d\n", ret);
+
 	cnss_pr_info("Platform driver probed successfully.\n");
 
 	return 0;
@@ -1794,6 +1983,7 @@ static int cnss_remove(struct platform_device *plat_dev)
 {
 	struct cnss_plat_data *plat_priv = platform_get_drvdata(plat_dev);
 
+	cnss_genl_exit();
 	cnss_misc_deinit(plat_priv);
 	cnss_debugfs_destroy(plat_priv);
 	cnss_qmi_deinit(plat_priv);
diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h
index 1fb8609..0b6279f 100644
--- a/drivers/net/wireless/cnss2/main.h
+++ b/drivers/net/wireless/cnss2/main.h
@@ -39,6 +39,7 @@
 enum cnss_dev_bus_type {
 	CNSS_BUS_NONE = -1,
 	CNSS_BUS_PCI,
+	CNSS_BUS_USB,
 };
 
 struct cnss_vreg_cfg {
@@ -170,6 +171,11 @@ enum cnss_driver_event_type {
 	CNSS_DRIVER_EVENT_FORCE_FW_ASSERT,
 	CNSS_DRIVER_EVENT_POWER_UP,
 	CNSS_DRIVER_EVENT_POWER_DOWN,
+	CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM,
+	CNSS_DRIVER_EVENT_QDSS_TRACE_SAVE,
+	CNSS_DRIVER_EVENT_QDSS_TRACE_FREE,
+	CNSS_DRIVER_EVENT_CAL_UPDATE,
+	CNSS_DRIVER_EVENT_CAL_DOWNLOAD,
 	CNSS_DRIVER_EVENT_MAX,
 };
 
@@ -225,6 +231,7 @@ enum cnss_debug_quirks {
 enum cnss_bdf_type {
 	CNSS_BDF_BIN,
 	CNSS_BDF_ELF,
+	CNSS_BDF_REGDB = 4,
 	CNSS_BDF_DUMMY = 255,
 };
 
@@ -235,6 +242,22 @@ struct cnss_control_params {
 	unsigned int bdf_type;
 };
 
+enum cnss_ce_index {
+	CNSS_CE_00,
+	CNSS_CE_01,
+	CNSS_CE_02,
+	CNSS_CE_03,
+	CNSS_CE_04,
+	CNSS_CE_05,
+	CNSS_CE_06,
+	CNSS_CE_07,
+	CNSS_CE_08,
+	CNSS_CE_09,
+	CNSS_CE_10,
+	CNSS_CE_11,
+	CNSS_CE_COMMON,
+};
+
 struct cnss_plat_data {
 	struct platform_device *plat_dev;
 	void *bus_priv;
@@ -265,6 +288,9 @@ struct cnss_plat_data {
 	u32 fw_mem_seg_len;
 	struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
 	struct cnss_fw_mem m3_mem;
+	u32 qdss_mem_seg_len;
+	struct cnss_fw_mem qdss_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
+	u32 *qdss_reg;
 	struct cnss_pin_connect_result pin_result;
 	struct dentry *root_dentry;
 	atomic_t pm_count;
@@ -279,6 +305,7 @@ struct cnss_plat_data {
 	bool cal_done;
 	char firmware_name[CNSS_FW_PATH_MAX_LEN];
 	struct completion rddm_complete;
+	struct completion recovery_complete;
 	struct cnss_control_params ctrl_params;
 	u32 is_converged_dt;
 	struct device_node *dev_node;
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index 12274bc..4b5697d 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/firmware.h>
+#include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/msi.h>
@@ -50,6 +51,7 @@
 
 #define FW_ASSERT_TIMEOUT		5000
 #define DEV_RDDM_TIMEOUT		5000
+#define RECOVERY_TIMEOUT		60000
 
 #ifdef CONFIG_CNSS_EMULATION
 #define EMULATION_HW			1
@@ -61,6 +63,189 @@ static DEFINE_SPINLOCK(pci_link_down_lock);
 
 #define MHI_TIMEOUT_OVERWRITE_MS	(plat_priv->ctrl_params.mhi_timeout)
 
+#define QCA6390_PCIE_REMAP_BAR_CTRL_OFFSET	0x310C
+
+#define QCA6390_CE_SRC_RING_REG_BASE		0xA00000
+#define QCA6390_CE_DST_RING_REG_BASE		0xA01000
+#define QCA6390_CE_COMMON_REG_BASE		0xA18000
+
+#define QCA6390_CE_SRC_RING_BASE_LSB_OFFSET	0x0
+#define QCA6390_CE_SRC_RING_BASE_MSB_OFFSET	0x4
+#define QCA6390_CE_SRC_RING_ID_OFFSET		0x8
+#define QCA6390_CE_SRC_RING_MISC_OFFSET		0x10
+#define QCA6390_CE_SRC_CTRL_OFFSET		0x58
+#define QCA6390_CE_SRC_R0_CE_CH_SRC_IS_OFFSET	0x5C
+#define QCA6390_CE_SRC_RING_HP_OFFSET		0x400
+#define QCA6390_CE_SRC_RING_TP_OFFSET		0x404
+
+#define QCA6390_CE_DEST_RING_BASE_LSB_OFFSET	0x0
+#define QCA6390_CE_DEST_RING_BASE_MSB_OFFSET	0x4
+#define QCA6390_CE_DEST_RING_ID_OFFSET		0x8
+#define QCA6390_CE_DEST_RING_MISC_OFFSET	0x10
+#define QCA6390_CE_DEST_CTRL_OFFSET		0xB0
+#define QCA6390_CE_CH_DST_IS_OFFSET		0xB4
+#define QCA6390_CE_CH_DEST_CTRL2_OFFSET		0xB8
+#define QCA6390_CE_DEST_RING_HP_OFFSET		0x400
+#define QCA6390_CE_DEST_RING_TP_OFFSET		0x404
+
+#define QCA6390_CE_STATUS_RING_BASE_LSB_OFFSET	0x58
+#define QCA6390_CE_STATUS_RING_BASE_MSB_OFFSET	0x5C
+#define QCA6390_CE_STATUS_RING_ID_OFFSET	0x60
+#define QCA6390_CE_STATUS_RING_MISC_OFFSET	0x68
+#define QCA6390_CE_STATUS_RING_HP_OFFSET	0x408
+#define QCA6390_CE_STATUS_RING_TP_OFFSET	0x40C
+
+#define QCA6390_CE_COMMON_GXI_ERR_INTS		0x14
+#define QCA6390_CE_COMMON_GXI_ERR_STATS		0x18
+#define QCA6390_CE_COMMON_GXI_WDOG_STATUS	0x2C
+#define QCA6390_CE_COMMON_TARGET_IE_0		0x48
+#define QCA6390_CE_COMMON_TARGET_IE_1		0x4C
+
+#define QCA6390_CE_REG_INTERVAL			0x2000
+
+#define QDSS_APB_DEC_CSR_BASE			0x1C01000
+
+#define QDSS_APB_DEC_CSR_ETRIRQCTRL_OFFSET	0x6C
+#define QDSS_APB_DEC_CSR_PRESERVEETF_OFFSET	0x70
+#define QDSS_APB_DEC_CSR_PRESERVEETR0_OFFSET	0x74
+#define QDSS_APB_DEC_CSR_PRESERVEETR1_OFFSET	0x78
+
+#define MAX_UNWINDOWED_ADDRESS			0x80000
+#define WINDOW_ENABLE_BIT			0x40000000
+#define WINDOW_SHIFT				19
+#define WINDOW_VALUE_MASK			0x3F
+#define WINDOW_START				MAX_UNWINDOWED_ADDRESS
+#define WINDOW_RANGE_MASK			0x7FFFF
+
+static struct cnss_pci_reg ce_src[] = {
+	{ "SRC_RING_BASE_LSB", QCA6390_CE_SRC_RING_BASE_LSB_OFFSET },
+	{ "SRC_RING_BASE_MSB", QCA6390_CE_SRC_RING_BASE_MSB_OFFSET },
+	{ "SRC_RING_ID", QCA6390_CE_SRC_RING_ID_OFFSET },
+	{ "SRC_RING_MISC", QCA6390_CE_SRC_RING_MISC_OFFSET },
+	{ "SRC_CTRL", QCA6390_CE_SRC_CTRL_OFFSET },
+	{ "SRC_R0_CE_CH_SRC_IS", QCA6390_CE_SRC_R0_CE_CH_SRC_IS_OFFSET },
+	{ "SRC_RING_HP", QCA6390_CE_SRC_RING_HP_OFFSET },
+	{ "SRC_RING_TP", QCA6390_CE_SRC_RING_TP_OFFSET },
+	{ NULL },
+};
+
+static struct cnss_pci_reg ce_dst[] = {
+	{ "DEST_RING_BASE_LSB", QCA6390_CE_DEST_RING_BASE_LSB_OFFSET },
+	{ "DEST_RING_BASE_MSB", QCA6390_CE_DEST_RING_BASE_MSB_OFFSET },
+	{ "DEST_RING_ID", QCA6390_CE_DEST_RING_ID_OFFSET },
+	{ "DEST_RING_MISC", QCA6390_CE_DEST_RING_MISC_OFFSET },
+	{ "DEST_CTRL", QCA6390_CE_DEST_CTRL_OFFSET },
+	{ "CE_CH_DST_IS", QCA6390_CE_CH_DST_IS_OFFSET },
+	{ "CE_CH_DEST_CTRL2", QCA6390_CE_CH_DEST_CTRL2_OFFSET },
+	{ "DEST_RING_HP", QCA6390_CE_DEST_RING_HP_OFFSET },
+	{ "DEST_RING_TP", QCA6390_CE_DEST_RING_TP_OFFSET },
+	{ "STATUS_RING_BASE_LSB", QCA6390_CE_STATUS_RING_BASE_LSB_OFFSET },
+	{ "STATUS_RING_BASE_MSB", QCA6390_CE_STATUS_RING_BASE_MSB_OFFSET },
+	{ "STATUS_RING_ID", QCA6390_CE_STATUS_RING_ID_OFFSET },
+	{ "STATUS_RING_MISC", QCA6390_CE_STATUS_RING_MISC_OFFSET },
+	{ "STATUS_RING_HP", QCA6390_CE_STATUS_RING_HP_OFFSET },
+	{ "STATUS_RING_TP", QCA6390_CE_STATUS_RING_TP_OFFSET },
+	{ NULL },
+};
+
+static struct cnss_pci_reg ce_cmn[] = {
+	{ "GXI_ERR_INTS", QCA6390_CE_COMMON_GXI_ERR_INTS },
+	{ "GXI_ERR_STATS", QCA6390_CE_COMMON_GXI_ERR_STATS },
+	{ "GXI_WDOG_STATUS", QCA6390_CE_COMMON_GXI_WDOG_STATUS },
+	{ "TARGET_IE_0", QCA6390_CE_COMMON_TARGET_IE_0 },
+	{ "TARGET_IE_1", QCA6390_CE_COMMON_TARGET_IE_1 },
+	{ NULL },
+};
+
+static struct cnss_pci_reg qdss_csr[] = {
+	{ "QDSSCSR_ETRIRQCTRL", QDSS_APB_DEC_CSR_ETRIRQCTRL_OFFSET },
+	{ "QDSSCSR_PRESERVEETF", QDSS_APB_DEC_CSR_PRESERVEETF_OFFSET },
+	{ "QDSSCSR_PRESERVEETR0", QDSS_APB_DEC_CSR_PRESERVEETR0_OFFSET },
+	{ "QDSSCSR_PRESERVEETR1", QDSS_APB_DEC_CSR_PRESERVEETR1_OFFSET },
+	{ NULL },
+};
+
+static void cnss_pci_select_window(struct cnss_pci_data *pci_priv, u32 offset)
+{
+	u32 window = (offset >> WINDOW_SHIFT) & WINDOW_VALUE_MASK;
+
+	if (window != pci_priv->remap_window) {
+		writel_relaxed(WINDOW_ENABLE_BIT | window,
+			       QCA6390_PCIE_REMAP_BAR_CTRL_OFFSET +
+			       pci_priv->bar);
+		pci_priv->remap_window = window;
+		cnss_pr_dbg("Config PCIe remap window register to 0x%x\n",
+			    WINDOW_ENABLE_BIT | window);
+	}
+}
+
+static u32 cnss_pci_reg_read(struct cnss_pci_data *pci_priv, u32 offset)
+{
+	if (pci_priv->pci_dev->device == QCA6174_DEVICE_ID ||
+	    offset < MAX_UNWINDOWED_ADDRESS)
+		return readl_relaxed(pci_priv->bar + offset);
+
+	cnss_pci_select_window(pci_priv, offset);
+
+	return readl_relaxed(pci_priv->bar + WINDOW_START +
+			     (offset & WINDOW_RANGE_MASK));
+}
+
+static void cnss_pci_disable_l1(struct cnss_pci_data *pci_priv)
+{
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+	struct pci_dev *pdev = pci_priv->pci_dev;
+	bool disable_l1;
+	u32 lnkctl_offset;
+	u32 val;
+
+	disable_l1 = of_property_read_bool(plat_priv->dev_node,
+					   "pcie-disable-l1");
+	cnss_pr_dbg("disable_l1 %d\n", disable_l1);
+
+	if (!disable_l1)
+		return;
+
+	lnkctl_offset = pdev->pcie_cap + PCI_EXP_LNKCTL;
+	pci_read_config_dword(pdev, lnkctl_offset, &val);
+	cnss_pr_dbg("lnkctl 0x%x\n", val);
+
+	val &= ~PCI_EXP_LNKCTL_ASPM_L1;
+	pci_write_config_dword(pdev, lnkctl_offset, val);
+}
+
+static void cnss_pci_disable_l1ss(struct cnss_pci_data *pci_priv)
+{
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+	struct pci_dev *pdev = pci_priv->pci_dev;
+	bool disable_l1ss;
+	u32 l1ss_cap_id_offset;
+	u32 l1ss_ctl1_offset;
+	u32 val;
+
+	disable_l1ss = of_property_read_bool(plat_priv->dev_node,
+					     "pcie-disable-l1ss");
+	cnss_pr_dbg("disable_l1ss %d\n", disable_l1ss);
+
+	if (!disable_l1ss)
+		return;
+
+	l1ss_cap_id_offset = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS);
+	if (!l1ss_cap_id_offset) {
+		cnss_pr_dbg("could not find L1ss capability register\n");
+		return;
+	}
+
+	l1ss_ctl1_offset = l1ss_cap_id_offset + PCI_L1SS_CTL1;
+
+	pci_read_config_dword(pdev, l1ss_ctl1_offset, &val);
+	cnss_pr_dbg("l1ss_ctl1 0x%x\n", val);
+
+	val &= ~(PCI_L1SS_CTL1_PCIPM_L1_1 | PCI_L1SS_CTL1_PCIPM_L1_2 |
+		 PCI_L1SS_CTL1_ASPM_L1_1 | PCI_L1SS_CTL1_ASPM_L1_2);
+	pci_write_config_dword(pdev, l1ss_ctl1_offset, val);
+}
+
 static int cnss_set_pci_config_space(struct cnss_pci_data *pci_priv, bool save)
 {
 	struct pci_dev *pci_dev = pci_priv->pci_dev;
@@ -89,6 +274,8 @@ static int cnss_set_pci_config_space(struct cnss_pci_data *pci_priv, bool save)
 						      &pci_priv->saved_state);
 			pci_restore_state(pci_dev);
 		}
+
+		cnss_pci_disable_l1ss(pci_priv);
 	}
 
 	return 0;
@@ -177,16 +364,16 @@ int cnss_resume_pci_link(struct cnss_pci_data *pci_priv)
 		}
 	}
 
+	ret = cnss_set_pci_config_space(pci_priv, RESTORE_PCI_CONFIG_SPACE);
+	if (ret)
+		goto out;
+
 	ret = pci_enable_device(pci_priv->pci_dev);
 	if (ret) {
 		cnss_pr_err("Failed to enable PCI device, err = %d\n", ret);
 		goto out;
 	}
 
-	ret = cnss_set_pci_config_space(pci_priv, RESTORE_PCI_CONFIG_SPACE);
-	if (ret)
-		goto out;
-
 	pci_set_master(pci_priv->pci_dev);
 
 	if (pci_priv->pci_link_down_ind)
@@ -231,6 +418,25 @@ int cnss_pci_link_down(struct device *dev)
 }
 EXPORT_SYMBOL(cnss_pci_link_down);
 
+static int cnss_pci_check_link_status(struct cnss_pci_data *pci_priv)
+{
+	u16 device_id;
+
+	if (pci_priv->pci_link_down_ind) {
+		cnss_pr_err("PCIe link is down\n");
+		return -EIO;
+	}
+
+	pci_read_config_word(pci_priv->pci_dev, PCI_DEVICE_ID, &device_id);
+	if (device_id != pci_priv->device_id)  {
+		cnss_fatal_err("PCI device ID mismatch, link possibly down, current read ID: 0x%x, record ID: 0x%x\n",
+			       device_id, pci_priv->device_id);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 int cnss_pci_is_device_down(struct device *dev)
 {
 	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
@@ -284,6 +490,7 @@ int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv)
 			goto out;
 		}
 		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
+		complete(&plat_priv->recovery_complete);
 	} else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)) {
 		ret = pci_priv->driver_ops->probe(pci_priv->pci_dev,
 						  pci_priv->pci_device_id);
@@ -331,6 +538,7 @@ int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv)
 		   test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
 		pci_priv->driver_ops->remove(pci_priv->pci_dev);
 		clear_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
+		clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
 	}
 
 	return 0;
@@ -492,7 +700,7 @@ static int cnss_qca6290_powerup(struct cnss_pci_data *pci_priv)
 
 	ret = cnss_pci_start_mhi(pci_priv);
 	if (ret) {
-		cnss_pr_err("Failed to start MHI, err = %d\n", ret);
+		cnss_fatal_err("Failed to start MHI, err = %d\n", ret);
 		if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state) &&
 		    !pci_priv->pci_link_down_ind && timeout)
 			mod_timer(&plat_priv->fw_boot_timer,
@@ -556,6 +764,8 @@ static int cnss_qca6290_shutdown(struct cnss_pci_data *pci_priv)
 
 	cnss_power_off_device(plat_priv);
 
+	pci_priv->remap_window = 0;
+
 	clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
 	clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
 	clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
@@ -570,11 +780,6 @@ static void cnss_qca6290_crash_shutdown(struct cnss_pci_data *pci_priv)
 	cnss_pr_dbg("Crash shutdown with driver_state 0x%lx\n",
 		    plat_priv->driver_state);
 
-	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
-		cnss_pr_dbg("Ignore crash shutdown\n");
-		return;
-	}
-
 	cnss_pci_collect_dump_info(pci_priv, true);
 }
 
@@ -771,12 +976,26 @@ EXPORT_SYMBOL(cnss_wlan_register_driver);
 void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver_ops)
 {
 	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
+	int ret = 0;
 
 	if (!plat_priv) {
 		cnss_pr_err("plat_priv is NULL\n");
 		return;
 	}
 
+	if (!test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
+	    !test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state))
+		goto skip_wait;
+
+	reinit_completion(&plat_priv->recovery_complete);
+	ret = wait_for_completion_timeout(&plat_priv->recovery_complete,
+					  RECOVERY_TIMEOUT);
+	if (!ret) {
+		cnss_pr_err("Timeout waiting for recovery to complete\n");
+		CNSS_ASSERT(0);
+	}
+
+skip_wait:
 	cnss_driver_event_post(plat_priv,
 			       CNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
 			       CNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
@@ -963,7 +1182,7 @@ static void cnss_pci_event_cb(struct msm_pcie_notify *notify)
 		pci_priv->pci_link_down_ind = true;
 		spin_unlock_irqrestore(&pci_link_down_lock, flags);
 
-		cnss_pr_err("PCI link down, schedule recovery!\n");
+		cnss_fatal_err("PCI link down, schedule recovery!\n");
 		if (pci_dev->device == QCA6174_DEVICE_ID)
 			disable_irq(pci_dev->irq);
 		cnss_schedule_recovery(&pci_dev->dev, CNSS_REASON_LINK_DOWN);
@@ -1112,6 +1331,9 @@ static int cnss_pci_suspend_noirq(struct device *dev)
 	if (driver_ops && driver_ops->suspend_noirq)
 		ret = driver_ops->suspend_noirq(pci_dev);
 
+	if (pci_priv->disable_pc && !pci_dev->state_saved)
+		pci_save_state(pci_dev);
+
 out:
 	return ret;
 }
@@ -1485,6 +1707,63 @@ int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv)
 	return 0;
 }
 
+int cnss_pci_alloc_qdss_mem(struct cnss_pci_data *pci_priv)
+{
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+	struct cnss_fw_mem *qdss_mem = plat_priv->qdss_mem;
+	int i, j;
+
+	for (i = 0; i < plat_priv->qdss_mem_seg_len; i++) {
+		if (!qdss_mem[i].va && qdss_mem[i].size) {
+			qdss_mem[i].va =
+				dma_alloc_coherent(&pci_priv->pci_dev->dev,
+						   qdss_mem[i].size,
+						   &qdss_mem[i].pa,
+						   GFP_KERNEL);
+			if (!qdss_mem[i].va) {
+				cnss_pr_err("Failed to allocate QDSS memory for FW, size: 0x%zx, type: %u, chuck-ID: %d\n",
+					    qdss_mem[i].size,
+					    qdss_mem[i].type, i);
+				break;
+			}
+		}
+	}
+
+	/* Best-effort allocation for QDSS trace */
+	if (i < plat_priv->qdss_mem_seg_len) {
+		for (j = i; j < plat_priv->qdss_mem_seg_len; j++) {
+			qdss_mem[j].type = 0;
+			qdss_mem[j].size = 0;
+		}
+		plat_priv->qdss_mem_seg_len = i;
+	}
+
+	return 0;
+}
+
+void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv)
+{
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+	struct cnss_fw_mem *qdss_mem = plat_priv->qdss_mem;
+	int i;
+
+	for (i = 0; i < plat_priv->qdss_mem_seg_len; i++) {
+		if (qdss_mem[i].va && qdss_mem[i].size) {
+			cnss_pr_dbg("Freeing memory for QDSS: pa: %pa, size: 0x%zx, type: %u\n",
+				    &qdss_mem[i].pa, qdss_mem[i].size,
+				    qdss_mem[i].type);
+			dma_free_coherent(&pci_priv->pci_dev->dev,
+					  qdss_mem[i].size, qdss_mem[i].va,
+					  qdss_mem[i].pa);
+			qdss_mem[i].va = NULL;
+			qdss_mem[i].pa = 0;
+			qdss_mem[i].size = 0;
+			qdss_mem[i].type = 0;
+		}
+	}
+	plat_priv->qdss_mem_seg_len = 0;
+}
+
 static void cnss_pci_free_fw_mem(struct cnss_pci_data *pci_priv)
 {
 	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
@@ -1576,17 +1855,12 @@ int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv)
 	if (!plat_priv)
 		return -ENODEV;
 
-	if (cnss_pci_is_device_down(&pci_priv->pci_dev->dev)) {
-		cnss_pr_info("Device is already in bad state, ignore force assert\n");
-		return 0;
-	}
-
 	ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_TRIGGER_RDDM);
 	if (ret) {
-		cnss_pr_err("Failed to trigger RDDM, err = %d\n", ret);
+		cnss_fatal_err("Failed to trigger RDDM, err = %d\n", ret);
 		cnss_schedule_recovery(&pci_priv->pci_dev->dev,
 				       CNSS_REASON_DEFAULT);
-		return 0;
+		return ret;
 	}
 
 	if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state)) {
@@ -1602,7 +1876,7 @@ void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv)
 	if (!pci_priv)
 		return;
 
-	cnss_pr_err("Timeout waiting for FW ready indication\n");
+	cnss_fatal_err("Timeout waiting for FW ready indication\n");
 
 	cnss_schedule_recovery(&pci_priv->pci_dev->dev,
 			       CNSS_REASON_TIMEOUT);
@@ -1961,6 +2235,83 @@ static char *cnss_mhi_state_to_str(enum cnss_mhi_state mhi_state)
 	}
 };
 
+static void cnss_pci_dump_qdss_reg(struct cnss_pci_data *pci_priv)
+{
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+	int i, array_size = ARRAY_SIZE(qdss_csr) - 1;
+	gfp_t gfp = GFP_KERNEL;
+	u32 reg_offset;
+
+	if (in_interrupt() || irqs_disabled())
+		gfp = GFP_ATOMIC;
+
+	if (!plat_priv->qdss_reg)
+		plat_priv->qdss_reg = devm_kzalloc(&pci_priv->pci_dev->dev,
+						   sizeof(*plat_priv->qdss_reg)
+						   * array_size, gfp);
+
+	for (i = 0; qdss_csr[i].name; i++) {
+		reg_offset = QDSS_APB_DEC_CSR_BASE + qdss_csr[i].offset;
+		plat_priv->qdss_reg[i] = cnss_pci_reg_read(pci_priv,
+							   reg_offset);
+		cnss_pr_dbg("%s[0x%x] = 0x%x\n", qdss_csr[i].name, reg_offset,
+			    plat_priv->qdss_reg[i]);
+	}
+}
+
+static void cnss_pci_dump_ce_reg(struct cnss_pci_data *pci_priv,
+				 enum cnss_ce_index ce)
+{
+	int i;
+	u32 ce_base = ce * QCA6390_CE_REG_INTERVAL;
+	u32 reg_offset;
+
+	switch (ce) {
+	case CNSS_CE_09:
+	case CNSS_CE_10:
+		for (i = 0; ce_src[i].name; i++) {
+			reg_offset = QCA6390_CE_SRC_RING_REG_BASE +
+				ce_base + ce_src[i].offset;
+			cnss_pr_dbg("CE_%02d_%s[0x%x] = 0x%x\n",
+				    ce, ce_src[i].name, reg_offset,
+				    cnss_pci_reg_read(pci_priv, reg_offset));
+		}
+
+		for (i = 0; ce_dst[i].name; i++) {
+			reg_offset = QCA6390_CE_DST_RING_REG_BASE +
+				ce_base + ce_dst[i].offset;
+			cnss_pr_dbg("CE_%02d_%s[0x%x] = 0x%x\n",
+				    ce, ce_dst[i].name, reg_offset,
+				    cnss_pci_reg_read(pci_priv, reg_offset));
+		}
+		break;
+	case CNSS_CE_COMMON:
+		for (i = 0; ce_cmn[i].name; i++) {
+			reg_offset = QCA6390_CE_COMMON_REG_BASE +
+				ce_cmn[i].offset;
+			cnss_pr_dbg("CE_COMMON_%s[0x%x] = 0x%x\n",
+				    ce_cmn[i].name, reg_offset,
+				    cnss_pci_reg_read(pci_priv, reg_offset));
+		}
+		break;
+	default:
+		cnss_pr_err("Unsupported CE[%d] registers dump\n", ce);
+	}
+}
+
+static void cnss_pci_dump_registers(struct cnss_pci_data *pci_priv)
+{
+	cnss_pr_dbg("Start to dump debug registers\n");
+
+	if (cnss_pci_check_link_status(pci_priv))
+		return;
+
+	mhi_debug_reg_dump(pci_priv->mhi_ctrl);
+	cnss_pci_dump_ce_reg(pci_priv, CNSS_CE_COMMON);
+	cnss_pci_dump_ce_reg(pci_priv, CNSS_CE_09);
+	cnss_pci_dump_ce_reg(pci_priv, CNSS_CE_10);
+}
+
 void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic)
 {
 	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
@@ -1977,9 +2328,13 @@ void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic)
 		return;
 	}
 
+	cnss_pci_dump_qdss_reg(pci_priv);
+
 	ret = mhi_download_rddm_img(pci_priv->mhi_ctrl, in_panic);
 	if (ret) {
-		cnss_pr_err("Failed to download RDDM image, err = %d\n", ret);
+		cnss_fatal_err("Failed to download RDDM image, err = %d\n",
+			       ret);
+		cnss_pci_dump_registers(pci_priv);
 		return;
 	}
 
@@ -2073,7 +2428,7 @@ static void cnss_dev_rddm_timeout_hdlr(unsigned long data)
 	if (!pci_priv)
 		return;
 
-	cnss_pr_err("Timeout waiting for RDDM notification\n");
+	cnss_fatal_err("Timeout waiting for RDDM notification\n");
 
 	cnss_schedule_recovery(&pci_priv->pci_dev->dev, CNSS_REASON_TIMEOUT);
 }
@@ -2081,21 +2436,13 @@ static void cnss_dev_rddm_timeout_hdlr(unsigned long data)
 static int cnss_mhi_link_status(struct mhi_controller *mhi_ctrl, void *priv)
 {
 	struct cnss_pci_data *pci_priv = priv;
-	u16 device_id;
 
 	if (!pci_priv) {
 		cnss_pr_err("pci_priv is NULL\n");
 		return -EINVAL;
 	}
 
-	pci_read_config_word(pci_priv->pci_dev, PCI_DEVICE_ID, &device_id);
-	if (device_id != pci_priv->device_id)  {
-		cnss_pr_err("PCI device ID mismatch, link possibly down, current read ID: 0x%x, record ID: 0x%x\n",
-			    device_id, pci_priv->device_id);
-		return -EIO;
-	}
-
-	return 0;
+	return cnss_pci_check_link_status(pci_priv);
 }
 
 static void cnss_mhi_notify_status(struct mhi_controller *mhi_ctrl, void *priv,
@@ -2659,6 +3006,8 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
 	if (ret)
 		goto dereg_pci_event;
 
+	cnss_pci_disable_l1(pci_priv);
+
 	pci_save_state(pci_dev);
 	pci_priv->default_state = pci_store_saved_state(pci_dev);
 
@@ -2728,6 +3077,7 @@ static void cnss_pci_remove(struct pci_dev *pci_dev)
 
 	cnss_pci_free_m3_mem(pci_priv);
 	cnss_pci_free_fw_mem(pci_priv);
+	cnss_pci_free_qdss_mem(pci_priv);
 
 	switch (pci_dev->device) {
 	case QCA6290_DEVICE_ID:
diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h
index 425f41a..5ba1526 100644
--- a/drivers/net/wireless/cnss2/pci.h
+++ b/drivers/net/wireless/cnss2/pci.h
@@ -46,6 +46,11 @@ struct cnss_msi_config {
 	struct cnss_msi_user *users;
 };
 
+struct cnss_pci_reg {
+	char *name;
+	u32 offset;
+};
+
 struct cnss_pci_data {
 	struct pci_dev *pci_dev;
 	struct cnss_plat_data *plat_priv;
@@ -71,6 +76,7 @@ struct cnss_pci_data {
 	u32 msi_ep_base_data;
 	struct mhi_controller *mhi_ctrl;
 	unsigned long mhi_state;
+	u32 remap_window;
 	struct timer_list dev_rddm_timer;
 	bool disable_pc;
 };
@@ -125,6 +131,8 @@ int cnss_resume_pci_link(struct cnss_pci_data *pci_priv);
 int cnss_pci_init(struct cnss_plat_data *plat_priv);
 void cnss_pci_deinit(struct cnss_plat_data *plat_priv);
 int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv);
+int cnss_pci_alloc_qdss_mem(struct cnss_pci_data *pci_priv);
+void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv);
 int cnss_pci_load_m3(struct cnss_pci_data *pci_priv);
 int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv,
 			   enum cnss_mhi_state state);
diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c
index 46d6ac5..966c5fd 100644
--- a/drivers/net/wireless/cnss2/qmi.c
+++ b/drivers/net/wireless/cnss2/qmi.c
@@ -21,10 +21,12 @@
 
 #define WLFW_SERVICE_INS_ID_V01		1
 #define WLFW_CLIENT_ID			0x4b4e454c
+#define BDF_FILE_NAME_PREFIX		"bdwlan"
 #define ELF_BDF_FILE_NAME		"bdwlan.elf"
 #define ELF_BDF_FILE_NAME_PREFIX	"bdwlan.e"
 #define BIN_BDF_FILE_NAME		"bdwlan.bin"
 #define BIN_BDF_FILE_NAME_PREFIX	"bdwlan.b"
+#define REGDB_FILE_NAME			"regdb.bin"
 #define DUMMY_BDF_FILE_NAME		"bdwlan.dmy"
 
 #define QMI_WLFW_TIMEOUT_MS		(plat_priv->ctrl_params.qmi_timeout)
@@ -90,6 +92,16 @@ static int cnss_wlfw_ind_register_send_sync(struct cnss_plat_data *plat_priv)
 	req->pin_connect_result_enable = 1;
 	req->cal_done_enable_valid = 1;
 	req->cal_done_enable = 1;
+	req->initiate_cal_download_enable_valid = 1;
+	req->initiate_cal_download_enable = 1;
+	req->initiate_cal_update_enable_valid = 1;
+	req->initiate_cal_update_enable = 1;
+	req->qdss_trace_req_mem_enable_valid = 1;
+	req->qdss_trace_req_mem_enable = 1;
+	req->qdss_trace_save_enable_valid = 1;
+	req->qdss_trace_save_enable = 1;
+	req->qdss_trace_free_enable_valid = 1;
+	req->qdss_trace_free_enable = 1;
 
 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
 			   wlfw_ind_register_resp_msg_v01_ei, resp);
@@ -320,6 +332,7 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
 	struct wlfw_cap_req_msg_v01 *req;
 	struct wlfw_cap_resp_msg_v01 *resp;
 	struct qmi_txn txn;
+	char *fw_build_timestamp;
 	int ret = 0;
 
 	cnss_pr_dbg("Sending target capability message, state: 0x%lx\n",
@@ -381,6 +394,8 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
 	if (resp->fw_version_info_valid) {
 		plat_priv->fw_version_info.fw_version =
 			resp->fw_version_info.fw_version;
+		fw_build_timestamp = resp->fw_version_info.fw_build_timestamp;
+		fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN] = '\0';
 		strlcpy(plat_priv->fw_version_info.fw_build_timestamp,
 			resp->fw_version_info.fw_build_timestamp,
 			QMI_WLFW_MAX_TIMESTAMP_LEN + 1);
@@ -404,7 +419,8 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
 	return ret;
 }
 
-int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv)
+int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
+				 u32 bdf_type)
 {
 	struct wlfw_bdf_download_req_msg_v01 *req;
 	struct wlfw_bdf_download_resp_msg_v01 *resp;
@@ -416,8 +432,8 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv)
 	int ret = 0;
 	const char *fw_path;
 
-	cnss_pr_dbg("Sending BDF download message, state: 0x%lx\n",
-		    plat_priv->driver_state);
+	cnss_pr_dbg("Sending BDF download message, state: 0x%lx, type: %d\n",
+		    plat_priv->driver_state, bdf_type);
 
 	req = kzalloc(sizeof(*req), GFP_KERNEL);
 	if (!req)
@@ -430,7 +446,7 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv)
 	}
 
 	fw_path = cnss_get_fw_path(plat_priv);
-	switch (plat_priv->ctrl_params.bdf_type) {
+	switch (bdf_type) {
 	case CNSS_BDF_ELF:
 		if (plat_priv->board_info.board_id == 0xFF)
 			snprintf(filename, sizeof(filename),
@@ -441,8 +457,10 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv)
 				 fw_path, plat_priv->board_info.board_id);
 		else
 			snprintf(filename, sizeof(filename),
-				 "%s" ELF_BDF_FILE_NAME_PREFIX "%04x",
-				 fw_path, plat_priv->board_info.board_id);
+				 "%s" BDF_FILE_NAME_PREFIX "%02x.e%02x",
+				 fw_path,
+				 plat_priv->board_info.board_id >> 8 & 0xFF,
+				 plat_priv->board_info.board_id & 0xFF);
 		break;
 	case CNSS_BDF_BIN:
 		if (plat_priv->board_info.board_id == 0xFF)
@@ -454,8 +472,13 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv)
 				 fw_path, plat_priv->board_info.board_id);
 		else
 			snprintf(filename, sizeof(filename),
-				 "%s" BIN_BDF_FILE_NAME_PREFIX "%04x",
-				 fw_path, plat_priv->board_info.board_id);
+				 "%s" BDF_FILE_NAME_PREFIX "%02x.b%02x",
+				 fw_path,
+				 plat_priv->board_info.board_id >> 8 & 0xFF,
+				 plat_priv->board_info.board_id & 0xFF);
+		break;
+	case CNSS_BDF_REGDB:
+		snprintf(filename, sizeof(filename), REGDB_FILE_NAME);
 		break;
 	case CNSS_BDF_DUMMY:
 		cnss_pr_dbg("CNSS_BDF_DUMMY is set, sending dummy BDF\n");
@@ -551,7 +574,8 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv)
 	if (plat_priv->ctrl_params.bdf_type != CNSS_BDF_DUMMY)
 		release_firmware(fw_entry);
 err_req_fw:
-	CNSS_ASSERT(0);
+	if (bdf_type != CNSS_BDF_REGDB)
+		CNSS_ASSERT(0);
 	kfree(req);
 	kfree(resp);
 	return ret;
@@ -1063,6 +1087,82 @@ int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
 	return ret;
 }
 
+int cnss_wlfw_qdss_trace_mem_info_send_sync(struct cnss_plat_data *plat_priv)
+{
+	struct wlfw_qdss_trace_mem_info_req_msg_v01 *req;
+	struct wlfw_qdss_trace_mem_info_resp_msg_v01 *resp;
+	struct qmi_txn txn;
+	struct cnss_fw_mem *qdss_mem = plat_priv->qdss_mem;
+	int ret = 0;
+	int i;
+
+	cnss_pr_dbg("Sending QDSS trace mem info, state: 0x%lx\n",
+		    plat_priv->driver_state);
+
+	req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		kfree(req);
+		return -ENOMEM;
+	}
+
+	req->mem_seg_len = plat_priv->qdss_mem_seg_len;
+	for (i = 0; i < req->mem_seg_len; i++) {
+		cnss_pr_dbg("Memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx, type: %u\n",
+			    qdss_mem[i].va, &qdss_mem[i].pa,
+			    qdss_mem[i].size, qdss_mem[i].type);
+
+		req->mem_seg[i].addr = qdss_mem[i].pa;
+		req->mem_seg[i].size = qdss_mem[i].size;
+		req->mem_seg[i].type = qdss_mem[i].type;
+	}
+
+	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
+			   wlfw_qdss_trace_mem_info_resp_msg_v01_ei, resp);
+	if (ret < 0) {
+		cnss_pr_err("Fail to initialize txn for QDSS trace mem request: err %d\n",
+			    ret);
+		goto out;
+	}
+
+	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
+			       QMI_WLFW_QDSS_TRACE_MEM_INFO_REQ_V01,
+			       WLFW_QDSS_TRACE_MEM_INFO_REQ_MSG_V01_MAX_MSG_LEN,
+			       wlfw_qdss_trace_mem_info_req_msg_v01_ei, req);
+	if (ret < 0) {
+		qmi_txn_cancel(&txn);
+		cnss_pr_err("Fail to send QDSS trace mem info request: err %d\n",
+			    ret);
+		goto out;
+	}
+
+	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
+	if (ret < 0) {
+		cnss_pr_err("Fail to wait for response of QDSS trace mem info request, err %d\n",
+			    ret);
+		goto out;
+	}
+
+	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
+		cnss_pr_err("QDSS trace mem info request failed, result: %d, err: %d\n",
+			    resp->resp.result, resp->resp.error);
+		ret = -resp->resp.result;
+		goto out;
+	}
+
+	kfree(req);
+	kfree(resp);
+	return 0;
+
+out:
+	kfree(req);
+	kfree(resp);
+	return ret;
+}
+
 unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv)
 {
 	cnss_pr_dbg("QMI timeout is %u ms\n", QMI_WLFW_TIMEOUT_MS);
@@ -1198,6 +1298,125 @@ static void cnss_wlfw_cal_done_ind_cb(struct qmi_handle *qmi_wlfw,
 			       0, NULL);
 }
 
+static void cnss_wlfw_initiate_cal_update_ind_cb(struct qmi_handle *qmi_wlfw,
+						 struct sockaddr_qrtr *sq,
+						 struct qmi_txn *txn,
+						 const void *data)
+{
+}
+
+static void cnss_wlfw_qdss_trace_req_mem_ind_cb(struct qmi_handle *qmi_wlfw,
+						struct sockaddr_qrtr *sq,
+						struct qmi_txn *txn,
+						const void *data)
+{
+	struct cnss_plat_data *plat_priv =
+		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
+	const struct wlfw_qdss_trace_req_mem_ind_msg_v01 *ind_msg = data;
+	int i;
+
+	cnss_pr_dbg("Received QMI WLFW QDSS trace request mem indication\n");
+
+	if (!txn) {
+		cnss_pr_err("Spurious indication\n");
+		return;
+	}
+
+	if (plat_priv->qdss_mem_seg_len) {
+		cnss_pr_err("Ignore double allocation for QDSS trace, current len %u\n",
+			    plat_priv->qdss_mem_seg_len);
+		return;
+	}
+
+	plat_priv->qdss_mem_seg_len = ind_msg->mem_seg_len;
+	for (i = 0; i < plat_priv->qdss_mem_seg_len; i++) {
+		cnss_pr_dbg("QDSS requests for memory, size: 0x%zx, type: %u\n",
+			    ind_msg->mem_seg[i].size, ind_msg->mem_seg[i].type);
+		plat_priv->qdss_mem[i].type = ind_msg->mem_seg[i].type;
+		plat_priv->qdss_mem[i].size = ind_msg->mem_seg[i].size;
+	}
+
+	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM,
+			       0, NULL);
+}
+
+static void cnss_wlfw_qdss_trace_save_ind_cb(struct qmi_handle *qmi_wlfw,
+					     struct sockaddr_qrtr *sq,
+					     struct qmi_txn *txn,
+					     const void *data)
+{
+	struct cnss_plat_data *plat_priv =
+		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
+	const struct wlfw_qdss_trace_save_ind_msg_v01 *ind_msg = data;
+	struct cnss_qmi_event_qdss_trace_save_data *event_data;
+	int i = 0;
+
+	cnss_pr_dbg("Received QMI WLFW QDSS trace save indication\n");
+
+	if (!txn) {
+		cnss_pr_err("Spurious indication\n");
+		return;
+	}
+
+	cnss_pr_dbg("QDSS_trace_save info: source %u, total_size %u, file_name_valid %u, file_name %s\n",
+		    ind_msg->source, ind_msg->total_size,
+		    ind_msg->file_name_valid, ind_msg->file_name);
+
+	if (ind_msg->source == 1)
+		return;
+
+	event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
+	if (!event_data)
+		return;
+
+	if (ind_msg->mem_seg_valid) {
+		if (ind_msg->mem_seg_len > QDSS_TRACE_SEG_LEN_MAX) {
+			cnss_pr_err("Invalid seg len %u\n",
+				    ind_msg->mem_seg_len);
+			goto free_event_data;
+		}
+		cnss_pr_dbg("QDSS_trace_save seg len %u\n",
+			    ind_msg->mem_seg_len);
+		event_data->mem_seg_len = ind_msg->mem_seg_len;
+		for (i = 0; i < ind_msg->mem_seg_len; i++) {
+			event_data->mem_seg[i].addr = ind_msg->mem_seg[i].addr;
+			event_data->mem_seg[i].size = ind_msg->mem_seg[i].size;
+			cnss_pr_dbg("seg-%d: addr 0x%llx size 0x%x\n",
+				    i, ind_msg->mem_seg[i].addr,
+				    ind_msg->mem_seg[i].size);
+		}
+	}
+
+	event_data->total_size = ind_msg->total_size;
+
+	if (ind_msg->file_name_valid)
+		strlcpy(event_data->file_name, ind_msg->file_name,
+			QDSS_TRACE_FILE_NAME_MAX + 1);
+	else
+		strlcpy(event_data->file_name, "qdss_trace",
+			QDSS_TRACE_FILE_NAME_MAX + 1);
+
+	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_QDSS_TRACE_SAVE,
+			       0, event_data);
+
+	return;
+
+free_event_data:
+	kfree(event_data);
+}
+
+static void cnss_wlfw_qdss_trace_free_ind_cb(struct qmi_handle *qmi_wlfw,
+					     struct sockaddr_qrtr *sq,
+					     struct qmi_txn *txn,
+					     const void *data)
+{
+	struct cnss_plat_data *plat_priv =
+		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
+
+	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_QDSS_TRACE_FREE,
+			       0, NULL);
+}
+
 static struct qmi_msg_handler qmi_wlfw_msg_handlers[] = {
 	{
 		.type = QMI_INDICATION,
@@ -1242,6 +1461,38 @@ static struct qmi_msg_handler qmi_wlfw_msg_handlers[] = {
 		.decoded_size = sizeof(struct wlfw_cal_done_ind_msg_v01),
 		.fn = cnss_wlfw_cal_done_ind_cb
 	},
+	{
+		.type = QMI_INDICATION,
+		.msg_id = QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01,
+		.ei = wlfw_qdss_trace_req_mem_ind_msg_v01_ei,
+		.decoded_size =
+		sizeof(struct wlfw_qdss_trace_req_mem_ind_msg_v01),
+		.fn = cnss_wlfw_qdss_trace_req_mem_ind_cb
+	},
+	{
+		.type = QMI_INDICATION,
+		.msg_id = QMI_WLFW_QDSS_TRACE_SAVE_IND_V01,
+		.ei = wlfw_qdss_trace_save_ind_msg_v01_ei,
+		.decoded_size =
+		sizeof(struct wlfw_qdss_trace_save_ind_msg_v01),
+		.fn = cnss_wlfw_qdss_trace_save_ind_cb
+	},
+	{
+		.type = QMI_INDICATION,
+		.msg_id = QMI_WLFW_QDSS_TRACE_FREE_IND_V01,
+		.ei = wlfw_qdss_trace_free_ind_msg_v01_ei,
+		.decoded_size =
+		sizeof(struct wlfw_qdss_trace_free_ind_msg_v01),
+		.fn = cnss_wlfw_qdss_trace_free_ind_cb
+	},
+	{
+		.type = QMI_INDICATION,
+		.msg_id = QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01,
+		.ei = wlfw_initiate_cal_update_ind_msg_v01_ei,
+		.decoded_size =
+			sizeof(struct wlfw_initiate_cal_update_ind_msg_v01),
+		.fn = cnss_wlfw_initiate_cal_update_ind_cb
+	},
 	{}
 };
 
diff --git a/drivers/net/wireless/cnss2/qmi.h b/drivers/net/wireless/cnss2/qmi.h
index 50a7b1c..276e6d1 100644
--- a/drivers/net/wireless/cnss2/qmi.h
+++ b/drivers/net/wireless/cnss2/qmi.h
@@ -17,14 +17,29 @@
 
 struct cnss_plat_data;
 
-#ifdef CONFIG_CNSS2_QMI
-#include "wlan_firmware_service_v01.h"
-
 struct cnss_qmi_event_server_arrive_data {
 	unsigned int node;
 	unsigned int port;
 };
 
+#define QDSS_TRACE_SEG_LEN_MAX 32
+#define QDSS_TRACE_FILE_NAME_MAX 16
+
+struct cnss_mem_seg {
+	u64 addr;
+	u32 size;
+};
+
+struct cnss_qmi_event_qdss_trace_save_data {
+	u32 total_size;
+	u32 mem_seg_len;
+	struct cnss_mem_seg mem_seg[QDSS_TRACE_SEG_LEN_MAX];
+	char file_name[QDSS_TRACE_FILE_NAME_MAX + 1];
+};
+
+#ifdef CONFIG_CNSS2_QMI
+#include "wlan_firmware_service_v01.h"
+
 int cnss_qmi_init(struct cnss_plat_data *plat_priv);
 void cnss_qmi_deinit(struct cnss_plat_data *plat_priv);
 unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv);
@@ -32,7 +47,8 @@ int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv, void *data);
 int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv);
-int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv);
+int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
+				 u32 bdf_type);
 int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
 				  enum cnss_driver_mode mode);
@@ -47,6 +63,7 @@ int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv,
 				      u32 data_len, u8 *data);
 int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
 			    u8 fw_log_mode);
+int cnss_wlfw_qdss_trace_mem_info_send_sync(struct cnss_plat_data *plat_priv);
 #else
 #define QMI_WLFW_TIMEOUT_MS		10000
 
@@ -87,7 +104,8 @@ static inline int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
 	return 0;
 }
 
-static inline int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv)
+static inline int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
+					       u32 bdf_type)
 {
 	return 0;
 }
@@ -134,6 +152,12 @@ int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
 {
 	return 0;
 }
+
+static inline
+int cnss_wlfw_qdss_trace_mem_info_send_sync(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
 #endif /* CONFIG_CNSS2_QMI */
 
 #endif /* _CNSS_QMI_H */
diff --git a/drivers/net/wireless/cnss2/usb.c b/drivers/net/wireless/cnss2/usb.c
new file mode 100644
index 0000000..0d28ebe
--- /dev/null
+++ b/drivers/net/wireless/cnss2/usb.c
@@ -0,0 +1,361 @@
+/* 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.
+ */
+
+#include "main.h"
+#include "bus.h"
+#include "debug.h"
+#include "usb.h"
+
+int cnss_usb_dev_powerup(struct cnss_usb_data *usb_priv)
+{
+	int ret = 0;
+
+	if (!usb_priv) {
+		cnss_pr_err("usb_priv is NULL\n");
+		return -ENODEV;
+	}
+	return ret;
+}
+
+int cnss_usb_wlan_register_driver(struct cnss_usb_wlan_driver *driver_ops)
+{
+	int ret = 0;
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
+	struct cnss_usb_data *usb_priv;
+
+	if (!plat_priv) {
+		cnss_pr_err("plat_priv is NULL\n");
+		return -ENODEV;
+	}
+
+	usb_priv = plat_priv->bus_priv;
+	if (!usb_priv) {
+		cnss_pr_err("usb_priv is NULL\n");
+		return -ENODEV;
+	}
+
+	if (usb_priv->driver_ops) {
+		cnss_pr_err("Driver has already registered\n");
+		return -EEXIST;
+	}
+
+	ret = cnss_driver_event_post(plat_priv,
+				     CNSS_DRIVER_EVENT_REGISTER_DRIVER,
+				     CNSS_EVENT_SYNC_UNINTERRUPTIBLE,
+				     driver_ops);
+	return ret;
+}
+EXPORT_SYMBOL(cnss_usb_wlan_register_driver);
+
+void cnss_usb_wlan_unregister_driver(struct cnss_usb_wlan_driver *driver_ops)
+{
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
+
+	if (!plat_priv) {
+		cnss_pr_err("plat_priv is NULL\n");
+		return;
+	}
+
+	cnss_driver_event_post(plat_priv,
+			       CNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
+			       CNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
+}
+EXPORT_SYMBOL(cnss_usb_wlan_unregister_driver);
+
+int cnss_usb_register_driver_hdlr(struct cnss_usb_data *usb_priv,
+				  void *data)
+{
+	int ret = 0;
+	struct cnss_plat_data *plat_priv = usb_priv->plat_priv;
+
+	set_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
+	usb_priv->driver_ops = data;
+
+	ret = cnss_bus_call_driver_probe(plat_priv);
+
+	return ret;
+}
+
+int cnss_usb_unregister_driver_hdlr(struct cnss_usb_data *usb_priv)
+{
+	struct cnss_plat_data *plat_priv = usb_priv->plat_priv;
+
+	set_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
+	cnss_usb_dev_shutdown(usb_priv);
+	usb_priv->driver_ops = NULL;
+
+	return 0;
+}
+
+int cnss_usb_dev_shutdown(struct cnss_usb_data *usb_priv)
+{
+	int ret = 0;
+
+	if (!usb_priv) {
+		cnss_pr_err("usb_priv is NULL\n");
+		return -ENODEV;
+	}
+
+	switch (usb_priv->device_id) {
+	case QCN7605_COMPOSITE_DEVICE_ID:
+	case QCN7605_STANDALONE_DEVICE_ID:
+		break;
+	default:
+		cnss_pr_err("Unknown device_id found: 0x%x\n",
+			    usb_priv->device_id);
+		ret = -ENODEV;
+	}
+	return ret;
+}
+
+int cnss_usb_call_driver_probe(struct cnss_usb_data *usb_priv)
+{
+	int ret = 0;
+	struct cnss_plat_data *plat_priv = usb_priv->plat_priv;
+
+	if (!usb_priv->driver_ops) {
+		cnss_pr_err("driver_ops is NULL\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
+	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
+		ret = usb_priv->driver_ops->reinit(usb_priv->usb_intf,
+						   usb_priv->usb_device_id);
+		if (ret) {
+			cnss_pr_err("Failed to reinit host driver, err = %d\n",
+				    ret);
+			goto out;
+		}
+		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
+	} else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)) {
+		ret = usb_priv->driver_ops->probe(usb_priv->usb_intf,
+						  usb_priv->usb_device_id);
+		if (ret) {
+			cnss_pr_err("Failed to probe host driver, err = %d\n",
+				    ret);
+			goto out;
+		}
+		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
+		clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
+		set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
+	}
+
+	return 0;
+
+out:
+	return ret;
+}
+
+int cnss_usb_call_driver_remove(struct cnss_usb_data *usb_priv)
+{
+	struct cnss_plat_data *plat_priv = usb_priv->plat_priv;
+
+	if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) ||
+	    test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state) ||
+	    test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
+		cnss_pr_dbg("Skip driver remove\n");
+		return 0;
+	}
+
+	if (!usb_priv->driver_ops) {
+		cnss_pr_err("driver_ops is NULL\n");
+		return -EINVAL;
+	}
+
+	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
+	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
+		usb_priv->driver_ops->shutdown(usb_priv->usb_intf);
+	} else if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
+		usb_priv->driver_ops->remove(usb_priv->usb_intf);
+		clear_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
+	}
+
+	return 0;
+}
+
+static struct usb_driver cnss_usb_driver;
+#define QCN7605_WLAN_INTERFACE_NUM      0x0000
+
+static int cnss_usb_probe(struct usb_interface *interface,
+			  const struct usb_device_id *id)
+{
+	int ret = 0;
+	struct cnss_usb_data *usb_priv;
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
+	struct usb_device *usb_dev;
+	unsigned short bcd_device;
+
+	cnss_pr_dbg("USB probe, vendor ID: 0x%x, product ID: 0x%x\n",
+		    id->idVendor, id->idProduct);
+
+	usb_dev = interface_to_usbdev(interface);
+	usb_priv = devm_kzalloc(&usb_dev->dev, sizeof(*usb_priv),
+				GFP_KERNEL);
+	if (!usb_priv) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (interface->cur_altsetting->desc.bInterfaceNumber ==
+	    QCN7605_WLAN_INTERFACE_NUM) {
+		if (usb_driver_claim_interface(&cnss_usb_driver,
+					       interface,
+					       NULL)) {
+			ret = -ENODEV;
+			goto reset_priv;
+		}
+	}
+	bcd_device = le16_to_cpu(usb_dev->descriptor.bcdDevice);
+	usb_priv->plat_priv = plat_priv;
+	usb_priv->usb_intf = interface;
+	usb_priv->usb_device_id = id;
+	usb_priv->device_id = id->idProduct;
+	usb_priv->target_version = bcd_device;
+	cnss_set_usb_priv(interface, usb_priv);
+	plat_priv->device_id = usb_priv->device_id;
+	plat_priv->bus_priv = usb_priv;
+
+	/*increment the ref count of usb dev structure*/
+	usb_get_dev(usb_dev);
+
+	ret = cnss_register_subsys(plat_priv);
+	if (ret)
+		goto reset_ctx;
+
+	ret = cnss_register_ramdump(plat_priv);
+	if (ret)
+		goto unregister_subsys;
+
+	switch (usb_priv->device_id) {
+	case QCN7605_COMPOSITE_DEVICE_ID:
+	case QCN7605_STANDALONE_DEVICE_ID:
+		break;
+	default:
+		cnss_pr_err("Unknown USB device found: 0x%x\n",
+			    usb_priv->device_id);
+		ret = -ENODEV;
+		goto unregister_ramdump;
+	}
+
+	return 0;
+
+unregister_ramdump:
+	cnss_unregister_ramdump(plat_priv);
+unregister_subsys:
+	cnss_unregister_subsys(plat_priv);
+reset_ctx:
+	plat_priv->bus_priv = NULL;
+reset_priv:
+	devm_kfree(&usb_dev->dev, usb_priv);
+out:
+	return ret;
+}
+
+static void cnss_usb_remove(struct usb_interface *interface)
+{
+	struct usb_device *usb_dev;
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
+	struct cnss_usb_data *usb_priv = plat_priv->bus_priv;
+
+	usb_priv->plat_priv = NULL;
+	plat_priv->bus_priv = NULL;
+	usb_dev = interface_to_usbdev(interface);
+	usb_put_dev(usb_dev);
+	devm_kfree(&usb_dev->dev, usb_priv);
+}
+
+static int cnss_usb_suspend(struct usb_interface *interface, pm_message_t state)
+{
+	int ret = 0;
+	struct cnss_usb_data *usb_priv;
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
+
+	usb_priv = plat_priv->bus_priv;
+	if (!usb_priv->driver_ops) {
+		cnss_pr_err("driver_ops is NULL\n");
+		ret = -EINVAL;
+		goto out;
+	}
+	ret = usb_priv->driver_ops->suspend(usb_priv->usb_intf,
+						  state);
+out:
+	return ret;
+}
+
+static int cnss_usb_resume(struct usb_interface *interface)
+{
+	int ret = 0;
+	struct cnss_usb_data *usb_priv;
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
+
+	usb_priv = plat_priv->bus_priv;
+	if (!usb_priv->driver_ops) {
+		cnss_pr_err("driver_ops is NULL\n");
+		ret = -EINVAL;
+		goto out;
+	}
+	ret = usb_priv->driver_ops->resume(usb_priv->usb_intf);
+
+out:
+	return ret;
+}
+
+static int cnss_usb_reset_resume(struct usb_interface *interface)
+{
+	return 0;
+}
+
+static struct usb_device_id cnss_usb_id_table[] = {
+	{ USB_DEVICE_AND_INTERFACE_INFO(QCN7605_USB_VENDOR_ID,
+				       QCN7605_COMPOSITE_PRODUCT_ID,
+				       QCN7605_WLAN_INTERFACE_NUM,
+				       0xFF, 0xFF) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(QCN7605_USB_VENDOR_ID,
+				       QCN7605_STANDALONE_PRODUCT_ID,
+				       QCN7605_WLAN_INTERFACE_NUM,
+				       0xFF, 0xFF) },
+	{}			/* Terminating entry */
+};
+
+static struct usb_driver cnss_usb_driver = {
+	.name       = "cnss_usb",
+	.id_table   = cnss_usb_id_table,
+	.probe      = cnss_usb_probe,
+	.disconnect = cnss_usb_remove,
+	.suspend    = cnss_usb_suspend,
+	.resume     = cnss_usb_resume,
+	.reset_resume = cnss_usb_reset_resume,
+	.supports_autosuspend = true,
+};
+
+int cnss_usb_init(struct cnss_plat_data *plat_priv)
+{
+	int ret = 0;
+
+	ret = usb_register(&cnss_usb_driver);
+	if (ret) {
+		cnss_pr_err("Failed to register to Linux USB framework, err = %d\n",
+			    ret);
+		goto out;
+	}
+
+	return 0;
+out:
+	return ret;
+}
+
+void cnss_usb_deinit(struct cnss_plat_data *plat_priv)
+{
+	usb_deregister(&cnss_usb_driver);
+}
diff --git a/drivers/net/wireless/cnss2/usb.h b/drivers/net/wireless/cnss2/usb.h
new file mode 100644
index 0000000..dd1c7f4
--- /dev/null
+++ b/drivers/net/wireless/cnss2/usb.h
@@ -0,0 +1,66 @@
+/* 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.
+ */
+
+#ifndef _CNSS_USB_H
+#define _CNSS_USB_H
+
+#include <linux/usb.h>
+
+#include "main.h"
+
+struct cnss_usb_data {
+	struct usb_interface *usb_intf;
+	struct cnss_plat_data *plat_priv;
+	const struct usb_device_id *usb_device_id;
+	u16 device_id; /*USB PID*/
+	u16 target_version; /* [QCN7605] - from bcdDevice*/
+	struct cnss_usb_wlan_driver *driver_ops;
+};
+
+static inline void cnss_set_usb_priv(struct usb_interface *usb_intf, void *data)
+{
+	usb_set_intfdata(usb_intf, data);
+}
+
+static inline struct cnss_usb_data *cnss_get_usb_priv(struct usb_interface
+						      *usb_intf)
+{
+	return usb_get_intfdata(usb_intf);
+}
+
+static inline struct cnss_plat_data *cnss_usb_priv_to_plat_priv(void *bus_priv)
+{
+	struct cnss_usb_data *usb_priv = bus_priv;
+
+	return usb_priv->plat_priv;
+}
+
+int cnss_usb_init(struct cnss_plat_data *plat_priv);
+void cnss_usb_deinit(struct cnss_plat_data *plat_priv);
+void cnss_usb_collect_dump_info(struct cnss_usb_data *usb_priv, bool in_panic);
+void cnss_usb_clear_dump_info(struct cnss_usb_data *usb_priv);
+int cnss_usb_force_fw_assert_hdlr(struct cnss_usb_data *usb_priv);
+void cnss_usb_fw_boot_timeout_hdlr(struct cnss_usb_data *usb_priv);
+int cnss_usb_call_driver_probe(struct cnss_usb_data *usb_priv);
+int cnss_usb_call_driver_remove(struct cnss_usb_data *usb_priv);
+int cnss_usb_dev_powerup(struct cnss_usb_data *usb_priv);
+int cnss_usb_dev_shutdown(struct cnss_usb_data *usb_priv);
+int cnss_usb_dev_crash_shutdown(struct cnss_usb_data *usb_priv);
+int cnss_usb_dev_ramdump(struct cnss_usb_data *usb_priv);
+
+int cnss_usb_register_driver_hdlr(struct cnss_usb_data *usb_priv, void *data);
+
+int cnss_usb_unregister_driver_hdlr(struct cnss_usb_data *usb_priv);
+int cnss_usb_call_driver_modem_status(struct cnss_usb_data *usb_priv,
+				      int modem_current_status);
+
+#endif /* _CNSS_USB_H */
diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c
index cc2ce60..f22c8ae 100644
--- a/drivers/net/wireless/st/cw1200/scan.c
+++ b/drivers/net/wireless/st/cw1200/scan.c
@@ -78,6 +78,10 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
 	if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS)
 		return -EINVAL;
 
+	/* will be unlocked in cw1200_scan_work() */
+	down(&priv->scan.lock);
+	mutex_lock(&priv->conf_mutex);
+
 	frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
 		req->ie_len);
 	if (!frame.skb)
@@ -86,19 +90,15 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
 	if (req->ie_len)
 		skb_put_data(frame.skb, req->ie, req->ie_len);
 
-	/* will be unlocked in cw1200_scan_work() */
-	down(&priv->scan.lock);
-	mutex_lock(&priv->conf_mutex);
-
 	ret = wsm_set_template_frame(priv, &frame);
 	if (!ret) {
 		/* Host want to be the probe responder. */
 		ret = wsm_set_probe_responder(priv, true);
 	}
 	if (ret) {
+		dev_kfree_skb(frame.skb);
 		mutex_unlock(&priv->conf_mutex);
 		up(&priv->scan.lock);
-		dev_kfree_skb(frame.skb);
 		return ret;
 	}
 
@@ -120,10 +120,9 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
 		++priv->scan.n_ssids;
 	}
 
-	mutex_unlock(&priv->conf_mutex);
-
 	if (frame.skb)
 		dev_kfree_skb(frame.skb);
+	mutex_unlock(&priv->conf_mutex);
 	queue_work(priv->workqueue, &priv->scan.work);
 	return 0;
 }
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index afb9987..06355ca 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -1624,8 +1624,9 @@ static void nvme_free_host_mem(struct nvme_dev *dev)
 		struct nvme_host_mem_buf_desc *desc = &dev->host_mem_descs[i];
 		size_t size = le32_to_cpu(desc->size) * dev->ctrl.page_size;
 
-		dma_free_coherent(dev->dev, size, dev->host_mem_desc_bufs[i],
-				le64_to_cpu(desc->addr));
+		dma_free_attrs(dev->dev, size, dev->host_mem_desc_bufs[i],
+			       le64_to_cpu(desc->addr),
+			       DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
 	}
 
 	kfree(dev->host_mem_desc_bufs);
@@ -1691,8 +1692,9 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
 	while (--i >= 0) {
 		size_t size = le32_to_cpu(descs[i].size) * dev->ctrl.page_size;
 
-		dma_free_coherent(dev->dev, size, bufs[i],
-				le64_to_cpu(descs[i].addr));
+		dma_free_attrs(dev->dev, size, bufs[i],
+			       le64_to_cpu(descs[i].addr),
+			       DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
 	}
 
 	kfree(bufs);
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
index 5d8140e..da56cc2 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
@@ -137,6 +137,10 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc);
 static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc);
 static void nvmet_rdma_qp_event(struct ib_event *event, void *priv);
 static void nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue);
+static void nvmet_rdma_free_rsp(struct nvmet_rdma_device *ndev,
+				struct nvmet_rdma_rsp *r);
+static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev,
+				struct nvmet_rdma_rsp *r);
 
 static struct nvmet_fabrics_ops nvmet_rdma_ops;
 
@@ -175,9 +179,17 @@ nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue)
 	spin_unlock_irqrestore(&queue->rsps_lock, flags);
 
 	if (unlikely(!rsp)) {
-		rsp = kmalloc(sizeof(*rsp), GFP_KERNEL);
+		int ret;
+
+		rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
 		if (unlikely(!rsp))
 			return NULL;
+		ret = nvmet_rdma_alloc_rsp(queue->dev, rsp);
+		if (unlikely(ret)) {
+			kfree(rsp);
+			return NULL;
+		}
+
 		rsp->allocated = true;
 	}
 
@@ -189,7 +201,8 @@ nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp)
 {
 	unsigned long flags;
 
-	if (rsp->allocated) {
+	if (unlikely(rsp->allocated)) {
+		nvmet_rdma_free_rsp(rsp->queue->dev, rsp);
 		kfree(rsp);
 		return;
 	}
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index e9ec931..89115b2 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -8,6 +8,20 @@
 #include <linux/of_pci.h>
 #include <linux/slab.h>
 
+static inline bool __of_pci_pci_compare_id(struct device_node *node,
+					struct pci_dev *dev)
+{
+	char dev_id_str[10];
+
+	scnprintf(dev_id_str, sizeof(dev_id_str), "%04x:%04x", dev->vendor,
+		dev->device);
+
+	if (of_property_match_string(node, "pci-ids", dev_id_str) < 0)
+		return false;
+
+	return true;
+}
+
 static inline int __of_pci_pci_compare(struct device_node *node,
 				       unsigned int data)
 {
@@ -20,14 +34,17 @@ static inline int __of_pci_pci_compare(struct device_node *node,
 	return devfn == data;
 }
 
-struct device_node *of_pci_find_child_device(struct device_node *parent,
-					     unsigned int devfn)
+struct device_node *of_pci_find_child_device(struct pci_dev *dev)
 {
 	struct device_node *node, *node2;
+	struct device_node *parent = dev->bus->dev.of_node;
+	unsigned int devfn = dev->devfn;
 
 	for_each_child_of_node(parent, node) {
 		if (__of_pci_pci_compare(node, devfn))
-			return node;
+			if (__of_pci_pci_compare_id(node, dev))
+				return node;
+
 		/*
 		 * Some OFs create a parent node "multifunc-device" as
 		 * a fake root for all functions of a multi-function
diff --git a/drivers/of/property.c b/drivers/of/property.c
index 264c355..fd9b734 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -810,6 +810,7 @@ struct device_node *of_graph_get_remote_node(const struct device_node *node,
 
 	if (!of_device_is_available(remote)) {
 		pr_debug("not available for remote node\n");
+		of_node_put(remote);
 		return NULL;
 	}
 
diff --git a/drivers/pci/dwc/pcie-designware-host.c b/drivers/pci/dwc/pcie-designware-host.c
index bc3e2d8..58b38c5 100644
--- a/drivers/pci/dwc/pcie-designware-host.c
+++ b/drivers/pci/dwc/pcie-designware-host.c
@@ -45,8 +45,19 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
 	return dw_pcie_write(pci->dbi_base + where, size, val);
 }
 
+static void dwc_irq_ack(struct irq_data *d)
+{
+	struct msi_desc *msi = irq_data_get_msi_desc(d);
+	struct pcie_port *pp = msi_desc_to_pci_sysdata(msi);
+	int pos = d->hwirq % 32;
+	int i = d->hwirq / 32;
+
+	dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, BIT(pos));
+}
+
 static struct irq_chip dw_msi_irq_chip = {
 	.name = "PCI-MSI",
+	.irq_ack = dwc_irq_ack,
 	.irq_enable = pci_msi_unmask_irq,
 	.irq_disable = pci_msi_mask_irq,
 	.irq_mask = pci_msi_mask_irq,
@@ -72,8 +83,6 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
 					    pos)) != 32) {
 			irq = irq_find_mapping(pp->irq_domain, i * 32 + pos);
 			generic_handle_irq(irq);
-			dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12,
-					    4, 1 << pos);
 			pos++;
 		}
 	}
@@ -263,7 +272,7 @@ static struct msi_controller dw_pcie_msi_chip = {
 static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
 			   irq_hw_number_t hwirq)
 {
-	irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq);
+	irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_edge_irq);
 	irq_set_chip_data(irq, domain->host_data);
 
 	return 0;
diff --git a/drivers/pci/host/pci-msm-msi.c b/drivers/pci/host/pci-msm-msi.c
index 16713d12..98d27c0 100644
--- a/drivers/pci/host/pci-msm-msi.c
+++ b/drivers/pci/host/pci-msm-msi.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
@@ -123,10 +123,40 @@ static void msm_msi_qgic_handler(struct irq_desc *desc)
 	chained_irq_exit(chip, desc);
 }
 
+static void msm_msi_mask_irq(struct irq_data *data)
+{
+	struct irq_data *parent_data;
+
+	if (!data->parent_data)
+		return;
+
+	parent_data = irq_get_irq_data(data->parent_data->hwirq);
+	if (!parent_data || !parent_data->chip)
+		return;
+
+	pci_msi_mask_irq(data);
+	parent_data->chip->irq_mask(parent_data);
+}
+
+static void msm_msi_unmask_irq(struct irq_data *data)
+{
+	struct irq_data *parent_data;
+
+	if (!data->parent_data)
+		return;
+
+	parent_data = irq_get_irq_data(data->parent_data->hwirq);
+	if (!parent_data || !parent_data->chip)
+		return;
+
+	parent_data->chip->irq_unmask(parent_data);
+	pci_msi_unmask_irq(data);
+}
+
 static struct irq_chip msm_msi_irq_chip = {
 	.name = "msm_pci_msi",
-	.irq_mask = pci_msi_mask_irq,
-	.irq_unmask = pci_msi_unmask_irq,
+	.irq_mask = msm_msi_mask_irq,
+	.irq_unmask = msm_msi_unmask_irq,
 };
 
 static int msm_msi_domain_prepare(struct irq_domain *domain, struct device *dev,
@@ -297,6 +327,10 @@ static int msm_msi_irq_domain_alloc(struct irq_domain *domain,
 				msi_irq->hwirq,
 				&msm_msi_bottom_irq_chip, msi_irq,
 				handle_simple_irq, NULL, NULL);
+
+		if (msi->type == MSM_MSI_TYPE_QCOM)
+			irq_set_status_flags(msi_irq->virq, IRQ_DISABLE_UNLAZY);
+
 		client->nr_irqs++;
 		pos++;
 	}
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index e6731ba..cd86fa1 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -22,8 +22,7 @@ void pci_set_of_node(struct pci_dev *dev)
 {
 	if (!dev->bus->dev.of_node)
 		return;
-	dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
-						    dev->devfn);
+	dev->dev.of_node = of_pci_find_child_device(dev);
 
 	if (dev->dev.of_node)
 		of_reserved_mem_device_init_by_idx(&dev->dev, dev->dev.of_node,
diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 620f5b9..e3aefda 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -1064,6 +1064,7 @@ static int ioctl_event_ctl(struct switchtec_dev *stdev,
 {
 	int ret;
 	int nr_idxs;
+	unsigned int event_flags;
 	struct switchtec_ioctl_event_ctl ctl;
 
 	if (copy_from_user(&ctl, uctl, sizeof(ctl)))
@@ -1085,7 +1086,9 @@ static int ioctl_event_ctl(struct switchtec_dev *stdev,
 		else
 			return -EINVAL;
 
+		event_flags = ctl.flags;
 		for (ctl.index = 0; ctl.index < nr_idxs; ctl.index++) {
+			ctl.flags = event_flags;
 			ret = event_ctl(stdev, &ctl);
 			if (ret < 0)
 				return ret;
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index afedb8c..d1ccff5 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -125,6 +125,7 @@ struct sun4i_usb_phy_cfg {
 	bool dedicated_clocks;
 	bool enable_pmu_unk1;
 	bool phy0_dual_route;
+	int missing_phys;
 };
 
 struct sun4i_usb_phy_data {
@@ -645,6 +646,9 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev,
 	if (args->args[0] >= data->cfg->num_phys)
 		return ERR_PTR(-ENODEV);
 
+	if (data->cfg->missing_phys & BIT(args->args[0]))
+		return ERR_PTR(-ENODEV);
+
 	return data->phys[args->args[0]].phy;
 }
 
@@ -740,6 +744,9 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 		struct sun4i_usb_phy *phy = data->phys + i;
 		char name[16];
 
+		if (data->cfg->missing_phys & BIT(i))
+			continue;
+
 		snprintf(name, sizeof(name), "usb%d_vbus", i);
 		phy->vbus = devm_regulator_get_optional(dev, name);
 		if (IS_ERR(phy->vbus)) {
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs.c b/drivers/phy/qualcomm/phy-qcom-ufs.c
index 6028f6e..f70871f 100644
--- a/drivers/phy/qualcomm/phy-qcom-ufs.c
+++ b/drivers/phy/qualcomm/phy-qcom-ufs.c
@@ -221,10 +221,12 @@ int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common)
 	__ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk_parent",
 				   &phy_common->ref_clk_parent, false);
 
-	err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk",
-				   &phy_common->ref_clk);
-	if (err)
-		goto out;
+	/*
+	 * Some platforms may not have the ON/OFF control for reference clock,
+	 * hence this clock may be optional.
+	 */
+	__ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk",
+				   &phy_common->ref_clk, false);
 
 	/*
 	 * "ref_aux_clk" is optional and only supported by certain
@@ -414,11 +416,17 @@ static int ufs_qcom_phy_enable_ref_clk(struct ufs_qcom_phy *phy)
 		}
 	}
 
-	ret = clk_prepare_enable(phy->ref_clk);
-	if (ret) {
-		dev_err(phy->dev, "%s: ref_clk enable failed %d\n",
-				__func__, ret);
-		goto out_disable_parent;
+	/*
+	 * "ref_clk" is optional clock hence make sure that clk reference
+	 * is available before trying to enable the clock.
+	 */
+	if (phy->ref_clk) {
+		ret = clk_prepare_enable(phy->ref_clk);
+		if (ret) {
+			dev_err(phy->dev, "%s: ref_clk enable failed %d\n",
+					__func__, ret);
+			goto out_disable_parent;
+		}
 	}
 
 	/*
@@ -455,9 +463,26 @@ static int ufs_qcom_phy_disable_vreg(struct device *dev,
 {
 	int ret = 0;
 
-	if (!vreg || !vreg->enabled || vreg->is_always_on)
+	if (!vreg || !vreg->enabled)
 		goto out;
 
+	if (vreg->is_always_on) {
+		/* voting 0 uA load will keep regulator in LPM mode */
+		ret = regulator_set_load(vreg->reg, 0);
+		if (ret >= 0) {
+			/*
+			 * regulator_set_load() returns new regulator
+			 * mode upon success.
+			 */
+			ret = 0;
+		} else {
+			dev_err(dev, "%s: %s set optimum mode(uA_load=0) failed, err=%d\n",
+					__func__, vreg->name, ret);
+		}
+
+		goto out;
+	}
+
 	ret = regulator_disable(vreg->reg);
 
 	if (!ret) {
@@ -482,7 +507,14 @@ static void ufs_qcom_phy_disable_ref_clk(struct ufs_qcom_phy *phy)
 		 */
 		if (phy->ref_aux_clk)
 			clk_disable_unprepare(phy->ref_aux_clk);
-		clk_disable_unprepare(phy->ref_clk);
+
+		/*
+		 * "ref_clk" is optional clock hence make sure that clk
+		 * reference is available before trying to disable the clock.
+		 */
+		if (phy->ref_clk)
+			clk_disable_unprepare(phy->ref_clk);
+
 		/*
 		 * "ref_clk_parent" is optional clock hence make sure that clk
 		 * reference is available before trying to disable the clock.
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index 63e916d..11aa590 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -418,7 +418,7 @@ tegra_xusb_port_find_lane(struct tegra_xusb_port *port,
 {
 	struct tegra_xusb_lane *lane, *match = ERR_PTR(-ENODEV);
 
-	for (map = map; map->type; map++) {
+	for (; map->type; map++) {
 		if (port->index != map->port)
 			continue;
 
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index ff782445..e72bf25 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -92,7 +92,7 @@ struct bcm2835_pinctrl {
 	struct gpio_chip gpio_chip;
 	struct pinctrl_gpio_range gpio_range;
 
-	spinlock_t irq_lock[BCM2835_NUM_BANKS];
+	raw_spinlock_t irq_lock[BCM2835_NUM_BANKS];
 };
 
 /* pins are just named GPIO0..GPIO53 */
@@ -471,10 +471,10 @@ static void bcm2835_gpio_irq_enable(struct irq_data *data)
 	unsigned bank = GPIO_REG_OFFSET(gpio);
 	unsigned long flags;
 
-	spin_lock_irqsave(&pc->irq_lock[bank], flags);
+	raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
 	set_bit(offset, &pc->enabled_irq_map[bank]);
 	bcm2835_gpio_irq_config(pc, gpio, true);
-	spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
+	raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
 }
 
 static void bcm2835_gpio_irq_disable(struct irq_data *data)
@@ -486,12 +486,12 @@ static void bcm2835_gpio_irq_disable(struct irq_data *data)
 	unsigned bank = GPIO_REG_OFFSET(gpio);
 	unsigned long flags;
 
-	spin_lock_irqsave(&pc->irq_lock[bank], flags);
+	raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
 	bcm2835_gpio_irq_config(pc, gpio, false);
 	/* Clear events that were latched prior to clearing event sources */
 	bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
 	clear_bit(offset, &pc->enabled_irq_map[bank]);
-	spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
+	raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
 }
 
 static int __bcm2835_gpio_irq_set_type_disabled(struct bcm2835_pinctrl *pc,
@@ -594,7 +594,7 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&pc->irq_lock[bank], flags);
+	raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
 
 	if (test_bit(offset, &pc->enabled_irq_map[bank]))
 		ret = __bcm2835_gpio_irq_set_type_enabled(pc, gpio, type);
@@ -606,7 +606,7 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
 	else
 		irq_set_handler_locked(data, handle_level_irq);
 
-	spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
+	raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
 
 	return ret;
 }
@@ -1021,7 +1021,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
 		for_each_set_bit(offset, &events, 32)
 			bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset));
 
-		spin_lock_init(&pc->irq_lock[i]);
+		raw_spin_lock_init(&pc->irq_lock[i]);
 	}
 
 	err = gpiochip_add_data(&pc->gpio_chip, pc);
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 6c43322..2998941 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -272,7 +272,8 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
 		case PIN_CONFIG_BIAS_DISABLE:
 			dev_dbg(pc->dev, "pin %u: disable bias\n", pin);
 
-			meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
+			meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg,
+					       &bit);
 			ret = regmap_update_bits(pc->reg_pullen, reg,
 						 BIT(bit), 0);
 			if (ret)
diff --git a/drivers/pinctrl/meson/pinctrl-meson8.c b/drivers/pinctrl/meson/pinctrl-meson8.c
index 970f6f1..591b016 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8.c
@@ -808,7 +808,9 @@ static const char * const gpio_groups[] = {
 	"BOOT_5", "BOOT_6", "BOOT_7", "BOOT_8", "BOOT_9",
 	"BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14",
 	"BOOT_15", "BOOT_16", "BOOT_17", "BOOT_18",
+};
 
+static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3",
 	"GPIOAO_4", "GPIOAO_5", "GPIOAO_6", "GPIOAO_7",
 	"GPIOAO_8", "GPIOAO_9", "GPIOAO_10", "GPIOAO_11",
@@ -1030,6 +1032,7 @@ static struct meson_pmx_func meson8_cbus_functions[] = {
 };
 
 static struct meson_pmx_func meson8_aobus_functions[] = {
+	FUNCTION(gpio_aobus),
 	FUNCTION(uart_ao),
 	FUNCTION(remote),
 	FUNCTION(i2c_slave_ao),
diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c
index 71f216b..a6fff21 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8b.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8b.c
@@ -649,16 +649,18 @@ static const char * const gpio_groups[] = {
 	"BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14",
 	"BOOT_15", "BOOT_16", "BOOT_17", "BOOT_18",
 
-	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3",
-	"GPIOAO_4", "GPIOAO_5", "GPIOAO_6", "GPIOAO_7",
-	"GPIOAO_8", "GPIOAO_9", "GPIOAO_10", "GPIOAO_11",
-	"GPIOAO_12", "GPIOAO_13", "GPIO_BSD_EN", "GPIO_TEST_N",
-
 	"DIF_0_P", "DIF_0_N", "DIF_1_P", "DIF_1_N",
 	"DIF_2_P", "DIF_2_N", "DIF_3_P", "DIF_3_N",
 	"DIF_4_P", "DIF_4_N"
 };
 
+static const char * const gpio_aobus_groups[] = {
+	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3",
+	"GPIOAO_4", "GPIOAO_5", "GPIOAO_6", "GPIOAO_7",
+	"GPIOAO_8", "GPIOAO_9", "GPIOAO_10", "GPIOAO_11",
+	"GPIOAO_12", "GPIOAO_13", "GPIO_BSD_EN", "GPIO_TEST_N"
+};
+
 static const char * const sd_a_groups[] = {
 	"sd_d0_a", "sd_d1_a", "sd_d2_a", "sd_d3_a", "sd_clk_a",
 	"sd_cmd_a"
@@ -874,6 +876,7 @@ static struct meson_pmx_func meson8b_cbus_functions[] = {
 };
 
 static struct meson_pmx_func meson8b_aobus_functions[] = {
+	FUNCTION(gpio_aobus),
 	FUNCTION(uart_ao),
 	FUNCTION(uart_ao_b),
 	FUNCTION(i2c_slave_ao),
diff --git a/drivers/pinctrl/pinctrl-max77620.c b/drivers/pinctrl/pinctrl-max77620.c
index b8d2180a..baef91a 100644
--- a/drivers/pinctrl/pinctrl-max77620.c
+++ b/drivers/pinctrl/pinctrl-max77620.c
@@ -34,14 +34,12 @@ enum max77620_pin_ppdrv {
 	MAX77620_PIN_PP_DRV,
 };
 
-enum max77620_pinconf_param {
-	MAX77620_ACTIVE_FPS_SOURCE = PIN_CONFIG_END + 1,
-	MAX77620_ACTIVE_FPS_POWER_ON_SLOTS,
-	MAX77620_ACTIVE_FPS_POWER_DOWN_SLOTS,
-	MAX77620_SUSPEND_FPS_SOURCE,
-	MAX77620_SUSPEND_FPS_POWER_ON_SLOTS,
-	MAX77620_SUSPEND_FPS_POWER_DOWN_SLOTS,
-};
+#define MAX77620_ACTIVE_FPS_SOURCE		(PIN_CONFIG_END + 1)
+#define MAX77620_ACTIVE_FPS_POWER_ON_SLOTS	(PIN_CONFIG_END + 2)
+#define MAX77620_ACTIVE_FPS_POWER_DOWN_SLOTS	(PIN_CONFIG_END + 3)
+#define MAX77620_SUSPEND_FPS_SOURCE		(PIN_CONFIG_END + 4)
+#define MAX77620_SUSPEND_FPS_POWER_ON_SLOTS	(PIN_CONFIG_END + 5)
+#define MAX77620_SUSPEND_FPS_POWER_DOWN_SLOTS	(PIN_CONFIG_END + 6)
 
 struct max77620_pin_function {
 	const char *name;
diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c
index 70a0228..2d0f4f7 100644
--- a/drivers/pinctrl/pinctrl-sx150x.c
+++ b/drivers/pinctrl/pinctrl-sx150x.c
@@ -1166,7 +1166,6 @@ static int sx150x_probe(struct i2c_client *client,
 	}
 
 	/* Register GPIO controller */
-	pctl->gpio.label = devm_kstrdup(dev, client->name, GFP_KERNEL);
 	pctl->gpio.base = -1;
 	pctl->gpio.ngpio = pctl->data->npins;
 	pctl->gpio.get_direction = sx150x_gpio_get_direction;
@@ -1180,6 +1179,10 @@ static int sx150x_probe(struct i2c_client *client,
 	pctl->gpio.of_node = dev->of_node;
 #endif
 	pctl->gpio.can_sleep = true;
+	pctl->gpio.label = devm_kstrdup(dev, client->name, GFP_KERNEL);
+	if (!pctl->gpio.label)
+		return -ENOMEM;
+
 	/*
 	 * Setting multiple pins is not safe when all pins are not
 	 * handled by the same regmap register. The oscio pin (present
@@ -1200,13 +1203,15 @@ static int sx150x_probe(struct i2c_client *client,
 
 	/* Add Interrupt support if an irq is specified */
 	if (client->irq > 0) {
-		pctl->irq_chip.name = devm_kstrdup(dev, client->name,
-						   GFP_KERNEL);
 		pctl->irq_chip.irq_mask = sx150x_irq_mask;
 		pctl->irq_chip.irq_unmask = sx150x_irq_unmask;
 		pctl->irq_chip.irq_set_type = sx150x_irq_set_type;
 		pctl->irq_chip.irq_bus_lock = sx150x_irq_bus_lock;
 		pctl->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
+		pctl->irq_chip.name = devm_kstrdup(dev, client->name,
+						   GFP_KERNEL);
+		if (!pctl->irq_chip.name)
+			return -ENOMEM;
 
 		pctl->irq.masked = ~0;
 		pctl->irq.sense = 0;
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index bf52590..a462ca9 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -189,6 +189,15 @@
 	  Qualcomm Technologies Inc TLMM block found on the Qualcomm
 	  Technologies Inc SM6150 platform.
 
+config PINCTRL_ATOLL
+	tristate "Qualcomm Technologies Inc ATOLL pin controller driver"
+	depends on GPIOLIB && OF
+	select PINCTRL_MSM
+	help
+	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+	  Qualcomm Technologies Inc TLMM block found on the Qualcomm
+	  Technologies Inc ATOLL platform.
+
 config PINCTRL_TRINKET
 	tristate "Qualcomm Technologies Inc TRINKET pin controller driver"
 	depends on GPIOLIB && OF
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 0156e56..b927708 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -22,6 +22,7 @@
 obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o
 obj-$(CONFIG_PINCTRL_SDMSHRIKE) += pinctrl-sdmshrike.o
 obj-$(CONFIG_PINCTRL_SM6150) += pinctrl-sm6150.o
+obj-$(CONFIG_PINCTRL_ATOLL) += pinctrl-atoll.o
 obj-$(CONFIG_PINCTRL_TRINKET) += pinctrl-trinket.o
 obj-$(CONFIG_PINCTRL_SDXPRAIRIE) += pinctrl-sdxprairie.o
 obj-$(CONFIG_PINCTRL_SDMMAGPIE) += pinctrl-sdmmagpie.o
diff --git a/drivers/pinctrl/qcom/pinctrl-atoll.c b/drivers/pinctrl/qcom/pinctrl-atoll.c
new file mode 100644
index 0000000..726f329
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-atoll.c
@@ -0,0 +1,1465 @@
+/*
+ * 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 <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+#define FUNCTION(fname)					\
+	[msm_mux_##fname] = {				\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+#define NORTH	0x00500000
+#define SOUTH	0x00900000
+#define WEST	0x00100000
+#define DUMMY	0x0
+#define REG_SIZE 0x1000
+#define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9)	\
+	{						\
+		.name = "gpio" #id,			\
+		.pins = gpio##id##_pins,		\
+		.npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins),	\
+		.funcs = (int[]){			\
+			msm_mux_gpio, /* gpio mode */	\
+			msm_mux_##f1,			\
+			msm_mux_##f2,			\
+			msm_mux_##f3,			\
+			msm_mux_##f4,			\
+			msm_mux_##f5,			\
+			msm_mux_##f6,			\
+			msm_mux_##f7,			\
+			msm_mux_##f8,			\
+			msm_mux_##f9			\
+		},					\
+		.nfuncs = 10,				\
+		.ctl_reg = base + REG_SIZE * id,		\
+		.io_reg = base + 0x4 + REG_SIZE * id,		\
+		.intr_cfg_reg = base + 0x8 + REG_SIZE * id,	\
+		.intr_status_reg = base + 0xc + REG_SIZE * id,	\
+		.intr_target_reg = base + 0x8 + REG_SIZE * id,	\
+		.mux_bit = 2,			\
+		.pull_bit = 0,			\
+		.drv_bit = 6,			\
+		.oe_bit = 9,			\
+		.in_bit = 0,			\
+		.out_bit = 1,			\
+		.intr_enable_bit = 0,		\
+		.intr_status_bit = 0,		\
+		.intr_target_bit = 5,		\
+		.intr_target_kpss_val = 3,	\
+		.intr_raw_status_bit = 4,	\
+		.intr_polarity_bit = 1,		\
+		.intr_detection_bit = 2,	\
+		.intr_detection_width = 2,	\
+	}
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv)	\
+	{						\
+		.name = #pg_name,			\
+		.pins = pg_name##_pins,			\
+		.npins = (unsigned int)ARRAY_SIZE(pg_name##_pins),	\
+		.ctl_reg = ctl,				\
+		.io_reg = 0,				\
+		.intr_cfg_reg = 0,			\
+		.intr_status_reg = 0,			\
+		.intr_target_reg = 0,			\
+		.mux_bit = -1,				\
+		.pull_bit = pull,			\
+		.drv_bit = drv,				\
+		.oe_bit = -1,				\
+		.in_bit = -1,				\
+		.out_bit = -1,				\
+		.intr_enable_bit = -1,			\
+		.intr_status_bit = -1,			\
+		.intr_target_bit = -1,			\
+		.intr_raw_status_bit = -1,		\
+		.intr_polarity_bit = -1,		\
+		.intr_detection_bit = -1,		\
+		.intr_detection_width = -1,		\
+	}
+
+#define UFS_RESET(pg_name, offset)				\
+	{						\
+		.name = #pg_name,			\
+		.pins = pg_name##_pins,			\
+		.npins = (unsigned int)ARRAY_SIZE(pg_name##_pins),	\
+		.ctl_reg = offset,			\
+		.io_reg = offset + 0x4,			\
+		.intr_cfg_reg = 0,			\
+		.intr_status_reg = 0,			\
+		.intr_target_reg = 0,			\
+		.mux_bit = -1,				\
+		.pull_bit = 3,				\
+		.drv_bit = 0,				\
+		.oe_bit = -1,				\
+		.in_bit = -1,				\
+		.out_bit = 0,				\
+		.intr_enable_bit = -1,			\
+		.intr_status_bit = -1,			\
+		.intr_target_bit = -1,			\
+		.intr_raw_status_bit = -1,		\
+		.intr_polarity_bit = -1,		\
+		.intr_detection_bit = -1,		\
+		.intr_detection_width = -1,		\
+	}
+static const struct pinctrl_pin_desc atoll_pins[] = {
+	PINCTRL_PIN(0, "GPIO_0"),
+	PINCTRL_PIN(1, "GPIO_1"),
+	PINCTRL_PIN(2, "GPIO_2"),
+	PINCTRL_PIN(3, "GPIO_3"),
+	PINCTRL_PIN(4, "GPIO_4"),
+	PINCTRL_PIN(5, "GPIO_5"),
+	PINCTRL_PIN(6, "GPIO_6"),
+	PINCTRL_PIN(7, "GPIO_7"),
+	PINCTRL_PIN(8, "GPIO_8"),
+	PINCTRL_PIN(9, "GPIO_9"),
+	PINCTRL_PIN(10, "GPIO_10"),
+	PINCTRL_PIN(11, "GPIO_11"),
+	PINCTRL_PIN(12, "GPIO_12"),
+	PINCTRL_PIN(13, "GPIO_13"),
+	PINCTRL_PIN(14, "GPIO_14"),
+	PINCTRL_PIN(15, "GPIO_15"),
+	PINCTRL_PIN(16, "GPIO_16"),
+	PINCTRL_PIN(17, "GPIO_17"),
+	PINCTRL_PIN(18, "GPIO_18"),
+	PINCTRL_PIN(19, "GPIO_19"),
+	PINCTRL_PIN(20, "GPIO_20"),
+	PINCTRL_PIN(21, "GPIO_21"),
+	PINCTRL_PIN(22, "GPIO_22"),
+	PINCTRL_PIN(23, "GPIO_23"),
+	PINCTRL_PIN(24, "GPIO_24"),
+	PINCTRL_PIN(25, "GPIO_25"),
+	PINCTRL_PIN(26, "GPIO_26"),
+	PINCTRL_PIN(27, "GPIO_27"),
+	PINCTRL_PIN(28, "GPIO_28"),
+	PINCTRL_PIN(29, "GPIO_29"),
+	PINCTRL_PIN(30, "GPIO_30"),
+	PINCTRL_PIN(31, "GPIO_31"),
+	PINCTRL_PIN(32, "GPIO_32"),
+	PINCTRL_PIN(33, "GPIO_33"),
+	PINCTRL_PIN(34, "GPIO_34"),
+	PINCTRL_PIN(35, "GPIO_35"),
+	PINCTRL_PIN(36, "GPIO_36"),
+	PINCTRL_PIN(37, "GPIO_37"),
+	PINCTRL_PIN(38, "GPIO_38"),
+	PINCTRL_PIN(39, "GPIO_39"),
+	PINCTRL_PIN(40, "GPIO_40"),
+	PINCTRL_PIN(41, "GPIO_41"),
+	PINCTRL_PIN(42, "GPIO_42"),
+	PINCTRL_PIN(43, "GPIO_43"),
+	PINCTRL_PIN(44, "GPIO_44"),
+	PINCTRL_PIN(45, "GPIO_45"),
+	PINCTRL_PIN(46, "GPIO_46"),
+	PINCTRL_PIN(47, "GPIO_47"),
+	PINCTRL_PIN(48, "GPIO_48"),
+	PINCTRL_PIN(49, "GPIO_49"),
+	PINCTRL_PIN(50, "GPIO_50"),
+	PINCTRL_PIN(51, "GPIO_51"),
+	PINCTRL_PIN(52, "GPIO_52"),
+	PINCTRL_PIN(53, "GPIO_53"),
+	PINCTRL_PIN(54, "GPIO_54"),
+	PINCTRL_PIN(55, "GPIO_55"),
+	PINCTRL_PIN(56, "GPIO_56"),
+	PINCTRL_PIN(57, "GPIO_57"),
+	PINCTRL_PIN(58, "GPIO_58"),
+	PINCTRL_PIN(59, "GPIO_59"),
+	PINCTRL_PIN(60, "GPIO_60"),
+	PINCTRL_PIN(61, "GPIO_61"),
+	PINCTRL_PIN(62, "GPIO_62"),
+	PINCTRL_PIN(63, "GPIO_63"),
+	PINCTRL_PIN(64, "GPIO_64"),
+	PINCTRL_PIN(65, "GPIO_65"),
+	PINCTRL_PIN(66, "GPIO_66"),
+	PINCTRL_PIN(67, "GPIO_67"),
+	PINCTRL_PIN(68, "GPIO_68"),
+	PINCTRL_PIN(69, "GPIO_69"),
+	PINCTRL_PIN(70, "GPIO_70"),
+	PINCTRL_PIN(71, "GPIO_71"),
+	PINCTRL_PIN(72, "GPIO_72"),
+	PINCTRL_PIN(73, "GPIO_73"),
+	PINCTRL_PIN(74, "GPIO_74"),
+	PINCTRL_PIN(75, "GPIO_75"),
+	PINCTRL_PIN(76, "GPIO_76"),
+	PINCTRL_PIN(77, "GPIO_77"),
+	PINCTRL_PIN(78, "GPIO_78"),
+	PINCTRL_PIN(79, "GPIO_79"),
+	PINCTRL_PIN(80, "GPIO_80"),
+	PINCTRL_PIN(81, "GPIO_81"),
+	PINCTRL_PIN(82, "GPIO_82"),
+	PINCTRL_PIN(83, "GPIO_83"),
+	PINCTRL_PIN(84, "GPIO_84"),
+	PINCTRL_PIN(85, "GPIO_85"),
+	PINCTRL_PIN(86, "GPIO_86"),
+	PINCTRL_PIN(87, "GPIO_87"),
+	PINCTRL_PIN(88, "GPIO_88"),
+	PINCTRL_PIN(89, "GPIO_89"),
+	PINCTRL_PIN(90, "GPIO_90"),
+	PINCTRL_PIN(91, "GPIO_91"),
+	PINCTRL_PIN(92, "GPIO_92"),
+	PINCTRL_PIN(93, "GPIO_93"),
+	PINCTRL_PIN(94, "GPIO_94"),
+	PINCTRL_PIN(95, "GPIO_95"),
+	PINCTRL_PIN(96, "GPIO_96"),
+	PINCTRL_PIN(97, "GPIO_97"),
+	PINCTRL_PIN(98, "GPIO_98"),
+	PINCTRL_PIN(99, "GPIO_99"),
+	PINCTRL_PIN(100, "GPIO_100"),
+	PINCTRL_PIN(101, "GPIO_101"),
+	PINCTRL_PIN(102, "GPIO_102"),
+	PINCTRL_PIN(103, "GPIO_103"),
+	PINCTRL_PIN(104, "GPIO_104"),
+	PINCTRL_PIN(105, "GPIO_105"),
+	PINCTRL_PIN(106, "GPIO_106"),
+	PINCTRL_PIN(107, "GPIO_107"),
+	PINCTRL_PIN(108, "GPIO_108"),
+	PINCTRL_PIN(109, "GPIO_109"),
+	PINCTRL_PIN(110, "GPIO_110"),
+	PINCTRL_PIN(111, "GPIO_111"),
+	PINCTRL_PIN(112, "GPIO_112"),
+	PINCTRL_PIN(113, "GPIO_113"),
+	PINCTRL_PIN(114, "GPIO_114"),
+	PINCTRL_PIN(115, "GPIO_115"),
+	PINCTRL_PIN(116, "GPIO_116"),
+	PINCTRL_PIN(117, "GPIO_117"),
+	PINCTRL_PIN(118, "GPIO_118"),
+	PINCTRL_PIN(119, "SDC1_RCLK"),
+	PINCTRL_PIN(120, "SDC1_CLK"),
+	PINCTRL_PIN(121, "SDC1_CMD"),
+	PINCTRL_PIN(122, "SDC1_DATA"),
+	PINCTRL_PIN(123, "SDC2_CLK"),
+	PINCTRL_PIN(124, "SDC2_CMD"),
+	PINCTRL_PIN(125, "SDC2_DATA"),
+	PINCTRL_PIN(126, "UFS_RESET"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+	static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+
+static const unsigned int sdc1_rclk_pins[] = { 119 };
+static const unsigned int sdc1_clk_pins[] = { 120 };
+static const unsigned int sdc1_cmd_pins[] = { 121 };
+static const unsigned int sdc1_data_pins[] = { 122 };
+static const unsigned int sdc2_clk_pins[] = { 123 };
+static const unsigned int sdc2_cmd_pins[] = { 124 };
+static const unsigned int sdc2_data_pins[] = { 125 };
+static const unsigned int ufs_reset_pins[] = { 126 };
+
+enum atoll_functions {
+	msm_mux_qup01,
+	msm_mux_gpio,
+	msm_mux_phase_flag0,
+	msm_mux_phase_flag1,
+	msm_mux_cri_trng,
+	msm_mux_phase_flag3,
+	msm_mux_sp_cmu,
+	msm_mux_dbg_out,
+	msm_mux_qdss_cti,
+	msm_mux_sdc1_tb,
+	msm_mux_sdc2_tb,
+	msm_mux_qup11,
+	msm_mux_ddr_bist,
+	msm_mux_GP_PDM1,
+	msm_mux_phase_flag6,
+	msm_mux_phase_flag9,
+	msm_mux_mdp_vsync,
+	msm_mux_edp_lcd,
+	msm_mux_phase_flag24,
+	msm_mux_ddr_pxi2,
+	msm_mux_m_voc,
+	msm_mux_phase_flag4,
+	msm_mux_wlan2_adc0,
+	msm_mux_atest_usb10,
+	msm_mux_ddr_pxi3,
+	msm_mux_cam_mclk,
+	msm_mux_pll_bypassnl,
+	msm_mux_qdss_gpio0,
+	msm_mux_pll_reset,
+	msm_mux_qdss_gpio1,
+	msm_mux_qup02,
+	msm_mux_qdss_gpio2,
+	msm_mux_qdss_gpio3,
+	msm_mux_cci_i2c,
+	msm_mux_phase_flag20,
+	msm_mux_qdss_gpio4,
+	msm_mux_wlan1_adc0,
+	msm_mux_atest_usb12,
+	msm_mux_ddr_pxi1,
+	msm_mux_atest_char,
+	msm_mux_AGERA_PLL,
+	msm_mux_phase_flag18,
+	msm_mux_qdss_gpio5,
+	msm_mux_vsense_trigger,
+	msm_mux_ddr_pxi0,
+	msm_mux_atest_char3,
+	msm_mux_phase_flag2,
+	msm_mux_qdss_gpio6,
+	msm_mux_atest_char2,
+	msm_mux_phase_flag10,
+	msm_mux_qdss_gpio7,
+	msm_mux_atest_char1,
+	msm_mux_cci_timer0,
+	msm_mux_gcc_gp2,
+	msm_mux_atest_char0,
+	msm_mux_cci_timer1,
+	msm_mux_gcc_gp3,
+	msm_mux_cci_timer2,
+	msm_mux_qdss_gpio9,
+	msm_mux_cci_timer3,
+	msm_mux_cci_async,
+	msm_mux_qdss_gpio15,
+	msm_mux_cci_timer4,
+	msm_mux_qup05,
+	msm_mux_phase_flag23,
+	msm_mux_qdss_gpio11,
+	msm_mux_phase_flag17,
+	msm_mux_qdss_gpio12,
+	msm_mux_atest_tsens,
+	msm_mux_atest_usb11,
+	msm_mux_PLL_BIST,
+	msm_mux_phase_flag27,
+	msm_mux_qdss_gpio13,
+	msm_mux_phase_flag31,
+	msm_mux_qdss_gpio14,
+	msm_mux_qdss_gpio,
+	msm_mux_phase_flag12,
+	msm_mux_sd_write,
+	msm_mux_phase_flag15,
+	msm_mux_qup00,
+	msm_mux_phase_flag14,
+	msm_mux_qdss_gpio8,
+	msm_mux_phase_flag28,
+	msm_mux_phase_flag29,
+	msm_mux_GP_PDM0,
+	msm_mux_phase_flag30,
+	msm_mux_qdss_gpio10,
+	msm_mux_qup03,
+	msm_mux_phase_flag19,
+	msm_mux_phase_flag16,
+	msm_mux_atest_tsens2,
+	msm_mux_wlan2_adc1,
+	msm_mux_atest_usb1,
+	msm_mux_qup12,
+	msm_mux_phase_flag22,
+	msm_mux_phase_flag21,
+	msm_mux_wlan1_adc1,
+	msm_mux_atest_usb13,
+	msm_mux_qup13,
+	msm_mux_gcc_gp1,
+	msm_mux_mi2s_1,
+	msm_mux_btfm_slimbus,
+	msm_mux_atest_usb2,
+	msm_mux_atest_usb23,
+	msm_mux_mi2s_0,
+	msm_mux_qup15,
+	msm_mux_atest_usb22,
+	msm_mux_atest_usb21,
+	msm_mux_atest_usb20,
+	msm_mux_phase_flag26,
+	msm_mux_lpass_ext,
+	msm_mux_audio_ref,
+	msm_mux_JITTER_BIST,
+	msm_mux_GP_PDM2,
+	msm_mux_phase_flag25,
+	msm_mux_phase_flag11,
+	msm_mux_qup10,
+	msm_mux_tgu_ch3,
+	msm_mux_qspi_clk,
+	msm_mux_mdp_vsync0,
+	msm_mux_mi2s_2,
+	msm_mux_mdp_vsync1,
+	msm_mux_mdp_vsync2,
+	msm_mux_mdp_vsync3,
+	msm_mux_tgu_ch0,
+	msm_mux_phase_flag8,
+	msm_mux_qspi_data,
+	msm_mux_tgu_ch1,
+	msm_mux_phase_flag7,
+	msm_mux_vfr_1,
+	msm_mux_tgu_ch2,
+	msm_mux_qspi_cs,
+	msm_mux_ldo_en,
+	msm_mux_ldo_update,
+	msm_mux_prng_rosc,
+	msm_mux_uim2_data,
+	msm_mux_uim2_clk,
+	msm_mux_uim2_reset,
+	msm_mux_uim2_present,
+	msm_mux_uim1_data,
+	msm_mux_uim1_clk,
+	msm_mux_uim1_reset,
+	msm_mux_uim1_present,
+	msm_mux_NAV_GPIO,
+	msm_mux_NAV_PPS_IN,
+	msm_mux_NAV_PPS_OUT,
+	msm_mux_GPS_TX,
+	msm_mux_uim_batt,
+	msm_mux_dp_hot,
+	msm_mux_aoss_cti,
+	msm_mux_qup14,
+	msm_mux_adsp_ext,
+	msm_mux_tsense_pwm1,
+	msm_mux_tsense_pwm2,
+	msm_mux_qlink_request,
+	msm_mux_qlink_enable,
+	msm_mux_pa_indicator,
+	msm_mux_usb_phy,
+	msm_mux_mss_lte,
+	msm_mux_phase_flag5,
+	msm_mux_phase_flag13,
+	msm_mux_qup04,
+	msm_mux_NA,
+};
+
+static const char * const qup01_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio12", "gpio94",
+};
+static const char * const gpio_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+	"gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+	"gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+	"gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+	"gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+	"gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+	"gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+	"gpio117", "gpio118",
+};
+static const char * const phase_flag0_groups[] = {
+	"gpio0",
+};
+static const char * const phase_flag1_groups[] = {
+	"gpio1",
+};
+static const char * const cri_trng_groups[] = {
+	"gpio0", "gpio1", "gpio2",
+};
+static const char * const phase_flag3_groups[] = {
+	"gpio2",
+};
+static const char * const sp_cmu_groups[] = {
+	"gpio3",
+};
+static const char * const dbg_out_groups[] = {
+	"gpio3",
+};
+static const char * const qdss_cti_groups[] = {
+	"gpio3", "gpio4", "gpio8", "gpio9", "gpio33", "gpio44", "gpio45",
+	"gpio72",
+};
+static const char * const sdc1_tb_groups[] = {
+	"gpio4",
+};
+static const char * const sdc2_tb_groups[] = {
+	"gpio5",
+};
+static const char * const qup11_groups[] = {
+	"gpio6", "gpio7",
+};
+static const char * const ddr_bist_groups[] = {
+	"gpio7", "gpio8", "gpio9", "gpio10",
+};
+static const char * const GP_PDM1_groups[] = {
+	"gpio8", "gpio50",
+};
+static const char * const phase_flag6_groups[] = {
+	"gpio8",
+};
+static const char * const phase_flag9_groups[] = {
+	"gpio9",
+};
+static const char * const mdp_vsync_groups[] = {
+	"gpio10", "gpio11", "gpio12", "gpio70", "gpio71",
+};
+static const char * const edp_lcd_groups[] = {
+	"gpio11",
+};
+static const char * const phase_flag24_groups[] = {
+	"gpio11",
+};
+static const char * const ddr_pxi2_groups[] = {
+	"gpio11", "gpio26",
+};
+static const char * const m_voc_groups[] = {
+	"gpio12",
+};
+static const char * const phase_flag4_groups[] = {
+	"gpio12",
+};
+static const char * const wlan2_adc0_groups[] = {
+	"gpio12",
+};
+static const char * const atest_usb10_groups[] = {
+	"gpio12",
+};
+static const char * const ddr_pxi3_groups[] = {
+	"gpio12", "gpio108",
+};
+static const char * const cam_mclk_groups[] = {
+	"gpio13", "gpio14", "gpio15", "gpio16", "gpio23",
+};
+static const char * const pll_bypassnl_groups[] = {
+	"gpio13",
+};
+static const char * const qdss_gpio0_groups[] = {
+	"gpio13", "gpio86",
+};
+static const char * const pll_reset_groups[] = {
+	"gpio14",
+};
+static const char * const qdss_gpio1_groups[] = {
+	"gpio14", "gpio87",
+};
+static const char * const qup02_groups[] = {
+	"gpio15", "gpio16",
+};
+static const char * const qdss_gpio2_groups[] = {
+	"gpio15", "gpio88",
+};
+static const char * const qdss_gpio3_groups[] = {
+	"gpio16", "gpio89",
+};
+static const char * const cci_i2c_groups[] = {
+	"gpio17", "gpio18", "gpio19", "gpio20", "gpio27", "gpio28",
+};
+static const char * const phase_flag20_groups[] = {
+	"gpio17",
+};
+static const char * const qdss_gpio4_groups[] = {
+	"gpio17", "gpio90",
+};
+static const char * const wlan1_adc0_groups[] = {
+	"gpio17",
+};
+static const char * const atest_usb12_groups[] = {
+	"gpio17",
+};
+static const char * const ddr_pxi1_groups[] = {
+	"gpio17", "gpio44",
+};
+static const char * const atest_char_groups[] = {
+	"gpio17",
+};
+static const char * const AGERA_PLL_groups[] = {
+	"gpio18",
+};
+static const char * const phase_flag18_groups[] = {
+	"gpio18",
+};
+static const char * const qdss_gpio5_groups[] = {
+	"gpio18", "gpio91",
+};
+static const char * const vsense_trigger_groups[] = {
+	"gpio18",
+};
+static const char * const ddr_pxi0_groups[] = {
+	"gpio18", "gpio27",
+};
+static const char * const atest_char3_groups[] = {
+	"gpio18",
+};
+static const char * const phase_flag2_groups[] = {
+	"gpio19",
+};
+static const char * const qdss_gpio6_groups[] = {
+	"gpio19", "gpio21",
+};
+static const char * const atest_char2_groups[] = {
+	"gpio19",
+};
+static const char * const phase_flag10_groups[] = {
+	"gpio20",
+};
+static const char * const qdss_gpio7_groups[] = {
+	"gpio20", "gpio22",
+};
+static const char * const atest_char1_groups[] = {
+	"gpio20",
+};
+static const char * const cci_timer0_groups[] = {
+	"gpio21",
+};
+static const char * const gcc_gp2_groups[] = {
+	"gpio21",
+};
+static const char * const atest_char0_groups[] = {
+	"gpio21",
+};
+static const char * const cci_timer1_groups[] = {
+	"gpio22",
+};
+static const char * const gcc_gp3_groups[] = {
+	"gpio22",
+};
+static const char * const cci_timer2_groups[] = {
+	"gpio23",
+};
+static const char * const qdss_gpio9_groups[] = {
+	"gpio23", "gpio54",
+};
+static const char * const cci_timer3_groups[] = {
+	"gpio24",
+};
+static const char * const cci_async_groups[] = {
+	"gpio24", "gpio25", "gpio26",
+};
+static const char * const qdss_gpio15_groups[] = {
+	"gpio24", "gpio36",
+};
+static const char * const cci_timer4_groups[] = {
+	"gpio25",
+};
+static const char * const qup05_groups[] = {
+	"gpio25", "gpio26", "gpio27", "gpio28",
+};
+static const char * const phase_flag23_groups[] = {
+	"gpio25",
+};
+static const char * const qdss_gpio11_groups[] = {
+	"gpio25", "gpio57",
+};
+static const char * const phase_flag17_groups[] = {
+	"gpio26",
+};
+static const char * const qdss_gpio12_groups[] = {
+	"gpio26", "gpio31",
+};
+static const char * const atest_tsens_groups[] = {
+	"gpio26",
+};
+static const char * const atest_usb11_groups[] = {
+	"gpio26",
+};
+static const char * const PLL_BIST_groups[] = {
+	"gpio27",
+};
+static const char * const phase_flag27_groups[] = {
+	"gpio27",
+};
+static const char * const qdss_gpio13_groups[] = {
+	"gpio27", "gpio56",
+};
+static const char * const phase_flag31_groups[] = {
+	"gpio28",
+};
+static const char * const qdss_gpio14_groups[] = {
+	"gpio28", "gpio29",
+};
+static const char * const qdss_gpio_groups[] = {
+	"gpio30", "gpio35", "gpio93", "gpio104",
+};
+static const char * const phase_flag12_groups[] = {
+	"gpio32",
+};
+static const char * const sd_write_groups[] = {
+	"gpio33",
+};
+static const char * const phase_flag15_groups[] = {
+	"gpio33",
+};
+static const char * const qup00_groups[] = {
+	"gpio34", "gpio35", "gpio36", "gpio37",
+};
+static const char * const phase_flag14_groups[] = {
+	"gpio34",
+};
+static const char * const qdss_gpio8_groups[] = {
+	"gpio34", "gpio53",
+};
+static const char * const phase_flag28_groups[] = {
+	"gpio35",
+};
+static const char * const phase_flag29_groups[] = {
+	"gpio36",
+};
+static const char * const GP_PDM0_groups[] = {
+	"gpio37", "gpio68",
+};
+static const char * const phase_flag30_groups[] = {
+	"gpio37",
+};
+static const char * const qdss_gpio10_groups[] = {
+	"gpio37", "gpio55",
+};
+static const char * const qup03_groups[] = {
+	"gpio38", "gpio39", "gpio40", "gpio41",
+};
+static const char * const phase_flag19_groups[] = {
+	"gpio38",
+};
+static const char * const phase_flag16_groups[] = {
+	"gpio39",
+};
+static const char * const atest_tsens2_groups[] = {
+	"gpio39",
+};
+static const char * const wlan2_adc1_groups[] = {
+	"gpio39",
+};
+static const char * const atest_usb1_groups[] = {
+	"gpio39",
+};
+static const char * const qup12_groups[] = {
+	"gpio42", "gpio43", "gpio44", "gpio45",
+};
+static const char * const phase_flag22_groups[] = {
+	"gpio42",
+};
+static const char * const phase_flag21_groups[] = {
+	"gpio44",
+};
+static const char * const wlan1_adc1_groups[] = {
+	"gpio44",
+};
+static const char * const atest_usb13_groups[] = {
+	"gpio44",
+};
+static const char * const qup13_groups[] = {
+	"gpio46", "gpio47",
+};
+static const char * const gcc_gp1_groups[] = {
+	"gpio48", "gpio56",
+};
+static const char * const mi2s_1_groups[] = {
+	"gpio49", "gpio50", "gpio51", "gpio52",
+};
+static const char * const btfm_slimbus_groups[] = {
+	"gpio49", "gpio50", "gpio51", "gpio52",
+};
+static const char * const atest_usb2_groups[] = {
+	"gpio51",
+};
+static const char * const atest_usb23_groups[] = {
+	"gpio52",
+};
+static const char * const mi2s_0_groups[] = {
+	"gpio53", "gpio54", "gpio55", "gpio56",
+};
+static const char * const qup15_groups[] = {
+	"gpio53", "gpio54", "gpio55", "gpio56",
+};
+static const char * const atest_usb22_groups[] = {
+	"gpio53",
+};
+static const char * const atest_usb21_groups[] = {
+	"gpio54",
+};
+static const char * const atest_usb20_groups[] = {
+	"gpio55",
+};
+static const char * const phase_flag26_groups[] = {
+	"gpio56",
+};
+static const char * const lpass_ext_groups[] = {
+	"gpio57", "gpio58",
+};
+static const char * const audio_ref_groups[] = {
+	"gpio57",
+};
+static const char * const JITTER_BIST_groups[] = {
+	"gpio57",
+};
+static const char * const GP_PDM2_groups[] = {
+	"gpio57",
+};
+static const char * const phase_flag25_groups[] = {
+	"gpio57",
+};
+static const char * const phase_flag11_groups[] = {
+	"gpio58",
+};
+static const char * const qup10_groups[] = {
+	"gpio59", "gpio60", "gpio61", "gpio62", "gpio68", "gpio72",
+};
+static const char * const tgu_ch3_groups[] = {
+	"gpio62",
+};
+static const char * const qspi_clk_groups[] = {
+	"gpio63",
+};
+static const char * const mdp_vsync0_groups[] = {
+	"gpio63",
+};
+static const char * const mi2s_2_groups[] = {
+	"gpio63", "gpio64", "gpio65", "gpio66",
+};
+static const char * const mdp_vsync1_groups[] = {
+	"gpio63",
+};
+static const char * const mdp_vsync2_groups[] = {
+	"gpio63",
+};
+static const char * const mdp_vsync3_groups[] = {
+	"gpio63",
+};
+static const char * const tgu_ch0_groups[] = {
+	"gpio63",
+};
+static const char * const phase_flag8_groups[] = {
+	"gpio63",
+};
+static const char * const qspi_data_groups[] = {
+	"gpio64", "gpio65", "gpio66", "gpio67",
+};
+static const char * const tgu_ch1_groups[] = {
+	"gpio64",
+};
+static const char * const phase_flag7_groups[] = {
+	"gpio64",
+};
+static const char * const vfr_1_groups[] = {
+	"gpio65",
+};
+static const char * const tgu_ch2_groups[] = {
+	"gpio65",
+};
+static const char * const qspi_cs_groups[] = {
+	"gpio68", "gpio72",
+};
+static const char * const ldo_en_groups[] = {
+	"gpio70",
+};
+static const char * const ldo_update_groups[] = {
+	"gpio71",
+};
+static const char * const prng_rosc_groups[] = {
+	"gpio72",
+};
+static const char * const uim2_data_groups[] = {
+	"gpio75",
+};
+static const char * const uim2_clk_groups[] = {
+	"gpio76",
+};
+static const char * const uim2_reset_groups[] = {
+	"gpio77",
+};
+static const char * const uim2_present_groups[] = {
+	"gpio78",
+};
+static const char * const uim1_data_groups[] = {
+	"gpio79",
+};
+static const char * const uim1_clk_groups[] = {
+	"gpio80",
+};
+static const char * const uim1_reset_groups[] = {
+	"gpio81",
+};
+static const char * const uim1_present_groups[] = {
+	"gpio82",
+};
+static const char * const NAV_GPIO_groups[] = {
+	"gpio83", "gpio84", "gpio107",
+};
+static const char * const NAV_PPS_IN_groups[] = {
+	"gpio83", "gpio84", "gpio107",
+};
+static const char * const NAV_PPS_OUT_groups[] = {
+	"gpio83", "gpio84", "gpio107",
+};
+static const char * const GPS_TX_groups[] = {
+	"gpio83", "gpio84", "gpio107", "gpio109",
+};
+static const char * const uim_batt_groups[] = {
+	"gpio85",
+};
+static const char * const dp_hot_groups[] = {
+	"gpio85", "gpio117",
+};
+static const char * const aoss_cti_groups[] = {
+	"gpio85",
+};
+static const char * const qup14_groups[] = {
+	"gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+};
+static const char * const adsp_ext_groups[] = {
+	"gpio87",
+};
+static const char * const tsense_pwm1_groups[] = {
+	"gpio88",
+};
+static const char * const tsense_pwm2_groups[] = {
+	"gpio88",
+};
+static const char * const qlink_request_groups[] = {
+	"gpio96",
+};
+static const char * const qlink_enable_groups[] = {
+	"gpio97",
+};
+static const char * const pa_indicator_groups[] = {
+	"gpio99",
+};
+static const char * const usb_phy_groups[] = {
+	"gpio104",
+};
+static const char * const mss_lte_groups[] = {
+	"gpio108", "gpio109",
+};
+static const char * const phase_flag5_groups[] = {
+	"gpio108",
+};
+static const char * const phase_flag13_groups[] = {
+	"gpio109",
+};
+static const char * const qup04_groups[] = {
+	"gpio115", "gpio116",
+};
+
+static const struct msm_function atoll_functions[] = {
+	FUNCTION(qup01),
+	FUNCTION(gpio),
+	FUNCTION(phase_flag0),
+	FUNCTION(phase_flag1),
+	FUNCTION(cri_trng),
+	FUNCTION(phase_flag3),
+	FUNCTION(sp_cmu),
+	FUNCTION(dbg_out),
+	FUNCTION(qdss_cti),
+	FUNCTION(sdc1_tb),
+	FUNCTION(sdc2_tb),
+	FUNCTION(qup11),
+	FUNCTION(ddr_bist),
+	FUNCTION(GP_PDM1),
+	FUNCTION(phase_flag6),
+	FUNCTION(phase_flag9),
+	FUNCTION(mdp_vsync),
+	FUNCTION(edp_lcd),
+	FUNCTION(phase_flag24),
+	FUNCTION(ddr_pxi2),
+	FUNCTION(m_voc),
+	FUNCTION(phase_flag4),
+	FUNCTION(wlan2_adc0),
+	FUNCTION(atest_usb10),
+	FUNCTION(ddr_pxi3),
+	FUNCTION(cam_mclk),
+	FUNCTION(pll_bypassnl),
+	FUNCTION(qdss_gpio0),
+	FUNCTION(pll_reset),
+	FUNCTION(qdss_gpio1),
+	FUNCTION(qup02),
+	FUNCTION(qdss_gpio2),
+	FUNCTION(qdss_gpio3),
+	FUNCTION(cci_i2c),
+	FUNCTION(phase_flag20),
+	FUNCTION(qdss_gpio4),
+	FUNCTION(wlan1_adc0),
+	FUNCTION(atest_usb12),
+	FUNCTION(ddr_pxi1),
+	FUNCTION(atest_char),
+	FUNCTION(AGERA_PLL),
+	FUNCTION(phase_flag18),
+	FUNCTION(qdss_gpio5),
+	FUNCTION(vsense_trigger),
+	FUNCTION(ddr_pxi0),
+	FUNCTION(atest_char3),
+	FUNCTION(phase_flag2),
+	FUNCTION(qdss_gpio6),
+	FUNCTION(atest_char2),
+	FUNCTION(phase_flag10),
+	FUNCTION(qdss_gpio7),
+	FUNCTION(atest_char1),
+	FUNCTION(cci_timer0),
+	FUNCTION(gcc_gp2),
+	FUNCTION(atest_char0),
+	FUNCTION(cci_timer1),
+	FUNCTION(gcc_gp3),
+	FUNCTION(cci_timer2),
+	FUNCTION(qdss_gpio9),
+	FUNCTION(cci_timer3),
+	FUNCTION(cci_async),
+	FUNCTION(qdss_gpio15),
+	FUNCTION(cci_timer4),
+	FUNCTION(qup05),
+	FUNCTION(phase_flag23),
+	FUNCTION(qdss_gpio11),
+	FUNCTION(phase_flag17),
+	FUNCTION(qdss_gpio12),
+	FUNCTION(atest_tsens),
+	FUNCTION(atest_usb11),
+	FUNCTION(PLL_BIST),
+	FUNCTION(phase_flag27),
+	FUNCTION(qdss_gpio13),
+	FUNCTION(phase_flag31),
+	FUNCTION(qdss_gpio14),
+	FUNCTION(qdss_gpio),
+	FUNCTION(phase_flag12),
+	FUNCTION(sd_write),
+	FUNCTION(phase_flag15),
+	FUNCTION(qup00),
+	FUNCTION(phase_flag14),
+	FUNCTION(qdss_gpio8),
+	FUNCTION(phase_flag28),
+	FUNCTION(phase_flag29),
+	FUNCTION(GP_PDM0),
+	FUNCTION(phase_flag30),
+	FUNCTION(qdss_gpio10),
+	FUNCTION(qup03),
+	FUNCTION(phase_flag19),
+	FUNCTION(phase_flag16),
+	FUNCTION(atest_tsens2),
+	FUNCTION(wlan2_adc1),
+	FUNCTION(atest_usb1),
+	FUNCTION(qup12),
+	FUNCTION(phase_flag22),
+	FUNCTION(phase_flag21),
+	FUNCTION(wlan1_adc1),
+	FUNCTION(atest_usb13),
+	FUNCTION(qup13),
+	FUNCTION(gcc_gp1),
+	FUNCTION(mi2s_1),
+	FUNCTION(btfm_slimbus),
+	FUNCTION(atest_usb2),
+	FUNCTION(atest_usb23),
+	FUNCTION(mi2s_0),
+	FUNCTION(qup15),
+	FUNCTION(atest_usb22),
+	FUNCTION(atest_usb21),
+	FUNCTION(atest_usb20),
+	FUNCTION(phase_flag26),
+	FUNCTION(lpass_ext),
+	FUNCTION(audio_ref),
+	FUNCTION(JITTER_BIST),
+	FUNCTION(GP_PDM2),
+	FUNCTION(phase_flag25),
+	FUNCTION(phase_flag11),
+	FUNCTION(qup10),
+	FUNCTION(tgu_ch3),
+	FUNCTION(qspi_clk),
+	FUNCTION(mdp_vsync0),
+	FUNCTION(mi2s_2),
+	FUNCTION(mdp_vsync1),
+	FUNCTION(mdp_vsync2),
+	FUNCTION(mdp_vsync3),
+	FUNCTION(tgu_ch0),
+	FUNCTION(phase_flag8),
+	FUNCTION(qspi_data),
+	FUNCTION(tgu_ch1),
+	FUNCTION(phase_flag7),
+	FUNCTION(vfr_1),
+	FUNCTION(tgu_ch2),
+	FUNCTION(qspi_cs),
+	FUNCTION(ldo_en),
+	FUNCTION(ldo_update),
+	FUNCTION(prng_rosc),
+	FUNCTION(uim2_data),
+	FUNCTION(uim2_clk),
+	FUNCTION(uim2_reset),
+	FUNCTION(uim2_present),
+	FUNCTION(uim1_data),
+	FUNCTION(uim1_clk),
+	FUNCTION(uim1_reset),
+	FUNCTION(uim1_present),
+	FUNCTION(NAV_GPIO),
+	FUNCTION(NAV_PPS_IN),
+	FUNCTION(NAV_PPS_OUT),
+	FUNCTION(GPS_TX),
+	FUNCTION(uim_batt),
+	FUNCTION(dp_hot),
+	FUNCTION(aoss_cti),
+	FUNCTION(qup14),
+	FUNCTION(adsp_ext),
+	FUNCTION(tsense_pwm1),
+	FUNCTION(tsense_pwm2),
+	FUNCTION(qlink_request),
+	FUNCTION(qlink_enable),
+	FUNCTION(pa_indicator),
+	FUNCTION(usb_phy),
+	FUNCTION(mss_lte),
+	FUNCTION(phase_flag5),
+	FUNCTION(phase_flag13),
+	FUNCTION(qup04),
+};
+
+/* Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
+static const struct msm_pingroup atoll_groups[] = {
+	[0] = PINGROUP(0, SOUTH, qup01, cri_trng, NA, phase_flag0, NA, NA, NA,
+		       NA, NA),
+	[1] = PINGROUP(1, SOUTH, qup01, cri_trng, NA, phase_flag1, NA, NA, NA,
+		       NA, NA),
+	[2] = PINGROUP(2, SOUTH, qup01, cri_trng, NA, phase_flag3, NA, NA, NA,
+		       NA, NA),
+	[3] = PINGROUP(3, SOUTH, qup01, sp_cmu, dbg_out, qdss_cti, NA, NA, NA,
+		       NA, NA),
+	[4] = PINGROUP(4, NORTH, sdc1_tb, NA, qdss_cti, NA, NA, NA, NA, NA, NA),
+	[5] = PINGROUP(5, NORTH, sdc2_tb, NA, NA, NA, NA, NA, NA, NA, NA),
+	[6] = PINGROUP(6, NORTH, qup11, qup11, NA, NA, NA, NA, NA, NA, NA),
+	[7] = PINGROUP(7, NORTH, qup11, qup11, ddr_bist, NA, NA, NA, NA, NA,
+		       NA),
+	[8] = PINGROUP(8, NORTH, GP_PDM1, ddr_bist, NA, phase_flag6, qdss_cti,
+		       NA, NA, NA, NA),
+	[9] = PINGROUP(9, NORTH, ddr_bist, NA, phase_flag9, qdss_cti, NA, NA,
+		       NA, NA, NA),
+	[10] = PINGROUP(10, NORTH, mdp_vsync, ddr_bist, NA, NA, NA, NA, NA, NA,
+			NA),
+	[11] = PINGROUP(11, NORTH, mdp_vsync, edp_lcd, NA, phase_flag24,
+			ddr_pxi2, NA, NA, NA, NA),
+	[12] = PINGROUP(12, SOUTH, mdp_vsync, m_voc, qup01, NA, phase_flag4,
+			wlan2_adc0, atest_usb10, ddr_pxi3, NA),
+	[13] = PINGROUP(13, SOUTH, cam_mclk, pll_bypassnl, qdss_gpio0, NA, NA,
+			NA, NA, NA, NA),
+	[14] = PINGROUP(14, SOUTH, cam_mclk, pll_reset, qdss_gpio1, NA, NA, NA,
+			NA, NA, NA),
+	[15] = PINGROUP(15, SOUTH, cam_mclk, qup02, qup02, qdss_gpio2, NA, NA,
+			NA, NA, NA),
+	[16] = PINGROUP(16, SOUTH, cam_mclk, qup02, qup02, qdss_gpio3, NA, NA,
+			NA, NA, NA),
+	[17] = PINGROUP(17, SOUTH, cci_i2c, NA, phase_flag20, qdss_gpio4, NA,
+			wlan1_adc0, atest_usb12, ddr_pxi1, atest_char),
+	[18] = PINGROUP(18, SOUTH, cci_i2c, AGERA_PLL, NA, phase_flag18,
+			qdss_gpio5, vsense_trigger, ddr_pxi0, atest_char3, NA),
+	[19] = PINGROUP(19, SOUTH, cci_i2c, NA, phase_flag2, qdss_gpio6,
+			atest_char2, NA, NA, NA, NA),
+	[20] = PINGROUP(20, SOUTH, cci_i2c, NA, phase_flag10, qdss_gpio7,
+			atest_char1, NA, NA, NA, NA),
+	[21] = PINGROUP(21, NORTH, cci_timer0, gcc_gp2, NA, qdss_gpio6,
+			atest_char0, NA, NA, NA, NA),
+	[22] = PINGROUP(22, NORTH, cci_timer1, gcc_gp3, NA, qdss_gpio7, NA, NA,
+			NA, NA, NA),
+	[23] = PINGROUP(23, SOUTH, cci_timer2, cam_mclk, qdss_gpio9, NA, NA,
+			NA, NA, NA, NA),
+	[24] = PINGROUP(24, SOUTH, cci_timer3, cci_async, qdss_gpio15, NA, NA,
+			NA, NA, NA, NA),
+	[25] = PINGROUP(25, SOUTH, cci_timer4, cci_async, qup05, NA,
+			phase_flag23, qdss_gpio11, NA, NA, NA),
+	[26] = PINGROUP(26, SOUTH, cci_async, qup05, NA, phase_flag17,
+			qdss_gpio12, atest_tsens, atest_usb11, ddr_pxi2, NA),
+	[27] = PINGROUP(27, SOUTH, cci_i2c, qup05, PLL_BIST, NA, phase_flag27,
+			qdss_gpio13, ddr_pxi0, NA, NA),
+	[28] = PINGROUP(28, SOUTH, cci_i2c, qup05, NA, phase_flag31,
+			qdss_gpio14, NA, NA, NA, NA),
+	[29] = PINGROUP(29, NORTH, NA, qdss_gpio14, NA, NA, NA, NA, NA, NA, NA),
+	[30] = PINGROUP(30, SOUTH, qdss_gpio, NA, NA, NA, NA, NA, NA, NA, NA),
+	[31] = PINGROUP(31, NORTH, NA, qdss_gpio12, NA, NA, NA, NA, NA, NA, NA),
+	[32] = PINGROUP(32, NORTH, NA, phase_flag12, NA, NA, NA, NA, NA, NA,
+			NA),
+	[33] = PINGROUP(33, NORTH, sd_write, NA, phase_flag15, qdss_cti, NA,
+			NA, NA, NA, NA),
+	[34] = PINGROUP(34, SOUTH, qup00, NA, phase_flag14, qdss_gpio8, NA, NA,
+			NA, NA, NA),
+	[35] = PINGROUP(35, SOUTH, qup00, NA, phase_flag28, qdss_gpio, NA, NA,
+			NA, NA, NA),
+	[36] = PINGROUP(36, SOUTH, qup00, NA, phase_flag29, qdss_gpio15, NA,
+			NA, NA, NA, NA),
+	[37] = PINGROUP(37, SOUTH, qup00, GP_PDM0, NA, phase_flag30,
+			qdss_gpio10, NA, NA, NA, NA),
+	[38] = PINGROUP(38, SOUTH, qup03, NA, phase_flag19, NA, NA, NA, NA, NA,
+			NA),
+	[39] = PINGROUP(39, SOUTH, qup03, NA, phase_flag16, atest_tsens2,
+			wlan2_adc1, atest_usb1, NA, NA, NA),
+	[40] = PINGROUP(40, SOUTH, qup03, NA, NA, NA, NA, NA, NA, NA, NA),
+	[41] = PINGROUP(41, SOUTH, qup03, NA, NA, NA, NA, NA, NA, NA, NA),
+	[42] = PINGROUP(42, NORTH, qup12, NA, phase_flag22, NA, NA, NA, NA, NA,
+			NA),
+	[43] = PINGROUP(43, NORTH, qup12, NA, NA, NA, NA, NA, NA, NA, NA),
+	[44] = PINGROUP(44, NORTH, qup12, NA, phase_flag21, qdss_cti,
+			wlan1_adc1, atest_usb13, ddr_pxi1, NA, NA),
+	[45] = PINGROUP(45, NORTH, qup12, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[46] = PINGROUP(46, NORTH, qup13, qup13, NA, NA, NA, NA, NA, NA, NA),
+	[47] = PINGROUP(47, NORTH, qup13, qup13, NA, NA, NA, NA, NA, NA, NA),
+	[48] = PINGROUP(48, NORTH, gcc_gp1, NA, NA, NA, NA, NA, NA, NA, NA),
+	[49] = PINGROUP(49, WEST, mi2s_1, btfm_slimbus, NA, NA, NA, NA, NA, NA,
+			NA),
+	[50] = PINGROUP(50, WEST, mi2s_1, btfm_slimbus, GP_PDM1, NA, NA, NA,
+			NA, NA, NA),
+	[51] = PINGROUP(51, WEST, mi2s_1, btfm_slimbus, atest_usb2, NA, NA, NA,
+			NA, NA, NA),
+	[52] = PINGROUP(52, WEST, mi2s_1, btfm_slimbus, atest_usb23, NA, NA,
+			NA, NA, NA, NA),
+	[53] = PINGROUP(53, WEST, mi2s_0, qup15, qdss_gpio8, atest_usb22, NA,
+			NA, NA, NA, NA),
+	[54] = PINGROUP(54, WEST, mi2s_0, qup15, qdss_gpio9, atest_usb21, NA,
+			NA, NA, NA, NA),
+	[55] = PINGROUP(55, WEST, mi2s_0, qup15, qdss_gpio10, atest_usb20, NA,
+			NA, NA, NA, NA),
+	[56] = PINGROUP(56, WEST, mi2s_0, qup15, gcc_gp1, NA, phase_flag26,
+			qdss_gpio13, NA, NA, NA),
+	[57] = PINGROUP(57, WEST, lpass_ext, audio_ref, JITTER_BIST, GP_PDM2,
+			NA, phase_flag25, qdss_gpio11, NA, NA),
+	[58] = PINGROUP(58, WEST, lpass_ext, NA, phase_flag11, NA, NA, NA, NA,
+			NA, NA),
+	[59] = PINGROUP(59, NORTH, qup10, NA, NA, NA, NA, NA, NA, NA, NA),
+	[60] = PINGROUP(60, NORTH, qup10, NA, NA, NA, NA, NA, NA, NA, NA),
+	[61] = PINGROUP(61, NORTH, qup10, NA, NA, NA, NA, NA, NA, NA, NA),
+	[62] = PINGROUP(62, NORTH, qup10, tgu_ch3, NA, NA, NA, NA, NA, NA, NA),
+	[63] = PINGROUP(63, NORTH, qspi_clk, mdp_vsync0, mi2s_2, mdp_vsync1,
+			mdp_vsync2, mdp_vsync3, tgu_ch0, NA, phase_flag8),
+	[64] = PINGROUP(64, NORTH, qspi_data, mi2s_2, tgu_ch1, NA, phase_flag7,
+			NA, NA, NA, NA),
+	[65] = PINGROUP(65, NORTH, qspi_data, mi2s_2, vfr_1, tgu_ch2, NA, NA,
+			NA, NA, NA),
+	[66] = PINGROUP(66, NORTH, qspi_data, mi2s_2, NA, NA, NA, NA, NA, NA,
+			NA),
+	[67] = PINGROUP(67, NORTH, qspi_data, NA, NA, NA, NA, NA, NA, NA, NA),
+	[68] = PINGROUP(68, NORTH, qspi_cs, qup10, GP_PDM0, NA, NA, NA, NA, NA,
+			NA),
+	[69] = PINGROUP(69, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[70] = PINGROUP(70, NORTH, NA, NA, mdp_vsync, ldo_en, NA, NA, NA, NA,
+			NA),
+	[71] = PINGROUP(71, NORTH, NA, mdp_vsync, ldo_update, NA, NA, NA, NA,
+			NA, NA),
+	[72] = PINGROUP(72, NORTH, qspi_cs, qup10, prng_rosc, NA, qdss_cti, NA,
+			NA, NA, NA),
+	[73] = PINGROUP(73, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[74] = PINGROUP(74, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[75] = PINGROUP(75, WEST, uim2_data, NA, NA, NA, NA, NA, NA, NA, NA),
+	[76] = PINGROUP(76, WEST, uim2_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+	[77] = PINGROUP(77, WEST, uim2_reset, NA, NA, NA, NA, NA, NA, NA, NA),
+	[78] = PINGROUP(78, WEST, uim2_present, NA, NA, NA, NA, NA, NA, NA, NA),
+	[79] = PINGROUP(79, WEST, uim1_data, NA, NA, NA, NA, NA, NA, NA, NA),
+	[80] = PINGROUP(80, WEST, uim1_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+	[81] = PINGROUP(81, WEST, uim1_reset, NA, NA, NA, NA, NA, NA, NA, NA),
+	[82] = PINGROUP(82, WEST, uim1_present, NA, NA, NA, NA, NA, NA, NA, NA),
+	[83] = PINGROUP(83, WEST, NA, NAV_GPIO, NAV_PPS_IN, NAV_PPS_OUT,
+			GPS_TX, NA, NA, NA, NA),
+	[84] = PINGROUP(84, WEST, NA, NAV_GPIO, NAV_PPS_IN, NAV_PPS_OUT,
+			GPS_TX, NA, NA, NA, NA),
+	[85] = PINGROUP(85, WEST, uim_batt, dp_hot, aoss_cti, NA, NA, NA, NA,
+			NA, NA),
+	[86] = PINGROUP(86, NORTH, qup14, qdss_gpio0, NA, NA, NA, NA, NA, NA,
+			NA),
+	[87] = PINGROUP(87, NORTH, qup14, adsp_ext, qdss_gpio1, NA, NA, NA, NA,
+			NA, NA),
+	[88] = PINGROUP(88, NORTH, qup14, qdss_gpio2, tsense_pwm1, tsense_pwm2,
+			NA, NA, NA, NA, NA),
+	[89] = PINGROUP(89, NORTH, qup14, qdss_gpio3, NA, NA, NA, NA, NA, NA,
+			NA),
+	[90] = PINGROUP(90, NORTH, qup14, qdss_gpio4, NA, NA, NA, NA, NA, NA,
+			NA),
+	[91] = PINGROUP(91, NORTH, qup14, qdss_gpio5, NA, NA, NA, NA, NA, NA,
+			NA),
+	[92] = PINGROUP(92, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[93] = PINGROUP(93, NORTH, qdss_gpio, NA, NA, NA, NA, NA, NA, NA, NA),
+	[94] = PINGROUP(94, SOUTH, qup01, NA, NA, NA, NA, NA, NA, NA, NA),
+	[95] = PINGROUP(95, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[96] = PINGROUP(96, WEST, qlink_request, NA, NA, NA, NA, NA, NA, NA,
+			NA),
+	[97] = PINGROUP(97, WEST, qlink_enable, NA, NA, NA, NA, NA, NA, NA, NA),
+	[98] = PINGROUP(98, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[99] = PINGROUP(99, WEST, NA, pa_indicator, NA, NA, NA, NA, NA, NA, NA),
+	[100] = PINGROUP(100, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[101] = PINGROUP(101, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[102] = PINGROUP(102, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[103] = PINGROUP(103, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[104] = PINGROUP(104, WEST, usb_phy, NA, qdss_gpio, NA, NA, NA, NA, NA,
+			 NA),
+	[105] = PINGROUP(105, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[106] = PINGROUP(106, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[107] = PINGROUP(107, WEST, NA, NAV_GPIO, NAV_PPS_IN, NAV_PPS_OUT,
+			GPS_TX, NA, NA, NA, NA),
+	[108] = PINGROUP(108, SOUTH, mss_lte, NA, phase_flag5, ddr_pxi3, NA,
+			 NA, NA, NA, NA),
+	[109] = PINGROUP(109, SOUTH, mss_lte, GPS_TX, NA, phase_flag13, NA, NA,
+			 NA, NA, NA),
+	[110] = PINGROUP(110, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[111] = PINGROUP(111, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[112] = PINGROUP(112, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[113] = PINGROUP(113, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[114] = PINGROUP(114, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[115] = PINGROUP(115, WEST, qup04, qup04, NA, NA, NA, NA, NA, NA, NA),
+	[116] = PINGROUP(116, WEST, qup04, qup04, NA, NA, NA, NA, NA, NA, NA),
+	[117] = PINGROUP(117, WEST, dp_hot, NA, NA, NA, NA, NA, NA, NA, NA),
+	[118] = PINGROUP(118, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[119] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x97a000, 15, 0),
+	[120] = SDC_QDSD_PINGROUP(sdc1_clk, 0x97a000, 13, 6),
+	[121] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x97a000, 11, 3),
+	[122] = SDC_QDSD_PINGROUP(sdc1_data, 0x97a000, 9, 0),
+	[123] = SDC_QDSD_PINGROUP(sdc2_clk, 0x97b000, 14, 6),
+	[124] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x97b000, 11, 3),
+	[125] = SDC_QDSD_PINGROUP(sdc2_data, 0x97b000, 9, 0),
+	[126] = UFS_RESET(ufs_reset, 0x97f000),
+};
+
+static const struct msm_pinctrl_soc_data atoll_pinctrl = {
+	.pins = atoll_pins,
+	.npins = ARRAY_SIZE(atoll_pins),
+	.functions = atoll_functions,
+	.nfunctions = ARRAY_SIZE(atoll_functions),
+	.groups = atoll_groups,
+	.ngroups = ARRAY_SIZE(atoll_groups),
+	.ngpios = 119,
+};
+
+static int atoll_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &atoll_pinctrl);
+}
+
+static const struct of_device_id atoll_pinctrl_of_match[] = {
+	{ .compatible = "qcom,atoll-pinctrl", },
+	{ },
+};
+
+static struct platform_driver atoll_pinctrl_driver = {
+	.driver = {
+		.name = "atoll-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = atoll_pinctrl_of_match,
+	},
+	.probe = atoll_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init atoll_pinctrl_init(void)
+{
+	return platform_driver_register(&atoll_pinctrl_driver);
+}
+arch_initcall(atoll_pinctrl_init);
+
+static void __exit atoll_pinctrl_exit(void)
+{
+	platform_driver_unregister(&atoll_pinctrl_driver);
+}
+module_exit(atoll_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI atoll pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, atoll_pinctrl_of_match);
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 475f264..e9c2795 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -1686,11 +1686,24 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
 		return ret;
 	}
 
-	ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio);
-	if (ret) {
-		dev_err(pctrl->dev, "Failed to add pin range\n");
-		gpiochip_remove(&pctrl->chip);
-		return ret;
+	/*
+	 * For DeviceTree-supported systems, the gpio core checks the
+	 * pinctrl's device node for the "gpio-ranges" property.
+	 * If it is present, it takes care of adding the pin ranges
+	 * for the driver. In this case the driver can skip ahead.
+	 *
+	 * In order to remain compatible with older, existing DeviceTree
+	 * files which don't set the "gpio-ranges" property or systems that
+	 * utilize ACPI the driver has to call gpiochip_add_pin_range().
+	 */
+	if (!of_property_read_bool(pctrl->dev->of_node, "gpio-ranges")) {
+		ret = gpiochip_add_pin_range(&pctrl->chip,
+			dev_name(pctrl->dev), 0, 0, chip->ngpio);
+		if (ret) {
+			dev_err(pctrl->dev, "Failed to add pin range\n");
+			gpiochip_remove(&pctrl->chip);
+			return ret;
+		}
 	}
 
 	irq_parent = of_irq_find_parent(chip->of_node);
diff --git a/drivers/pinctrl/qcom/pinctrl-sdxprairie.c b/drivers/pinctrl/qcom/pinctrl-sdxprairie.c
index 6bf719e..cda5cab 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdxprairie.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdxprairie.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
@@ -1311,7 +1311,11 @@ static struct msm_pdc_mux_output sdxprairie_mux_out[] = {
 	{0, 195},
 	{0, 196},
 	{0, 197},
-	{0, 198},
+	/*
+	 * PDC pin 198 is used by USB (gp_irq_hv[56]) and is configured
+	 * in the firmware. TLMM driver should not request a GPIO line
+	 * for this pin.
+	 */
 };
 
 static struct msm_dir_conn sdxprairie_dir_conn[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-sm6150.c b/drivers/pinctrl/qcom/pinctrl-sm6150.c
index 916a2f6..792ad98 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm6150.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm6150.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
@@ -519,9 +519,11 @@ enum sm6150_functions {
 	msm_mux_qdss_cti,
 	msm_mux_phase_flag12,
 	msm_mux_copy_gp,
+	msm_mux_usb0_hs_ac,
 	msm_mux_emac_phy,
 	msm_mux_pcie_ep,
 	msm_mux_tgu_ch3,
+	msm_mux_usb1_hs_ac,
 	msm_mux_mdp_vsync0,
 	msm_mux_mdp_vsync1,
 	msm_mux_mdp_vsync2,
@@ -982,6 +984,9 @@ static const char * const phase_flag12_groups[] = {
 static const char * const copy_gp_groups[] = {
 	"gpio86",
 };
+static const char * const usb0_hs_ac_groups[] = {
+	"gpio88",
+};
 static const char * const emac_phy_groups[] = {
 	"gpio89",
 };
@@ -991,6 +996,9 @@ static const char * const pcie_ep_groups[] = {
 static const char * const tgu_ch3_groups[] = {
 	"gpio89",
 };
+static const char * const usb1_hs_ac_groups[] = {
+	"gpio89",
+};
 static const char * const mdp_vsync0_groups[] = {
 	"gpio90",
 };
@@ -1280,9 +1288,11 @@ static const struct msm_function sm6150_functions[] = {
 	FUNCTION(qdss_cti),
 	FUNCTION(phase_flag12),
 	FUNCTION(copy_gp),
+	FUNCTION(usb0_hs_ac),
 	FUNCTION(emac_phy),
 	FUNCTION(pcie_ep),
 	FUNCTION(tgu_ch3),
+	FUNCTION(usb1_hs_ac),
 	FUNCTION(mdp_vsync0),
 	FUNCTION(mdp_vsync1),
 	FUNCTION(mdp_vsync2),
@@ -1491,9 +1501,9 @@ static const struct msm_pingroup sm6150_groups[] = {
 	[85] = PINGROUP(85, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 	[86] = PINGROUP(86, SOUTH, copy_gp, NA, NA, NA, NA, NA, NA, NA, NA),
 	[87] = PINGROUP(87, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[88] = PINGROUP(88, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
-	[89] = PINGROUP(89, WEST, emac_phy, pcie_ep, tgu_ch3, NA, NA, NA, NA,
-			NA, NA),
+	[88] = PINGROUP(88, WEST, NA, usb0_hs_ac, NA, NA, NA, NA, NA, NA, NA),
+	[89] = PINGROUP(89, WEST, emac_phy, pcie_ep, tgu_ch3, usb1_hs_ac, NA,
+			NA, NA, NA, NA),
 	[90] = PINGROUP(90, WEST, mdp_vsync, mdp_vsync0, mdp_vsync1,
 			mdp_vsync2, mdp_vsync3, mdp_vsync4, mdp_vsync5,
 			pcie_clk, tgu_ch0),
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
index e7bbdf9..2ac4a71 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -551,6 +551,7 @@ static int get_keyboard_state_event(struct cros_ec_device *ec_dev)
 
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event)
 {
+	u8 event_type;
 	u32 host_event;
 	int ret;
 
@@ -570,11 +571,22 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event)
 		return ret;
 
 	if (wake_event) {
+		event_type = ec_dev->event_data.event_type;
 		host_event = cros_ec_get_host_event(ec_dev);
 
-		/* Consider non-host_event as wake event */
-		*wake_event = !host_event ||
-			      !!(host_event & ec_dev->host_event_wake_mask);
+		/*
+		 * Sensor events need to be parsed by the sensor sub-device.
+		 * Defer them, and don't report the wakeup here.
+		 */
+		if (event_type == EC_MKBP_EVENT_SENSOR_FIFO)
+			*wake_event = false;
+		/* Masked host-events should not count as wake events. */
+		else if (host_event &&
+			 !(host_event & ec_dev->host_event_wake_mask))
+			*wake_event = false;
+		/* Consider all other events as wake events. */
+		else
+			*wake_event = true;
 	}
 
 	return ret;
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 030115a..c77bac2 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -128,6 +128,15 @@
 	  Kernel and user-space processes can call the IPA driver
 	  to configure IPA core.
 
+config IPA_DEBUG
+	bool "IPA DEBUG for non-perf build"
+	depends on IPA3
+	help
+	  This driver support more debug info for non-perf build.
+	  If you use the non-perf build and want to have more debug
+	  info enabled, then this flag can be enabled.
+	  It is not suggested to enable this flag for perf build.
+
 config IPA_WDI_UNIFIED_API
 	bool "IPA WDI unified API support"
 	depends on IPA3
@@ -138,6 +147,27 @@
 	  The IPA WDI unified API supports all WDI versions through a unified
 	  interface.
 
+config IPA_ETH
+	bool "IPA Ethernet Offload Sub-system support"
+	depends on IPA3
+	help
+	  Enables IPA Ethernet Offload Subsystem for offloading PCI based
+	  ethernet devices to IPA. The offload subsystem still require a
+	  compatible network driver to register with it and a corresponding
+	  offload driver to manage one of more offload data paths that uses
+	  the network device.
+
+config IPA_ETH_NOAUTO
+	bool "Disable automatic offload initialization of interfaces"
+	depends on IPA_ETH
+	help
+	  Enabling this option prevents automatic initialization of offload on
+	  ethernet interfaces. Debugfs control interface will instead be used
+	  to enable offloading. This feature is meant only for debugging.
+	  If unsure, say N.
+
+source "drivers/platform/msm/ipa/ipa_v3/ethernet/aquantia/Kconfig"
+
 config RMNET_IPA3
 	tristate "IPA3 RMNET WWAN Network Device"
 	depends on IPA3 && QCOM_QMI_HELPERS
@@ -176,6 +206,15 @@
 	  the MHI device without AP involvement, with the exception of
 	  power management.
 
+config IPA3_MHI_PRIME_MANAGER
+	tristate "IPA3 MHI Prime Manager driver"
+	depends on IPA3
+	help
+	  This driver functionality is to setup MHI Prime channels between Host and
+	  Modem and enable the ability for MHI Prime communication.
+	  Once the configuration is set up modem will communicate directly with
+	  the Host without AP involvement for tethering data offload.
+
 config IPA_UT
 	tristate "IPA Unit-Test Framework and Test Suites"
 	depends on IPA3 && DEBUG_FS
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
index 46530a9..4e54d20 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
@@ -56,6 +56,10 @@
 #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE_HI     0x35C
 #define PCIE20_PARF_ATU_BASE_ADDR      0x634
 #define PCIE20_PARF_ATU_BASE_ADDR_HI   0x638
+#define PCIE20_PARF_BUS_DISCONNECT_CTRL          0x648
+#define PCIE20_PARF_BUS_DISCONNECT_STATUS        0x64c
+#define PCIE20_PARF_BDF_TO_SID_CFG		0x2c00
+
 #define PCIE20_PARF_DEVICE_TYPE        0x1000
 #define PCIE20_PARF_EDMA_BASE_ADDR      0x64C
 #define PCIE20_PARF_EDMA_BASE_ADDR_HI   0x650
@@ -66,6 +70,8 @@
 #define PCIE20_ELBI_CS2_ENABLE         0xA4
 
 #define PCIE20_DEVICE_ID_VENDOR_ID     0x00
+#define PCIE20_MASK_DEVICE_ID          GENMASK(31, 16)
+#define PCIE20_MASK_VENDOR_ID          GENMASK(15, 0)
 #define PCIE20_COMMAND_STATUS          0x04
 #define PCIE20_CLASS_CODE_REVISION_ID  0x08
 #define PCIE20_BIST_HDR_TYPE           0x0C
@@ -233,6 +239,7 @@ enum ep_pcie_res {
 	EP_PCIE_RES_ELBI,
 	EP_PCIE_RES_IATU,
 	EP_PCIE_RES_EDMA,
+	EP_PCIE_RES_TCSR_PERST,
 	EP_PCIE_MAX_RES,
 };
 
@@ -325,9 +332,13 @@ struct ep_pcie_dev_t {
 	void __iomem                 *edma;
 	void __iomem                 *elbi;
 	void __iomem                 *iatu;
+	void __iomem		     *tcsr_perst_en;
 
 	struct msm_bus_scale_pdata   *bus_scale_table;
 	u32                          bus_client;
+	u16                          vendor_id;
+	u16                          device_id;
+	u32                          subsystem_id;
 	u32                          link_speed;
 	bool                         active_config;
 	bool                         aggregated_irq;
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
index e9ec55e..c18fb38 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
@@ -39,6 +39,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 
+#define PCIE_MHI_STATUS(n)			((n) + 0x148)
 /* debug mask sys interface */
 static int ep_pcie_debug_mask;
 static int ep_pcie_debug_keep_resource;
@@ -96,6 +97,7 @@ static const struct ep_pcie_res_info_t ep_pcie_res_info[EP_PCIE_MAX_RES] = {
 	{"elbi",	NULL, NULL},
 	{"iatu",	NULL, NULL},
 	{"edma",	NULL, NULL},
+	{"tcsr_pcie_perst_en",	NULL, NULL},
 };
 
 static const struct ep_pcie_irq_info_t ep_pcie_irq_info[EP_PCIE_MAX_IRQ] = {
@@ -138,6 +140,63 @@ static bool ep_pcie_confirm_linkup(struct ep_pcie_dev_t *dev,
 	return true;
 }
 
+static int ep_pcie_reset_init(struct ep_pcie_dev_t *dev)
+{
+	int i, rc = 0;
+	struct ep_pcie_reset_info_t *reset_info;
+
+	for (i = 0; i < EP_PCIE_MAX_RESET; i++) {
+		reset_info = &dev->reset[i];
+		if (!reset_info->hdl)
+			continue;
+
+		rc = reset_control_assert(reset_info->hdl);
+		if (rc) {
+			if (!reset_info->required) {
+				EP_PCIE_ERR(dev,
+				"PCIe V%d: Optional reset: %s assert failed\n",
+					dev->rev, reset_info->name);
+				continue;
+			} else {
+				EP_PCIE_ERR(dev,
+				"PCIe V%d: failed to assert reset for %s\n",
+					dev->rev, reset_info->name);
+				return rc;
+			}
+		} else {
+			EP_PCIE_DBG(dev,
+			"PCIe V%d: successfully asserted reset for %s\n",
+				dev->rev, reset_info->name);
+		}
+		EP_PCIE_ERR(dev, "After Reset assert %s\n",
+						reset_info->name);
+		/* add a 1ms delay to ensure the reset is asserted */
+		usleep_range(1000, 1005);
+
+		rc = reset_control_deassert(reset_info->hdl);
+		if (rc) {
+			if (!reset_info->required) {
+				EP_PCIE_ERR(dev,
+				"PCIe V%d: Optional reset: %s deassert failed\n",
+					dev->rev, reset_info->name);
+				continue;
+			} else {
+				EP_PCIE_ERR(dev,
+				"PCIe V%d: failed to deassert reset for %s\n",
+					dev->rev, reset_info->name);
+				return rc;
+			}
+		} else {
+			EP_PCIE_DBG(dev,
+			"PCIe V%d: successfully deasserted reset for %s\n",
+				dev->rev, reset_info->name);
+		}
+		EP_PCIE_ERR(dev, "After Reset de-assert %s\n",
+						reset_info->name);
+	}
+	return 0;
+}
+
 static int ep_pcie_gpio_init(struct ep_pcie_dev_t *dev)
 {
 	int i, rc = 0;
@@ -282,7 +341,6 @@ static int ep_pcie_clk_init(struct ep_pcie_dev_t *dev)
 {
 	int i, rc = 0;
 	struct ep_pcie_clk_info_t *info;
-	struct ep_pcie_reset_info_t *reset_info;
 
 	EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);
 
@@ -354,34 +412,6 @@ static int ep_pcie_clk_init(struct ep_pcie_dev_t *dev)
 		regulator_disable(dev->gdsc);
 	}
 
-	for (i = 0; i < EP_PCIE_MAX_RESET; i++) {
-		reset_info = &dev->reset[i];
-		if (reset_info->hdl) {
-			rc = reset_control_assert(reset_info->hdl);
-			if (rc)
-				EP_PCIE_ERR(dev,
-					"PCIe V%d: failed to assert reset for %s\n",
-					dev->rev, reset_info->name);
-			else
-				EP_PCIE_DBG(dev,
-					"PCIe V%d: successfully asserted reset for %s\n",
-					dev->rev, reset_info->name);
-
-			/* add a 1ms delay to ensure the reset is asserted */
-			usleep_range(1000, 1005);
-
-			rc = reset_control_deassert(reset_info->hdl);
-			if (rc)
-				EP_PCIE_ERR(dev,
-					"PCIe V%d: failed to deassert reset for %s\n",
-					dev->rev, reset_info->name);
-			else
-				EP_PCIE_DBG(dev,
-					"PCIe V%d: successfully deasserted reset for %s\n",
-					dev->rev, reset_info->name);
-		}
-	}
-
 	return rc;
 }
 
@@ -504,6 +534,9 @@ static void ep_pcie_bar_init(struct ep_pcie_dev_t *dev)
 
 static void ep_pcie_config_mmio(struct ep_pcie_dev_t *dev)
 {
+	u32 mhi_status;
+	void __iomem *mhi_status_addr;
+
 	EP_PCIE_DBG(dev,
 		"Initial version of MMIO is:0x%x\n",
 		readl_relaxed(dev->mmio + PCIE20_MHIVER));
@@ -515,6 +548,15 @@ static void ep_pcie_config_mmio(struct ep_pcie_dev_t *dev)
 		return;
 	}
 
+	mhi_status_addr = PCIE_MHI_STATUS(dev->mmio);
+	mhi_status = readl_relaxed(mhi_status_addr);
+	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);
@@ -529,11 +571,31 @@ static void ep_pcie_config_mmio(struct ep_pcie_dev_t *dev)
 
 static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
 {
-	EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);
+	uint32_t val = 0;
 
+	EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);
+	EP_PCIE_DBG(dev,
+		"PCIe V%d: WRITING TO BDF TO SID\n",
+			dev->rev);
+	/* PARF_BDF_TO_SID disable */
+	ep_pcie_write_mask(dev->parf + PCIE20_PARF_BDF_TO_SID_CFG,
+			0, BIT(0));
+
+	EP_PCIE_DBG(dev,
+		"PCIe V%d: FINISHED WRITING BDF TO SID\n",
+			dev->rev);
 	/* enable debug IRQ */
 	ep_pcie_write_mask(dev->parf + PCIE20_PARF_DEBUG_INT_EN,
 			0, BIT(3) | BIT(2) | BIT(1));
+	/* Reconnect AXI master port */
+	val = readl_relaxed(dev->parf + PCIE20_PARF_BUS_DISCONNECT_STATUS);
+	if (val & BIT(0)) {
+		EP_PCIE_DBG(dev,
+		"PCIe V%d: AXI Master port was disconnected, reconnecting...\n",
+			dev->rev);
+		ep_pcie_write_mask(dev->parf + PCIE20_PARF_BUS_DISCONNECT_CTRL,
+								0, BIT(0));
+	}
 
 	if (!configured) {
 		/* Configure PCIe to endpoint mode */
@@ -570,7 +632,7 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
 		EP_PCIE_DBG2(dev, "PCIe V%d: Enable L1\n", dev->rev);
 		ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, BIT(5), 0);
 
-		ep_pcie_write_mask(dev->parf + PCIE20_PARF_SLV_ADDR_MSB_CTRL,
+		ep_pcie_write_reg(dev->parf + PCIE20_PARF_SLV_ADDR_MSB_CTRL,
 					0, BIT(0));
 		ep_pcie_write_reg(dev->parf, PCIE20_PARF_SLV_ADDR_SPACE_SIZE_HI,
 					0x200);
@@ -659,6 +721,17 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
 		ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, 0,
 			BIT(0));
 
+		/* Set Vendor ID and Device ID */
+		if (ep_pcie_dev.device_id != 0xFFFF)
+			ep_pcie_write_reg_field(dev->dm_core,
+						PCIE20_DEVICE_ID_VENDOR_ID,
+						PCIE20_MASK_DEVICE_ID,
+						ep_pcie_dev.device_id);
+		if (ep_pcie_dev.vendor_id != 0xFFFF)
+			ep_pcie_write_reg_field(dev->dm_core,
+						PCIE20_DEVICE_ID_VENDOR_ID,
+						PCIE20_MASK_VENDOR_ID,
+						ep_pcie_dev.vendor_id);
 		/* Set class code and revision ID */
 		ep_pcie_write_reg(dev->dm_core, PCIE20_CLASS_CODE_REVISION_ID,
 			0xff000000);
@@ -667,7 +740,9 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
 		ep_pcie_write_reg(dev->dm_core, PCIE20_BIST_HDR_TYPE, 0x10);
 
 		/* Set Subsystem ID and Subsystem Vendor ID */
-		ep_pcie_write_reg(dev->dm_core, PCIE20_SUBSYSTEM, 0xa01f17cb);
+		if (ep_pcie_dev.subsystem_id)
+			ep_pcie_write_reg(dev->dm_core, PCIE20_SUBSYSTEM,
+					ep_pcie_dev.subsystem_id);
 
 		/* Set the PMC Register - to support PME in D0/D3hot/D3cold */
 		ep_pcie_write_mask(dev->dm_core + PCIE20_CAP_ID_NXT_PTR, 0,
@@ -750,8 +825,8 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
 		ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, BIT(5), 0);
 	}
 
-	/* Configure MMIO */
-	ep_pcie_config_mmio(dev);
+	if (!configured)
+		ep_pcie_config_mmio(dev);
 }
 
 static void ep_pcie_config_inbound_iatu(struct ep_pcie_dev_t *dev)
@@ -1203,6 +1278,7 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev,
 	dev->edma = dev->res[EP_PCIE_RES_EDMA].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);
@@ -1232,6 +1308,11 @@ static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev)
 
 	spin_lock_irqsave(&dev->isr_lock, irqsave_flags);
 
+	if (dev->enumerated) {
+		EP_PCIE_DBG(dev, "PCIe V%d: Enumeration already done\n",
+				dev->rev);
+		goto done;
+	}
 	dev->enumerated = true;
 	dev->link_status = EP_PCIE_LINK_ENABLED;
 
@@ -1265,6 +1346,7 @@ static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev)
 			"PCIe V%d: do not notify client about linkup\n",
 			dev->rev);
 
+done:
 	spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags);
 }
 
@@ -1318,42 +1400,86 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
 		}
 
 		dev->power_on = true;
+
+		 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;
+			EP_PCIE_DBG(dev, "PCIe V%d: Link status is 0x%x.\n",
+					dev->rev, val);
+			if (val) {
+				EP_PCIE_INFO(dev,
+					"PCIe V%d: link initialized by bootloader for LE PCIe endpoint; skip link training in HLOS.\n",
+					dev->rev);
+				/*
+				 * Read and save the subsystem id set in PBL
+				 * (needed for restore during D3->D0)
+				 */
+				ep_pcie_dev.subsystem_id =
+					readl_relaxed(dev->dm_core +
+							PCIE20_SUBSYSTEM);
+				/*
+				 * 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;
+				goto checkbme;
+			} else {
+				ltssm_en = readl_relaxed(dev->parf
+					+ PCIE20_PARF_LTSSM) & BIT(8);
+
+				if (ltssm_en) {
+					EP_PCIE_ERR(dev,
+						"PCIe V%d: link is not up when LTSSM has already enabled by bootloader.\n",
+						dev->rev);
+					ret = EP_PCIE_ERROR;
+					goto link_fail;
+				} else {
+					EP_PCIE_DBG(dev,
+						"PCIe V%d: Proceed with regular link training.\n",
+						dev->rev);
+				}
+			}
+		}
+
+		ret = ep_pcie_reset_init(dev);
+		if (ret)
+			goto link_fail;
 	}
 
 	if (!(opt & EP_PCIE_OPT_ENUM))
 		goto out;
 
-	/* check link status during initial bootup */
-	if (!dev->enumerated) {
-		val = readl_relaxed(dev->parf + PCIE20_PARF_PM_STTS);
-		val = val & PARF_XMLH_LINK_UP;
-		EP_PCIE_DBG(dev, "PCIe V%d: Link status is 0x%x\n", dev->rev,
-				val);
-		if (val) {
-			EP_PCIE_INFO(dev,
-				"PCIe V%d: link initialized by bootloader for LE PCIe endpoint; skip link training in HLOS\n",
-				dev->rev);
-			ep_pcie_core_init(dev, true);
-			dev->link_status = EP_PCIE_LINK_UP;
-			dev->l23_ready = false;
-			goto checkbme;
-		} else {
-			ltssm_en = readl_relaxed(dev->parf
-					+ PCIE20_PARF_LTSSM) & BIT(8);
+	EP_PCIE_DBG(dev,
+		"TCSR PERST_EN value before configure:0x%x\n",
+		readl_relaxed(dev->tcsr_perst_en + 0x258));
 
-			if (ltssm_en) {
-				EP_PCIE_ERR(dev,
-					"PCIe V%d: link is not up when LTSSM has already enabled by bootloader\n",
-					dev->rev);
-				ret = EP_PCIE_ERROR;
-				goto link_fail;
-			} else {
-				EP_PCIE_DBG(dev,
-					"PCIe V%d: Proceed with regular link training\n",
-					dev->rev);
-			}
-		}
-	}
+	/*
+	 * 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));
 
 	if (opt & EP_PCIE_OPT_AST_WAKE) {
 		/* assert PCIe WAKE# */
@@ -1406,6 +1532,9 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
 		}
 	}
 
+	ret = ep_pcie_reset_init(dev);
+	if (ret)
+		goto link_fail;
 	/* init PCIe PHY */
 	ep_pcie_phy_init(dev);
 
@@ -2512,6 +2641,30 @@ static int ep_pcie_probe(struct platform_device *pdev)
 		EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: pcie-link-speed:%d\n",
 			ep_pcie_dev.rev, ep_pcie_dev.link_speed);
 
+	ep_pcie_dev.vendor_id = 0xFFFF;
+	ret = of_property_read_u16((&pdev->dev)->of_node,
+				"qcom,pcie-vendor-id",
+				&ep_pcie_dev.vendor_id);
+	if (ret)
+		EP_PCIE_DBG(&ep_pcie_dev,
+				"PCIe V%d: pcie-vendor-id does not exist.\n",
+				ep_pcie_dev.rev);
+	else
+		EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: pcie-vendor-id:%d.\n",
+				ep_pcie_dev.rev, ep_pcie_dev.vendor_id);
+
+	ep_pcie_dev.device_id = 0xFFFF;
+	ret = of_property_read_u16((&pdev->dev)->of_node,
+				"qcom,pcie-device-id",
+				&ep_pcie_dev.device_id);
+	if (ret)
+		EP_PCIE_DBG(&ep_pcie_dev,
+				"PCIe V%d: pcie-device-id does not exist.\n",
+				ep_pcie_dev.rev);
+	else
+		EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: pcie-device-id:%d.\n",
+				ep_pcie_dev.rev, ep_pcie_dev.device_id);
+
 	ret = of_property_read_u32((&pdev->dev)->of_node,
 				"qcom,dbi-base-reg",
 				&ep_pcie_dev.dbi_base_reg);
@@ -2798,7 +2951,7 @@ static void __exit ep_pcie_exit(void)
 	platform_driver_unregister(&ep_pcie_driver);
 }
 
-module_init(ep_pcie_init);
+subsys_initcall(ep_pcie_init);
 module_exit(ep_pcie_exit);
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("MSM PCIe Endpoint Driver");
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index b37859e..6d3390c 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -2323,7 +2323,13 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl,
 		return -GSI_STATUS_NODEV;
 	}
 	memset(ctx, 0, sizeof(*ctx));
-	user_data_size = props->ring_len / props->re_size;
+
+	/* For IPA offloaded WDI channels not required user_data pointer */
+	if (props->prot != GSI_CHAN_PROT_WDI2 &&
+		props->prot != GSI_CHAN_PROT_WDI3)
+		user_data_size = props->ring_len / props->re_size;
+	else
+		user_data_size = props->re_size;
 	/*
 	 * GCI channels might have OOO event completions up to GSI_VEID_MAX.
 	 * user_data needs to be large enough to accommodate those.
@@ -3433,7 +3439,7 @@ int gsi_queue_xfer(unsigned long chan_hdl, uint16_t num_xfers,
 		return -GSI_STATUS_NODEV;
 	}
 
-	if (chan_hdl >= gsi_ctx->max_ch || !num_xfers || !xfer) {
+	if (chan_hdl >= gsi_ctx->max_ch || (num_xfers && !xfer)) {
 		GSIERR("bad params chan_hdl=%lu num_xfers=%u xfer=%pK\n",
 				chan_hdl, num_xfers, xfer);
 		return -GSI_STATUS_INVALID_PARAMS;
@@ -3453,6 +3459,11 @@ int gsi_queue_xfer(unsigned long chan_hdl, uint16_t num_xfers,
 		slock = &ctx->ring.slock;
 
 	spin_lock_irqsave(slock, flags);
+
+	/* allow only ring doorbell */
+	if (!num_xfers)
+		goto ring_doorbell;
+
 	/*
 	 * for GCI channels the responsibility is on the caller to make sure
 	 * there is enough room in the TRE.
@@ -3488,11 +3499,12 @@ int gsi_queue_xfer(unsigned long chan_hdl, uint16_t num_xfers,
 
 	ctx->stats.queued += num_xfers;
 
-	/* ensure TRE is set before ringing doorbell */
-	wmb();
-
-	if (ring_db)
+ring_doorbell:
+	if (ring_db) {
+		/* ensure TRE is set before ringing doorbell */
+		wmb();
 		gsi_ring_chan_doorbell(ctx);
+	}
 
 	spin_unlock_irqrestore(slock, flags);
 
@@ -3622,6 +3634,7 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
 	struct gsi_chan_ctx *ctx;
 	enum gsi_chan_mode curr;
 	unsigned long flags;
+	enum gsi_chan_mode chan_mode;
 
 	if (!gsi_ctx) {
 		pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__);
@@ -3693,13 +3706,20 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
 					GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_OFFS(
 							gsi_ctx->per.ee));
 				spin_unlock_irqrestore(&gsi_ctx->slock, flags);
-				spin_lock_irqsave(&ctx->ring.slock, flags);
-				atomic_set(
-					&ctx->poll_mode, GSI_CHAN_MODE_POLL);
+				spin_lock_irqsave(&ctx->evtr->ring.slock,
+									flags);
+				chan_mode = atomic_xchg(&ctx->poll_mode,
+						GSI_CHAN_MODE_POLL);
 				spin_unlock_irqrestore(
-					&ctx->ring.slock, flags);
+					&ctx->evtr->ring.slock, flags);
 				ctx->stats.poll_pending_irq++;
-				return -GSI_STATUS_PENDING_IRQ;
+				GSIDBG("In IEOB WA pnd cnt = %d prvmode = %d\n",
+						ctx->stats.poll_pending_irq,
+						chan_mode);
+				if (chan_mode == GSI_CHAN_MODE_POLL)
+					return GSI_STATUS_SUCCESS;
+				else
+					return -GSI_STATUS_PENDING_IRQ;
 			}
 		}
 		ctx->stats.poll_to_callback++;
diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h
index b86301e..5f9c3383 100644
--- a/drivers/platform/msm/gsi/gsi.h
+++ b/drivers/platform/msm/gsi/gsi.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
@@ -32,7 +32,7 @@
 #define GSI_EVT_RING_MAX  24
 #define GSI_NO_EVT_ERINDEX 31
 
-#define gsi_readl(c)	({ u32 __v = readl_relaxed(c); __iormb(); __v; })
+#define gsi_readl(c)	(readl(c))
 #define gsi_writel(v, c)	({ __iowmb(); writel_relaxed((v), (c)); })
 
 #define GSI_IPC_LOGGING(buf, fmt, args...) \
diff --git a/drivers/platform/msm/gsi/gsi_emulation.h b/drivers/platform/msm/gsi/gsi_emulation.h
index cd9a5c0..79ea403 100644
--- a/drivers/platform/msm/gsi/gsi_emulation.h
+++ b/drivers/platform/msm/gsi/gsi_emulation.h
@@ -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
@@ -18,7 +18,7 @@
 # include "gsi_reg.h"
 # include "gsi_emulation_stubs.h"
 
-# define gsi_emu_readl(c)     ({ u32 __v = readl_relaxed(c); __iormb(); __v; })
+# define gsi_emu_readl(c)     (readl(c))
 # define gsi_emu_writel(v, c) ({ __iowmb(); writel_relaxed((v), (c)); })
 
 # define CNTRLR_BASE 0
diff --git a/drivers/platform/msm/gsi/gsi_emulation_stubs.h b/drivers/platform/msm/gsi/gsi_emulation_stubs.h
index dd9d0df..109abc3 100644
--- a/drivers/platform/msm/gsi/gsi_emulation_stubs.h
+++ b/drivers/platform/msm/gsi/gsi_emulation_stubs.h
@@ -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
@@ -14,7 +14,6 @@
 # define _GSI_EMULATION_STUBS_H_
 
 # include <asm/barrier.h>
-# define __iormb()       rmb() /* used in gsi.h */
 # define __iowmb()       wmb() /* used in gsi.h */
 
 #endif /* #if !defined(_GSI_EMULATION_STUBS_H_) */
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index b035093..133bf92 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -210,6 +210,11 @@ const char *ipa_clients_strings[IPA_CLIENT_MAX] = {
 	__stringify(IPA_CLIENT_WIGIG4_CONS),
 	__stringify(IPA_CLIENT_AQC_ETHERNET_PROD),
 	__stringify(IPA_CLIENT_AQC_ETHERNET_CONS),
+	__stringify(IPA_CLIENT_MHI_PRIME_RMNET_PROD),
+	__stringify(IPA_CLIENT_MHI_PRIME_RMNET_CONS),
+	__stringify(IPA_CLIENT_MHI_PRIME_TETH_PROD),
+	__stringify(IPA_CLIENT_MHI_PRIME_TETH_CONS),
+	__stringify(IPA_CLIENT_MHI_PRIME_DPL_PROD),
 };
 
 /**
@@ -3513,6 +3518,20 @@ int ipa_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info, u16 num_regs)
 	return ret;
 }
 
+void ipa_register_client_callback(int (*client_cb)(bool is_lock),
+				bool (*teth_port_state)(void), u32 ipa_ep_idx)
+{
+	IPA_API_DISPATCH(ipa_register_client_callback,
+		client_cb, teth_port_state, ipa_ep_idx);
+}
+
+void ipa_deregister_client_callback(u32 ipa_ep_idx)
+{
+	IPA_API_DISPATCH(ipa_deregister_client_callback,
+		ipa_ep_idx);
+}
+
+
 /**
  * ipa_pm_is_used() - Returns if IPA PM framework is used
  */
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index d633eeb..9978603 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.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
@@ -454,6 +454,12 @@ struct ipa_api_controller {
 	int (*ipa_enable_wigig_pipe_i)(enum ipa_client_type client);
 
 	int (*ipa_disable_wigig_pipe_i)(enum ipa_client_type client);
+
+	void (*ipa_register_client_callback)(
+		int (*client_cb)(bool is_lock),
+		bool (*teth_port_state)(void), u32 ipa_ep_idx);
+
+	void (*ipa_deregister_client_callback)(u32 ipa_ep_idx);
 };
 
 #ifdef CONFIG_IPA3
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 269b5c6..2a6e18d 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -162,6 +162,7 @@ struct ipa_mhi_client_ctx {
 };
 
 static struct ipa_mhi_client_ctx *ipa_mhi_client_ctx;
+static DEFINE_MUTEX(mhi_client_general_mutex);
 
 #ifdef CONFIG_DEBUG_FS
 #define IPA_MHI_MAX_MSG_LEN 512
@@ -182,6 +183,18 @@ static char *ipa_mhi_channel_state_str[] = {
 	ipa_mhi_channel_state_str[(state)] : \
 	"INVALID")
 
+static int ipa_mhi_set_lock_unlock(bool is_lock)
+{
+	IPA_MHI_DBG("entry\n");
+	if (is_lock)
+		mutex_lock(&mhi_client_general_mutex);
+	else
+		mutex_unlock(&mhi_client_general_mutex);
+	IPA_MHI_DBG("exit\n");
+
+	return 0;
+}
+
 static int ipa_mhi_read_write_host(enum ipa_mhi_dma_dir dir, void *dev_addr,
 	u64 host_addr, int size)
 {
@@ -1595,6 +1608,7 @@ int ipa_mhi_connect_pipe(struct ipa_mhi_connect_params *in, u32 *clnt_hdl)
 				&channel->cached_gsi_evt_ring_hdl;
 		internal.start.gsi.evchid = channel->index;
 
+		mutex_lock(&mhi_client_general_mutex);
 		res = ipa_connect_mhi_pipe(&internal, clnt_hdl);
 		if (res) {
 			IPA_MHI_ERR("ipa_connect_mhi_pipe failed %d\n", res);
@@ -1610,6 +1624,8 @@ int ipa_mhi_connect_pipe(struct ipa_mhi_connect_params *in, u32 *clnt_hdl)
 				sizeof(((struct ipa_mhi_ch_ctx *)0)->chstate));
 		if (res) {
 			IPA_MHI_ERR("ipa_mhi_read_write_host failed\n");
+			mutex_unlock(&mhi_client_general_mutex);
+			IPA_ACTIVE_CLIENTS_DEC_EP(in->sys.client);
 			return res;
 
 		}
@@ -1629,6 +1645,12 @@ int ipa_mhi_connect_pipe(struct ipa_mhi_connect_params *in, u32 *clnt_hdl)
 		channel->state = IPA_HW_MHI_CHANNEL_STATE_RUN;
 	}
 
+	if (IPA_CLIENT_IS_PROD(in->sys.client)) {
+		ipa_register_client_callback(&ipa_mhi_set_lock_unlock,
+			NULL, *clnt_hdl);
+	}
+	mutex_unlock(&mhi_client_general_mutex);
+
 	if (!in->sys.keep_ipa_awake)
 		IPA_ACTIVE_CLIENTS_DEC_EP(in->sys.client);
 
@@ -1636,6 +1658,7 @@ int ipa_mhi_connect_pipe(struct ipa_mhi_connect_params *in, u32 *clnt_hdl)
 
 	return 0;
 fail_connect_pipe:
+	mutex_unlock(&mhi_client_general_mutex);
 	ipa_mhi_reset_channel(channel);
 fail_start_channel:
 	IPA_ACTIVE_CLIENTS_DEC_EP(in->sys.client);
@@ -1690,19 +1713,27 @@ int ipa_mhi_disconnect_pipe(u32 clnt_hdl)
 		goto fail_reset_channel;
 	}
 
+	mutex_lock(&mhi_client_general_mutex);
 	res = ipa_disconnect_mhi_pipe(clnt_hdl);
 	if (res) {
 		IPA_MHI_ERR(
 			"IPA core driver failed to disconnect the pipe hdl %d, res %d"
 				, clnt_hdl, res);
-		return res;
+		goto fail_disconnect_pipe;
 	}
 
+	if (IPA_CLIENT_IS_PROD(client))
+		ipa_deregister_client_callback(clnt_hdl);
+
+	mutex_unlock(&mhi_client_general_mutex);
+
 	IPA_ACTIVE_CLIENTS_DEC_EP(ipa_get_client_mapping(clnt_hdl));
 
 	IPA_MHI_DBG("client (ep: %d) disconnected\n", clnt_hdl);
 	IPA_MHI_FUNC_EXIT();
 	return 0;
+fail_disconnect_pipe:
+	mutex_unlock(&mhi_client_general_mutex);
 fail_reset_channel:
 	IPA_ACTIVE_CLIENTS_DEC_EP(ipa_get_client_mapping(clnt_hdl));
 	return res;
@@ -2866,6 +2897,5 @@ const char *ipa_mhi_get_state_str(int state)
 	return MHI_STATE_STR(state);
 }
 EXPORT_SYMBOL(ipa_mhi_get_state_str);
-
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("IPA MHI client driver");
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
index ac3d62e..ea01462 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.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
@@ -296,6 +296,17 @@ static char *ipa3_usb_notify_event_to_string(enum ipa_usb_notify_event event)
 	return "UNSUPPORTED";
 }
 
+static bool ipa3_usb_get_teth_port_state(void)
+{
+	if (ipa3_usb_ctx == NULL)
+		return false;
+	if (ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].state ==
+					IPA_USB_CONNECTED)
+		return true;
+	else
+		return false;
+}
+
 static bool ipa3_usb_set_state(enum ipa3_usb_state new_state, bool err_permit,
 	enum ipa3_usb_transport_type ttype)
 {
@@ -1917,6 +1928,15 @@ static int ipa3_usb_xdci_connect_internal(
 		goto connect_dl_fail;
 	}
 
+	/* MHIP pipe enablement */
+	if (ipa3_is_mhip_offload_enabled()) {
+		result = ipa_mpm_mhip_xdci_pipe_enable(params->teth_prot);
+		if (result) {
+			IPA_USB_ERR("failed to connect MHIP channel\n");
+			goto connect_dl_fail;
+		}
+	}
+
 	/* Connect tethering protocol */
 	result = ipa3_usb_connect_teth_prot(params->teth_prot);
 	if (result) {
@@ -2238,8 +2258,8 @@ int ipa_usb_xdci_connect(struct ipa_usb_xdci_chan_params *ul_chan_params,
 	 * For IPA_USB_DIAG/DPL config there will not be any UL ep.
 	 */
 	if (connect_params->teth_prot != IPA_USB_DIAG)
-		ipa3_register_lock_unlock_callback(&ipa_usb_set_lock_unlock,
-			ul_out_params->clnt_hdl);
+		ipa3_register_client_callback(&ipa_usb_set_lock_unlock,
+			&ipa3_usb_get_teth_port_state, ul_out_params->clnt_hdl);
 
 	IPA_USB_DBG_LOW("exit\n");
 	mutex_unlock(&ipa3_usb_ctx->general_mutex);
@@ -2325,7 +2345,7 @@ static int ipa_usb_xdci_dismiss_channels(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
 	 * For IPA_USB_DIAG/DPL config there will not be any UL config.
 	 */
 	if (!IPA3_USB_IS_TTYPE_DPL(ttype))
-		ipa3_deregister_lock_unlock_callback(ul_clnt_hdl);
+		ipa3_deregister_client_callback(ul_clnt_hdl);
 
 	/* Change state to STOPPED */
 	if (!ipa3_usb_set_state(IPA_USB_STOPPED, false, ttype))
@@ -2410,6 +2430,16 @@ int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
 		if (orig_state != IPA_USB_SUSPENDED) {
 			spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock,
 				flags);
+
+			/* Stop UL MHIP channel */
+			if (ipa3_is_mhip_offload_enabled()) {
+				result = ipa_mpm_mhip_ul_data_stop(teth_prot);
+				if (result) {
+					IPA_USB_ERR("fail UL MHIPData stop\n");
+					goto bad_params;
+				}
+			}
+
 			/* Stop UL channel */
 			result = ipa3_xdci_disconnect(ul_clnt_hdl,
 				true,
@@ -2430,6 +2460,16 @@ int ipa_usb_xdci_disconnect(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
 	if (result)
 		goto bad_params;
 
+	/* Stop UL/DL MHIP channels */
+	if (ipa3_is_mhip_offload_enabled()) {
+		result = ipa_mpm_mhip_xdci_pipe_disable(teth_prot);
+		if (result) {
+			IPA_USB_ERR("failed to disconnect MHIP channel\n");
+			goto bad_params;
+		}
+	}
+
+
 	/* Disconnect tethering protocol */
 	result = ipa3_usb_disconnect_teth_prot(teth_prot);
 	if (result)
@@ -2740,6 +2780,15 @@ int ipa_usb_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
 	}
 	spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags);
 
+	/* Stop MHIP channel */
+	if (ipa3_is_mhip_offload_enabled()) {
+		result = ipa_mpm_mhip_xdci_pipe_disable(teth_prot);
+		if (result) {
+			IPA_USB_ERR("failed to disconnect MHIP channel\n");
+			goto release_prod_fail;
+		}
+	}
+
 	IPA_USB_DBG_LOW("exit\n");
 	mutex_unlock(&ipa3_usb_ctx->general_mutex);
 	return 0;
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index 425f181..13d09af 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -475,4 +475,9 @@ int ipa_wigig_send_msg(int msg_type,
 	const char *netdev_name, u8 *mac,
 	enum ipa_client_type client, bool to_wigig);
 
+void ipa_register_client_callback(int (*client_cb)(bool is_lock),
+			bool (*teth_port_state)(void), u32 ipa_ep_idx);
+
+void ipa_deregister_client_callback(u32 ipa_ep_idx);
+
 #endif /* _IPA_COMMON_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/Makefile b/drivers/platform/msm/ipa/ipa_v3/Makefile
index 2587e0c..a7b5393 100644
--- a/drivers/platform/msm/ipa/ipa_v3/Makefile
+++ b/drivers/platform/msm/ipa/ipa_v3/Makefile
@@ -12,6 +12,12 @@
 
 obj-$(CONFIG_IPA3_MHI_PROXY) += ipa_mhi_proxy.o
 
+obj-$(CONFIG_IPA_ETH) += ethernet/
+
 ipat-$(CONFIG_IPA3_REGDUMP) += dump/ipa_reg_dump.o
 
+ccflags-$(CONFIG_IPA3_REGDUMP) += -Idrivers/platform/msm/ipa/ipa_v3/dump
+
 ccflags-$(CONFIG_IPA3_REGDUMP_SM8150) += -Idrivers/platform/msm/ipa/ipa_v3/dump/sm8150
+
+obj-$(CONFIG_IPA3_MHI_PRIME_MANAGER) += ipa_mpm.o
diff --git a/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.c b/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.c
index aaedc8c..47c1976 100644
--- a/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.c
+++ b/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.c
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 #include "ipa_reg_dump.h"
+#include "ipa_access_control.h"
 
 /* Total size required for test bus */
 #define IPA_MEM_OVERLAY_SIZE     0x66000
@@ -338,13 +339,13 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = {
 					    ipa_dst_rsrc_grp_23_rsrc_type_n),
 
 	/* Source Resource Group Count Registers */
-	IPA_REG_SAVE_CFG_ENTRY_SRC_RSRC_CNT_GRP
-		(IPA_SRC_RSRC_GRP_0123_RSRC_TYPE_CNT_n,
+	IPA_REG_SAVE_CFG_ENTRY_SRC_RSRC_CNT_GRP(
+		IPA_SRC_RSRC_GRP_0123_RSRC_TYPE_CNT_n,
 		ipa_src_rsrc_grp_0123_rsrc_type_cnt_n),
 
 	/* Destination Resource Group Count Registers */
-	IPA_REG_SAVE_CFG_ENTRY_DST_RSRC_CNT_GRP
-		(IPA_DST_RSRC_GRP_0123_RSRC_TYPE_CNT_n,
+	IPA_REG_SAVE_CFG_ENTRY_DST_RSRC_CNT_GRP(
+		IPA_DST_RSRC_GRP_0123_RSRC_TYPE_CNT_n,
 		ipa_dst_rsrc_grp_0123_rsrc_type_cnt_n),
 
 	/*
@@ -360,6 +361,9 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = {
 	GEN_SRC_DST_ADDR_MAP(GSI_REE_CFG,
 			     gsi.gen,
 			     gsi_ree_cfg),
+	IPA_REG_SAVE_GSI_VER(
+			     IPA_GSI_TOP_GSI_INST_RAM_n,
+			     ipa_gsi_top_gsi_inst_ram_n),
 
 	/* GSI Debug Registers */
 	GEN_SRC_DST_ADDR_MAP(IPA_GSI_TOP_GSI_DEBUG_BUSY_REG,
@@ -651,6 +655,73 @@ static void ipa_hal_save_regs_ipa_cmdq(void);
 static void ipa_hal_save_regs_rsrc_db(void);
 static void ipa_reg_save_anomaly_check(void);
 
+static struct reg_access_funcs_s *get_access_funcs(u32 addr)
+{
+	u32 i, asub = ipa3_ctx->sd_state;
+
+	for (i = 0; i < ARRAY_SIZE(mem_access_map); i++) {
+		if (addr >= mem_access_map[i].addr_range_begin &&
+		    addr <= mem_access_map[i].addr_range_end) {
+			return mem_access_map[i].access[asub];
+		}
+	}
+
+	IPAERR("Unknown register offset(0x%08X). Using dflt access methods\n",
+		   addr);
+
+	return &io_matrix[AA_COMBO];
+}
+
+static u32 in_dword(
+	u32 addr)
+{
+	struct reg_access_funcs_s *io = get_access_funcs(addr);
+
+	return io->read(ipa3_ctx->reg_collection_base + addr);
+}
+
+static u32 in_dword_masked(
+	u32 addr,
+	u32 mask)
+{
+	struct reg_access_funcs_s *io = get_access_funcs(addr);
+	u32 val;
+
+	val = io->read(ipa3_ctx->reg_collection_base + addr);
+
+	if (io->read == act_read)
+		return val & mask;
+
+	return val;
+}
+
+static void out_dword(
+	u32 addr,
+	u32 val)
+{
+	struct reg_access_funcs_s *io = get_access_funcs(addr);
+
+	io->write(ipa3_ctx->reg_collection_base + addr, val);
+}
+
+/*
+ * FUNCTION:  ipa_save_gsi_ver
+ *
+ * Saves the gsi version
+ *
+ * @return
+ * None
+ */
+void ipa_save_gsi_ver(void)
+{
+	if (!ipa3_ctx->do_register_collection_on_crash)
+		return;
+
+	ipa_reg_save.gsi.fw_ver =
+		IPA_READ_1xVECTOR_REG(IPA_GSI_TOP_GSI_INST_RAM_n, 0) &
+		0x0000FFFF;
+}
+
 /*
  * FUNCTION:  ipa_save_registers
  *
@@ -669,7 +740,7 @@ void ipa_save_registers(void)
 	union ipa_hwio_def_ipa_rsrc_mngr_db_rsrc_read_u
 	    ipa_rsrc_mngr_db_rsrc_read;
 
-	if (ipa3_ctx->do_register_collection_on_crash == false)
+	if (!ipa3_ctx->do_register_collection_on_crash)
 		return;
 
 	IPAERR("Commencing\n");
@@ -831,35 +902,48 @@ void ipa_save_registers(void)
 	 * true, via dtsi, and the collection will be done.
 	 */
 	if (ipa3_ctx->do_non_tn_collection_on_crash == true) {
-		/* Copy Pkt context directly from IPA_CTX_ID register space */
-		memcpy((void *)ipa_reg_save.pkt_ctntx,
-		       (void *)((u8 *) ipa3_ctx->reg_collection_base +
-				GEN_2xVECTOR_REG_OFST(
-				    IPA_CTX_ID_m_CTX_NUM_n, 0, 0)),
-		       sizeof(ipa_reg_save.pkt_ctntx));
+		u32 ofst = GEN_2xVECTOR_REG_OFST(IPA_CTX_ID_m_CTX_NUM_n, 0, 0);
+		struct reg_access_funcs_s *io = get_access_funcs(ofst);
+		/*
+		 * If the memory is accessible, copy pkt context directly from
+		 * IPA_CTX_ID register space
+		 */
+		if (io->read == act_read) {
+			memcpy((void *)ipa_reg_save.pkt_ctntx,
+				   (const void *)
+				   (ipa3_ctx->reg_collection_base + ofst),
+				   sizeof(ipa_reg_save.pkt_ctntx));
 
-		ipa_rsrc_mngr_db_cfg.value =
-			IPA_READ_SCALER_REG(IPA_RSRC_MNGR_DB_CFG);
+			ipa_rsrc_mngr_db_cfg.value =
+				IPA_READ_SCALER_REG(IPA_RSRC_MNGR_DB_CFG);
 
-		ipa_rsrc_mngr_db_cfg.def.rsrc_type_sel = 0;
-		IPA_WRITE_SCALER_REG(IPA_RSRC_MNGR_DB_CFG,
-				     ipa_rsrc_mngr_db_cfg.value);
+			ipa_rsrc_mngr_db_cfg.def.rsrc_type_sel = 0;
 
-		for (i = 0; i < IPA_HW_PKT_CTNTX_MAX; i++) {
-			ipa_rsrc_mngr_db_cfg.def.rsrc_id_sel = i;
-			IPA_WRITE_SCALER_REG(IPA_RSRC_MNGR_DB_CFG,
-					     ipa_rsrc_mngr_db_cfg.value);
+			IPA_WRITE_SCALER_REG(
+				IPA_RSRC_MNGR_DB_CFG,
+				ipa_rsrc_mngr_db_cfg.value);
 
-			ipa_rsrc_mngr_db_rsrc_read.value =
-				IPA_READ_SCALER_REG(IPA_RSRC_MNGR_DB_RSRC_READ);
+			for (i = 0; i < IPA_HW_PKT_CTNTX_MAX; i++) {
+				ipa_rsrc_mngr_db_cfg.def.rsrc_id_sel = i;
 
-			if (ipa_rsrc_mngr_db_rsrc_read.def.rsrc_occupied ==
-			    true) {
-				ipa_reg_save.pkt_ctntx_active[i] = true;
-				ipa_reg_save.pkt_cntxt_state[i] =
-					(enum ipa_hw_pkt_cntxt_state_e)
-					ipa_reg_save.pkt_ctntx[i].state;
+				IPA_WRITE_SCALER_REG(
+					IPA_RSRC_MNGR_DB_CFG,
+					ipa_rsrc_mngr_db_cfg.value);
+
+				ipa_rsrc_mngr_db_rsrc_read.value =
+					IPA_READ_SCALER_REG(
+						IPA_RSRC_MNGR_DB_RSRC_READ);
+
+				if (ipa_rsrc_mngr_db_rsrc_read.def.rsrc_occupied
+					== true) {
+					ipa_reg_save.pkt_ctntx_active[i] = true;
+					ipa_reg_save.pkt_cntxt_state[i] =
+						(enum ipa_hw_pkt_cntxt_state_e)
+						ipa_reg_save.pkt_ctntx[i].state;
+				}
 			}
+		} else {
+			IPAERR("IPA_CTX_ID is not currently accessible\n");
 		}
 	}
 
@@ -1316,11 +1400,11 @@ static void ipa_hal_save_regs_save_ipa_testbus(void)
  *
  * @return
  */
-int ipa_reg_save_init(u8 value)
+int ipa_reg_save_init(u32 value)
 {
 	u32 i, num_regs = ARRAY_SIZE(ipa_regs_to_save_array);
 
-	if (ipa3_ctx->do_register_collection_on_crash == false)
+	if (!ipa3_ctx->do_register_collection_on_crash)
 		return 0;
 
 	memset(&ipa_reg_save, value, sizeof(ipa_reg_save));
diff --git a/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.h b/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.h
index ca4af90..9753fa4 100644
--- a/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.h
+++ b/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.h
@@ -25,22 +25,10 @@
  * are required by some of the macros and include files that follow...
  */
 #define my_in_dword(addr) \
-	({ u32 __v = readl_relaxed((addr)); __iormb(); __v; })
-#define in_dword(addr) \
-	my_in_dword((u8 *) ipa3_ctx->reg_collection_base + \
-		    (u32)(addr))
-
-#define my_in_dword_masked(addr, mask) \
-	(my_in_dword(addr) & (mask))
-#define in_dword_masked(addr, mask) \
-	my_in_dword_masked((u8 *) ipa3_ctx->reg_collection_base + \
-			   (u32)(addr), (mask))
+	(readl(addr))
 
 #define my_out_dword(addr, val) \
 	({ __iowmb(); writel_relaxed((val), (addr)); })
-#define out_dword(addr, val) \
-	my_out_dword((u8 *) ipa3_ctx->reg_collection_base + \
-		     (u32)(addr), (val))
 
 #define IPA_0_IPA_WRAPPER_BASE 0 /* required by following includes */
 
@@ -239,6 +227,12 @@ struct map_src_dst_addr_s {
 		[rsrc_grp].testbus_data.value)
 
 /*
+ * Macro to pluck the gsi version from ram.
+ */
+#define IPA_REG_SAVE_GSI_VER(reg_name, var_name)	\
+	{ GEN_1xVECTOR_REG_OFST(reg_name, 0), \
+		(u32 *)&ipa_reg_save.gsi.gen.var_name }
+/*
  * Macro to define a particular register cfg entry for all 3 EE
  * indexed register
  */
@@ -435,6 +429,8 @@ struct map_src_dst_addr_s {
 		(u32 *)&ipa_reg_save.gsi.ch_cntxt.a7[12].var_name }, \
 	{ GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_A7_EE, 13), \
 		(u32 *)&ipa_reg_save.gsi.ch_cntxt.a7[13].var_name }, \
+	{ GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_A7_EE, 14), \
+		(u32 *)&ipa_reg_save.gsi.ch_cntxt.a7[14].var_name }, \
 	{ GEN_2xVECTOR_REG_OFST(reg_name, IPA_REG_SAVE_HWP_GSI_EE, 1), \
 		(u32 *)&ipa_reg_save.gsi.ch_cntxt.uc[0].var_name }, \
 	{ GEN_2xVECTOR_REG_OFST(reg_name, IPA_REG_SAVE_HWP_GSI_EE, 3), \
@@ -916,6 +912,8 @@ struct ipa_reg_save_gsi_gen_s {
 	  gsi_cfg;
 	struct gsi_hwio_def_gsi_ree_cfg_s
 	  gsi_ree_cfg;
+	struct ipa_hwio_def_ipa_gsi_top_gsi_inst_ram_n_s
+	  ipa_gsi_top_gsi_inst_ram_n;
 };
 
 /* GSI General EE register save data struct */
@@ -1226,6 +1224,7 @@ struct ipa_regs_save_hierarchy_s {
 
 /* Top level GSI register save data struct */
 struct gsi_regs_save_hierarchy_s {
+	u32 fw_ver;
 	struct ipa_reg_save_gsi_gen_s		gen;
 	struct ipa_reg_save_gsi_gen_ee_s	gen_ee[IPA_REG_SAVE_GSI_NUM_EE];
 	struct ipa_reg_save_gsi_ch_cntxt_s	ch_cntxt;
@@ -1268,17 +1267,121 @@ struct ipa_reg_save_rsrc_cnts_s {
 
 /* Top level IPA and GSI registers save data struct */
 struct regs_save_hierarchy_s {
-	struct ipa_regs_save_hierarchy_s	ipa;
-	struct gsi_regs_save_hierarchy_s	gsi;
-	bool pkt_ctntx_active[IPA_HW_PKT_CTNTX_MAX];
-	union ipa_hwio_def_ipa_ctxh_ctrl_u	pkt_ctntxt_lock;
+	struct ipa_regs_save_hierarchy_s
+		ipa;
+	struct gsi_regs_save_hierarchy_s
+		gsi;
+	bool
+		pkt_ctntx_active[IPA_HW_PKT_CTNTX_MAX];
+	union ipa_hwio_def_ipa_ctxh_ctrl_u
+		pkt_ctntxt_lock;
 	enum ipa_hw_pkt_cntxt_state_e
-	  pkt_cntxt_state[IPA_HW_PKT_CTNTX_MAX];
+		pkt_cntxt_state[IPA_HW_PKT_CTNTX_MAX];
 	struct ipa_pkt_ctntx_s
-	  pkt_ctntx[IPA_HW_PKT_CTNTX_MAX];
-	struct ipa_reg_save_rsrc_cnts_s		rsrc_cnts;
+		pkt_ctntx[IPA_HW_PKT_CTNTX_MAX];
+	struct ipa_reg_save_rsrc_cnts_s
+		rsrc_cnts;
 	struct ipa_reg_save_gsi_fifo_status_s
-	  gsi_fifo_status[IPA_HW_PIPE_ID_MAX];
+		gsi_fifo_status[IPA_HW_PIPE_ID_MAX];
+};
+
+/*
+ * The following section deals with handling IPA registers' memory
+ * access relative to pre-defined memory protection schemes
+ * (ie. "access control").
+ *
+ * In a nut shell, the intent of the data stuctures below is to allow
+ * higher level register accessors to be unaware of what really is
+ * going on at the lowest level (ie. real vs non-real access).  This
+ * methodology is also designed to allow for platform specific "access
+ * maps."
+ */
+
+/*
+ * Function for doing an actual read
+ */
+static inline u32
+act_read(void __iomem *addr)
+{
+	u32 val = my_in_dword(addr);
+
+	return val;
+}
+
+/*
+ * Function for doing an actual write
+ */
+static inline void
+act_write(void __iomem *addr, u32 val)
+{
+	my_out_dword(addr, val);
+}
+
+/*
+ * Function that pretends to do a read
+ */
+static inline u32
+nop_read(void __iomem *addr)
+{
+	return IPA_MEM_INIT_VAL;
+}
+
+/*
+ * Function that pretends to do a write
+ */
+static inline void
+nop_write(void __iomem *addr, u32 val)
+{
+}
+
+/*
+ * The following are used to define struct reg_access_funcs_s below...
+ */
+typedef u32 (*reg_read_func_t)(
+	void __iomem *addr);
+typedef void (*reg_write_func_t)(
+	void __iomem *addr,
+	u32 val);
+
+/*
+ * The following in used to define io_matrix[] below...
+ */
+struct reg_access_funcs_s {
+	reg_read_func_t  read;
+	reg_write_func_t write;
+};
+
+/*
+ * The following will be used to appropriately index into the
+ * read/write combos defined in io_matrix[] below...
+ */
+#define AA_COMBO 0 /* actual read, actual write */
+#define AN_COMBO 1 /* actual read, no-op write  */
+#define NA_COMBO 2 /* no-op read,  actual write */
+#define NN_COMBO 3 /* no-op read,  no-op write  */
+
+/*
+ * The following will be used to dictate registers' access methods
+ * relative to the state of secure debug...whether it's enabled or
+ * disabled.
+ *
+ * NOTE: The table below defines all access combinations.
+ */
+static struct reg_access_funcs_s io_matrix[] = {
+	{ act_read, act_write }, /* the AA_COMBO */
+	{ act_read, nop_write }, /* the AN_COMBO */
+	{ nop_read, act_write }, /* the NA_COMBO */
+	{ nop_read, nop_write }, /* the NN_COMBO */
+};
+
+/*
+ * The following will be used to define and drive IPA's register
+ * access rules.
+ */
+struct reg_mem_access_map_t {
+	u32 addr_range_begin;
+	u32 addr_range_end;
+	struct reg_access_funcs_s *access[2];
 };
 
 #endif /* #if !defined(_IPA_REG_DUMP_H_) */
diff --git a/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_access_control.h b/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_access_control.h
new file mode 100644
index 0000000..064e030
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_access_control.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+#if !defined(_IPA_ACCESS_CONTROL_H_)
+#define _IPA_ACCESS_CONTROL_H_
+
+#include "ipa_reg_dump.h"
+
+/*
+ * The following is target specific.
+ */
+static struct reg_mem_access_map_t mem_access_map[] = {
+	/*------------------------------------------------------------*/
+	/*      Range               Use when              Use when    */
+	/*  Begin    End           SD_ENABLED           SD_DISABLED   */
+	/*------------------------------------------------------------*/
+	{ 0x04000, 0x05000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } },
+	{ 0x07000, 0x0f000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } },
+	{ 0x05000, 0x07000, { &io_matrix[AA_COMBO], &io_matrix[AN_COMBO] } },
+	{ 0x0f000, 0x10000, { &io_matrix[NN_COMBO], &io_matrix[NN_COMBO] } },
+	{ 0x20000, 0x24000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } },
+	{ 0x24000, 0x28000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } },
+	{ 0x28000, 0x2c000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } },
+	{ 0x10000, 0x11000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } },
+	{ 0x11000, 0x12000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } },
+	{ 0x12000, 0x13000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } },
+	{ 0x43000, 0x44000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } },
+	{ 0x44000, 0x45000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } },
+	{ 0x45000, 0x47000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } },
+	{ 0x40000, 0x42000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } },
+	{ 0x42000, 0x43000, { &io_matrix[AA_COMBO], &io_matrix[AN_COMBO] } },
+	{ 0x47000, 0x4a000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } },
+	{ 0x4a000, 0x5a000, { &io_matrix[AN_COMBO], &io_matrix[NN_COMBO] } },
+	{ 0x5a000, 0x5c000, { &io_matrix[NN_COMBO], &io_matrix[NN_COMBO] } },
+	{ 0x5e000, 0x60000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } },
+	{ 0x60000, 0x70000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } },
+	{ 0x70000, 0x72000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } },
+	{ 0x72000, 0x80000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } },
+};
+
+#endif /* #if !defined(_IPA_ACCESS_CONTROL_H_) */
diff --git a/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hw_common_ex.h b/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hw_common_ex.h
index 5a84940..29e31d2 100644
--- a/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hw_common_ex.h
+++ b/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hw_common_ex.h
@@ -382,7 +382,7 @@ enum ipa_hw_irq_srcs_e {
 /*
  * Total number of channel contexts that need to be saved for APPS
  */
-#define IPA_HW_REG_SAVE_GSI_NUM_CH_CNTXT_A7          14
+#define IPA_HW_REG_SAVE_GSI_NUM_CH_CNTXT_A7          15
 
 /*
  * Total number of channel contexts that need to be saved for Q6
diff --git a/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hwio.h b/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hwio.h
index 0affad1..9492d36 100644
--- a/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hwio.h
+++ b/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hwio.h
@@ -966,6 +966,27 @@
 		IPA_GSI_TOP_GSI_REG_BASE_PHYS + 0x00004000 + 0x4 * (n))
 #define HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_OFFS(n) ( \
 		IPA_GSI_TOP_GSI_REG_BASE_OFFS + 0x00004000 + 0x4 * (n))
+#define HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_RMSK 0xffffffff
+#define HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_MAXn 6143
+#define HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_ATTR 0x3
+#define HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_INI(n) \
+	in_dword_masked( \
+		HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_ADDR(n), \
+		HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_RMSK)
+#define HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_INMI(n, mask) \
+	in_dword_masked( \
+		HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_ADDR(n), \
+		mask)
+#define HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_OUTI(n, val) \
+	out_dword( \
+		HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_ADDR(n), \
+		val)
+#define HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_OUTMI(n, mask, val) \
+	out_dword_masked_ns( \
+		HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_ADDR(n), \
+		mask, \
+		val, \
+		HWIO_IPA_GSI_TOP_GSI_INST_RAM_n_INI(n))
 #define HWIO_IPA_GSI_TOP_GSI_SHRAM_n_ADDR(n) (IPA_GSI_TOP_GSI_REG_BASE + \
 					      0x00002000 + 0x4 * (n))
 #define HWIO_IPA_GSI_TOP_GSI_SHRAM_n_PHYS(n) ( \
diff --git a/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hwio_def.h b/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hwio_def.h
index 6c7eceb..86fa99f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hwio_def.h
+++ b/drivers/platform/msm/ipa/ipa_v3/dump/sm8150/ipa_hwio_def.h
@@ -224,6 +224,17 @@ union ipa_hwio_def_ipa_gsi_top_gsi_iram_ptr_int_mod_stopped_u {
 		def;
 	u32 value;
 };
+struct ipa_hwio_def_ipa_gsi_top_gsi_inst_ram_n_s {
+	u32 inst_byte_0 : 8;
+	u32 inst_byte_1 : 8;
+	u32 inst_byte_2 : 8;
+	u32 inst_byte_3 : 8;
+};
+union ipa_hwio_def_ipa_gsi_top_gsi_inst_ram_n_u {
+	struct ipa_hwio_def_ipa_gsi_top_gsi_inst_ram_n_s
+		def;
+	u32 value;
+};
 struct ipa_hwio_def_ipa_gsi_top_gsi_shram_n_s {
 	u32 shram : 32;
 };
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/Makefile b/drivers/platform/msm/ipa/ipa_v3/ethernet/Makefile
new file mode 100644
index 0000000..ea66a4d
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/Makefile
@@ -0,0 +1,16 @@
+
+obj-$(CONFIG_IPA_ETH) += ipa-eth.o
+
+ipa-eth-y := \
+	ipa_eth_bus.o \
+	ipa_eth.o \
+	ipa_eth_ep.o \
+	ipa_eth_gsi.o \
+	ipa_eth_offload.o \
+	ipa_eth_pci.o \
+	ipa_eth_pm.o \
+	ipa_eth_uc.o
+
+ifneq ($(wildcard $(srctree)/$(src)/aquantia/Makefile),)
+obj-$(CONFIG_AQC_IPA) += aquantia/
+endif
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/aquantia/Kconfig b/drivers/platform/msm/ipa/ipa_v3/ethernet/aquantia/Kconfig
new file mode 100644
index 0000000..8fdbbbc
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/aquantia/Kconfig
@@ -0,0 +1,43 @@
+
+config AQC_IPA
+	tristate "Aquantia IPA Ethernet Offload Driver"
+	depends on IPA_ETH
+	help
+	  This driver supports offloading to IPA, data that is
+	  tethered over Aquantia ethernet interfaces. The driver
+	  require a compatible Aquantia network driver to be
+	  registered with IPA Offload Sub-System.
+	  If unsure, say N.
+
+choice
+	prompt "Default Rx Interrupt Proxy Method"
+	default AQC_IPA_PROXY_HOST
+
+config AQC_IPA_PROXY_UC
+	bool "via IPA uC"
+	help
+	  IPA uC acts as a proxy for AQC Rx interrupt, receiving the
+	  MSI and forwarding the indication to an IPA GSI doorbell
+	  either with a monotonically increasing counter or the Rx
+	  ring descriptor address at AQC tail pointer. IPA uC need to
+	  have support for AQC protocol in its firmware.
+
+config AQC_IPA_PROXY_HOST
+	bool "via Host/Linux"
+	help
+	  Host/Linux acts as proxy for AQC Rx interrupt, receiving the
+	  MSI and forwarding the indication to an IPA GSI doorbell  with
+	  the Rx ring descriptor address at AQC tail pointer. A host SPI
+	  need to be available and configured to receive the MSI.
+
+endchoice
+
+config AQC_IPA_DEBUG
+	bool "Aquantia IPA Ethernet Offload Driver Debugging Support"
+	depends on AQC_IPA
+	help
+	  Enable various debug features provided by Aquantia IPA
+	  offload driver. Using this feature may add a lot of
+	  additional log messages and panic on bugs. Enable this
+	  option with caution.
+	  If unsure, say N.
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth.c
new file mode 100644
index 0000000..9923619
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth.c
@@ -0,0 +1,972 @@
+/* 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/printk.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+
+#include <linux/msm_ipa.h>
+
+#include "ipa_eth_i.h"
+
+static bool ipa_eth_is_ready;
+static bool ipa_eth_ipa_is_ready;
+static bool ipa_eth_ipa_uc_is_ready;
+
+static struct dentry *ipa_eth_debugfs;
+static struct dentry *ipa_eth_drivers_debugfs;
+static struct dentry *ipa_eth_devices_debugfs;
+
+static LIST_HEAD(ipa_eth_devices);
+static DEFINE_MUTEX(ipa_eth_devices_lock);
+
+static bool ipa_eth_noauto = IPA_ETH_NOAUTO_DEFAULT;
+module_param(ipa_eth_noauto, bool, 0444);
+MODULE_PARM_DESC(ipa_eth_noauto,
+	"Disable automatic offload initialization of interfaces");
+
+static bool ipa_eth_ipc_logdbg = IPA_ETH_IPC_LOGDBG_DEFAULT;
+module_param(ipa_eth_ipc_logdbg, bool, 0444);
+MODULE_PARM_DESC(ipa_eth_ipc_logdbg, "Log debug IPC messages");
+
+static inline bool ipa_eth_ready(void)
+{
+	return ipa_eth_is_ready &&
+		ipa_eth_ipa_is_ready &&
+		ipa_eth_ipa_uc_is_ready;
+}
+
+static int ipa_eth_init_device(struct ipa_eth_device *eth_dev)
+{
+	int rc;
+
+	if (eth_dev->state == IPA_ETH_ST_INITED)
+		return 0;
+
+	if (eth_dev->state != IPA_ETH_ST_DEINITED)
+		return -EFAULT;
+
+	rc = ipa_eth_ep_init_headers(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to init EP headers");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	rc = ipa_eth_pm_register(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to register with IPA PM");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	rc = ipa_eth_offload_init(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to init offload");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	rc = ipa_eth_ep_register_interface(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to register EP interface");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	ipa_eth_dev_log(eth_dev, "Initialized device");
+
+	eth_dev->state = IPA_ETH_ST_INITED;
+
+	return 0;
+}
+
+static int ipa_eth_deinit_device(struct ipa_eth_device *eth_dev)
+{
+	int rc;
+
+	if (eth_dev->state == IPA_ETH_ST_DEINITED)
+		return 0;
+
+	if (eth_dev->state != IPA_ETH_ST_INITED)
+		return -EFAULT;
+
+	rc = ipa_eth_ep_unregister_interface(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to unregister IPA interface");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	rc = ipa_eth_offload_deinit(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to deinit offload");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	rc = ipa_eth_pm_unregister(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to unregister with IPA PM");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	ipa_eth_dev_log(eth_dev, "Deinitialized device");
+
+	eth_dev->state = IPA_ETH_ST_DEINITED;
+
+	return 0;
+}
+
+static int ipa_eth_start_device(struct ipa_eth_device *eth_dev)
+{
+	int rc;
+
+	if (eth_dev->state == IPA_ETH_ST_STARTED)
+		return 0;
+
+	if (eth_dev->state != IPA_ETH_ST_INITED)
+		return -EFAULT;
+
+	rc = ipa_eth_pm_activate(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to activate device PM");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	rc = ipa_eth_offload_start(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to start offload");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	ipa_eth_dev_log(eth_dev, "Started device");
+
+	eth_dev->state = IPA_ETH_ST_STARTED;
+
+	return 0;
+}
+
+static int ipa_eth_stop_device(struct ipa_eth_device *eth_dev)
+{
+	int rc;
+
+	if (eth_dev->state == IPA_ETH_ST_DEINITED)
+		return 0;
+
+	if (eth_dev->state != IPA_ETH_ST_STARTED)
+		return -EFAULT;
+
+	rc = ipa_eth_offload_stop(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to stop offload");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	rc = ipa_eth_pm_deactivate(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to deactivate device PM");
+		eth_dev->state = IPA_ETH_ST_ERROR;
+		return rc;
+	}
+
+	ipa_eth_dev_log(eth_dev, "Stopped device");
+
+	eth_dev->state = IPA_ETH_ST_INITED;
+
+	return 0;
+}
+
+static void __ipa_eth_refresh_device(struct ipa_eth_device *eth_dev)
+{
+	ipa_eth_dev_log(eth_dev, "Refreshing offload state for device");
+
+	if (eth_dev->state == IPA_ETH_ST_ERROR) {
+		ipa_eth_dev_err(eth_dev,
+				"Device in ERROR state, skipping refresh");
+		return;
+	}
+
+	if (eth_dev->init) {
+		if (eth_dev->state == IPA_ETH_ST_DEINITED) {
+			(void) ipa_eth_init_device(eth_dev);
+
+			if (eth_dev->state != IPA_ETH_ST_INITED) {
+				ipa_eth_dev_err(eth_dev,
+						"Failed to init device");
+				return;
+			}
+		}
+	}
+
+
+	if (eth_dev->init && eth_dev->start && eth_dev->link_up) {
+		(void) ipa_eth_start_device(eth_dev);
+
+		if (eth_dev->state != IPA_ETH_ST_STARTED) {
+			ipa_eth_dev_err(eth_dev, "Failed to start device");
+			return;
+		}
+
+		if (ipa_eth_pm_vote_bw(eth_dev))
+			ipa_eth_dev_err(eth_dev,
+					"Failed to vote for required BW");
+	} else {
+		ipa_eth_dev_log(eth_dev, "Start is disallowed for the device");
+
+		if (eth_dev->state == IPA_ETH_ST_STARTED) {
+			ipa_eth_stop_device(eth_dev);
+
+			if (eth_dev->state != IPA_ETH_ST_INITED) {
+				ipa_eth_dev_err(eth_dev,
+						"Failed to stop device");
+				return;
+			}
+		}
+	}
+
+	if (!eth_dev->init) {
+		ipa_eth_dev_log(eth_dev, "Init is disallowed for the device");
+
+		ipa_eth_deinit_device(eth_dev);
+
+		if (eth_dev->state != IPA_ETH_ST_DEINITED) {
+			ipa_eth_dev_err(eth_dev, "Failed to deinit device");
+			return;
+		}
+	}
+}
+
+static void ipa_eth_refresh_device(struct ipa_eth_device *eth_dev)
+{
+	mutex_lock(&ipa_eth_devices_lock);
+
+	if (ipa_eth_ready())
+		__ipa_eth_refresh_device(eth_dev);
+
+	mutex_unlock(&ipa_eth_devices_lock);
+}
+
+static void ipa_eth_refresh_devices(void)
+{
+	struct ipa_eth_device *eth_dev;
+
+	mutex_lock(&ipa_eth_devices_lock);
+
+	if (ipa_eth_ready()) {
+		list_for_each_entry(eth_dev, &ipa_eth_devices, device_list) {
+			__ipa_eth_refresh_device(eth_dev);
+		}
+	}
+
+	mutex_unlock(&ipa_eth_devices_lock);
+}
+
+static int ipa_eth_netdev_event(struct notifier_block *nb,
+	unsigned long event, void *ptr)
+{
+	struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
+
+	struct ipa_eth_device *eth_dev = container_of(nb,
+				struct ipa_eth_device, netdevice_nb);
+
+	if (net_dev != eth_dev->net_dev)
+		return NOTIFY_DONE;
+
+	ipa_eth_dev_log(eth_dev, "Received netdev event %lu", event);
+
+	if (event == NETDEV_CHANGE) {
+		eth_dev->link_up =
+			!test_bit(__LINK_STATE_NOCARRIER, &net_dev->state);
+
+		ipa_eth_refresh_device(eth_dev);
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int ipa_eth_uc_ready_cb(struct notifier_block *nb,
+	unsigned long action, void *data)
+{
+	ipa_eth_log("IPA uC is ready");
+
+	ipa_eth_ipa_uc_is_ready = true;
+
+	ipa_eth_refresh_devices();
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block uc_ready_cb = {
+	.notifier_call = ipa_eth_uc_ready_cb,
+};
+
+static void ipa_eth_ipa_ready_cb(void *data)
+{
+	ipa_eth_log("IPA is ready");
+
+	ipa_eth_ipa_is_ready = true;
+
+	ipa_eth_refresh_devices();
+}
+
+struct ipa_eth_device *ipa_eth_find_device(struct device *dev)
+{
+	struct ipa_eth_device *eth_dev;
+
+	list_for_each_entry(eth_dev, &ipa_eth_devices, device_list) {
+		if (eth_dev->dev == dev)
+			return eth_dev;
+	}
+
+	return NULL;
+}
+
+static ssize_t ipa_eth_dev_write_init(struct file *file,
+				      const char __user *user_buf,
+				      size_t count, loff_t *ppos)
+{
+	ssize_t ret = debugfs_write_file_bool(file, user_buf, count, ppos);
+	struct ipa_eth_device *eth_dev = container_of(file->private_data,
+						      struct ipa_eth_device,
+						      init);
+
+	ipa_eth_refresh_device(eth_dev);
+
+	return ret;
+}
+
+static const struct file_operations fops_eth_dev_init = {
+	.read = debugfs_read_file_bool,
+	.write = ipa_eth_dev_write_init,
+	.open = simple_open,
+	.llseek = default_llseek,
+};
+
+static ssize_t ipa_eth_dev_write_start(struct file *file,
+				       const char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	ssize_t ret = debugfs_write_file_bool(file, user_buf, count, ppos);
+	struct ipa_eth_device *eth_dev = container_of(file->private_data,
+						      struct ipa_eth_device,
+						      start);
+
+	ipa_eth_refresh_device(eth_dev);
+
+	return ret;
+}
+
+static const struct file_operations fops_eth_dev_start = {
+	.read = debugfs_read_file_bool,
+	.write = ipa_eth_dev_write_start,
+	.open = simple_open,
+	.llseek = default_llseek,
+};
+
+static ssize_t eth_dev_stats_print_one(char *buf, const size_t size,
+				   const char *dir, const char *link,
+				   struct ipa_eth_offload_link_stats *stats)
+{
+	return scnprintf(buf, size,
+			 "%10s%10s%10s%10llu%10llu%10llu%10llu\n",
+			 dir, link, (stats->valid ? "yes" : "no"),
+			 stats->events, stats->frames,
+			 stats->packets, stats->octets);
+}
+
+static ssize_t eth_dev_stats_print(char *buf, const size_t size,
+			       struct ipa_eth_device *eth_dev)
+{
+	ssize_t n = 0;
+	struct ipa_eth_offload_stats stats;
+
+	if (!eth_dev->od->ops->get_stats)
+		return scnprintf(buf, size - n, "Not supported\n");
+
+	memset(&stats, 0, sizeof(stats));
+
+	if (eth_dev->od->ops->get_stats(eth_dev, &stats))
+		return scnprintf(buf, size - n, "Operation failed\n");
+
+	n += scnprintf(&buf[n], size - n,
+		       "%10s%10s%10s%10s%10s%10s%10s\n",
+		       "Dir", "Link", "Valid",
+		       "Events", "Frames", "Packets", "Octets");
+
+	n += eth_dev_stats_print_one(&buf[n], size - n,
+				     "rx", "ndev", &stats.rx.ndev);
+	n += eth_dev_stats_print_one(&buf[n], size - n,
+				     "rx", "host", &stats.rx.host);
+	n += eth_dev_stats_print_one(&buf[n], size - n,
+				     "rx", "uc", &stats.rx.uc);
+	n += eth_dev_stats_print_one(&buf[n], size - n,
+				     "rx", "gsi", &stats.rx.gsi);
+	n += eth_dev_stats_print_one(&buf[n], size - n,
+				     "rx", "ipa", &stats.rx.ipa);
+
+	n += scnprintf(&buf[n], size - n, "\n");
+
+	n += eth_dev_stats_print_one(&buf[n], size - n,
+				     "tx", "ndev", &stats.tx.ndev);
+	n += eth_dev_stats_print_one(&buf[n], size - n,
+				     "tx", "host", &stats.tx.host);
+	n += eth_dev_stats_print_one(&buf[n], size - n,
+				     "tx", "uc", &stats.tx.uc);
+	n += eth_dev_stats_print_one(&buf[n], size - n,
+				     "tx", "gsi", &stats.tx.gsi);
+	n += eth_dev_stats_print_one(&buf[n], size - n,
+				     "tx", "ipa", &stats.tx.ipa);
+
+	return n;
+}
+
+static ssize_t eth_dev_stats_read(struct file *file, char __user *user_buf,
+				  size_t count, loff_t *ppos)
+{
+	ssize_t n;
+	char *buf = NULL;
+	struct ipa_eth_device *eth_dev = file->private_data;
+
+	buf = kzalloc(2048, GFP_KERNEL);
+	if (buf == NULL)
+		return 0;
+
+	n = eth_dev_stats_print(buf, sizeof(buf), eth_dev);
+	n = simple_read_from_buffer(user_buf, count, ppos, buf, n);
+
+	kfree(buf);
+
+	return n;
+}
+
+static const struct file_operations fops_eth_dev_stats = {
+	.read = eth_dev_stats_read,
+	.open = simple_open,
+	.llseek = default_llseek,
+};
+
+static int ipa_eth_device_debugfs_create(struct ipa_eth_device *eth_dev)
+{
+	eth_dev->debugfs = debugfs_create_dir(eth_dev->net_dev->name,
+					      ipa_eth_devices_debugfs);
+	if (IS_ERR_OR_NULL(eth_dev->debugfs)) {
+		ipa_eth_dev_err(eth_dev, "Failed to create debugfs root");
+		return -EFAULT;
+	}
+
+	debugfs_create_file("init", 0644, eth_dev->debugfs, &eth_dev->init,
+			    &fops_eth_dev_init);
+
+	debugfs_create_file("start", 0644, eth_dev->debugfs, &eth_dev->start,
+			    &fops_eth_dev_start);
+
+	debugfs_create_file("stats", 0644, eth_dev->debugfs, eth_dev,
+			    &fops_eth_dev_stats);
+
+	return 0;
+}
+
+static void ipa_eth_device_debugfs_remove(struct ipa_eth_device *eth_dev)
+{
+	debugfs_remove_recursive(eth_dev->debugfs);
+	eth_dev->debugfs = NULL;
+}
+
+static int __ipa_eth_pair_device(struct ipa_eth_device *eth_dev)
+{
+	int rc;
+
+	if (ipa_eth_offload_device_paired(eth_dev)) {
+		ipa_eth_dev_dbg(eth_dev, "Device already paired. Skipping.");
+		return 0;
+	}
+
+	rc = ipa_eth_offload_pair_device(eth_dev);
+	if (rc) {
+		ipa_eth_dev_log(eth_dev, "Failed to pair device. Deferring.");
+		return rc;
+	}
+
+	eth_dev->netdevice_nb.notifier_call = ipa_eth_netdev_event;
+	rc = register_netdevice_notifier(&eth_dev->netdevice_nb);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to register netdev notifier");
+		ipa_eth_offload_unpair_device(eth_dev);
+		return rc;
+	}
+
+	(void) ipa_eth_device_debugfs_create(eth_dev);
+
+	ipa_eth_dev_log(eth_dev, "Paired device with offload driver %s",
+			eth_dev->od->name);
+
+	return 0;
+}
+
+static void __ipa_eth_unpair_device(struct ipa_eth_device *eth_dev)
+{
+	if (!ipa_eth_offload_device_paired(eth_dev)) {
+		ipa_eth_dev_dbg(eth_dev, "Device already unpaired. Skipping.");
+		return;
+	}
+
+	ipa_eth_dev_log(eth_dev, "Unpairing device from offload driver %s",
+			eth_dev->od->name);
+
+	ipa_eth_device_debugfs_remove(eth_dev);
+
+	eth_dev->init = eth_dev->start = false;
+
+	__ipa_eth_refresh_device(eth_dev);
+
+	unregister_netdevice_notifier(&eth_dev->netdevice_nb);
+	ipa_eth_offload_unpair_device(eth_dev);
+}
+
+static void ipa_eth_pair_devices(void)
+{
+	struct ipa_eth_device *eth_dev;
+
+	mutex_lock(&ipa_eth_devices_lock);
+
+	list_for_each_entry(eth_dev, &ipa_eth_devices, device_list)
+		(void) __ipa_eth_pair_device(eth_dev);
+
+	mutex_unlock(&ipa_eth_devices_lock);
+}
+
+static void ipa_eth_unpair_devices(struct ipa_eth_offload_driver *od)
+{
+	struct ipa_eth_device *eth_dev;
+
+	mutex_lock(&ipa_eth_devices_lock);
+
+	list_for_each_entry(eth_dev, &ipa_eth_devices, device_list) {
+		if (eth_dev->od == od)
+			__ipa_eth_unpair_device(eth_dev);
+	}
+
+	mutex_unlock(&ipa_eth_devices_lock);
+}
+
+int ipa_eth_register_device(struct ipa_eth_device *eth_dev)
+{
+	eth_dev->state = IPA_ETH_ST_DEINITED;
+	eth_dev->pm_handle = IPA_PM_MAX_CLIENTS;
+
+	eth_dev->init = eth_dev->start = !ipa_eth_noauto;
+
+	mutex_lock(&ipa_eth_devices_lock);
+
+	list_add(&eth_dev->device_list, &ipa_eth_devices);
+
+	ipa_eth_dev_log(eth_dev, "Registered new device");
+
+	(void) __ipa_eth_pair_device(eth_dev);
+
+	mutex_unlock(&ipa_eth_devices_lock);
+
+	return 0;
+}
+
+void ipa_eth_unregister_device(struct ipa_eth_device *eth_dev)
+{
+	mutex_lock(&ipa_eth_devices_lock);
+
+	__ipa_eth_unpair_device(eth_dev);
+	list_del(&eth_dev->device_list);
+
+	ipa_eth_dev_log(eth_dev, "Unregistered device");
+
+	mutex_unlock(&ipa_eth_devices_lock);
+}
+
+static phys_addr_t ipa_eth_vmalloc_to_pa(void *vaddr)
+{
+	struct page *pg = vmalloc_to_page(vaddr);
+
+	if (pg)
+		return page_to_phys(pg);
+	else
+		return 0;
+}
+
+static phys_addr_t ipa_eth_va_to_pa(void *vaddr)
+{
+	return is_vmalloc_addr(vaddr) ?
+			ipa_eth_vmalloc_to_pa(vaddr) :
+			virt_to_phys(vaddr);
+}
+
+/**
+ * ipa_eth_iommu_map() - Create IOMMU mapping from a given DMA address to a
+ *                       physical/virtual address
+ * @domain: IOMMU domain in which the mapping need to be created
+ * @daddr: DMA address (IO Virtual Address) that need to be mapped
+ * @addr: Physical or CPU Virtual Address of memory
+ * @is_va: True if @addr is CPU Virtual Address
+ * @size: Total size of the mapping
+ * @prot: Flags for iommu_map() call
+ * @split: If True, separate page sized mapping is created
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_iommu_map(struct iommu_domain *domain,
+	dma_addr_t daddr, void *addr, bool is_va,
+	size_t size, int prot, bool split)
+{
+	int rc;
+	dma_addr_t daddr_r = rounddown(daddr, PAGE_SIZE);
+	void *addr_r = (void *)rounddown((unsigned long)addr, PAGE_SIZE);
+	size_t size_r = roundup(size + (daddr - daddr_r), PAGE_SIZE);
+	const size_t MAP_SIZE = split ? PAGE_SIZE : size_r;
+
+	if ((daddr - daddr_r) != (addr - addr_r)) {
+		ipa_eth_err("Alignment mismatch between paddr and addr");
+		return -EINVAL;
+	}
+
+	if (daddr != daddr_r)
+		ipa_eth_dbg("DMA address %p realigned to %p", daddr, daddr_r);
+
+	if (addr != addr_r)
+		ipa_eth_dbg("PA/VA address %p realigned to %p", addr, addr_r);
+
+	if (size != size_r)
+		ipa_eth_dbg("DMA map size %zx realigned to %zx", size, size_r);
+
+	for (size = 0; size < size_r;
+	     size += MAP_SIZE, daddr_r += MAP_SIZE, addr_r += MAP_SIZE) {
+		phys_addr_t paddr = is_va ?
+					ipa_eth_va_to_pa(addr_r) :
+					(phys_addr_t) (addr_r);
+		phys_addr_t paddr_r = rounddown(paddr, PAGE_SIZE);
+
+		if (!paddr_r) {
+			rc = -EFAULT;
+			ipa_eth_err("Failed to find paddr for vaddr %p", addr);
+			goto failed_map;
+		}
+
+		if (paddr != paddr_r) {
+			rc = -EFAULT;
+			ipa_eth_err("paddr %p is not page aligned", paddr);
+			goto failed_map;
+		}
+
+		rc = ipa3_iommu_map(domain, daddr_r, paddr_r, MAP_SIZE, prot);
+		if (rc) {
+			ipa_eth_err("Failed to map daddr %p to %s domain",
+				    daddr, domain->name);
+			goto failed_map;
+		}
+
+		ipa_eth_log(
+			"Mapped %zu bytes of daddr %p to paddr %p in domain %s",
+			MAP_SIZE, daddr_r, paddr_r, domain->name);
+	}
+
+	return 0;
+
+failed_map:
+	ipa_eth_iommu_unmap(domain, daddr_r - size, size, split);
+	return rc;
+
+}
+
+/**
+ * ipa_eth_iommu_unmap() - Remove an IOMMU mapping previously made using
+ *                         ipa_eth_iommu_map()
+ * @domain: IOMMU domain from which the mapping need to be removed
+ * @daddr: DMA address (IO Virtual Address) that was mapped
+ * @size: Total size of the mapping
+ * @split: If True, separate page sized mappings were created
+ *
+ * Return: 0 on success, negative errno if at least one of the mappings could
+ *         not be removed.
+ */
+int ipa_eth_iommu_unmap(struct iommu_domain *domain,
+	dma_addr_t daddr, size_t size, bool split)
+{
+	int rc = 0;
+	dma_addr_t daddr_r = rounddown(daddr, PAGE_SIZE);
+	size_t size_r = roundup(size + (daddr - daddr_r), PAGE_SIZE);
+	const size_t MAP_SIZE = split ? PAGE_SIZE : size_r;
+
+	if (!size_r) {
+		ipa_eth_dbg("Ignoring unmap request of size 0");
+		return 0;
+	}
+
+	for (size = 0; size < size_r; size += MAP_SIZE) {
+		if (iommu_unmap(domain, daddr_r + size, MAP_SIZE) != MAP_SIZE) {
+			rc = -EFAULT;
+			ipa_eth_err("Failed to unmap daddr %p", daddr_r + size);
+		}
+
+		ipa_eth_log(
+			"Unmapped %zu bytes of daddr %p in domain %s",
+			MAP_SIZE, daddr_r + size, domain->name);
+	}
+
+	return rc;
+}
+
+/**
+ * ipa_eth_register_net_driver() - Register a network driver with the offload
+ *                                 subsystem
+ * @nd: Network driver to register
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_register_net_driver(struct ipa_eth_net_driver *nd)
+{
+	int rc;
+
+	rc = ipa_eth_bus_register_driver(nd);
+	if (rc)
+		ipa_eth_err("Failed to register network driver %s", nd->name);
+	else
+		ipa_eth_log("Registered network driver %s", nd->name);
+
+	return rc;
+}
+EXPORT_SYMBOL(ipa_eth_register_net_driver);
+
+/**
+ * ipa_eth_unregister_net_driver() - Unregister a network driver
+ * @nd: Network driver to unregister
+ */
+void ipa_eth_unregister_net_driver(struct ipa_eth_net_driver *nd)
+{
+	ipa_eth_bus_unregister_driver(nd);
+}
+EXPORT_SYMBOL(ipa_eth_unregister_net_driver);
+
+/**
+ * ipa_eth_register_offload_driver - Register an offload driver with the offload
+ *                                   subsystem
+ * @nd: Offload driver to register
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_register_offload_driver(struct ipa_eth_offload_driver *od)
+{
+	int rc;
+
+	rc = ipa_eth_offload_register_driver(od);
+	if (rc) {
+		ipa_eth_err("Failed to register offload driver %s", od->name);
+		return rc;
+	}
+
+	ipa_eth_log("Registered offload driver %s", od->name);
+
+	ipa_eth_pair_devices();
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_eth_register_offload_driver);
+
+/**
+ * ipa_eth_unregister_offload_driver() - Unregister an offload driver
+ * @nd: Offload driver to unregister
+ */
+void ipa_eth_unregister_offload_driver(struct ipa_eth_offload_driver *od)
+{
+	ipa_eth_unpair_devices(od);
+	ipa_eth_offload_unregister_driver(od);
+
+	ipa_eth_log("Unregistered offload driver %s", od->name);
+}
+EXPORT_SYMBOL(ipa_eth_unregister_offload_driver);
+
+static void ipa_eth_debugfs_cleanup(void)
+{
+	debugfs_remove_recursive(ipa_eth_debugfs);
+}
+
+static int ipa_eth_debugfs_init(void)
+{
+	int rc = 0;
+	struct dentry *ipa_debugfs = ipa_debugfs_get_root();
+
+	if (IS_ERR_OR_NULL(ipa_debugfs))
+		return 0;
+
+	ipa_eth_debugfs =
+		debugfs_create_dir("ethernet", ipa_debugfs);
+	if (IS_ERR_OR_NULL(ipa_eth_debugfs)) {
+		ipa_eth_log("Unable to create debugfs root");
+		rc = ipa_eth_debugfs ?
+			PTR_ERR(ipa_eth_debugfs) : -EFAULT;
+		goto err_exit;
+	}
+
+	ipa_eth_drivers_debugfs =
+		debugfs_create_dir("drivers", ipa_eth_debugfs);
+	if (IS_ERR_OR_NULL(ipa_eth_drivers_debugfs)) {
+		ipa_eth_log("Unable to create debugfs root for drivers");
+
+		rc = ipa_eth_drivers_debugfs ?
+			PTR_ERR(ipa_eth_drivers_debugfs) : -EFAULT;
+		goto err_exit;
+	}
+
+	ipa_eth_devices_debugfs =
+		debugfs_create_dir("devices", ipa_eth_debugfs);
+	if (IS_ERR_OR_NULL(ipa_eth_devices_debugfs)) {
+		ipa_eth_log("Unable to create debugfs root for devices");
+
+		rc = ipa_eth_devices_debugfs ?
+			PTR_ERR(ipa_eth_devices_debugfs) : -EFAULT;
+		goto err_exit;
+	}
+
+	(void) debugfs_create_bool("ready", 0444,
+				   ipa_eth_debugfs, &ipa_eth_is_ready);
+
+	(void) debugfs_create_bool("ipa_ready", 0444,
+				   ipa_eth_debugfs, &ipa_eth_ipa_is_ready);
+
+	(void) debugfs_create_bool("uc_ready", 0444,
+				   ipa_eth_debugfs, &ipa_eth_ipa_uc_is_ready);
+
+	(void) debugfs_create_bool("no_auto", 0644,
+				   ipa_eth_debugfs, &ipa_eth_noauto);
+
+	(void) debugfs_create_bool("ipc_logdbg", 0644,
+				   ipa_eth_debugfs, &ipa_eth_ipc_logdbg);
+
+	return 0;
+
+err_exit:
+	ipa_eth_debugfs_cleanup();
+	return rc;
+}
+
+static void *ipa_eth_ipc_logbuf;
+
+void *ipa_eth_get_ipc_logbuf(void)
+{
+	return ipa_eth_ipc_logbuf;
+}
+EXPORT_SYMBOL(ipa_eth_get_ipc_logbuf);
+
+void *ipa_eth_get_ipc_logbuf_dbg(void)
+{
+	return ipa_eth_ipc_logdbg ? ipa_eth_ipc_logbuf : NULL;
+}
+EXPORT_SYMBOL(ipa_eth_get_ipc_logbuf_dbg);
+
+#define IPA_ETH_IPC_LOG_PAGES 50
+
+static int ipa_eth_ipc_log_init(void)
+{
+	if (ipa_eth_ipc_logbuf)
+		return 0;
+
+	ipa_eth_ipc_logbuf = ipc_log_context_create(
+				IPA_ETH_IPC_LOG_PAGES, IPA_ETH_SUBSYS, 0);
+
+	return ipa_eth_ipc_logbuf ? 0 : -EFAULT;
+}
+
+static void ipa_eth_ipc_log_cleanup(void)
+{
+	if (ipa_eth_ipc_logbuf) {
+		ipc_log_context_destroy(ipa_eth_ipc_logbuf);
+		ipa_eth_ipc_logbuf = NULL;
+	}
+}
+
+int ipa_eth_init(void)
+{
+	int rc;
+
+	ipa_eth_dbg("Initializing IPA Ethernet Offload Sub-System");
+
+	rc = ipa_eth_ipc_log_init();
+	if (rc) {
+		ipa_eth_err("Failed to initialize IPC logging");
+		goto err_ipclog;
+	}
+
+	rc = ipa_eth_debugfs_init();
+	if (rc) {
+		ipa_eth_err("Failed to initialize debugfs");
+		goto err_dbgfs;
+	}
+
+	rc = ipa_eth_bus_modinit(ipa_eth_drivers_debugfs);
+	if (rc) {
+		ipa_eth_err("Failed to initialize bus");
+		goto err_bus;
+	}
+
+	rc = ipa_eth_offload_modinit(ipa_eth_drivers_debugfs);
+	if (rc) {
+		ipa_eth_err("Failed to initialize offload");
+		goto err_offload;
+	}
+
+	rc = ipa3_uc_register_ready_cb(&uc_ready_cb);
+	if (rc) {
+		ipa_eth_err("Failed to register for uC ready cb");
+		goto err_uc;
+	}
+
+	rc = ipa_register_ipa_ready_cb(ipa_eth_ipa_ready_cb, NULL);
+	if (rc == -EEXIST) {
+		ipa_eth_ipa_is_ready = true;
+	} else if (rc) {
+		ipa_eth_err("Failed to register for IPA ready cb");
+		goto err_ipa;
+	}
+
+	ipa_eth_is_ready = true;
+
+	return 0;
+
+err_ipa:
+	ipa3_uc_unregister_ready_cb(&uc_ready_cb);
+err_uc:
+	ipa_eth_offload_modexit();
+err_offload:
+	ipa_eth_bus_modexit();
+err_bus:
+	ipa_eth_debugfs_cleanup();
+err_dbgfs:
+	ipa_eth_ipc_log_cleanup();
+err_ipclog:
+	return rc;
+}
+
+void ipa_eth_exit(void)
+{
+	ipa_eth_dbg("De-initializing IPA Ethernet Offload Sub-System");
+
+	ipa_eth_is_ready = false;
+
+	// IPA ready CB can not be unregistered; just unregister uC ready CB
+	ipa3_uc_unregister_ready_cb(&uc_ready_cb);
+
+	ipa_eth_offload_modexit();
+	ipa_eth_bus_modexit();
+	ipa_eth_debugfs_cleanup();
+	ipa_eth_ipc_log_cleanup();
+}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_bus.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_bus.c
new file mode 100644
index 0000000..7120e67
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_bus.c
@@ -0,0 +1,139 @@
+/* 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 "ipa_eth_i.h"
+
+static bool ipa_eth_bus_is_ready;
+
+static struct dentry *ipa_eth_bus_debugfs;
+
+struct ipa_eth_bus_map {
+	struct bus_type *bus;
+	struct ipa_eth_bus *eth_bus;
+	int (*modinit)(struct dentry *);
+	void (*modexit)(void);
+} bus_map[] = {
+	{
+		&pci_bus_type,
+		&ipa_eth_pci_bus,
+		&ipa_eth_pci_modinit,
+		&ipa_eth_pci_modexit
+	},
+	{},
+};
+
+static int ipa_eth_bus_debugfs_init(struct dentry *dbgfs_root)
+{
+	if (!dbgfs_root)
+		return 0;
+
+	ipa_eth_bus_debugfs = debugfs_create_dir("bus", dbgfs_root);
+	if (IS_ERR_OR_NULL(ipa_eth_bus_debugfs)) {
+		int rc = ipa_eth_bus_debugfs ?
+			PTR_ERR(ipa_eth_bus_debugfs) : -EFAULT;
+
+		ipa_eth_bus_debugfs = NULL;
+		return rc;
+	}
+
+	return 0;
+}
+
+static void ipa_eth_bus_debugfs_cleanup(void)
+{
+	debugfs_remove_recursive(ipa_eth_bus_debugfs);
+}
+
+static struct ipa_eth_bus *lookup_eth_bus(struct bus_type *bus)
+{
+	struct ipa_eth_bus_map *map;
+
+	for (map = bus_map; map->bus != NULL; map++) {
+		if (map->bus == bus)
+			return map->eth_bus;
+	}
+
+	return NULL;
+}
+
+int ipa_eth_bus_register_driver(struct ipa_eth_net_driver *nd)
+{
+	struct ipa_eth_bus *eth_bus;
+
+	if (!nd->bus) {
+		ipa_eth_err("Missing bus info in net driver");
+		return -EINVAL;
+	}
+
+	eth_bus = lookup_eth_bus(nd->bus);
+	if (!eth_bus) {
+		ipa_eth_err("Unsupported bus %s", nd->bus->name);
+		return -ENOTSUPP;
+	}
+
+	return eth_bus->register_net_driver(nd);
+}
+
+void ipa_eth_bus_unregister_driver(struct ipa_eth_net_driver *nd)
+{
+	struct ipa_eth_bus *eth_bus = lookup_eth_bus(nd->bus);
+
+	eth_bus->unregister_net_driver(nd);
+}
+
+int ipa_eth_bus_modinit(struct dentry *dbgfs_root)
+{
+	int rc;
+	struct ipa_eth_bus_map *map;
+
+	rc = ipa_eth_bus_debugfs_init(dbgfs_root);
+	if (rc) {
+		ipa_eth_err("Unable to create debugfs root for bus");
+		return rc;
+	}
+
+	/* initialize all registered busses */
+	for (rc = 0, map = bus_map; map->bus != NULL; map++)
+		rc |= map->modinit(ipa_eth_bus_debugfs);
+
+	if (rc) {
+		ipa_eth_err("Failed to initialize one or more busses");
+		goto err_init;
+	}
+
+	ipa_eth_bus_is_ready = true;
+
+	return 0;
+
+err_init:
+	for (map = bus_map; map->bus != NULL; map++)
+		map->modexit();
+
+	ipa_eth_bus_debugfs_cleanup();
+
+	return rc;
+}
+
+void ipa_eth_bus_modexit(void)
+{
+	struct ipa_eth_bus_map *map;
+
+	if (!ipa_eth_bus_is_ready)
+		return;
+
+	ipa_eth_bus_is_ready = false;
+
+	for (map = bus_map; map->bus != NULL; map++)
+		map->modexit();
+
+	ipa_eth_bus_debugfs_cleanup();
+}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_ep.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_ep.c
new file mode 100644
index 0000000..a75970d
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_ep.c
@@ -0,0 +1,389 @@
+/* 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/if_vlan.h>
+
+#include "ipa_eth_i.h"
+
+static void handle_ipa_receive(struct ipa_eth_channel *ch,
+			       unsigned long data)
+{
+	bool success = false;
+	struct sk_buff *skb = (struct sk_buff *) data;
+
+	ch->exception_total++;
+
+#ifndef IPA_ETH_EP_LOOPBACK
+	success = ch->process_skb && !ch->process_skb(ch, skb);
+#else
+	success = !ipa_tx_dp(IPA_CLIENT_AQC_ETHERNET_CONS, skb, NULL);
+	if (success)
+		ch->exception_loopback++;
+#endif
+
+	if (!success) {
+		ch->exception_drops++;
+		dev_kfree_skb_any(skb);
+	}
+}
+
+static void ipa_ep_client_notifier(void *priv, enum ipa_dp_evt_type evt,
+				   unsigned long data)
+{
+	struct ipa_eth_channel *ch = (struct ipa_eth_channel *) priv;
+
+	if (evt == IPA_RECEIVE)
+		handle_ipa_receive(ch, data);
+}
+
+static void ipa_eth_init_header_common(struct ipa_eth_device *eth_dev,
+				       struct ipa_hdr_add *hdr_add)
+{
+	hdr_add->type = IPA_HDR_L2_ETHERNET_II;
+	hdr_add->is_partial = 1;
+	hdr_add->is_eth2_ofst_valid = 1;
+	hdr_add->eth2_ofst = 0;
+}
+
+static void ipa_eth_init_l2_header_v4(struct ipa_eth_device *eth_dev,
+				      struct ipa_hdr_add *hdr_add)
+{
+	struct ethhdr eth_hdr;
+
+	memset(&eth_hdr, 0, sizeof(eth_hdr));
+	memcpy(&eth_hdr.h_source, eth_dev->net_dev->dev_addr, ETH_ALEN);
+	eth_hdr.h_proto = htons(ETH_P_IP);
+
+	hdr_add->hdr_len = ETH_HLEN;
+	memcpy(hdr_add->hdr, &eth_hdr, hdr_add->hdr_len);
+
+	ipa_eth_init_header_common(eth_dev, hdr_add);
+}
+
+static void ipa_eth_init_l2_header_v6(struct ipa_eth_device *eth_dev,
+				      struct ipa_hdr_add *hdr_add)
+{
+	struct ethhdr eth_hdr;
+
+	memset(&eth_hdr, 0, sizeof(eth_hdr));
+	memcpy(&eth_hdr.h_source, eth_dev->net_dev->dev_addr, ETH_ALEN);
+	eth_hdr.h_proto = htons(ETH_P_IPV6);
+
+	hdr_add->hdr_len = ETH_HLEN;
+	memcpy(hdr_add->hdr, &eth_hdr, hdr_add->hdr_len);
+
+	ipa_eth_init_header_common(eth_dev, hdr_add);
+}
+
+static void ipa_eth_init_vlan_header_v4(struct ipa_eth_device *eth_dev,
+					struct ipa_hdr_add *hdr_add)
+{
+	struct vlan_ethhdr eth_hdr;
+
+	memset(&eth_hdr, 0, sizeof(eth_hdr));
+	memcpy(&eth_hdr.h_source, eth_dev->net_dev->dev_addr, ETH_ALEN);
+
+	eth_hdr.h_vlan_proto = htons(ETH_P_8021Q);
+	eth_hdr.h_vlan_encapsulated_proto = htons(ETH_P_IP);
+
+	hdr_add->hdr_len = ETH_HLEN;
+	memcpy(hdr_add->hdr, &eth_hdr, hdr_add->hdr_len);
+
+	ipa_eth_init_header_common(eth_dev, hdr_add);
+}
+
+
+static void ipa_eth_init_vlan_header_v6(struct ipa_eth_device *eth_dev,
+					struct ipa_hdr_add *hdr_add)
+{
+	struct vlan_ethhdr eth_hdr;
+
+	memset(&eth_hdr, 0, sizeof(eth_hdr));
+	memcpy(&eth_hdr.h_source, eth_dev->net_dev->dev_addr, ETH_ALEN);
+
+	eth_hdr.h_vlan_proto = htons(ETH_P_8021Q);
+	eth_hdr.h_vlan_encapsulated_proto = htons(ETH_P_IPV6);
+
+	hdr_add->hdr_len = ETH_HLEN;
+	memcpy(hdr_add->hdr, &eth_hdr, hdr_add->hdr_len);
+
+	ipa_eth_init_header_common(eth_dev, hdr_add);
+}
+
+/**
+ * ipa_eth_ep_init_headers() - Install partial headers
+ * @eth_dev: Offload device
+ *
+ * Installs partial headers in IPA for IPv4 and IPv6 traffic.
+ *
+ * Return: 0 on success, negative errno code otherwise
+ */
+int ipa_eth_ep_init_headers(struct ipa_eth_device *eth_dev)
+{
+	int rc = 0;
+	bool vlan_mode;
+	const size_t num_hdrs = 2; // one each for IPv4 and IPv6
+	size_t hdr_alloc_sz = sizeof(struct ipa_ioc_add_hdr) +
+				num_hdrs * sizeof(struct ipa_hdr_add);
+	struct ipa_hdr_add *hdr_v4 = NULL;
+	struct ipa_hdr_add *hdr_v6 = NULL;
+	struct ipa_ioc_add_hdr *hdrs = NULL;
+
+	rc = ipa3_is_vlan_mode(IPA_VLAN_IF_ETH, &vlan_mode);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Could not determine IPA VLAN mode");
+		return rc;
+	}
+
+	hdrs = kzalloc(hdr_alloc_sz, GFP_KERNEL);
+	if (hdrs == NULL) {
+		ipa_eth_dev_err(eth_dev, "Failed to alloc partial headers");
+		return -ENOMEM;
+	}
+
+	hdr_v4 = &hdrs->hdr[0];
+	hdr_v6 = &hdrs->hdr[1];
+
+	hdrs->commit = 1;
+	hdrs->num_hdrs = num_hdrs;
+
+	// Initialize IPv4 headers
+	snprintf(hdr_v4->name, sizeof(hdr_v4->name), "%s_ipv4",
+		eth_dev->net_dev->name);
+
+	if (!vlan_mode)
+		ipa_eth_init_l2_header_v4(eth_dev, hdr_v4);
+	else
+		ipa_eth_init_vlan_header_v4(eth_dev, hdr_v4);
+
+	// Initialize IPv6 headers
+	snprintf(hdr_v6->name, sizeof(hdr_v6->name), "%s_ipv6",
+		eth_dev->net_dev->name);
+
+	if (!vlan_mode)
+		ipa_eth_init_l2_header_v6(eth_dev, hdr_v6);
+	else
+		ipa_eth_init_vlan_header_v6(eth_dev, hdr_v6);
+
+	rc = ipa_add_hdr(hdrs);
+	if (rc)
+		ipa_eth_dev_err(eth_dev, "Failed to install partial headers");
+
+	kfree(hdrs);
+
+	return rc;
+}
+
+static void ipa_eth_ep_init_tx_props_v4(struct ipa_eth_device *eth_dev,
+					struct ipa_ioc_tx_intf_prop *props)
+{
+	props->ip = IPA_IP_v4;
+	props->dst_pipe = eth_dev->ch_tx->ipa_client;
+
+	props->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+	snprintf(props->hdr_name, sizeof(props->hdr_name), "%s_ipv4",
+		eth_dev->net_dev->name);
+
+}
+
+static void ipa_eth_ep_init_tx_props_v6(struct ipa_eth_device *eth_dev,
+					struct ipa_ioc_tx_intf_prop *props)
+{
+	props->ip = IPA_IP_v6;
+	props->dst_pipe = eth_dev->ch_tx->ipa_client;
+
+	props->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+	snprintf(props->hdr_name, sizeof(props->hdr_name), "%s_ipv6",
+		eth_dev->net_dev->name);
+}
+
+static void ipa_eth_ep_init_rx_props_v4(struct ipa_eth_device *eth_dev,
+					struct ipa_ioc_rx_intf_prop *props)
+{
+	props->ip = IPA_IP_v4;
+	props->src_pipe = eth_dev->ch_rx->ipa_client;
+
+	props->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+
+	// TODO: what about attrib?
+}
+
+static void ipa_eth_ep_init_rx_props_v6(struct ipa_eth_device *eth_dev,
+					struct ipa_ioc_rx_intf_prop *props)
+{
+	props->ip = IPA_IP_v6;
+	props->src_pipe = eth_dev->ch_rx->ipa_client;
+
+	props->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
+
+	// TODO: what about attrib?
+}
+
+/**
+ * ipa_eth_ep_register_interface() - Set Rx and Tx properties and register the
+ *                                   interface with IPA
+ * @eth_dev: Offload device to register
+ *
+ * Register a logical interface with IPA. The API expects netdev and channels
+ * allocated prior to being called.
+ *
+ * Return: 0 on success, negative errno code otherwise
+ */
+int ipa_eth_ep_register_interface(struct ipa_eth_device *eth_dev)
+{
+	struct ipa_tx_intf tx_intf;
+	struct ipa_rx_intf rx_intf;
+	const size_t num_props = 2; // one each for IPv4 and IPv6
+	struct ipa_ioc_tx_intf_prop tx_props[num_props];
+	struct ipa_ioc_rx_intf_prop rx_props[num_props];
+
+	memset(&tx_props, 0, sizeof(tx_props));
+	ipa_eth_ep_init_tx_props_v4(eth_dev, &tx_props[0]);
+	ipa_eth_ep_init_tx_props_v6(eth_dev, &tx_props[1]);
+
+	tx_intf.num_props = num_props;
+	tx_intf.prop = tx_props;
+
+	memset(&rx_props, 0, sizeof(rx_props));
+	ipa_eth_ep_init_rx_props_v4(eth_dev, &rx_props[0]);
+	ipa_eth_ep_init_rx_props_v6(eth_dev, &rx_props[1]);
+
+	rx_intf.num_props = num_props;
+	rx_intf.prop = rx_props;
+
+	return ipa_register_intf(eth_dev->net_dev->name, &tx_intf, &rx_intf);
+}
+
+/**
+ * ipa_eth_ep_unregister_interface() - Unregister a previously registered
+ *                                     interface
+ * @eth_dev: Offload device to unregister
+ */
+int ipa_eth_ep_unregister_interface(struct ipa_eth_device *eth_dev)
+{
+	return ipa_deregister_intf(eth_dev->net_dev->name);
+}
+
+/**
+ * ipa_eth_ep_init - Initialize IPA endpoint for a channel
+ * @ch: Channel for which EP need to be initialized
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_ep_init(struct ipa_eth_channel *ch)
+{
+	int rc = 0;
+	bool vlan_mode;
+	const bool client_prod = IPA_CLIENT_IS_PROD(ch->ipa_client);
+	const int ep_num = ipa_get_ep_mapping(ch->ipa_client);
+
+	struct ipa3_ep_context *ep_ctx = NULL;
+
+	if (ep_num == IPA_EP_NOT_ALLOCATED) {
+		ipa_eth_dev_err(ch->eth_dev,
+				"Could not determine EP number for client %d",
+				ch->ipa_client);
+		rc = -EFAULT;
+		goto err_exit;
+	}
+
+	ch->ipa_ep_num = ep_num;
+
+	rc = ipa3_is_vlan_mode(IPA_VLAN_IF_ETH, &vlan_mode);
+	if (rc) {
+		ipa_eth_dev_err(ch->eth_dev,
+				"Could not determine IPA VLAN mode");
+		goto err_exit;
+	}
+
+	ep_ctx = &ipa3_ctx->ep[ep_num];
+	if (ep_ctx->valid) {
+		ipa_eth_dev_err(ch->eth_dev,
+				"EP context is already initialiazed");
+		rc = -EEXIST;
+		goto err_exit;
+	}
+
+	memset(ep_ctx, 0, offsetof(typeof(*ep_ctx), sys));
+
+	ep_ctx->valid = 1;
+	ep_ctx->client = ch->ipa_client;
+	ep_ctx->client_notify = ipa_ep_client_notifier;
+	ep_ctx->priv = ch;
+
+	ep_ctx->cfg.nat.nat_en =  client_prod ? IPA_SRC_NAT : IPA_BYPASS_NAT;
+	ep_ctx->cfg.hdr.hdr_len = vlan_mode ? VLAN_ETH_HLEN : ETH_HLEN;
+
+	ep_ctx->cfg.mode.mode = IPA_BASIC;
+
+#ifdef IPA_ETH_DMA_MODE
+	if (IPA_ETH_CH_IS_RX(ch)) {
+		ep_ctx->cfg.mode.mode = IPA_DMA;
+		ep_ctx->cfg.mode.dst = IPA_CLIENT_AQC_ETHERNET_CONS;
+	}
+#endif
+
+	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
+
+	rc = ipa3_cfg_ep(ep_num, &ep_ctx->cfg);
+	if (rc) {
+		ipa_eth_dev_err(ch->eth_dev,
+				"Failed to configure EP %d", ep_num);
+		IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+		goto err_exit;
+	}
+
+	if (IPA_ETH_CH_IS_RX(ch))
+		ipa3_install_dflt_flt_rules(ep_num);
+
+	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+
+err_exit:
+	return rc;
+}
+EXPORT_SYMBOL(ipa_eth_ep_init);
+
+/**
+ * ipa_eth_ep_start() - Start an IPA endpoint
+ * @ch: Channel for which the IPA EP need to be started
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_ep_start(struct ipa_eth_channel *ch)
+{
+	int rc = ipa3_enable_data_path(ch->ipa_ep_num);
+
+	if (rc)
+		ipa_eth_dev_err(ch->eth_dev,
+				"Failed to start EP %d", ch->ipa_ep_num);
+
+	return rc;
+}
+EXPORT_SYMBOL(ipa_eth_ep_start);
+
+/**
+ * ipa_eth_ep_stop() - Stop an IPA endpoint
+ * @ch: Channel for which the IPA EP need to be stopped
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_ep_stop(struct ipa_eth_channel *ch)
+{
+	int rc = ipa3_disable_data_path(ch->ipa_ep_num);
+
+	if (rc)
+		ipa_eth_dev_err(ch->eth_dev,
+				"Failed to stop EP %d", ch->ipa_ep_num);
+
+	return rc;
+}
+EXPORT_SYMBOL(ipa_eth_ep_stop);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_gsi.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_gsi.c
new file mode 100644
index 0000000..ebdc5a2
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_gsi.c
@@ -0,0 +1,405 @@
+/* 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/msm_gsi.h>
+
+#include "ipa_eth_i.h"
+
+static void ipa_eth_gsi_ev_err(struct gsi_evt_err_notify *notify)
+{
+	struct ipa_eth_channel *ch = notify->user_data;
+	struct ipa3_ep_context *ep_ctx = &ipa3_ctx->ep[ch->ipa_ep_num];
+
+	ipa_eth_dev_err(ch->eth_dev,
+			"Error (id=%d, edesc=%04x) in GSI event ring %u",
+			notify->evt_id, notify->err_desc,
+			ep_ctx->gsi_evt_ring_hdl);
+}
+
+static void ipa_eth_gsi_ch_err(struct gsi_chan_err_notify *notify)
+{
+	struct ipa_eth_channel *ch = notify->chan_user_data;
+	struct ipa3_ep_context *ep_ctx = &ipa3_ctx->ep[ch->ipa_ep_num];
+
+	ipa_eth_dev_err(ch->eth_dev,
+			"Error (id=%d, edesc=%04x) in GSI channel %u",
+			notify->evt_id, notify->err_desc,
+			ep_ctx->gsi_chan_hdl);
+}
+
+/*
+ * ipa_eth_gsi_alloc() - Allocate GSI channel and event ring for an offload
+ *                       channel, optionally writing to the ring scratch
+ *                       register and fetch the ring doorbell address
+ * @ch: Offload channel
+ * @gsi_ev_props: Properties of the GSI event ring to be allocated
+ * @gsi_ev_scratch: Optional. Points to the value to be written to GSI
+ *                  event ring scratch register
+ * @gsi_ev_db: Optional. Writes event ring doorbell LSB address to the location
+ *                       pointed to by the argument
+ * @gsi_ch_props: Properties of the GSI channel to be allocated
+ * @gsi_ch_scratch: Optional. Points to the value to be written to GSI
+ *                  event ring scratch register
+ * @gsi_ch_db: Optional. Writes channel doorbell LSB address to the location
+ *                       pointed to by the argument
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_gsi_alloc(struct ipa_eth_channel *ch,
+		      struct gsi_evt_ring_props *gsi_ev_props,
+		      union gsi_evt_scratch *gsi_ev_scratch,
+		      phys_addr_t *gsi_ev_db,
+		      struct gsi_chan_props *gsi_ch_props,
+		      union gsi_channel_scratch *gsi_ch_scratch,
+		      phys_addr_t *gsi_ch_db)
+{
+	enum gsi_status gsi_rc = GSI_STATUS_SUCCESS;
+	const struct ipa_gsi_ep_config *gsi_ep_cfg;
+	struct ipa3_ep_context *ep_ctx = &ipa3_ctx->ep[ch->ipa_ep_num];
+
+	if (!ep_ctx->valid) {
+		ipa_eth_dev_err(ch->eth_dev, "EP context is not initialized");
+		return -EFAULT;
+	}
+
+	gsi_ep_cfg = ipa3_get_gsi_ep_info(ep_ctx->client);
+	if (!gsi_ep_cfg) {
+		ipa_eth_dev_err(ch->eth_dev, "Failed to obtain GSI EP info");
+		return -EFAULT;
+	}
+
+	if (!gsi_ev_props->err_cb) {
+		gsi_ev_props->err_cb = ipa_eth_gsi_ev_err;
+		gsi_ev_props->user_data = ch;
+	}
+
+	gsi_rc = gsi_alloc_evt_ring(gsi_ev_props, ipa3_ctx->gsi_dev_hdl,
+		&ep_ctx->gsi_evt_ring_hdl);
+	if (gsi_rc != GSI_STATUS_SUCCESS) {
+		ipa_eth_dev_err(ch->eth_dev, "Failed to alloc GSI event ring");
+		return -EFAULT;
+	}
+
+	ipa_eth_dev_dbg(ch->eth_dev, "GSI event ring handle is %lu",
+			ep_ctx->gsi_evt_ring_hdl);
+
+	if (gsi_ev_db) {
+		u32 db_addr_lsb = 0;
+		u32 db_addr_msb = 0;
+
+		gsi_rc = gsi_query_evt_ring_db_addr(ep_ctx->gsi_evt_ring_hdl,
+			&db_addr_lsb, &db_addr_msb);
+		if (gsi_rc != GSI_STATUS_SUCCESS) {
+			ipa_eth_dev_err(ch->eth_dev,
+				"Failed to get DB address for event ring %lu",
+				ep_ctx->gsi_evt_ring_hdl);
+			goto err_free_ev;
+		}
+
+		ipa_eth_dev_dbg(ch->eth_dev,
+				"GSI event ring %lu DB address LSB is 0x%08x",
+				ep_ctx->gsi_evt_ring_hdl, db_addr_lsb);
+		ipa_eth_dev_dbg(ch->eth_dev,
+				"GSI event ring %lu DB address MSB is 0x%08x",
+				ep_ctx->gsi_evt_ring_hdl, db_addr_msb);
+
+		*gsi_ev_db = db_addr_lsb;
+	}
+
+	if (gsi_ev_scratch) {
+		gsi_rc = gsi_write_evt_ring_scratch(ep_ctx->gsi_evt_ring_hdl,
+				*gsi_ev_scratch);
+		if (gsi_rc != GSI_STATUS_SUCCESS) {
+			ipa_eth_dev_err(ch->eth_dev,
+				"Failed to write scratch for event ring %lu",
+				ep_ctx->gsi_evt_ring_hdl);
+			goto err_free_ev;
+		}
+	}
+
+	gsi_ch_props->ch_id = gsi_ep_cfg->ipa_gsi_chan_num;
+	gsi_ch_props->evt_ring_hdl = ep_ctx->gsi_evt_ring_hdl;
+
+	gsi_ch_props->prefetch_mode = gsi_ep_cfg->prefetch_mode;
+	gsi_ch_props->empty_lvl_threshold = gsi_ep_cfg->prefetch_threshold;
+
+	if (!gsi_ch_props->err_cb) {
+		gsi_ch_props->err_cb = ipa_eth_gsi_ch_err;
+		gsi_ch_props->chan_user_data = ch;
+	}
+
+	gsi_rc = gsi_alloc_channel(gsi_ch_props, ipa3_ctx->gsi_dev_hdl,
+		&ep_ctx->gsi_chan_hdl);
+	if (gsi_rc != GSI_STATUS_SUCCESS) {
+		ipa_eth_dev_err(ch->eth_dev, "Failed to alloc GSI channel");
+		goto err_free_ev;
+	}
+
+	ipa_eth_dev_dbg(ch->eth_dev, "GSI channel handle is %lu",
+			ep_ctx->gsi_chan_hdl);
+
+	if (gsi_ch_db) {
+		u32 db_addr_lsb = 0;
+		u32 db_addr_msb = 0;
+
+		gsi_rc = gsi_query_channel_db_addr(ep_ctx->gsi_chan_hdl,
+			&db_addr_lsb, &db_addr_msb);
+		if (gsi_rc != GSI_STATUS_SUCCESS) {
+			ipa_eth_dev_err(ch->eth_dev,
+				"Failed to get DB address for channel %lu",
+				ep_ctx->gsi_chan_hdl);
+			goto err_free_ch;
+		}
+
+		ipa_eth_dev_dbg(ch->eth_dev,
+				"GSI channel %lu DB address LSB is 0x%08x",
+				ep_ctx->gsi_chan_hdl, db_addr_lsb);
+		ipa_eth_dev_dbg(ch->eth_dev,
+				"GSI channel %lu DB address MSB is 0x%08x",
+				ep_ctx->gsi_chan_hdl, db_addr_msb);
+
+		*gsi_ch_db = db_addr_lsb;
+	}
+
+	if (gsi_ch_scratch) {
+		gsi_rc = gsi_write_channel_scratch(ep_ctx->gsi_chan_hdl,
+				*gsi_ch_scratch);
+		if (gsi_rc != GSI_STATUS_SUCCESS) {
+			ipa_eth_dev_err(ch->eth_dev,
+				"Failed to write scratch for channel %lu",
+				ep_ctx->gsi_chan_hdl);
+			goto err_free_ch;
+		}
+	}
+
+	return 0;
+
+err_free_ch:
+	if (gsi_dealloc_channel(ep_ctx->gsi_chan_hdl))
+		ipa_eth_dev_err(ch->eth_dev,
+				"Failed to dealloc GSI channel %lu",
+				ep_ctx->gsi_chan_hdl);
+
+	ep_ctx->gsi_chan_hdl = ~0;
+
+err_free_ev:
+	if (gsi_dealloc_evt_ring(ep_ctx->gsi_evt_ring_hdl))
+		ipa_eth_dev_err(ch->eth_dev,
+				"Failed to dealloc GSI event ring %lu",
+				ep_ctx->gsi_evt_ring_hdl);
+
+	ep_ctx->gsi_evt_ring_hdl = ~0;
+
+	return gsi_rc;
+}
+EXPORT_SYMBOL(ipa_eth_gsi_alloc);
+
+/**
+ * ipa_eth_gsi_dealloc() - De-allocate GSI event ring and channel associated
+ *                         with an offload channel, previously allocated with
+ *                         ipa_eth_gsi_alloc()
+ * @ch: Offload channel
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_gsi_dealloc(struct ipa_eth_channel *ch)
+{
+	enum gsi_status gsi_rc = GSI_STATUS_SUCCESS;
+	struct ipa3_ep_context *ep_ctx = &ipa3_ctx->ep[ch->ipa_ep_num];
+
+	if (!ep_ctx->valid) {
+		ipa_eth_dev_err(ch->eth_dev, "EP context is not initialized");
+		return -EFAULT;
+	}
+
+	if (ep_ctx->gsi_chan_hdl != ~0) {
+		gsi_rc = gsi_dealloc_channel(ep_ctx->gsi_chan_hdl);
+		if (gsi_rc != GSI_STATUS_SUCCESS) {
+			ipa_eth_dev_err(ch->eth_dev,
+					"Failed to dealloc channel %lu",
+					ep_ctx->gsi_chan_hdl);
+			return gsi_rc;
+		}
+
+		ep_ctx->gsi_chan_hdl = ~0;
+	}
+
+	if (ep_ctx->gsi_evt_ring_hdl != ~0) {
+		gsi_rc = gsi_dealloc_evt_ring(ep_ctx->gsi_evt_ring_hdl);
+		if (gsi_rc != GSI_STATUS_SUCCESS) {
+			ipa_eth_dev_err(ch->eth_dev,
+					"Failed to dealloc event ring %lu",
+					ep_ctx->gsi_evt_ring_hdl);
+			return gsi_rc;
+		}
+
+		ep_ctx->gsi_evt_ring_hdl = ~0;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_eth_gsi_dealloc);
+
+/*
+ * ipa_eth_gsi_ring_evtring() - Ring an offload channel event ring doorbell
+ * @ch: Offload channel associated with the event ring
+ * @value: Value to write to the doorbell
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_gsi_ring_evtring(struct ipa_eth_channel *ch, u64 value)
+{
+	enum gsi_status gsi_rc = GSI_STATUS_SUCCESS;
+	struct ipa3_ep_context *ep_ctx = &ipa3_ctx->ep[ch->ipa_ep_num];
+
+	if (!ep_ctx->valid) {
+		ipa_eth_dev_err(ch->eth_dev, "EP context is not initialized");
+		return -EFAULT;
+	}
+
+	gsi_rc = gsi_ring_evt_ring_db(ep_ctx->gsi_evt_ring_hdl, value);
+	if (gsi_rc != GSI_STATUS_SUCCESS) {
+		ipa_eth_dev_err(ch->eth_dev,
+				"Failed to ring DB for event ring %lu",
+				ep_ctx->gsi_evt_ring_hdl);
+		return gsi_rc;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_eth_gsi_ring_evtring);
+
+/*
+ * ipa_eth_gsi_ring_channel() - Ring an offload channel GSI channel doorbell
+ * @ch: Offload channel associated with the GSI channel
+ * @value: Value to write to the doorbell
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_gsi_ring_channel(struct ipa_eth_channel *ch, u64 value)
+{
+	enum gsi_status gsi_rc = GSI_STATUS_SUCCESS;
+	struct ipa3_ep_context *ep_ctx = &ipa3_ctx->ep[ch->ipa_ep_num];
+
+	if (!ep_ctx->valid) {
+		ipa_eth_dev_err(ch->eth_dev, "EP context is not initialized");
+		return -EFAULT;
+	}
+
+	gsi_rc = gsi_ring_ch_ring_db(ep_ctx->gsi_chan_hdl, value);
+	if (gsi_rc != GSI_STATUS_SUCCESS) {
+		ipa_eth_dev_err(ch->eth_dev,
+				"Failed to ring DB for channel %lu",
+				ep_ctx->gsi_chan_hdl);
+		return gsi_rc;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_eth_gsi_ring_channel);
+
+/**
+ * ipa_eth_gsi_start() - Start GSI channel associated with offload channel
+ * @ch: Offload channel
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_gsi_start(struct ipa_eth_channel *ch)
+{
+	enum gsi_status gsi_rc = GSI_STATUS_SUCCESS;
+	struct ipa3_ep_context *ep_ctx = &ipa3_ctx->ep[ch->ipa_ep_num];
+
+	if (!ep_ctx->valid) {
+		ipa_eth_dev_err(ch->eth_dev, "EP context is not initialized");
+		return -EFAULT;
+	}
+
+	gsi_rc = gsi_start_channel(ep_ctx->gsi_chan_hdl);
+	if (gsi_rc != GSI_STATUS_SUCCESS) {
+		ipa_eth_dev_err(ch->eth_dev, "Failed to start GSI channel %lu",
+				ep_ctx->gsi_chan_hdl);
+		return gsi_rc;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_eth_gsi_start);
+
+/**
+ * ipa_eth_gsi_stop() - Stop GSI channel associated with offload channel
+ * @ch: Offload channel
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_gsi_stop(struct ipa_eth_channel *ch)
+{
+	enum gsi_status gsi_rc = GSI_STATUS_SUCCESS;
+	struct ipa3_ep_context *ep_ctx = &ipa3_ctx->ep[ch->ipa_ep_num];
+
+	if (!ep_ctx->valid) {
+		ipa_eth_dev_err(ch->eth_dev, "EP context is not initialized");
+		return -EFAULT;
+	}
+
+	gsi_rc = gsi_stop_channel(ep_ctx->gsi_chan_hdl);
+	if (gsi_rc != GSI_STATUS_SUCCESS) {
+		ipa_eth_dev_err(ch->eth_dev, "Failed to stop GSI channel %lu",
+				ep_ctx->gsi_chan_hdl);
+		return gsi_rc;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_eth_gsi_stop);
+
+int ipa_eth_gsi_iommu_unmap(dma_addr_t daddr, size_t size, bool split)
+{
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
+
+	if (!cb->valid) {
+		ipa_eth_err("SMMU CB not valid for AP");
+		return -EFAULT;
+	}
+
+	return ipa_eth_iommu_unmap(cb->mapping->domain, daddr, size, split);
+}
+EXPORT_SYMBOL(ipa_eth_gsi_iommu_unmap);
+
+static int ipa_eth_gsi_iommu_map(dma_addr_t daddr, void *addr, bool is_va,
+	size_t size, int prot, bool split)
+{
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
+
+	if (!cb->valid) {
+		ipa_eth_err("SMMU CB not valid for AP");
+		return -EFAULT;
+	}
+
+	return ipa_eth_iommu_map(cb->mapping->domain, daddr, addr, is_va,
+				 size, prot, split);
+}
+
+int ipa_eth_gsi_iommu_pamap(dma_addr_t daddr, phys_addr_t paddr,
+	size_t size, int prot, bool split)
+{
+	return ipa_eth_gsi_iommu_map(daddr, (void *)paddr, false, size,
+				     prot, split);
+}
+EXPORT_SYMBOL(ipa_eth_gsi_iommu_pamap);
+
+int ipa_eth_gsi_iommu_vamap(dma_addr_t daddr, void *vaddr,
+	size_t size, int prot, bool split)
+{
+	return ipa_eth_gsi_iommu_map(daddr, vaddr, true, size,
+				     prot, split);
+}
+EXPORT_SYMBOL(ipa_eth_gsi_iommu_vamap);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_i.h b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_i.h
new file mode 100644
index 0000000..4c00ac4
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_i.h
@@ -0,0 +1,133 @@
+/* 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 _IPA_ETH_I_H_
+#define _IPA_ETH_I_H_
+
+#include <linux/pci.h>
+#include <linux/ipa_eth.h>
+
+#include "../ipa_i.h"
+
+#ifdef CONFIG_IPA_ETH_NOAUTO
+#define IPA_ETH_NOAUTO_DEFAULT true
+#else
+#define IPA_ETH_NOAUTO_DEFAULT false
+#endif
+
+#ifdef DEBUG
+#define IPA_ETH_IPC_LOGDBG_DEFAULT true
+#else
+#define IPA_ETH_IPC_LOGDBG_DEFAULT false
+#endif
+
+#define IPA_ETH_PFDEV (ipa3_ctx ? ipa3_ctx->pdev : NULL)
+#define IPA_ETH_SUBSYS "ipa_eth"
+
+#define ipa_eth_err(fmt, args...) \
+	do { \
+		dev_err(IPA_ETH_PFDEV, \
+			IPA_ETH_SUBSYS " %s:%d ERROR: " fmt "\n", \
+			__func__, __LINE__, ## args); \
+		ipa_eth_ipc_log("ERROR: " fmt, ## args); \
+	} while (0)
+
+#define ipa_eth_log(fmt, args...) \
+	do { \
+		dev_dbg(IPA_ETH_PFDEV, \
+			IPA_ETH_SUBSYS " %s:%d " fmt "\n", \
+			__func__, __LINE__, ## args); \
+		ipa_eth_ipc_log(fmt, ## args); \
+	} while (0)
+
+#define ipa_eth_dbg(fmt, args...) \
+	do { \
+		dev_dbg(IPA_ETH_PFDEV, \
+			IPA_ETH_SUBSYS " %s:%d " fmt "\n", \
+			__func__, __LINE__, ## args); \
+		ipa_eth_ipc_dbg("ERROR: " fmt, ## args); \
+	} while (0)
+
+#define ipa_eth_dev_err(edev, fmt, args...) \
+	ipa_eth_err("(%s) " fmt, \
+		(edev->net_dev ? edev->net_dev->name : "<unpaired>"), ## args)
+
+#define ipa_eth_dev_dbg(edev, fmt, args...) \
+	ipa_eth_dbg("(%s) " fmt, \
+		(edev->net_dev ? edev->net_dev->name : "<unpaired>"), ## args)
+
+#define ipa_eth_dev_log(edev, fmt, args...) \
+	ipa_eth_log("(%s) " fmt, \
+		(edev->net_dev ? edev->net_dev->name : "<unpaired>"), ## args)
+
+
+struct ipa_eth_bus {
+	struct list_head bus_list;
+
+	struct bus_type *bus;
+
+	int (*register_net_driver)(struct ipa_eth_net_driver *nd);
+	void (*unregister_net_driver)(struct ipa_eth_net_driver *nd);
+};
+
+extern struct ipa_eth_bus ipa_eth_pci_bus;
+
+int ipa_eth_register_device(struct ipa_eth_device *eth_dev);
+void ipa_eth_unregister_device(struct ipa_eth_device *eth_dev);
+
+int ipa_eth_iommu_map(struct iommu_domain *domain,
+	dma_addr_t daddr, void *addr, bool is_va,
+	size_t size, int prot, bool split);
+int ipa_eth_iommu_unmap(struct iommu_domain *domain,
+	dma_addr_t daddr, size_t size, bool split);
+
+int ipa_eth_pci_modinit(struct dentry *dbgfs_root);
+void ipa_eth_pci_modexit(void);
+
+int ipa_eth_bus_modinit(struct dentry *dbgfs_root);
+void ipa_eth_bus_modexit(void);
+
+int ipa_eth_bus_register_driver(struct ipa_eth_net_driver *nd);
+void ipa_eth_bus_unregister_driver(struct ipa_eth_net_driver *nd);
+
+int ipa_eth_offload_modinit(struct dentry *dbgfs_root);
+void ipa_eth_offload_modexit(void);
+
+int ipa_eth_offload_register_driver(struct ipa_eth_offload_driver *od);
+void ipa_eth_offload_unregister_driver(struct ipa_eth_offload_driver *od);
+
+static inline bool ipa_eth_offload_device_paired(struct ipa_eth_device *eth_dev)
+{
+	return eth_dev->od != NULL;
+}
+
+int ipa_eth_offload_pair_device(struct ipa_eth_device *eth_dev);
+void ipa_eth_offload_unpair_device(struct ipa_eth_device *eth_dev);
+
+int ipa_eth_offload_init(struct ipa_eth_device *eth_dev);
+int ipa_eth_offload_deinit(struct ipa_eth_device *eth_dev);
+int ipa_eth_offload_start(struct ipa_eth_device *eth_dev);
+int ipa_eth_offload_stop(struct ipa_eth_device *eth_dev);
+
+int ipa_eth_ep_init_headers(struct ipa_eth_device *eth_dev);
+int ipa_eth_ep_register_interface(struct ipa_eth_device *eth_dev);
+int ipa_eth_ep_unregister_interface(struct ipa_eth_device *eth_dev);
+
+int ipa_eth_pm_register(struct ipa_eth_device *eth_dev);
+int ipa_eth_pm_unregister(struct ipa_eth_device *eth_dev);
+
+int ipa_eth_pm_activate(struct ipa_eth_device *eth_dev);
+int ipa_eth_pm_deactivate(struct ipa_eth_device *eth_dev);
+
+int ipa_eth_pm_vote_bw(struct ipa_eth_device *eth_dev);
+
+#endif // _IPA_ETH_I_H_
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_offload.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_offload.c
new file mode 100644
index 0000000..c417f87
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_offload.c
@@ -0,0 +1,217 @@
+/* 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 "ipa_eth_i.h"
+
+static LIST_HEAD(ipa_eth_offload_drivers);
+static DEFINE_MUTEX(ipa_eth_offload_drivers_lock);
+
+static struct dentry *ipa_eth_offload_debugfs;
+
+static void ipa_eth_offload_debugfs_cleanup(void)
+{
+	debugfs_remove_recursive(ipa_eth_offload_debugfs);
+}
+
+static int ipa_eth_offload_debugfs_init(struct dentry *dbgfs_root)
+{
+	if (!dbgfs_root)
+		return 0;
+
+	ipa_eth_offload_debugfs = debugfs_create_dir("offload", dbgfs_root);
+	if (IS_ERR_OR_NULL(ipa_eth_offload_debugfs)) {
+		int rc = ipa_eth_offload_debugfs ?
+			PTR_ERR(ipa_eth_offload_debugfs) : -EFAULT;
+
+		ipa_eth_offload_debugfs = NULL;
+		return rc;
+	}
+
+	return 0;
+}
+
+int ipa_eth_offload_init(struct ipa_eth_device *eth_dev)
+{
+	int rc;
+
+	rc = eth_dev->od->ops->init_tx(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to init offload for tx");
+		return rc;
+	}
+
+	rc = eth_dev->od->ops->init_rx(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to init offload for rx");
+		(void) eth_dev->od->ops->deinit_tx(eth_dev);
+		return rc;
+	}
+
+	return 0;
+}
+
+int ipa_eth_offload_deinit(struct ipa_eth_device *eth_dev)
+{
+	int rc_rx, rc_tx;
+
+	rc_rx = eth_dev->od->ops->deinit_rx(eth_dev);
+	if (rc_rx)
+		ipa_eth_dev_err(eth_dev, "Failed to deinit offload for rx");
+
+	rc_tx = eth_dev->od->ops->deinit_tx(eth_dev);
+	if (rc_tx)
+		ipa_eth_dev_err(eth_dev, "Failed to deinit offload for tx");
+
+	return rc_rx || rc_tx;
+}
+
+int ipa_eth_offload_start(struct ipa_eth_device *eth_dev)
+{
+	int rc;
+
+	rc = eth_dev->od->ops->start_tx(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to start offload for tx");
+		return rc;
+	}
+
+	rc = eth_dev->od->ops->start_rx(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to start offload for rx");
+		(void) eth_dev->od->ops->stop_tx(eth_dev);
+		return rc;
+	}
+
+	return 0;
+}
+
+int ipa_eth_offload_stop(struct ipa_eth_device *eth_dev)
+{
+	int rc_rx, rc_tx;
+
+	rc_rx = eth_dev->od->ops->stop_rx(eth_dev);
+	if (rc_rx)
+		ipa_eth_dev_err(eth_dev, "Failed to stop offload for rx");
+
+	rc_tx = eth_dev->od->ops->stop_tx(eth_dev);
+	if (rc_tx)
+		ipa_eth_dev_err(eth_dev, "Failed to stop offload for tx");
+
+	return rc_rx || rc_tx;
+}
+
+static int try_pair_device(struct ipa_eth_device *eth_dev,
+			   struct ipa_eth_offload_driver *od)
+{
+	if (od->bus && od->bus != eth_dev->dev->bus) {
+		ipa_eth_dev_dbg(eth_dev,
+			"Offload driver %s is not a bus match for %s",
+			od->name, eth_dev->nd->name);
+
+		return -ENOTSUPP;
+	}
+
+	if (od->bus_ops->probe) {
+		int rc = od->bus_ops->probe(eth_dev);
+
+		if (!rc) {
+			eth_dev->od = od;
+			return 0;
+		}
+
+		ipa_eth_dev_dbg(eth_dev,
+			"Offload driver %s passed up paring with %s",
+			od->name, eth_dev->nd->name);
+
+		return rc;
+	}
+
+	ipa_eth_dev_dbg(eth_dev,
+		"Bus probe is unsupported by the offload driver %s",
+		od->name);
+
+	return -ENOTSUPP;
+}
+
+int ipa_eth_offload_pair_device(struct ipa_eth_device *eth_dev)
+{
+	struct ipa_eth_offload_driver *od;
+
+	if (ipa_eth_offload_device_paired(eth_dev))
+		return 0;
+
+	list_for_each_entry(od, &ipa_eth_offload_drivers, driver_list) {
+		if (!try_pair_device(eth_dev, od))
+			return 0;
+	}
+
+	return -ENODEV;
+}
+
+void ipa_eth_offload_unpair_device(struct ipa_eth_device *eth_dev)
+{
+	struct ipa_eth_offload_driver *od = eth_dev->od;
+
+	if (!ipa_eth_offload_device_paired(eth_dev))
+		return;
+
+	eth_dev->od = NULL;
+
+	if (od->bus_ops->remove)
+		od->bus_ops->remove(eth_dev);
+	else
+		ipa_eth_dev_dbg(eth_dev,
+			"Bus remove is unsupported by the offload driver %s",
+			od->name);
+}
+
+int ipa_eth_offload_register_driver(struct ipa_eth_offload_driver *od)
+{
+	if (!od->bus) {
+		ipa_eth_err("Bus info missing for offload driver %s", od->name);
+		return -EINVAL;
+	}
+
+	if (!od->debugfs && ipa_eth_offload_debugfs) {
+		od->debugfs =
+			debugfs_create_dir(od->name, ipa_eth_offload_debugfs);
+		if (IS_ERR_OR_NULL(od->debugfs)) {
+			int rc = od->debugfs ? PTR_ERR(od->debugfs) : -EFAULT;
+
+			od->debugfs = NULL;
+			return rc;
+		}
+	}
+
+	mutex_lock(&ipa_eth_offload_drivers_lock);
+	list_add(&od->driver_list, &ipa_eth_offload_drivers);
+	mutex_unlock(&ipa_eth_offload_drivers_lock);
+
+	return 0;
+}
+
+void ipa_eth_offload_unregister_driver(struct ipa_eth_offload_driver *od)
+{
+	mutex_lock(&ipa_eth_offload_drivers_lock);
+	list_del(&od->driver_list);
+	mutex_unlock(&ipa_eth_offload_drivers_lock);
+}
+
+int ipa_eth_offload_modinit(struct dentry *dbgfs_root)
+{
+	return ipa_eth_offload_debugfs_init(dbgfs_root);
+}
+
+void ipa_eth_offload_modexit(void)
+{
+	ipa_eth_offload_debugfs_cleanup();
+}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pci.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pci.c
new file mode 100644
index 0000000..88a94ee
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pci.c
@@ -0,0 +1,257 @@
+/* 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/list.h>
+#include <linux/mutex.h>
+#include <linux/debugfs.h>
+
+#include <linux/pci.h>
+
+#include "ipa_eth_i.h"
+
+struct ipa_eth_pci_driver {
+	struct list_head driver_list;
+
+	struct ipa_eth_net_driver *nd;
+
+	int (*probe_real)(struct pci_dev *dev, const struct pci_device_id *id);
+	void (*remove_real)(struct pci_dev *dev);
+};
+
+static LIST_HEAD(pci_drivers);
+static DEFINE_MUTEX(pci_drivers_mutex);
+
+static LIST_HEAD(pci_devices);
+static DEFINE_MUTEX(pci_devices_mutex);
+
+static struct dentry *ipa_eth_pci_debugfs;
+
+static bool ipa_eth_pci_is_ready;
+
+static void ipa_eth_pci_debugfs_cleanup(void)
+{
+	debugfs_remove_recursive(ipa_eth_pci_debugfs);
+}
+
+static int ipa_eth_pci_debugfs_init(struct dentry *dbgfs_root)
+{
+	if (!dbgfs_root)
+		return 0;
+
+	ipa_eth_pci_debugfs = debugfs_create_dir("pci", dbgfs_root);
+	if (IS_ERR_OR_NULL(ipa_eth_pci_debugfs)) {
+		int rc = ipa_eth_pci_debugfs ?
+			PTR_ERR(ipa_eth_pci_debugfs) : -EFAULT;
+
+		ipa_eth_pci_debugfs = NULL;
+		return rc;
+	}
+
+	return 0;
+}
+
+static struct ipa_eth_pci_driver *__lookup_driver(struct pci_driver *pci_drv)
+{
+	struct ipa_eth_pci_driver *epci_drv;
+
+	list_for_each_entry(epci_drv, &pci_drivers, driver_list) {
+		if (epci_drv->nd->driver == &pci_drv->driver)
+			return epci_drv;
+	}
+
+	return NULL;
+}
+
+static struct ipa_eth_pci_driver *lookup_epci_driver(struct pci_driver *pci_drv)
+{
+	struct ipa_eth_pci_driver *epci_drv;
+
+	mutex_lock(&pci_drivers_mutex);
+	epci_drv = __lookup_driver(pci_drv);
+	mutex_unlock(&pci_drivers_mutex);
+
+	return epci_drv;
+}
+
+static struct ipa_eth_device *__lookup_eth_dev(struct pci_dev *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ipa_eth_device *eth_dev;
+
+	list_for_each_entry(eth_dev, &pci_devices, bus_device_list) {
+		if (eth_dev->dev == dev)
+			return eth_dev;
+	}
+
+	return NULL;
+}
+
+static struct ipa_eth_device *lookup_eth_dev(struct pci_dev *pdev)
+{
+	struct ipa_eth_device *eth_dev;
+
+	mutex_lock(&pci_devices_mutex);
+	eth_dev = __lookup_eth_dev(pdev);
+	mutex_unlock(&pci_devices_mutex);
+
+	return eth_dev;
+}
+
+static int ipa_eth_pci_probe_handler(struct pci_dev *pdev,
+				     const struct pci_device_id *id)
+{
+	int rc = 0;
+	struct device *dev = &pdev->dev;
+	struct ipa_eth_device *eth_dev;
+	struct ipa_eth_pci_driver *epci_drv;
+
+	ipa_eth_dbg("PCI probe called for %s driver with devfn %u",
+		    pdev->driver->name, pdev->devfn);
+
+	epci_drv = lookup_epci_driver(pdev->driver);
+
+	rc = epci_drv->probe_real(pdev, id);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed real PCI probe of devfn=%u");
+		goto err_probe;
+	}
+
+	eth_dev = devm_kzalloc(dev, sizeof(*eth_dev), GFP_KERNEL);
+	if (!eth_dev) {
+		rc = -ENOMEM;
+		goto err_alloc;
+	}
+
+	eth_dev->dev = dev;
+	eth_dev->nd = epci_drv->nd;
+	eth_dev->bus_priv = epci_drv;
+
+	rc = ipa_eth_register_device(eth_dev);
+	if (rc) {
+		ipa_eth_dev_err(eth_dev, "Failed to register PCI devfn=%u");
+		goto err_register;
+	}
+
+	mutex_lock(&pci_devices_mutex);
+	list_add(&eth_dev->bus_device_list, &pci_devices);
+	mutex_unlock(&pci_devices_mutex);
+
+	return 0;
+
+err_register:
+	devm_kfree(dev, eth_dev);
+err_alloc:
+	epci_drv->remove_real(pdev);
+err_probe:
+	return rc;
+}
+
+static void ipa_eth_pci_remove_handler(struct pci_dev *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ipa_eth_device *eth_dev = NULL;
+	struct ipa_eth_pci_driver *epci_drv = NULL;
+
+	ipa_eth_dbg("PCI remove called for %s driver with devfn %u",
+		    pdev->driver->name, pdev->devfn);
+
+	eth_dev = lookup_eth_dev(pdev);
+
+	mutex_lock(&pci_devices_mutex);
+	list_del(&eth_dev->bus_device_list);
+	mutex_unlock(&pci_devices_mutex);
+
+	ipa_eth_unregister_device(eth_dev);
+
+	epci_drv = eth_dev->bus_priv;
+	epci_drv->remove_real(pdev);
+
+	devm_kfree(dev, eth_dev);
+}
+
+static int ipa_eth_pci_register_net_driver(struct ipa_eth_net_driver *nd)
+{
+	struct ipa_eth_pci_driver *epci_drv = NULL;
+	struct pci_driver *pci_drv = container_of(nd->driver,
+		struct pci_driver, driver);
+
+	if (WARN_ON(!pci_drv->probe || !pci_drv->remove)) {
+		ipa_eth_err("PCI driver lacking probe/remove callbacks");
+		return -EFAULT;
+	}
+
+	epci_drv = kzalloc(sizeof(*epci_drv), GFP_KERNEL);
+	if (!epci_drv)
+		return -ENOMEM;
+
+	epci_drv->probe_real = pci_drv->probe;
+	pci_drv->probe = ipa_eth_pci_probe_handler;
+
+	epci_drv->remove_real = pci_drv->remove;
+	pci_drv->remove = ipa_eth_pci_remove_handler;
+
+	epci_drv->nd = nd;
+
+	mutex_lock(&pci_drivers_mutex);
+	list_add(&epci_drv->driver_list, &pci_drivers);
+	mutex_unlock(&pci_drivers_mutex);
+
+	return 0;
+
+}
+
+static void ipa_eth_pci_unregister_net_driver(struct ipa_eth_net_driver *nd)
+{
+	struct pci_driver *pci_drv = container_of(nd->driver,
+		struct pci_driver, driver);
+	struct ipa_eth_pci_driver *epci_drv = lookup_epci_driver(pci_drv);
+
+	mutex_lock(&pci_drivers_mutex);
+	list_del(&epci_drv->driver_list);
+	mutex_unlock(&pci_drivers_mutex);
+
+	pci_drv->probe = epci_drv->probe_real;
+	pci_drv->remove = epci_drv->remove_real;
+
+	kfree(epci_drv);
+}
+
+struct ipa_eth_bus ipa_eth_pci_bus = {
+	.bus = &pci_bus_type,
+	.register_net_driver = ipa_eth_pci_register_net_driver,
+	.unregister_net_driver = ipa_eth_pci_unregister_net_driver,
+};
+
+int ipa_eth_pci_modinit(struct dentry *dbgfs_root)
+{
+	int rc;
+
+	rc = ipa_eth_pci_debugfs_init(dbgfs_root);
+	if (rc) {
+		ipa_eth_err("Unable to create debugfs root for pci bus");
+		return rc;
+	}
+
+	ipa_eth_pci_is_ready = true;
+
+	return 0;
+}
+
+void ipa_eth_pci_modexit(void)
+{
+	if (!ipa_eth_pci_is_ready)
+		return;
+
+	ipa_eth_pci_is_ready = false;
+
+	ipa_eth_pci_debugfs_cleanup();
+}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pm.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pm.c
new file mode 100644
index 0000000..633b41f
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pm.c
@@ -0,0 +1,101 @@
+/* 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 "ipa_eth_i.h"
+
+#define IPA_ETH_MIN_BW_MBPS 1
+
+static void ipa_eth_pm_callback(void *arg, enum ipa_pm_cb_event event)
+{
+	struct ipa_eth_device *eth_dev = (struct ipa_eth_device *)arg;
+
+	ipa_eth_dev_log(eth_dev, "Received PM event 0x%x", event);
+}
+
+/**
+ * ipa_eth_pm_register() - Register offload device with IPA PM
+ * @eth_dev: Offload device to register with PM
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_pm_register(struct ipa_eth_device *eth_dev)
+{
+	int rc = 0;
+	char name[IPA_PM_MAX_EX_CL];
+	struct ipa_pm_register_params pm_params;
+
+	if (!ipa_pm_is_used())
+		return 0;
+
+	if (eth_dev->pm_handle != IPA_PM_MAX_CLIENTS)
+		return -EEXIST;
+
+	snprintf(name, sizeof(name), IPA_ETH_SUBSYS ":%s",
+		 eth_dev->net_dev->name);
+
+	memset(&pm_params, 0, sizeof(pm_params));
+	pm_params.name = name;
+	pm_params.callback = ipa_eth_pm_callback;
+	pm_params.user_data = eth_dev;
+	pm_params.group = IPA_PM_GROUP_DEFAULT;
+	pm_params.skip_clk_vote = false;
+
+	rc = ipa_pm_register(&pm_params, &eth_dev->pm_handle);
+	if (rc)
+		eth_dev->pm_handle = IPA_PM_MAX_CLIENTS;
+
+	return rc;
+}
+
+/**
+ * ipa_eth_pm_unregister() - Unregister offload device from IPA PM
+ * @eth_dev: Offload device to unregister
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_pm_unregister(struct ipa_eth_device *eth_dev)
+{
+	int rc = 0;
+
+	if (!ipa_pm_is_used())
+		return 0;
+
+	rc = ipa_pm_deregister(eth_dev->pm_handle);
+	if (!rc)
+		eth_dev->pm_handle = IPA_PM_MAX_CLIENTS;
+
+	return rc;
+}
+
+int ipa_eth_pm_activate(struct ipa_eth_device *eth_dev)
+{
+	if (!ipa_pm_is_used())
+		return 0;
+
+	return ipa_pm_activate_sync(eth_dev->pm_handle);
+}
+
+int ipa_eth_pm_deactivate(struct ipa_eth_device *eth_dev)
+{
+	if (!ipa_pm_is_used())
+		return 0;
+
+	return ipa_pm_deactivate_sync(eth_dev->pm_handle);
+}
+
+int ipa_eth_pm_vote_bw(struct ipa_eth_device *eth_dev)
+{
+	if (!ipa_pm_is_used())
+		return 0;
+
+	return ipa_pm_set_throughput(eth_dev->pm_handle, IPA_ETH_MIN_BW_MBPS);
+}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_uc.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_uc.c
new file mode 100644
index 0000000..dc83818
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_uc.c
@@ -0,0 +1,141 @@
+/* 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 "../ipa_i.h"
+#include "../ipa_uc_offload_i.h"
+
+#include "ipa_eth_i.h"
+
+#define IPA_ETH_UC_RESPONSE_SUCCESS \
+	FEATURE_ENUM_VAL(IPA_HW_FEATURE_OFFLOAD, IPA_ETH_UC_RSP_SUCCESS)
+
+struct ipa_eth_uc_cmd_param {
+	u32 protocol;
+	u8 protocol_data[];
+} __packed;
+
+struct ipa_eth_uc_cmd_param_mem {
+	struct ipa_eth_uc_cmd_param *param;
+	dma_addr_t dma_addr;
+	size_t size;
+};
+
+struct ipa_eth_uc_cmd_ctx {
+	u8 cmd_op;
+	u32 protocol;
+	const void *protocol_data;
+	size_t data_size;
+
+	struct ipa_eth_uc_cmd_param_mem pmem;
+};
+
+static int ipa_eth_uc_init_cmd_ctx(struct ipa_eth_uc_cmd_ctx *cmd_ctx,
+				   enum ipa_eth_uc_op op, u32 protocol,
+				   const void *prot_data, size_t datasz)
+{
+	struct ipa_eth_uc_cmd_param_mem *pmem = &cmd_ctx->pmem;
+
+	if (op == IPA_ETH_UC_OP_NOP || op >= IPA_ETH_UC_OP_MAX) {
+		ipa_eth_err("Invalid uC op code");
+		return -EINVAL;
+	}
+
+	cmd_ctx->cmd_op = FEATURE_ENUM_VAL(IPA_HW_FEATURE_OFFLOAD, op);
+	cmd_ctx->protocol = protocol;
+	cmd_ctx->protocol_data = prot_data;
+	cmd_ctx->data_size = datasz;
+
+	pmem->size = sizeof(*pmem->param) + datasz;
+	pmem->param = dma_alloc_coherent(ipa3_ctx->uc_pdev, pmem->size,
+				&pmem->dma_addr, GFP_KERNEL);
+	if (!pmem->param) {
+		ipa_eth_err("Failed to alloc uC command DMA buffer of size %u",
+			    pmem->size);
+		return -ENOMEM;
+	}
+
+	pmem->param->protocol = protocol;
+	memcpy(pmem->param->protocol_data, prot_data, datasz);
+
+	return 0;
+}
+
+static void ipa_eth_uc_deinit_cmd_ctx(struct ipa_eth_uc_cmd_ctx *cmd_ctx)
+{
+	struct ipa_eth_uc_cmd_param_mem *pmem = &cmd_ctx->pmem;
+
+	dma_free_coherent(ipa3_ctx->uc_pdev, pmem->size,
+		pmem->param, pmem->dma_addr);
+}
+
+/**
+ * ipa_eth_uc_send_cmd() - Send an offload command to IPA uC
+ * @op: uC offload op code
+ * @protocol: uC offload protocol value
+ * @prot_data: uC offload command data, specific to the protocol
+ * @datasz: size of command data
+ *
+ * Return: 0 on success, negative errno otherwise
+ */
+int ipa_eth_uc_send_cmd(enum ipa_eth_uc_op op, u32 protocol,
+			const void *prot_data, size_t datasz)
+{
+	int rc = 0;
+	struct ipa_eth_uc_cmd_ctx cmd_ctx;
+
+	rc = ipa_eth_uc_init_cmd_ctx(&cmd_ctx, op, protocol, prot_data, datasz);
+	if (rc) {
+		ipa_eth_err("Failed to init command context for op=%u", op);
+		return rc;
+	}
+
+	ipa_eth_log("Sending uC command, op=%u, prot=%u, data size=%u",
+		    cmd_ctx.cmd_op, cmd_ctx.protocol, cmd_ctx.data_size);
+
+	rc = ipa3_uc_send_cmd((u32)cmd_ctx.pmem.dma_addr, cmd_ctx.cmd_op,
+			IPA_ETH_UC_RESPONSE_SUCCESS, false, 10*HZ);
+
+	ipa_eth_uc_deinit_cmd_ctx(&cmd_ctx);
+
+	return rc;
+}
+EXPORT_SYMBOL(ipa_eth_uc_send_cmd);
+
+static int ipa_eth_uc_iommu_map(dma_addr_t daddr, void *addr, bool is_va,
+	size_t size, int prot, bool split)
+{
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
+
+	if (!cb->valid) {
+		ipa_eth_err("SMMU CB not valid for uC");
+		return -EFAULT;
+	}
+
+	return ipa_eth_iommu_map(cb->mapping->domain, daddr, addr, is_va,
+				 size, prot, split);
+}
+
+int ipa_eth_uc_iommu_pamap(dma_addr_t daddr, phys_addr_t paddr,
+	size_t size, int prot, bool split)
+{
+	return ipa_eth_uc_iommu_map(daddr, (void *)paddr, false, size,
+				    prot, split);
+}
+EXPORT_SYMBOL(ipa_eth_uc_iommu_pamap);
+
+int ipa_eth_uc_iommu_vamap(dma_addr_t daddr, void *vaddr,
+	size_t size, int prot, bool split)
+{
+	return ipa_eth_uc_iommu_map(daddr, vaddr, true, size,
+				    prot, split);
+}
+EXPORT_SYMBOL(ipa_eth_uc_iommu_vamap);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 4c4c617..0fe3d2c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -269,6 +269,7 @@ static struct notifier_block ipa3_active_clients_panic_blk = {
 	.notifier_call  = ipa3_active_clients_panic_notifier,
 };
 
+#ifdef CONFIG_IPA_DEBUG
 static int ipa3_active_clients_log_insert(const char *string)
 {
 	int head;
@@ -293,6 +294,7 @@ static int ipa3_active_clients_log_insert(const char *string)
 
 	return 0;
 }
+#endif
 
 static int ipa3_active_clients_log_init(void)
 {
@@ -2632,6 +2634,19 @@ static int ipa3_q6_set_ex_path_to_apps(void)
 	return retval;
 }
 
+/*
+ * ipa3_update_ssr_state() - updating current SSR state
+ * @is_ssr:	[in] Current SSR state
+ */
+
+void ipa3_update_ssr_state(bool is_ssr)
+{
+	if (is_ssr)
+		atomic_set(&ipa3_ctx->is_ssr, 1);
+	else
+		atomic_set(&ipa3_ctx->is_ssr, 0);
+}
+
 /**
  * ipa3_q6_pre_shutdown_cleanup() - A cleanup for all Q6 related configuration
  *                    in IPA HW. This is performed in case of SSR.
@@ -2645,7 +2660,9 @@ void ipa3_q6_pre_shutdown_cleanup(void)
 
 	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 
-	ipa3_q6_pipe_delay(true);
+	ipa3_update_ssr_state(true);
+	if (!ipa3_ctx->ipa_endp_delay_wa)
+		ipa3_q6_pipe_delay(true);
 	ipa3_q6_avoid_holb();
 	if (ipa3_ctx->ipa_config_is_mhi)
 		ipa3_set_reset_client_cons_pipe_sus_holb(true,
@@ -2669,12 +2686,14 @@ void ipa3_q6_pre_shutdown_cleanup(void)
 	/* Remove delay from Q6 PRODs to avoid pending descriptors
 	 * on pipe reset procedure
 	 */
-	ipa3_q6_pipe_delay(false);
-	ipa3_set_reset_client_prod_pipe_delay(true,
-		IPA_CLIENT_USB_PROD);
-	if (ipa3_ctx->ipa_config_is_mhi)
+	if (!ipa3_ctx->ipa_endp_delay_wa) {
+		ipa3_q6_pipe_delay(false);
 		ipa3_set_reset_client_prod_pipe_delay(true,
-		IPA_CLIENT_MHI_PROD);
+			IPA_CLIENT_USB_PROD);
+	} else {
+		ipa3_start_stop_client_prod_gsi_chnl(IPA_CLIENT_USB_PROD,
+						false);
+	}
 
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 	IPADBG_LOW("Exit with success\n");
@@ -2737,6 +2756,47 @@ void ipa3_q6_post_shutdown_cleanup(void)
 	IPADBG_LOW("Exit with success\n");
 }
 
+/**
+ * ipa3_q6_pre_powerup_cleanup() - A cleanup routine for pheripheral
+ * configuration in IPA HW. This is performed in case of SSR.
+ *
+ * This is a mandatory procedure, in case one of the steps fails, the
+ * AP needs to restart.
+ */
+void ipa3_q6_pre_powerup_cleanup(void)
+{
+	IPADBG_LOW("ENTER\n");
+
+	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
+
+	if (ipa3_ctx->ipa_config_is_mhi)
+		ipa3_set_reset_client_prod_pipe_delay(true,
+			IPA_CLIENT_MHI_PROD);
+
+	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+	IPADBG_LOW("Exit with success\n");
+}
+
+/*
+ * ipa3_client_prod_post_shutdown_cleanup () - As part of this function
+ * set end point delay client producer pipes and starting corresponding
+ * gsi channels
+ */
+
+void ipa3_client_prod_post_shutdown_cleanup(void)
+{
+	IPADBG_LOW("ENTER\n");
+
+	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
+
+	ipa3_set_reset_client_prod_pipe_delay(true,
+				IPA_CLIENT_USB_PROD);
+	ipa3_start_stop_client_prod_gsi_chnl(IPA_CLIENT_USB_PROD, true);
+
+	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+	IPADBG_LOW("Exit with success\n");
+}
+
 static inline void ipa3_sram_set_canary(u32 *sram_mmio, int offset)
 {
 	/* Set 4 bytes of CANARY before the offset */
@@ -3784,7 +3844,9 @@ static void ipa3_start_tag_process(struct work_struct *work)
  * - Remove and deallocate unneeded data structure
  * - Log the call in the circular history buffer (unless it is a simple call)
  */
-void ipa3_active_clients_log_mod(struct ipa_active_client_logging_info *id,
+#ifdef CONFIG_IPA_DEBUG
+static void ipa3_active_clients_log_mod(
+		struct ipa_active_client_logging_info *id,
 		bool inc, bool int_ctx)
 {
 	char temp_str[IPA3_ACTIVE_CLIENTS_LOG_LINE_LEN];
@@ -3846,6 +3908,13 @@ void ipa3_active_clients_log_mod(struct ipa_active_client_logging_info *id,
 	spin_unlock_irqrestore(&ipa3_ctx->ipa3_active_clients_logging.lock,
 		flags);
 }
+#else
+static void ipa3_active_clients_log_mod(
+		struct ipa_active_client_logging_info *id,
+		bool inc, bool int_ctx)
+{
+}
+#endif
 
 void ipa3_active_clients_log_dec(struct ipa_active_client_logging_info *id,
 		bool int_ctx)
@@ -3895,7 +3964,7 @@ void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id)
 		atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));
 	ipa3_suspend_apps_pipes(false);
 	if (!ipa3_uc_state_check() &&
-		(ipa3_ctx->ipa_hw_type >= IPA_HW_v4_1)) {
+		(ipa3_ctx->ipa_hw_type == IPA_HW_v4_1)) {
 		ipa3_read_mailbox_17(IPA_PC_RESTORE_CONTEXT_STATUS_SUCCESS);
 		/* assert if intset = 0 */
 		if (ipa3_ctx->gsi_chk_intset_value == 0) {
@@ -4503,7 +4572,7 @@ static int ipa3_panic_notifier(struct notifier_block *this,
 	if (res)
 		IPAERR("uC panic handler failed %d\n", res);
 
-	if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) != 0) {
+	if (atomic_read(&ipa3_ctx->ipa_clk_vote)) {
 		ipahal_print_all_regs(false);
 		ipa_save_registers();
 	}
@@ -4676,6 +4745,9 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
 	if (ipa3_ctx->ipa_hw_type != IPA_HW_v4_0)
 		ipa3_proxy_clk_vote();
 
+	/* The following will retrieve and save the gsi fw version */
+	ipa_save_gsi_ver();
+
 	/*
 	 * In Virtual and Emulation mode, IPAHAL initialized at
 	 * pre_init as there is no SMMU. In normal mode need to wait
@@ -5270,6 +5342,32 @@ static int ipa3_alloc_pkt_init(void)
 	return 0;
 }
 
+/*
+ * SCM call to check if secure dump is allowed.
+ *
+ * Returns true in secure dump allowed.
+ * Return false when secure dump not allowed.
+ */
+#define TZ_UTIL_GET_SEC_DUMP_STATE  0x10
+static bool ipa_is_mem_dump_allowed(void)
+{
+	struct scm_desc desc = {0};
+	int ret = 0;
+
+	desc.args[0] = 0;
+	desc.arginfo = 0;
+
+	ret = scm_call2(
+		SCM_SIP_FNID(SCM_SVC_UTIL, TZ_UTIL_GET_SEC_DUMP_STATE),
+		&desc);
+	if (ret) {
+		IPAERR("SCM DUMP_STATE call failed\n");
+		return false;
+	}
+
+	return (desc.ret[0] == 1);
+}
+
 /**
  * ipa3_pre_init() - Initialize the IPA Driver.
  * This part contains all initialization which doesn't require IPA HW, such
@@ -5361,6 +5459,31 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 	    resource_p->do_testbus_collection_on_crash;
 	ipa3_ctx->do_non_tn_collection_on_crash =
 	    resource_p->do_non_tn_collection_on_crash;
+	ipa3_ctx->ipa_endp_delay_wa = resource_p->ipa_endp_delay_wa;
+	ipa3_ctx->secure_debug_check_action =
+	    resource_p->secure_debug_check_action;
+
+	if (ipa3_ctx->secure_debug_check_action == USE_SCM) {
+		if (ipa_is_mem_dump_allowed())
+			ipa3_ctx->sd_state = SD_ENABLED;
+		else
+			ipa3_ctx->sd_state = SD_DISABLED;
+	} else {
+		if (ipa3_ctx->secure_debug_check_action == OVERRIDE_SCM_TRUE)
+			ipa3_ctx->sd_state = SD_ENABLED;
+		else
+			/* secure_debug_check_action == OVERRIDE_SCM_FALSE */
+			ipa3_ctx->sd_state = SD_DISABLED;
+	}
+
+	if (ipa3_ctx->sd_state == SD_ENABLED) {
+		/* secure debug is enabled. */
+		IPADBG("secure debug enabled\n");
+	} else {
+		/* secure debug is disabled. */
+		IPADBG("secure debug disabled\n");
+		ipa3_ctx->do_testbus_collection_on_crash = false;
+	}
 
 	WARN(ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL,
 		"Non NORMAL IPA HW mode, is this emulation platform ?");
@@ -5482,7 +5605,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 	/*
 	 * Setup access for register collection/dump on crash
 	 */
-	if (ipa_reg_save_init(0xFF) != 0) {
+	if (ipa_reg_save_init(IPA_MEM_INIT_VAL) != 0) {
 		result = -EFAULT;
 		goto fail_gsi_map;
 	}
@@ -5724,6 +5847,13 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 		goto fail_ipa_dma_setup;
 	}
 
+	result = ipa_eth_init();
+	if (result) {
+		IPAERR("Failed to initialize Ethernet Offload Subsystem\n");
+		result = -ENODEV;
+		goto fail_eth_init;
+	}
+
 	/*
 	 * We can't register the GSI driver yet, as it expects
 	 * the GSI FW to be up and running before the registration.
@@ -5778,6 +5908,8 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 	return 0;
 fail_cdev_add:
 fail_gsi_pre_fw_load_init:
+	ipa_eth_exit();
+fail_eth_init:
 	ipa3_dma_shutdown();
 fail_ipa_dma_setup:
 	if (ipa3_ctx->use_ipa_pm)
@@ -5978,6 +6110,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
 	ipa_drv_res->mhi_evid_limits[0] = IPA_MHI_GSI_EVENT_RING_ID_START;
 	ipa_drv_res->mhi_evid_limits[1] = IPA_MHI_GSI_EVENT_RING_ID_END;
 	ipa_drv_res->ipa_fltrt_not_hashable = false;
+	ipa_drv_res->ipa_endp_delay_wa = false;
 
 	/* Get IPA HW Version */
 	result = of_property_read_u32(pdev->dev.of_node, "qcom,ipa-hw-ver",
@@ -6063,6 +6196,12 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
 	IPADBG(": WDI-2.0 over gsi= %s\n",
 			ipa_drv_res->ipa_wdi2_over_gsi
 			? "True" : "False");
+	ipa_drv_res->ipa_endp_delay_wa =
+			of_property_read_bool(pdev->dev.of_node,
+			"qcom,ipa-endp-delay-wa");
+	IPADBG(": endppoint delay wa = %s\n",
+			ipa_drv_res->ipa_endp_delay_wa
+			? "True" : "False");
 
 	ipa_drv_res->ipa_wdi3_over_gsi =
 			of_property_read_bool(pdev->dev.of_node,
@@ -6341,6 +6480,19 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
 	IPADBG(": doing register collection on crash = %s\n",
 	       ipa_drv_res->do_register_collection_on_crash ? "True":"False");
 
+	result = of_property_read_u32(
+		pdev->dev.of_node,
+		"qcom,secure-debug-check-action",
+		&ipa_drv_res->secure_debug_check_action);
+	if (result ||
+		(ipa_drv_res->secure_debug_check_action != 0 &&
+		 ipa_drv_res->secure_debug_check_action != 1 &&
+		 ipa_drv_res->secure_debug_check_action != 2))
+		ipa_drv_res->secure_debug_check_action = USE_SCM;
+
+	IPADBG(": secure-debug-check-action = %d\n",
+		   ipa_drv_res->secure_debug_check_action);
+
 	return 0;
 }
 
@@ -6768,6 +6920,7 @@ static int ipa_smmu_ap_cb_probe(struct device *dev)
 
 	smmu_info.present[IPA_SMMU_CB_AP] = true;
 	ipa3_ctx->pdev = dev;
+	cb->next_addr = cb->va_end;
 
 	return 0;
 }
@@ -7167,8 +7320,18 @@ int ipa3_get_smmu_params(struct ipa_smmu_in_params *in,
 
 	switch (in->smmu_client) {
 	case IPA_SMMU_WLAN_CLIENT:
-		is_smmu_enable = !(ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_UC] |
-			ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_WLAN]);
+		if (ipa3_ctx->ipa_wdi3_over_gsi)
+			is_smmu_enable =
+				!(ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_AP] |
+				ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_WLAN]);
+		else
+			is_smmu_enable =
+				!(ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_UC] |
+				ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_WLAN]);
+		break;
+	case IPA_SMMU_AP_CLIENT:
+		is_smmu_enable =
+			!(ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_AP]);
 		break;
 	default:
 		is_smmu_enable = 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index 7d2e947..ba7acc0 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -373,66 +373,86 @@ int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt,
 	return 0;
 }
 
-void ipa3_register_lock_unlock_callback(int (*client_cb)(bool is_lock),
-						u32 ipa_ep_idx)
+static enum ipa_client_cb_type ipa_get_client_cb_type(
+					enum ipa_client_type client_type)
 {
-	struct ipa3_ep_context *ep;
+	enum ipa_client_cb_type client_cb;
+
+	if (client_type == IPA_CLIENT_USB_PROD ||
+			client_type == IPA_CLIENT_USB_CONS) {
+		IPADBG("USB Client registered\n");
+		client_cb = IPA_USB_CLNT;
+	} else if (client_type == IPA_CLIENT_MHI_PROD ||
+			client_type == IPA_CLIENT_MHI_CONS) {
+		IPADBG("MHI Client registered\n");
+		client_cb = IPA_MHI_CLNT;
+	} else {
+		IPAERR("Invalid IPA client\n");
+		client_cb = IPA_MAX_CLNT;
+	}
+
+	return client_cb;
+}
+void ipa3_register_client_callback(int (*client_cb)(bool is_lock),
+				bool (*teth_port_state)(void), u32 ipa_ep_idx)
+{
+	enum ipa_client_cb_type client;
+	enum ipa_client_type client_type;
 
 	IPADBG("entry\n");
 
-	ep = &ipa3_ctx->ep[ipa_ep_idx];
-
-	if (!ep->valid) {
-		IPAERR("Invalid EP\n");
+	client_type = ipa3_get_client_by_pipe(ipa_ep_idx);
+	client = ipa_get_client_cb_type(client_type);
+	if (client == IPA_MAX_CLNT)
 		return;
-	}
 
 	if (client_cb == NULL) {
 		IPAERR("Bad Param");
 		return;
 	}
 
-	ep->client_lock_unlock = client_cb;
+	if (!ipa3_ctx->client_lock_unlock[client])
+		ipa3_ctx->client_lock_unlock[client] = client_cb;
+	if (!ipa3_ctx->get_teth_port_state[client])
+		ipa3_ctx->get_teth_port_state[client] = teth_port_state;
 	IPADBG("exit\n");
 }
 
-void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx)
+void ipa3_deregister_client_callback(u32 ipa_ep_idx)
 {
-	struct ipa3_ep_context *ep;
+	enum ipa_client_cb_type client_cb;
+	enum ipa_client_type client_type;
 
 	IPADBG("entry\n");
 
-	ep = &ipa3_ctx->ep[ipa_ep_idx];
-
-	if (!ep->valid) {
-		IPAERR("Invalid EP\n");
+	client_type = ipa3_get_client_by_pipe(ipa_ep_idx);
+	client_cb = ipa_get_client_cb_type(client_type);
+	if (client_cb == IPA_MAX_CLNT)
 		return;
-	}
 
-	if (ep->client_lock_unlock == NULL) {
+	if (ipa3_ctx->client_lock_unlock[client_cb] == NULL &&
+		ipa3_ctx->get_teth_port_state[client_cb] == NULL) {
 		IPAERR("client_lock_unlock is already NULL");
 		return;
 	}
 
-	ep->client_lock_unlock = NULL;
+	ipa3_ctx->client_lock_unlock[client_cb] = NULL;
+	ipa3_ctx->get_teth_port_state[client_cb] = NULL;
 	IPADBG("exit\n");
 }
 
-static void client_lock_unlock_cb(u32 ipa_ep_idx, bool is_lock)
+static void client_lock_unlock_cb(enum ipa_client_type client, bool is_lock)
 {
-	struct ipa3_ep_context *ep;
+	enum ipa_client_cb_type client_cb;
 
 	IPADBG("entry\n");
 
-	ep = &ipa3_ctx->ep[ipa_ep_idx];
-
-	if (!ep->valid) {
-		IPAERR("Invalid EP\n");
+	client_cb = ipa_get_client_cb_type(client);
+	if (client_cb == IPA_MAX_CLNT)
 		return;
-	}
 
-	if (ep->client_lock_unlock)
-		ep->client_lock_unlock(is_lock);
+	if (ipa3_ctx->client_lock_unlock[client_cb])
+		ipa3_ctx->client_lock_unlock[client_cb](is_lock);
 
 	IPADBG("exit\n");
 }
@@ -750,7 +770,7 @@ int ipa3_xdci_start(u32 clnt_hdl, u8 xferrscidx, bool xferrscidx_valid)
 	return result;
 }
 
-static int ipa3_get_gsi_chan_info(struct gsi_chan_info *gsi_chan_info,
+int ipa3_get_gsi_chan_info(struct gsi_chan_info *gsi_chan_info,
 	unsigned long chan_hdl)
 {
 	enum gsi_status gsi_res;
@@ -1112,7 +1132,7 @@ int ipa3_set_reset_client_prod_pipe_delay(bool set_reset,
 	ep = &ipa3_ctx->ep[pipe_idx];
 
 	/* Setting delay on USB_PROD with skip_ep_cfg */
-	client_lock_unlock_cb(pipe_idx, true);
+	client_lock_unlock_cb(client, true);
 	if (ep->valid && ep->skip_ep_cfg) {
 		ep->ep_delay_set = ep_ctrl.ipa_ep_delay;
 		result = ipa3_cfg_ep_ctrl(pipe_idx, &ep_ctrl);
@@ -1122,10 +1142,56 @@ int ipa3_set_reset_client_prod_pipe_delay(bool set_reset,
 		else
 			IPADBG("client (ep: %d) success\n", pipe_idx);
 	}
-	client_lock_unlock_cb(pipe_idx, false);
+	client_lock_unlock_cb(client, false);
 	return result;
 }
 
+static bool ipa3_get_teth_port_status(enum ipa_client_type client)
+{
+	enum ipa_client_cb_type client_cb;
+
+	client_cb = ipa_get_client_cb_type(client);
+	if (client_cb == IPA_MAX_CLNT)
+		return false;
+	if (ipa3_ctx->get_teth_port_state[client_cb])
+		return ipa3_ctx->get_teth_port_state[client_cb]();
+	return false;
+}
+
+/*
+ * Start/stop the CLIENT PROD pipes in SSR scenarios
+ */
+
+int ipa3_start_stop_client_prod_gsi_chnl(enum ipa_client_type client,
+		bool start_chnl)
+{
+	int result = 0;
+	int pipe_idx;
+	struct ipa3_ep_context *ep;
+
+	if (IPA_CLIENT_IS_CONS(client)) {
+		IPAERR("client (%d) not PROD\n", client);
+		return -EINVAL;
+	}
+
+	pipe_idx = ipa3_get_ep_mapping(client);
+
+	if (pipe_idx == IPA_EP_NOT_ALLOCATED) {
+		IPAERR("client (%d) not valid\n", client);
+		return -EINVAL;
+	}
+
+	client_lock_unlock_cb(client, true);
+	ep = &ipa3_ctx->ep[pipe_idx];
+	if (ep->valid && ep->skip_ep_cfg && ipa3_get_teth_port_status(client)) {
+		if (start_chnl)
+			result = ipa3_start_gsi_channel(pipe_idx);
+		else
+			result = ipa3_stop_gsi_channel(pipe_idx);
+	}
+	client_lock_unlock_cb(client, false);
+	return result;
+}
 int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset,
 		enum ipa_client_type client)
 {
@@ -1155,7 +1221,7 @@ int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset,
 
 	ep = &ipa3_ctx->ep[pipe_idx];
 	/* Setting sus/holb on MHI_CONS with skip_ep_cfg */
-	client_lock_unlock_cb(pipe_idx, true);
+	client_lock_unlock_cb(client, true);
 	if (ep->valid && ep->skip_ep_cfg) {
 		if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0)
 			ipahal_write_reg_n_fields(
@@ -1174,7 +1240,7 @@ int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset,
 			IPA_ENDP_INIT_HOL_BLOCK_EN_n,
 			pipe_idx, &ep_holb);
 	}
-	client_lock_unlock_cb(pipe_idx, false);
+	client_lock_unlock_cb(client, false);
 	return 0;
 }
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index f09f858..0ba9ca7 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -1584,7 +1584,7 @@ static ssize_t ipa3_read_msg(struct file *file, char __user *ubuf,
 	int cnt = 0;
 	int i;
 
-	for (i = 0; i < IPA_EVENT_MAX_NUM; i++) {
+	for (i = 0; i < ARRAY_SIZE(ipa3_event_name); i++) {
 		nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt,
 				"msg[%u:%27s] W:%u R:%u\n", i,
 				ipa3_event_name[i],
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 649b2f0..6d0a5fb 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -78,6 +78,7 @@
 
 #define IPA_DEFAULT_SYS_YELLOW_WM 32
 #define IPA_REPL_XFER_THRESH 20
+#define IPA_REPL_XFER_MAX 36
 
 #define IPA_TX_SEND_COMPL_NOP_DELAY_NS (2 * 1000 * 1000)
 
@@ -774,7 +775,8 @@ static int ipa3_rx_switch_to_intr_mode(struct ipa3_sys_context *sys)
 	ipa3_dec_release_wakelock();
 	ret = gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
 		GSI_CHAN_MODE_CALLBACK);
-	if (ret != GSI_STATUS_SUCCESS) {
+	if ((ret != GSI_STATUS_SUCCESS) &&
+		!atomic_read(&sys->curr_polling_state)) {
 		if (ret == -GSI_STATUS_PENDING_IRQ) {
 			ipa3_inc_acquire_wakelock();
 			atomic_set(&sys->curr_polling_state, 1);
@@ -2058,7 +2060,7 @@ static void ipa3_replenish_rx_cache(struct ipa3_sys_context *sys)
 	int ret;
 	int idx = 0;
 	int rx_len_cached = 0;
-	struct gsi_xfer_elem gsi_xfer_elem_array[IPA_REPL_XFER_THRESH];
+	struct gsi_xfer_elem gsi_xfer_elem_array[IPA_REPL_XFER_MAX];
 	gfp_t flag = GFP_NOWAIT | __GFP_NOWARN;
 
 	rx_len_cached = sys->len;
@@ -2102,15 +2104,13 @@ static void ipa3_replenish_rx_cache(struct ipa3_sys_context *sys)
 		idx++;
 		rx_len_cached++;
 		/*
-		 * gsi_xfer_elem_buffer has a size of IPA_REPL_XFER_THRESH.
+		 * gsi_xfer_elem_buffer has a size of IPA_REPL_XFER_MAX.
 		 * If this size is reached we need to queue the xfers.
 		 */
-		if (idx == IPA_REPL_XFER_THRESH) {
+		if (idx == IPA_REPL_XFER_MAX) {
 			ret = gsi_queue_xfer(sys->ep->gsi_chan_hdl, idx,
-				gsi_xfer_elem_array, true);
-			if (ret == GSI_STATUS_SUCCESS) {
-				sys->len = rx_len_cached;
-			} else {
+				gsi_xfer_elem_array, false);
+			if (ret != GSI_STATUS_SUCCESS) {
 				/* we don't expect this will happen */
 				IPAERR("failed to provide buffer: %d\n", ret);
 				WARN_ON(1);
@@ -2130,16 +2130,15 @@ static void ipa3_replenish_rx_cache(struct ipa3_sys_context *sys)
 		queue_delayed_work(sys->wq, &sys->replenish_rx_work,
 				msecs_to_jiffies(1));
 done:
-	if (idx) {
-		ret = gsi_queue_xfer(sys->ep->gsi_chan_hdl, idx,
-			gsi_xfer_elem_array, true);
-		if (ret == GSI_STATUS_SUCCESS) {
-			sys->len = rx_len_cached;
-		} else {
-			/* we don't expect this will happen */
-			IPAERR("failed to provide buffer: %d\n", ret);
-			WARN_ON(1);
-		}
+	/* only ring doorbell once here */
+	ret = gsi_queue_xfer(sys->ep->gsi_chan_hdl, idx,
+		gsi_xfer_elem_array, true);
+	if (ret == GSI_STATUS_SUCCESS) {
+		sys->len = rx_len_cached;
+	} else {
+		/* we don't expect this will happen */
+		IPAERR("failed to provide buffer: %d\n", ret);
+		WARN_ON(1);
 	}
 }
 
@@ -2150,7 +2149,7 @@ static void ipa3_replenish_rx_cache_recycle(struct ipa3_sys_context *sys)
 	int ret;
 	int idx = 0;
 	int rx_len_cached = 0;
-	struct gsi_xfer_elem gsi_xfer_elem_array[IPA_REPL_XFER_THRESH];
+	struct gsi_xfer_elem gsi_xfer_elem_array[IPA_REPL_XFER_MAX];
 	gfp_t flag = GFP_NOWAIT | __GFP_NOWARN;
 
 	/* start replenish only when buffers go lower than the threshold */
@@ -2212,15 +2211,13 @@ static void ipa3_replenish_rx_cache_recycle(struct ipa3_sys_context *sys)
 		idx++;
 		rx_len_cached++;
 		/*
-		* gsi_xfer_elem_buffer has a size of IPA_REPL_XFER_THRESH.
+		* gsi_xfer_elem_buffer has a size of IPA_REPL_XFER_MAX.
 		* If this size is reached we need to queue the xfers.
 		*/
-		if (idx == IPA_REPL_XFER_THRESH) {
+		if (idx == IPA_REPL_XFER_MAX) {
 			ret = gsi_queue_xfer(sys->ep->gsi_chan_hdl, idx,
-				gsi_xfer_elem_array, true);
-			if (ret == GSI_STATUS_SUCCESS) {
-				sys->len = rx_len_cached;
-			} else {
+				gsi_xfer_elem_array, false);
+			if (ret != GSI_STATUS_SUCCESS) {
 				/* we don't expect this will happen */
 				IPAERR("failed to provide buffer: %d\n", ret);
 				WARN_ON(1);
@@ -2240,16 +2237,15 @@ static void ipa3_replenish_rx_cache_recycle(struct ipa3_sys_context *sys)
 		queue_delayed_work(sys->wq, &sys->replenish_rx_work,
 		msecs_to_jiffies(1));
 done:
-	if (idx) {
-		ret = gsi_queue_xfer(sys->ep->gsi_chan_hdl, idx,
-			gsi_xfer_elem_array, true);
-		if (ret == GSI_STATUS_SUCCESS) {
-			sys->len = rx_len_cached;
-		} else {
-			/* we don't expect this will happen */
-			IPAERR("failed to provide buffer: %d\n", ret);
-			WARN_ON(1);
-		}
+	/* only ring doorbell once here */
+	ret = gsi_queue_xfer(sys->ep->gsi_chan_hdl, idx,
+		gsi_xfer_elem_array, true);
+	if (ret == GSI_STATUS_SUCCESS) {
+		sys->len = rx_len_cached;
+	} else {
+		/* we don't expect this will happen */
+		IPAERR("failed to provide buffer: %d\n", ret);
+		WARN_ON(1);
 	}
 }
 
@@ -2275,7 +2271,7 @@ static void ipa3_fast_replenish_rx_cache(struct ipa3_sys_context *sys)
 	struct ipa3_rx_pkt_wrapper *rx_pkt;
 	int ret;
 	int rx_len_cached = 0;
-	struct gsi_xfer_elem gsi_xfer_elem_array[IPA_REPL_XFER_THRESH];
+	struct gsi_xfer_elem gsi_xfer_elem_array[IPA_REPL_XFER_MAX];
 	u32 curr;
 	int idx = 0;
 
@@ -2305,15 +2301,10 @@ static void ipa3_fast_replenish_rx_cache(struct ipa3_sys_context *sys)
 		 * gsi_xfer_elem_buffer has a size of IPA_REPL_XFER_THRESH.
 		 * If this size is reached we need to queue the xfers.
 		 */
-		if (idx == IPA_REPL_XFER_THRESH) {
+		if (idx == IPA_REPL_XFER_MAX) {
 			ret = gsi_queue_xfer(sys->ep->gsi_chan_hdl, idx,
-				gsi_xfer_elem_array, true);
-			if (ret == GSI_STATUS_SUCCESS) {
-				/* ensure write is done before setting head */
-				mb();
-				atomic_set(&sys->repl->head_idx, curr);
-				sys->len = rx_len_cached;
-			} else {
+				gsi_xfer_elem_array, false);
+			if (ret != GSI_STATUS_SUCCESS) {
 				/* we don't expect this will happen */
 				IPAERR("failed to provide buffer: %d\n", ret);
 				WARN_ON(1);
@@ -2322,21 +2313,20 @@ static void ipa3_fast_replenish_rx_cache(struct ipa3_sys_context *sys)
 			idx = 0;
 		}
 	}
-	/* There can still be something left which has not been xfer yet */
-	if (idx) {
-		ret = gsi_queue_xfer(sys->ep->gsi_chan_hdl, idx,
-				gsi_xfer_elem_array, true);
-		if (ret == GSI_STATUS_SUCCESS) {
-			/* ensure write is done before setting head index */
-			mb();
-			atomic_set(&sys->repl->head_idx, curr);
-			sys->len = rx_len_cached;
-		} else {
-			/* we don't expect this will happen */
-			IPAERR("failed to provide buffer: %d\n", ret);
-			WARN_ON(1);
-		}
+	/* only ring doorbell once here */
+	ret = gsi_queue_xfer(sys->ep->gsi_chan_hdl, idx,
+			gsi_xfer_elem_array, true);
+	if (ret == GSI_STATUS_SUCCESS) {
+		/* ensure write is done before setting head index */
+		mb();
+		atomic_set(&sys->repl->head_idx, curr);
+		sys->len = rx_len_cached;
+	} else {
+		/* we don't expect this will happen */
+		IPAERR("failed to provide buffer: %d\n", ret);
+		WARN_ON(1);
 	}
+
 	spin_unlock_bh(&sys->spinlock);
 
 	__trigger_repl_work(sys);
@@ -2855,8 +2845,7 @@ static int ipa3_wan_rx_pyld_hdlr(struct sk_buff *skb,
 
 		IPA_STATS_INC_CNT(ipa3_ctx->stats.rx_pkts);
 		if (status.endp_dest_idx >= ipa3_ctx->ipa_num_pipes ||
-			status.endp_src_idx >= ipa3_ctx->ipa_num_pipes ||
-			status.pkt_len > IPA_GENERIC_AGGR_BYTE_LIMIT * 1024) {
+			status.endp_src_idx >= ipa3_ctx->ipa_num_pipes) {
 			IPAERR("status fields invalid\n");
 			WARN_ON(1);
 			goto bail;
@@ -3055,7 +3044,9 @@ static struct sk_buff *handle_skb_completion(struct gsi_chan_xfer_notify
 	INIT_LIST_HEAD(&rx_pkt->link);
 	list_add_tail(&rx_pkt->link, head);
 
-	if (notify->evt_id == GSI_CHAN_EVT_EOT) {
+	/* Check added for handling LAN consumer packet without EOT flag */
+	if (notify->evt_id == GSI_CHAN_EVT_EOT ||
+		sys->ep->client == IPA_CLIENT_APPS_LAN_CONS) {
 	/* go over the list backward to save computations on updating length */
 		list_for_each_entry_safe_reverse(rx_pkt, tmp, head, link) {
 			rx_skb = rx_pkt->data.skb;
@@ -3085,6 +3076,10 @@ static void ipa3_wq_rx_common(struct ipa3_sys_context *sys,
 	struct ipa3_sys_context *coal_sys;
 	int ipa_ep_idx;
 
+	if (!notify) {
+		IPAERR_RL("gsi_chan_xfer_notify is null\n");
+		return;
+	}
 	rx_skb = handle_skb_completion(notify, true);
 
 	if (rx_skb) {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index 0daae6d..8bc5c71 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.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
@@ -62,7 +62,7 @@ static int ipa3_generate_hdr_hw_tbl(struct ipa_mem_buffer *mem)
 }
 
 static int ipa3_hdr_proc_ctx_to_hw_format(struct ipa_mem_buffer *mem,
-	u32 hdr_base_addr)
+	u64 hdr_base_addr)
 {
 	struct ipa3_hdr_proc_ctx_entry *entry;
 	int ret;
@@ -100,7 +100,8 @@ static int ipa3_hdr_proc_ctx_to_hw_format(struct ipa_mem_buffer *mem,
 				entry->hdr->phys_base,
 				hdr_base_addr,
 				entry->hdr->offset_entry,
-				entry->l2tp_params);
+				entry->l2tp_params,
+				ipa3_ctx->use_64_bit_dma_mask);
 		if (ret)
 			return ret;
 	}
@@ -117,10 +118,10 @@ static int ipa3_hdr_proc_ctx_to_hw_format(struct ipa_mem_buffer *mem,
  *
  * Returns:	0 on success, negative on failure
  */
-static int ipa3_generate_hdr_proc_ctx_hw_tbl(u32 hdr_sys_addr,
+static int ipa3_generate_hdr_proc_ctx_hw_tbl(u64 hdr_sys_addr,
 	struct ipa_mem_buffer *mem, struct ipa_mem_buffer *aligned_mem)
 {
-	u32 hdr_base_addr;
+	u64 hdr_base_addr;
 
 	mem->size = (ipa3_ctx->hdr_proc_ctx_tbl.end) ? : 4;
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index dd6c5e9..fea9b48 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -252,8 +252,8 @@ enum {
 #define IPA_PIPE_MEM_START_OFST (0x0)
 #define IPA_PIPE_MEM_SIZE (0x0)
 #define IPA_MOBILE_AP_MODE(x) (x == IPA_MODE_MOBILE_AP_ETH || \
-			       x == IPA_MODE_MOBILE_AP_WAN || \
-			       x == IPA_MODE_MOBILE_AP_WLAN)
+				   x == IPA_MODE_MOBILE_AP_WAN || \
+				   x == IPA_MODE_MOBILE_AP_WLAN)
 #define IPA_CNOC_CLK_RATE (75 * 1000 * 1000UL)
 #define IPA_A5_MUX_HEADER_LENGTH (8)
 
@@ -306,6 +306,19 @@ enum {
 #define IPA_FWS_PATH_3_5_1   "ipa/3.5.1/ipa_fws.elf"
 #define IPA_FWS_PATH_4_5     "ipa/4.5/ipa_fws.elf"
 
+/*
+ * The following will be used for determining/using access control
+ * policy.
+ */
+#define USE_SCM            0 /* use scm call to determine policy */
+#define OVERRIDE_SCM_TRUE  1 /* override scm call with true */
+#define OVERRIDE_SCM_FALSE 2 /* override scm call with false */
+
+#define SD_ENABLED  0 /* secure debug enabled. */
+#define SD_DISABLED 1 /* secure debug disabled. */
+
+#define IPA_MEM_INIT_VAL 0xFFFFFFFF
+
 #ifdef CONFIG_COMPAT
 #define IPA_IOC_ADD_HDR32 _IOWR(IPA_IOC_MAGIC, \
 					IPA_IOCTL_ADD_HDR, \
@@ -812,8 +825,6 @@ struct ipa3_ep_context {
 	u32 eot_in_poll_err;
 	bool ep_delay_set;
 
-	int (*client_lock_unlock)(bool is_lock);
-
 	/* sys MUST be the last element of this struct */
 	struct ipa3_sys_context *sys;
 };
@@ -1442,6 +1453,12 @@ enum ipa_smmu_cb_type {
 	IPA_SMMU_CB_MAX
 };
 
+enum ipa_client_cb_type {
+	IPA_USB_CLNT,
+	IPA_MHI_CLNT,
+	IPA_MAX_CLNT
+};
+
 /**
  * struct ipa3_char_device_context - IPA character device
  * @class: pointer to the struct class
@@ -1625,6 +1642,7 @@ struct ipa3_context {
 	bool ipa_wdi2;
 	bool ipa_wdi2_over_gsi;
 	bool ipa_wdi3_over_gsi;
+	bool ipa_endp_delay_wa;
 	bool ipa_fltrt_not_hashable;
 	bool use_64_bit_dma_mask;
 	/* featurize if memory footprint becomes a concern */
@@ -1692,6 +1710,8 @@ struct ipa3_context {
 	bool do_register_collection_on_crash;
 	bool do_testbus_collection_on_crash;
 	bool do_non_tn_collection_on_crash;
+	u32 secure_debug_check_action;
+	u32 sd_state;
 	void __iomem *reg_collection_base;
 	struct ipa3_wdi2_ctx wdi2_ctx;
 	struct mbox_client mbox_client;
@@ -1700,6 +1720,9 @@ struct ipa3_context {
 	int gsi_chk_intset_value;
 	int uc_mailbox17_chk;
 	int uc_mailbox17_mismatch;
+	int (*client_lock_unlock[IPA_MAX_CLNT])(bool is_lock);
+	atomic_t is_ssr;
+	bool (*get_teth_port_state[IPA_MAX_CLNT])(void);
 };
 
 struct ipa3_plat_drv_res {
@@ -1743,6 +1766,8 @@ struct ipa3_plat_drv_res {
 	bool do_register_collection_on_crash;
 	bool do_testbus_collection_on_crash;
 	bool do_non_tn_collection_on_crash;
+	bool ipa_endp_delay_wa;
+	u32 secure_debug_check_action;
 };
 
 /**
@@ -2020,10 +2045,16 @@ int ipa3_xdci_connect(u32 clnt_hdl);
 int ipa3_xdci_disconnect(u32 clnt_hdl, bool should_force_clear, u32 qmi_req_id);
 
 void ipa3_xdci_ep_delay_rm(u32 clnt_hdl);
-void ipa3_register_lock_unlock_callback(int (*client_cb)(bool), u32 ipa_ep_idx);
-void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx);
+void ipa3_register_client_callback(int (*client_cb)(bool),
+		bool (*teth_port_state)(void), u32 ipa_ep_idx);
+void ipa3_deregister_client_callback(u32 ipa_ep_idx);
 int ipa3_set_reset_client_prod_pipe_delay(bool set_reset,
 		enum ipa_client_type client);
+int ipa3_start_stop_client_prod_gsi_chnl(enum ipa_client_type client,
+		bool start_chnl);
+void ipa3_client_prod_post_shutdown_cleanup(void);
+
+
 int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset,
 		enum ipa_client_type client);
 
@@ -2556,6 +2587,8 @@ int ipa3_tag_process(struct ipa3_desc *desc, int num_descs,
 
 void ipa3_q6_pre_shutdown_cleanup(void);
 void ipa3_q6_post_shutdown_cleanup(void);
+void ipa3_update_ssr_state(bool is_ssr);
+void ipa3_q6_pre_powerup_cleanup(void);
 int ipa3_init_q6_smem(void);
 
 int ipa3_mhi_handle_ipa_config_req(struct ipa_config_req_msg_v01 *config_req);
@@ -2743,10 +2776,54 @@ int ipa3_get_transport_info(
 irq_handler_t ipa3_get_isr(void);
 void ipa_pc_qmp_enable(void);
 #if defined(CONFIG_IPA3_REGDUMP)
-int ipa_reg_save_init(uint8_t value);
+int ipa_reg_save_init(u32 value);
 void ipa_save_registers(void);
+void ipa_save_gsi_ver(void);
 #else
-static inline int ipa_reg_save_init(uint8_t value) { return 0; }
+static inline int ipa_reg_save_init(u32 value) { return 0; }
 static inline void ipa_save_registers(void) {};
+static inline void ipa_save_gsi_ver(void) {};
 #endif
+
+#ifdef CONFIG_IPA_ETH
+int ipa_eth_init(void);
+void ipa_eth_exit(void);
+#else
+static inline int ipa_eth_init(void) { return 0; }
+static inline void ipa_eth_exit(void) { }
+#endif // CONFIG_IPA_ETH
+int ipa3_get_gsi_chan_info(struct gsi_chan_info *gsi_chan_info,
+	unsigned long chan_hdl);
+#ifdef CONFIG_IPA3_MHI_PRIME_MANAGER
+int ipa_mpm_mhip_xdci_pipe_enable(enum ipa_usb_teth_prot prot);
+int ipa_mpm_mhip_xdci_pipe_disable(enum ipa_usb_teth_prot xdci_teth_prot);
+int ipa_mpm_notify_wan_state(void);
+int ipa_mpm_mhip_ul_data_stop(enum ipa_usb_teth_prot xdci_teth_prot);
+int ipa3_is_mhip_offload_enabled(void);
+#else
+static inline int ipa_mpm_mhip_xdci_pipe_enable(
+	enum ipa_usb_teth_prot prot)
+{
+	return 0;
+}
+static inline int ipa_mpm_mhip_xdci_pipe_disable(
+	enum ipa_usb_teth_prot xdci_teth_prot)
+{
+	return 0;
+}
+static inline int ipa_mpm_notify_wan_state(void)
+{
+	return 0;
+}
+static inline int ipa_mpm_mhip_ul_data_stop(
+	enum ipa_usb_teth_prot xdci_teth_prot)
+{
+	return 0;
+}
+static inline int ipa3_is_mhip_offload_enabled(void)
+{
+	return 0;
+}
+#endif /* CONFIG_IPA3_MHI_PRIME_MANAGER */
+
 #endif /* _IPA3_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
index 9bde043..2d728d6 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.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
@@ -400,6 +400,8 @@ static int wlan_msg_process(struct ipa_msg_meta *meta, void *buff)
 	uint8_t mac[IPA_MAC_ADDR_SIZE];
 	uint8_t mac2[IPA_MAC_ADDR_SIZE];
 
+	if (!buff)
+		return -EINVAL;
 	if (meta->msg_type == WLAN_CLIENT_CONNECT_EX) {
 		/* debug print */
 		event_ex_cur_con = buff;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c
index 98cbcfa7..0b46190 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi_proxy.c
@@ -1091,7 +1091,6 @@ void imp_handle_modem_shutdown(void)
 		}
 	}
 
-	imp_ctx->state = IMP_PROBED;
 	mutex_unlock(&imp_ctx->mutex);
 
 	IMP_FUNC_EXIT();
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c
new file mode 100644
index 0000000..d229f4c
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c
@@ -0,0 +1,2407 @@
+/* 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/dma-mapping.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/mhi.h>
+#include <linux/msm_gsi.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+#include "../ipa_common_i.h"
+#include "ipa_i.h"
+
+#define IPA_MPM_DRV_NAME "ipa_mpm"
+
+#define IPA_MPM_DBG(fmt, args...) \
+	do { \
+		pr_debug(IPA_MPM_DRV_NAME " %s:%d " fmt, \
+			__func__, __LINE__, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+			IPA_MPM_DRV_NAME " %s:%d " fmt, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+			IPA_MPM_DRV_NAME " %s:%d " fmt, ## args); \
+	} while (0)
+
+#define IPA_MPM_DBG_LOW(fmt, args...) \
+	do { \
+		pr_debug(IPA_MPM_DRV_NAME " %s:%d " fmt, \
+			__func__, __LINE__, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+			IPA_MPM_DRV_NAME " %s:%d " fmt, ## args); \
+	} while (0)
+
+
+#define IPA_MPM_ERR(fmt, args...) \
+	do { \
+		pr_err(IPA_MPM_DRV_NAME " %s:%d " fmt, \
+			__func__, __LINE__, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+				IPA_MPM_DRV_NAME " %s:%d " fmt, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+				IPA_MPM_DRV_NAME " %s:%d " fmt, ## args); \
+	} while (0)
+
+
+#define IPA_MPM_FUNC_ENTRY() \
+	IPA_MPM_DBG("ENTRY\n")
+#define IPA_MPM_FUNC_EXIT() \
+	IPA_MPM_DBG("EXIT\n")
+
+#define IPA_MPM_MAX_MHIP_CHAN 3
+
+#define IPA_MPM_NUM_RING_DESC 0x400
+#define IPA_MPM_RING_LEN (IPA_MPM_NUM_RING_DESC - 10)
+
+#define IPA_MPM_MHI_HOST_UL_CHANNEL 4
+#define IPA_MPM_MHI_HOST_DL_CHANNEL  5
+#define DEFAULT_AGGR_TIME_LIMIT 1000 /* 1ms */
+#define DEFAULT_AGGR_PKT_LIMIT 0
+#define TRE_BUFF_SIZE 32768
+#define IPA_HOLB_TMR_EN 0x1
+#define IPA_HOLB_TMR_DIS 0x0
+#define RNDIS_IPA_DFLT_RT_HDL 0
+#define IPA_POLL_FOR_EMPTINESS_NUM 50
+#define IPA_POLL_FOR_EMPTINESS_SLEEP_USEC 20
+#define IPA_CHANNEL_STOP_IN_PROC_TO_MSEC 5
+#define IPA_CHANNEL_STOP_IN_PROC_SLEEP_USEC 200
+
+enum mhip_re_type {
+	MHIP_RE_XFER = 0x2,
+	MHIP_RE_NOP = 0x4,
+};
+
+enum ipa_mpm_mhi_ch_id_type {
+	IPA_MPM_MHIP_CH_ID_0,
+	IPA_MPM_MHIP_CH_ID_1,
+	IPA_MPM_MHIP_CH_ID_2,
+	IPA_MPM_MHIP_CH_ID_MAX,
+};
+
+enum ipa_mpm_dma_data_direction {
+	DMA_HIPA_BIDIRECTIONAL = 0,
+	DMA_TO_HIPA = 1,
+	DMA_FROM_HIPA = 2,
+	DMA_HIPA_NONE = 3,
+};
+
+enum ipa_mpm_ipa_teth_client_type {
+	IPA_MPM_MHIP_USB,
+	IPA_MPM_MHIP_WIFI,
+};
+
+enum ipa_mpm_mhip_client_type {
+	IPA_MPM_MHIP_INIT,
+	/* USB RMNET CLIENT */
+	IPA_MPM_MHIP_USB_RMNET,
+	/* USB RNDIS / WIFI CLIENT */
+	IPA_MPM_MHIP_TETH,
+	/* USB DPL CLIENT */
+	IPA_MPM_MHIP_USB_DPL,
+	IPA_MPM_MHIP_NONE,
+};
+
+enum ipa_mpm_start_stop_type {
+	STOP,
+	START,
+};
+
+enum ipa_mpm_clk_vote_type {
+	CLK_ON,
+	CLK_OFF,
+};
+
+enum mhip_status_type {
+	MHIP_STATUS_SUCCESS,
+	MHIP_STATUS_NO_OP,
+	MHIP_STATUS_FAIL,
+	MHIP_STATUS_BAD_STATE,
+	MHIP_STATUS_EP_NOT_FOUND,
+	MHIP_STATUS_EP_NOT_READY,
+};
+
+enum mhip_smmu_domain_type {
+	MHIP_SMMU_DOMAIN_IPA,
+	MHIP_SMMU_DOMAIN_PCIE,
+	MHIP_SMMU_DOMAIN_NONE,
+};
+
+/* each pair of UL/DL channels are defined below */
+static const struct mhi_device_id mhi_driver_match_table[] = {
+	{ .chan = "IP_HW_MHIP_0" }, // for rmnet pipes
+	{ .chan = "IP_HW_MHIP_1" }, // for MHIP teth pipes - rndis/wifi
+	{ .chan = "IP_HW_ADPL" }, // DPL/ODL DL pipe
+};
+
+/*
+ * MHI PRIME GSI Descriptor format that Host IPA uses.
+ */
+struct __packed mhi_p_desc {
+	uint64_t buffer_ptr;
+	uint16_t buff_len;
+	uint16_t resvd1;
+	uint16_t chain : 1;
+	uint16_t resvd4 : 7;
+	uint16_t ieob : 1;
+	uint16_t ieot : 1;
+	uint16_t bei : 1;
+	uint16_t sct : 1;
+	uint16_t resvd3 : 4;
+	uint8_t re_type;
+	uint8_t resvd2;
+};
+
+/*
+ * MHI PRIME Channel Context and Event Context Array
+ * Information that is sent to Device IPA.
+ */
+struct ipa_mpm_channel_context_type {
+	u32 chstate : 8;
+	u32 reserved1 : 24;
+	u32 chtype;
+	u32 erindex;
+	u64 rbase;
+	u64 rlen;
+	u64 reserved2;
+	u64 reserved3;
+} __packed;
+
+struct ipa_mpm_event_context_type {
+	u32 reserved1 : 8;
+	u32 update_rp_modc : 8;
+	u32 update_rp_intmodt : 16;
+	u32 ertype;
+	u32 update_rp_addr;
+	u64 rbase;
+	u64 rlen;
+	u32 buff_size : 16;
+	u32 reserved2 : 16;
+	u32 reserved3;
+	u64 reserved4;
+} __packed;
+
+struct ipa_mpm_pipes_info_type {
+	enum ipa_client_type ipa_client;
+	struct ipa_ep_cfg ep_cfg;
+};
+
+struct ipa_mpm_channel_type {
+	struct ipa_mpm_pipes_info_type dl_cons;
+	struct ipa_mpm_pipes_info_type ul_prod;
+	enum ipa_mpm_mhip_client_type mhip_client;
+};
+
+static struct ipa_mpm_channel_type ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_MAX];
+
+/* For configuring IPA_CLIENT_MHI_PRIME_TETH_CONS */
+static struct ipa_ep_cfg mhip_dl_teth_ep_cfg = {
+	.mode = {
+		.mode = IPA_BASIC,
+		.dst = IPA_CLIENT_MHI_PRIME_TETH_CONS,
+	},
+};
+
+static struct ipa_ep_cfg mhip_ul_teth_ep_cfg = {
+	.mode = {
+		.mode = IPA_BASIC,
+		.dst = IPA_CLIENT_MHI_PRIME_TETH_PROD,
+	},
+};
+
+/* WARNING!! Temporary for rndis intgration only */
+
+
+/* For configuring IPA_CLIENT_MHIP_RMNET_PROD */
+static struct ipa_ep_cfg mhip_dl_rmnet_ep_cfg = {
+	.mode = {
+		.mode = IPA_DMA,
+		.dst = IPA_CLIENT_USB_CONS,
+	},
+};
+
+/* For configuring IPA_CLIENT_MHIP_RMNET_CONS */
+static struct ipa_ep_cfg mhip_ul_rmnet_ep_cfg = {
+	.mode = {
+		.mode = IPA_DMA,
+		.dst = IPA_CLIENT_USB_CONS,
+	},
+};
+
+/* For configuring IPA_CLIENT_MHIP_DPL_PROD */
+static struct ipa_ep_cfg mhip_dl_dpl_ep_cfg = {
+	.mode = {
+		.mode = IPA_DMA,
+		.dst = IPA_CLIENT_USB_CONS,
+	},
+};
+
+
+struct ipa_mpm_iova_addr {
+	dma_addr_t base;
+	unsigned int size;
+};
+
+struct ipa_mpm_dev_info {
+	struct platform_device *pdev;
+	struct device *dev;
+	bool ipa_smmu_enabled;
+	bool pcie_smmu_enabled;
+	struct ipa_mpm_iova_addr ctrl;
+	struct ipa_mpm_iova_addr data;
+	u32 chdb_base;
+	u32 erdb_base;
+};
+
+struct ipa_mpm_event_props {
+	u16 id;
+	phys_addr_t device_db;
+	struct ipa_mpm_event_context_type ev_ctx;
+};
+
+struct ipa_mpm_channel_props {
+	u16 id;
+	phys_addr_t device_db;
+	struct ipa_mpm_channel_context_type ch_ctx;
+};
+
+struct ipa_mpm_channel {
+	struct ipa_mpm_channel_props chan_props;
+	struct ipa_mpm_event_props evt_props;
+};
+
+enum ipa_mpm_gsi_state {
+	GSI_ERR,
+	GSI_INIT,
+	GSI_ALLOCATED,
+	GSI_STARTED,
+	GSI_STOPPED,
+};
+
+enum ipa_mpm_teth_state {
+	IPA_MPM_TETH_INIT = 0,
+	IPA_MPM_TETH_INPROGRESS,
+	IPA_MPM_TETH_CONNECTED,
+};
+
+enum ipa_mpm_mhip_chan {
+	IPA_MPM_MHIP_CHAN_UL,
+	IPA_MPM_MHIP_CHAN_DL,
+	IPA_MPM_MHIP_CHAN_BOTH,
+};
+
+struct producer_rings {
+	struct mhi_p_desc *tr_va;
+	struct mhi_p_desc *er_va;
+	dma_addr_t tr_pa;
+	dma_addr_t er_pa;
+	void *tre_buff[IPA_MPM_RING_LEN];
+	/*
+	 * The iova generated for AP CB,
+	 * used only for dma_map_single to flush the cache.
+	 */
+	dma_addr_t ap_iova_er;
+	dma_addr_t ap_iova_tr;
+	dma_addr_t ap_iova_buff[IPA_MPM_RING_LEN];
+};
+
+struct ipa_mpm_mhi_driver {
+	struct mhi_device *mhi_dev;
+	struct producer_rings ul_prod_ring;
+	struct producer_rings dl_prod_ring;
+	struct ipa_mpm_channel ul_prod;
+	struct ipa_mpm_channel dl_cons;
+	enum ipa_mpm_mhip_client_type mhip_client;
+	enum ipa_mpm_gsi_state gsi_state;
+	enum ipa_mpm_teth_state teth_state;
+	struct mutex mutex;
+	bool init_complete;
+};
+
+struct ipa_mpm_context {
+	struct ipa_mpm_dev_info dev_info;
+	struct ipa_mpm_mhi_driver md[IPA_MPM_MAX_MHIP_CHAN];
+	struct mutex mutex;
+	atomic_t ipa_clk_ref_cnt;
+	atomic_t pcie_clk_ref_cnt;
+	struct device *parent_pdev;
+	struct ipa_smmu_cb_ctx carved_smmu_cb;
+};
+
+#define IPA_MPM_DESC_SIZE (sizeof(struct mhi_p_desc))
+#define IPA_MPM_RING_TOTAL_SIZE (IPA_MPM_RING_LEN * IPA_MPM_DESC_SIZE)
+#define IPA_MPM_PAGE_SIZE roundup_pow_of_two(IPA_MPM_RING_TOTAL_SIZE)
+
+
+static struct ipa_mpm_context *ipa_mpm_ctx;
+static struct platform_device *m_pdev;
+static int ipa_mpm_mhi_probe_cb(struct mhi_device *,
+	const struct mhi_device_id *);
+static void ipa_mpm_mhi_remove_cb(struct mhi_device *);
+static void ipa_mpm_mhi_status_cb(struct mhi_device *, enum MHI_CB);
+static void ipa_mpm_change_teth_state(int probe_id,
+	enum ipa_mpm_teth_state ip_state);
+static void ipa_mpm_change_gsi_state(int probe_id,
+	enum ipa_mpm_gsi_state next_state);
+static int ipa_mpm_start_stop_mhip_data_path(int probe_id,
+	enum ipa_mpm_start_stop_type start);
+static int ipa_mpm_probe(struct platform_device *pdev);
+static int ipa_mpm_vote_unvote_pcie_clk(enum ipa_mpm_clk_vote_type vote,
+	int probe_id);
+static void ipa_mpm_vote_unvote_ipa_clk(enum ipa_mpm_clk_vote_type vote);
+static enum mhip_status_type ipa_mpm_start_stop_mhip_chan(
+	enum ipa_mpm_mhip_chan mhip_chan,
+	int probe_id,
+	enum ipa_mpm_start_stop_type start_stop);
+
+static struct mhi_driver mhi_driver = {
+	.id_table = mhi_driver_match_table,
+	.probe = ipa_mpm_mhi_probe_cb,
+	.remove = ipa_mpm_mhi_remove_cb,
+	.status_cb = ipa_mpm_mhi_status_cb,
+	.driver = {
+		.name = IPA_MPM_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static void ipa_mpm_ipa3_delayed_probe(struct work_struct *work)
+{
+	(void)ipa_mpm_probe(m_pdev);
+}
+
+static DECLARE_WORK(ipa_mpm_ipa3_scheduled_probe, ipa_mpm_ipa3_delayed_probe);
+
+static void ipa_mpm_ipa3_ready_cb(void *user_data)
+{
+	struct platform_device *pdev = (struct platform_device *)(user_data);
+
+	m_pdev = pdev;
+
+	IPA_MPM_DBG("IPA ready callback has been triggered\n");
+
+	schedule_work(&ipa_mpm_ipa3_scheduled_probe);
+}
+
+static void ipa_mpm_gsi_evt_ring_err_cb(struct gsi_evt_err_notify *err_data)
+{
+	IPA_MPM_ERR("GSI EVT RING ERROR, not expected..\n");
+	ipa_assert();
+}
+
+static void ipa_mpm_gsi_chan_err_cb(struct gsi_chan_err_notify *err_data)
+{
+	IPA_MPM_ERR("GSI CHAN ERROR, not expected..\n");
+	ipa_assert();
+}
+
+/**
+ * ipa_mpm_smmu_map() - SMMU maps ring and the buffer pointer.
+ * @va_addr: virtual address that needs to be mapped
+ * @sz: size of the address to be mapped
+ * @dir: ipa_mpm_dma_data_direction
+ * @ap_cb_iova: iova for AP context bank
+ *
+ * This function SMMU maps both ring and the buffer pointer.
+ * The ring pointers will be aligned to ring size and
+ * the buffer pointers should be aligned to buffer size.
+ *
+ * Returns: iova of the mapped address
+ */
+static dma_addr_t ipa_mpm_smmu_map(void *va_addr,
+	int sz,
+	int dir,
+	dma_addr_t *ap_cb_iova)
+{
+	struct iommu_domain *ipa_smmu_domain, *pcie_smmu_domain;
+	phys_addr_t phys_addr;
+	dma_addr_t iova;
+	int smmu_enabled;
+	unsigned long iova_p;
+	phys_addr_t pa_p;
+	u32 size_p;
+	int prot = IOMMU_READ | IOMMU_WRITE;
+	struct ipa_smmu_cb_ctx *cb = &ipa_mpm_ctx->carved_smmu_cb;
+	unsigned long carved_iova = roundup(cb->next_addr, IPA_MPM_PAGE_SIZE);
+	int ret = 0;
+
+	if (carved_iova >= cb->va_end) {
+		IPA_MPM_ERR("running out of carved_iova %x\n", carved_iova);
+		ipa_assert();
+	}
+	/*
+	 * Both Host IPA and PCIE SMMU should be enabled or disabled
+	 * for proceed.
+	 * If SMMU Enabled => iova == pa
+	 * If SMMU Disabled => iova == iommu mapped iova
+	 * dma_map_single ensures cache is flushed and the memory is not
+	 * touched again until dma_unmap_single() is called
+	 */
+	smmu_enabled = (ipa_mpm_ctx->dev_info.ipa_smmu_enabled &&
+		ipa_mpm_ctx->dev_info.pcie_smmu_enabled) ? 1 : 0;
+
+	if (smmu_enabled) {
+		/* Map the phys addr to both PCIE and IPA AP CB
+		 * from the carved out common iova range.
+		 */
+		ipa_smmu_domain = ipa3_get_smmu_domain();
+
+		if (!ipa_smmu_domain) {
+			IPA_MPM_ERR("invalid IPA smmu domain\n");
+			ipa_assert();
+		}
+
+		if (!ipa_mpm_ctx->md[0].mhi_dev->dev.parent) {
+			IPA_MPM_ERR("invalid PCIE SMMU domain\n");
+			ipa_assert();
+		}
+
+		phys_addr = virt_to_phys((void *) va_addr);
+		IPA_SMMU_ROUND_TO_PAGE(carved_iova, phys_addr, sz,
+					iova_p, pa_p, size_p);
+
+		/* Flush the cache with dma_map_single for IPA AP CB */
+		*ap_cb_iova = dma_map_single(ipa3_ctx->pdev, va_addr,
+						sz, dir);
+		ret = ipa3_iommu_map(ipa_smmu_domain, iova_p,
+					pa_p, size_p, prot);
+		if (ret) {
+			IPA_MPM_ERR("IPA IOMMU returned failure, ret = %d\n",
+					ret);
+			ipa_assert();
+		}
+
+		pcie_smmu_domain = iommu_get_domain_for_dev(
+			ipa_mpm_ctx->md[0].mhi_dev->dev.parent);
+		ret = iommu_map(pcie_smmu_domain, iova_p, pa_p, size_p, prot);
+
+		if (ret) {
+			IPA_MPM_ERR("PCIe IOMMU returned failure, ret = %d\n",
+				ret);
+			ipa_assert();
+		}
+
+		iova = iova_p;
+		cb->next_addr = iova_p + size_p;
+	} else {
+		iova = dma_map_single(ipa3_ctx->pdev, va_addr, sz, dir);
+		*ap_cb_iova = iova;
+	}
+	return iova;
+}
+
+/**
+ * ipa_mpm_smmu_unmap() - SMMU unmaps ring and the buffer pointer.
+ * @va_addr: virtual address that needs to be mapped
+ * @sz: size of the address to be mapped
+ * @dir: ipa_mpm_dma_data_direction
+ * @ap_cb_iova: iova for AP context bank
+ *
+ * This function SMMU unmaps both ring and the buffer pointer.
+ * The ring pointers will be aligned to ring size and
+ * the buffer pointers should be aligned to buffer size.
+ *
+ * Return: none
+ */
+static void ipa_mpm_smmu_unmap(dma_addr_t carved_iova, int sz, int dir,
+	dma_addr_t ap_cb_iova)
+{
+	int ret;
+	unsigned long iova_p;
+	unsigned long pa_p;
+	u32 size_p = 0;
+	struct iommu_domain *ipa_smmu_domain, *pcie_smmu_domain;
+	struct ipa_smmu_cb_ctx *cb = &ipa_mpm_ctx->carved_smmu_cb;
+	int smmu_enabled = (ipa_mpm_ctx->dev_info.ipa_smmu_enabled &&
+		ipa_mpm_ctx->dev_info.pcie_smmu_enabled) ? 1 : 0;
+
+	if (smmu_enabled) {
+		ipa_smmu_domain = ipa3_get_smmu_domain();
+		if (!ipa_smmu_domain) {
+			IPA_MPM_ERR("invalid IPA smmu domain\n");
+			ipa_assert();
+		}
+
+		if (!ipa_mpm_ctx->md[0].mhi_dev->dev.parent) {
+			IPA_MPM_ERR("invalid PCIE SMMU domain\n");
+			ipa_assert();
+		}
+
+		IPA_SMMU_ROUND_TO_PAGE(carved_iova, carved_iova, sz,
+					iova_p, pa_p, size_p);
+
+		ret = iommu_unmap(ipa_smmu_domain, carved_iova, size_p);
+		if (ret) {
+			IPA_MPM_ERR("IPA IOMMU Unmap failure, ret = %d\n",
+					ret);
+			ipa_assert();
+		}
+		pcie_smmu_domain = iommu_get_domain_for_dev(
+			ipa_mpm_ctx->md[0].mhi_dev->dev.parent);
+
+		ret = iommu_unmap(pcie_smmu_domain, carved_iova, size_p);
+
+		if (ret) {
+			IPA_MPM_ERR("PCIe IOMMU Unmap failure, ret = %d\n",
+				ret);
+			ipa_assert();
+		}
+		cb->next_addr -= size_p;
+		dma_unmap_single(ipa3_ctx->pdev, ap_cb_iova, size_p, dir);
+	} else {
+		dma_unmap_single(ipa3_ctx->pdev, ap_cb_iova, sz, dir);
+	}
+}
+
+static u32 ipa_mpm_smmu_map_doorbell(enum mhip_smmu_domain_type smmu_domain,
+	u32 pa_addr)
+{
+	/*
+	 * Doorbells are already in PA, map these to
+	 * PCIE/IPA doman if SMMUs are enabled.
+	 */
+	struct iommu_domain *ipa_smmu_domain, *pcie_smmu_domain;
+	int smmu_enabled;
+	unsigned long iova_p;
+	phys_addr_t pa_p;
+	u32 size_p;
+	int ret = 0;
+	int prot = IOMMU_READ | IOMMU_WRITE;
+	struct ipa_smmu_cb_ctx *cb = &ipa_mpm_ctx->carved_smmu_cb;
+	unsigned long carved_iova = roundup(cb->next_addr, PAGE_SIZE);
+	u32 iova = 0;
+	u64 offset = 0;
+
+	if (carved_iova >= cb->va_end) {
+		IPA_MPM_ERR("running out of carved_iova %x\n", carved_iova);
+		ipa_assert();
+	}
+
+	smmu_enabled = (ipa_mpm_ctx->dev_info.ipa_smmu_enabled &&
+		ipa_mpm_ctx->dev_info.pcie_smmu_enabled) ? 1 : 0;
+
+	if (smmu_enabled) {
+		IPA_SMMU_ROUND_TO_PAGE(carved_iova, pa_addr, PAGE_SIZE,
+					iova_p, pa_p, size_p);
+		if (smmu_domain == MHIP_SMMU_DOMAIN_IPA) {
+			ipa_smmu_domain = ipa3_get_smmu_domain();
+			ret = ipa3_iommu_map(ipa_smmu_domain,
+				iova_p, pa_p, size_p, prot);
+			if (ret) {
+				IPA_MPM_ERR("IPA doorbell mapping failed\n");
+				ipa_assert();
+			}
+			offset = pa_addr - pa_p;
+		} else if (smmu_domain == MHIP_SMMU_DOMAIN_PCIE) {
+			pcie_smmu_domain = iommu_get_domain_for_dev(
+				ipa_mpm_ctx->md[0].mhi_dev->dev.parent);
+			 ret = iommu_map(pcie_smmu_domain,
+				iova_p, pa_p, size_p, prot);
+			if (ret) {
+				IPA_MPM_ERR("PCIe doorbell mapping failed\n");
+				ipa_assert();
+			}
+			offset = pa_addr - pa_p;
+		}
+		iova = iova_p + offset;
+		cb->next_addr = iova_p + PAGE_SIZE;
+	} else {
+		iova = pa_addr;
+	}
+	return iova;
+}
+
+static int get_idx_from_id(const struct mhi_device_id *id)
+{
+	return (id - mhi_driver_match_table);
+}
+
+static void get_ipa3_client(int id,
+	enum ipa_client_type *ul_prod,
+	enum ipa_client_type *dl_cons)
+{
+	IPA_MPM_FUNC_ENTRY();
+
+	if (id >= IPA_MPM_MHIP_CH_ID_MAX) {
+		*ul_prod = IPA_CLIENT_MAX;
+		*dl_cons = IPA_CLIENT_MAX;
+	} else {
+		*ul_prod = ipa_mpm_pipes[id].ul_prod.ipa_client;
+		*dl_cons = ipa_mpm_pipes[id].dl_cons.ipa_client;
+	}
+	IPA_MPM_FUNC_EXIT();
+}
+
+static int ipa_mpm_connect_mhip_gsi_pipe(enum ipa_client_type mhip_client,
+	int mhi_idx, struct ipa_req_chan_out_params *out_params)
+{
+	int ipa_ep_idx;
+	int res;
+	struct mhi_p_desc *ev_ring;
+	struct mhi_p_desc *tr_ring;
+	int tr_ring_sz, ev_ring_sz;
+	dma_addr_t ev_ring_iova, tr_ring_iova;
+	dma_addr_t ap_cb_iova;
+	struct ipa_request_gsi_channel_params gsi_params;
+	int dir;
+	int i;
+	void *buff;
+	int result;
+	int k;
+	struct ipa3_ep_context *ep;
+
+	if (mhip_client == IPA_CLIENT_MAX)
+		goto fail_gen;
+
+	if (mhi_idx == IPA_MPM_MHIP_CH_ID_MAX)
+		goto fail_gen;
+
+	ipa_ep_idx = ipa3_get_ep_mapping(mhip_client);
+	if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) {
+		IPA_MPM_ERR("fail to find channel EP.\n");
+		goto fail_gen;
+	}
+	ep = &ipa3_ctx->ep[ipa_ep_idx];
+	if (ep->valid == 1) {
+		IPAERR("EP %d already allocated.\n", ipa_ep_idx);
+		return 0;
+	}
+
+	IPA_MPM_DBG("connecting client %d (ep: %d)\n", mhip_client, ipa_ep_idx);
+
+	IPA_MPM_FUNC_ENTRY();
+
+	ev_ring_sz = IPA_MPM_RING_TOTAL_SIZE;
+	ev_ring = kzalloc(ev_ring_sz, GFP_KERNEL);
+	if (!ev_ring)
+		goto fail_evt_alloc;
+
+	tr_ring_sz = IPA_MPM_RING_TOTAL_SIZE;
+	tr_ring = kzalloc(tr_ring_sz, GFP_KERNEL);
+	if (!tr_ring)
+		goto fail_tr_alloc;
+
+	tr_ring[0].re_type = MHIP_RE_NOP;
+
+	dir = IPA_CLIENT_IS_PROD(mhip_client) ?
+		DMA_TO_HIPA : DMA_FROM_HIPA;
+
+	/* allocate transfer ring elements */
+	for (i = 1, k = 0; i < IPA_MPM_RING_LEN; i++, k++) {
+		buff = kzalloc(TRE_BUFF_SIZE, GFP_KERNEL);
+
+		if (!buff)
+			goto fail_buff_alloc;
+
+		if (IPA_CLIENT_IS_PROD(mhip_client))
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tre_buff[k] =
+									buff;
+		else
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tre_buff[k] =
+									buff;
+
+		tr_ring[i].buffer_ptr =
+			ipa_mpm_smmu_map(buff, TRE_BUFF_SIZE, dir,
+				&ap_cb_iova);
+
+		if (!tr_ring[i].buffer_ptr)
+			goto fail_smmu_map_ring;
+
+		tr_ring[i].buff_len = TRE_BUFF_SIZE;
+		tr_ring[i].chain = 0;
+		tr_ring[i].ieob = 0;
+		tr_ring[i].ieot = 0;
+		tr_ring[i].bei = 0;
+		tr_ring[i].sct = 0;
+		tr_ring[i].re_type = MHIP_RE_XFER;
+
+		if (IPA_CLIENT_IS_PROD(mhip_client))
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.ap_iova_buff[k] =
+				ap_cb_iova;
+		else
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.ap_iova_buff[k] =
+				ap_cb_iova;
+	}
+
+	tr_ring_iova = ipa_mpm_smmu_map(tr_ring, tr_ring_sz, dir,
+		&ap_cb_iova);
+	if (!tr_ring_iova)
+		goto fail_smmu_map_ring;
+
+	ev_ring_iova = ipa_mpm_smmu_map(ev_ring, ev_ring_sz, dir,
+		&ap_cb_iova);
+	if (!ev_ring_iova)
+		goto fail_smmu_map_ring;
+
+	/* Store Producer channel rings */
+	if (IPA_CLIENT_IS_PROD(mhip_client)) {
+		/* Device UL */
+		ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.er_va = ev_ring;
+		ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tr_va = tr_ring;
+		ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.er_pa = ev_ring_iova;
+		ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tr_pa = tr_ring_iova;
+		ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.ap_iova_tr =
+			ap_cb_iova;
+	} else {
+		/* Host UL */
+		ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.er_va = ev_ring;
+		ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tr_va = tr_ring;
+		ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.er_pa = ev_ring_iova;
+		ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tr_pa = tr_ring_iova;
+		ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.ap_iova_tr =
+			ap_cb_iova;
+	}
+
+	memset(&gsi_params, 0, sizeof(struct ipa_request_gsi_channel_params));
+
+	if (IPA_CLIENT_IS_PROD(mhip_client))
+		gsi_params.ipa_ep_cfg =
+		ipa_mpm_pipes[mhi_idx].dl_cons.ep_cfg;
+	else
+		gsi_params.ipa_ep_cfg =
+		ipa_mpm_pipes[mhi_idx].ul_prod.ep_cfg;
+
+	gsi_params.client = mhip_client;
+	gsi_params.skip_ep_cfg = false;
+
+	/*
+	 * RP update address = Device channel DB address
+	 * CLIENT_PROD -> Host DL
+	 * CLIENT_CONS -> Host UL
+	 */
+	if (IPA_CLIENT_IS_PROD(mhip_client)) {
+		gsi_params.evt_ring_params.rp_update_addr =
+			ipa_mpm_smmu_map_doorbell(
+			MHIP_SMMU_DOMAIN_IPA,
+			ipa_mpm_ctx->md[mhi_idx].dl_cons.chan_props.device_db);
+		if (gsi_params.evt_ring_params.rp_update_addr == 0)
+			goto fail_smmu_map_db;
+		gsi_params.evt_ring_params.ring_base_addr =
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tr_pa;
+		gsi_params.chan_params.ring_base_addr =
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.er_pa;
+	} else {
+		gsi_params.evt_ring_params.rp_update_addr =
+			ipa_mpm_smmu_map_doorbell(
+			MHIP_SMMU_DOMAIN_IPA,
+			ipa_mpm_ctx->md[mhi_idx].ul_prod.chan_props.device_db);
+		if (gsi_params.evt_ring_params.rp_update_addr == 0)
+			goto fail_smmu_map_db;
+		gsi_params.evt_ring_params.ring_base_addr =
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.er_pa;
+		gsi_params.chan_params.ring_base_addr =
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tr_pa;
+	}
+
+	/* Fill Event ring params */
+	gsi_params.evt_ring_params.intf = GSI_EVT_CHTYPE_MHIP_EV;
+	gsi_params.evt_ring_params.intr = GSI_INTR_MSI;
+	gsi_params.evt_ring_params.re_size = GSI_EVT_RING_RE_SIZE_16B;
+	gsi_params.evt_ring_params.ring_len =
+		(IPA_MPM_RING_LEN) * GSI_EVT_RING_RE_SIZE_16B;
+	gsi_params.evt_ring_params.ring_base_vaddr = NULL;
+	gsi_params.evt_ring_params.int_modt = 0;
+	gsi_params.evt_ring_params.int_modc = 0;
+	gsi_params.evt_ring_params.intvec = 0;
+	gsi_params.evt_ring_params.msi_addr = 0;
+	gsi_params.evt_ring_params.exclusive = true;
+	gsi_params.evt_ring_params.err_cb = ipa_mpm_gsi_evt_ring_err_cb;
+	gsi_params.evt_ring_params.user_data = NULL;
+
+	/* Evt Scratch Params */
+	/* Disable the Moderation for ringing doorbells */
+	gsi_params.evt_scratch.mhip.rp_mod_threshold = 1;
+	gsi_params.evt_scratch.mhip.rp_mod_timer = 0;
+	gsi_params.evt_scratch.mhip.rp_mod_counter = 0;
+	gsi_params.evt_scratch.mhip.rp_mod_timer_id = 0;
+	gsi_params.evt_scratch.mhip.rp_mod_timer_running = 0;
+	gsi_params.evt_scratch.mhip.fixed_buffer_sz = TRE_BUFF_SIZE;
+
+	if (IPA_CLIENT_IS_PROD(mhip_client))
+		gsi_params.evt_scratch.mhip.rp_mod_threshold = 4;
+
+	/* Channel Params */
+	gsi_params.chan_params.prot = GSI_CHAN_PROT_MHIP;
+	gsi_params.chan_params.dir = IPA_CLIENT_IS_PROD(mhip_client) ?
+		GSI_CHAN_DIR_TO_GSI : GSI_CHAN_DIR_FROM_GSI;
+	/* chan_id is set in ipa3_request_gsi_channel() */
+	gsi_params.chan_params.re_size = GSI_CHAN_RE_SIZE_16B;
+	gsi_params.chan_params.ring_len =
+		(IPA_MPM_RING_LEN) * GSI_EVT_RING_RE_SIZE_16B;
+	gsi_params.chan_params.ring_base_vaddr = NULL;
+	gsi_params.chan_params.use_db_eng = GSI_CHAN_DIRECT_MODE;
+	gsi_params.chan_params.max_prefetch = GSI_ONE_PREFETCH_SEG;
+	gsi_params.chan_params.low_weight = 1;
+	gsi_params.chan_params.xfer_cb = NULL;
+	gsi_params.chan_params.err_cb = ipa_mpm_gsi_chan_err_cb;
+	gsi_params.chan_params.chan_user_data = NULL;
+
+	/* Channel scratch */
+	gsi_params.chan_scratch.mhip.assert_bit_40 = 0;
+	gsi_params.chan_scratch.mhip.host_channel = 1;
+
+	res = ipa3_request_gsi_channel(&gsi_params, out_params);
+	if (res) {
+		IPA_MPM_ERR("failed to allocate GSI channel res=%d\n", res);
+		goto fail_alloc_channel;
+	}
+
+	ipa_mpm_change_gsi_state(mhi_idx, GSI_ALLOCATED);
+
+	result = ipa3_start_gsi_channel(ipa_ep_idx);
+	if (result) {
+		IPA_MPM_ERR("start MHIP channel %d failed\n", mhip_client);
+		ipa_mpm_ctx->md[mhi_idx].gsi_state = GSI_ERR;
+		goto fail_start_channel;
+	}
+	ipa_mpm_change_gsi_state(mhi_idx, GSI_STARTED);
+
+	/* Fill in the Device Context params */
+	if (IPA_CLIENT_IS_PROD(mhip_client)) {
+		/* This is the DL channel :: Device -> Host */
+		ipa_mpm_ctx->md[mhi_idx].dl_cons.evt_props.ev_ctx.rbase =
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.er_pa;
+		ipa_mpm_ctx->md[mhi_idx].dl_cons.chan_props.ch_ctx.rbase =
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tr_pa;
+	} else {
+		ipa_mpm_ctx->md[mhi_idx].ul_prod.evt_props.ev_ctx.rbase =
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tr_pa;
+		ipa_mpm_ctx->md[mhi_idx].ul_prod.chan_props.ch_ctx.rbase =
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.er_pa;
+	}
+
+	IPA_MPM_FUNC_EXIT();
+
+	return 0;
+
+fail_start_channel:
+	ipa3_disable_data_path(ipa_ep_idx);
+	ipa3_stop_gsi_channel(ipa_ep_idx);
+fail_alloc_channel:
+	ipa3_release_gsi_channel(ipa_ep_idx);
+fail_smmu_map_db:
+fail_smmu_map_ring:
+fail_tr_alloc:
+fail_evt_alloc:
+fail_buff_alloc:
+	ipa_assert();
+fail_gen:
+	return -EFAULT;
+}
+
+static void ipa_mpm_clean_mhip_chan(int mhi_idx,
+				enum ipa_client_type mhip_client)
+{
+	int dir;
+	int i;
+	int result;
+	int ipa_ep_idx;
+	struct mhi_p_desc *ev_ring;
+	struct mhi_p_desc *tr_ring;
+	int tr_ring_sz, ev_ring_sz;
+
+	IPA_MPM_FUNC_ENTRY();
+
+	if (mhip_client == IPA_CLIENT_MAX)
+		return;
+	if (mhi_idx == IPA_MPM_MHIP_CH_ID_MAX)
+		return;
+
+	dir = IPA_CLIENT_IS_PROD(mhip_client) ?
+		DMA_TO_HIPA : DMA_FROM_HIPA;
+
+	ipa_ep_idx = ipa3_get_ep_mapping(mhip_client);
+	if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) {
+		IPA_MPM_ERR("fail to find channel EP.\n");
+		return;
+	}
+
+	/* Release channel */
+	result = ipa3_release_gsi_channel(ipa_ep_idx);
+	if (result) {
+		IPA_MPM_ERR("start MHIP channel %d failed\n", mhip_client);
+		ipa_mpm_ctx->md[mhi_idx].gsi_state = GSI_ERR;
+	}
+
+	ipa_mpm_change_gsi_state(mhi_idx, GSI_INIT);
+
+
+	/* deallocate transfer ring buffers  */
+	for (i = 0; i < IPA_MPM_RING_LEN; i++) {
+		if (IPA_CLIENT_IS_PROD(mhip_client)) {
+			ipa_mpm_smmu_unmap(
+			(dma_addr_t)
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tre_buff[i],
+			TRE_BUFF_SIZE, dir,
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.ap_iova_buff[i]);
+
+			kfree(
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tre_buff[i]);
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tre_buff[i]
+								= NULL;
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.ap_iova_buff[i]
+								= 0;
+		} else {
+			ipa_mpm_smmu_unmap(
+			(dma_addr_t)
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tre_buff[i],
+			TRE_BUFF_SIZE, dir,
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.ap_iova_buff[i]
+			);
+
+			kfree(
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tre_buff[i]);
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tre_buff[i]
+								= NULL;
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.ap_iova_buff[i]
+								= 0;
+		}
+	}
+
+	tr_ring_sz = sizeof(*tr_ring) * (IPA_MPM_RING_LEN);
+	ev_ring_sz = sizeof(*ev_ring) * (IPA_MPM_RING_LEN);
+
+	if (IPA_CLIENT_IS_PROD(mhip_client)) {
+		ipa_mpm_smmu_unmap(
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.er_pa,
+			ev_ring_sz, dir,
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.ap_iova_er);
+
+		ipa_mpm_smmu_unmap(
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tr_pa,
+			tr_ring_sz, dir,
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.ap_iova_tr);
+
+		kfree(ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.er_va);
+		ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.er_va = NULL;
+
+		kfree(ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tr_va);
+		ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.tr_va = NULL;
+
+		ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.ap_iova_er = 0;
+		ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.ap_iova_tr = 0;
+	} else {
+		ipa_mpm_smmu_unmap(
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.er_pa,
+			ev_ring_sz, dir,
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.ap_iova_er);
+
+		ipa_mpm_smmu_unmap(
+			ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tr_pa,
+			tr_ring_sz, dir,
+			ipa_mpm_ctx->md[mhi_idx].dl_prod_ring.ap_iova_tr);
+
+		kfree(ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.er_va);
+		ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.er_va = NULL;
+
+		kfree(ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tr_va);
+		ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.tr_va = NULL;
+
+		ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.ap_iova_er = 0;
+		ipa_mpm_ctx->md[mhi_idx].ul_prod_ring.ap_iova_tr = 0;
+	}
+
+	IPA_MPM_FUNC_EXIT();
+}
+
+/* round addresses for closest page per SMMU requirements */
+static inline void ipa_mpm_smmu_round_to_page(uint64_t iova, uint64_t pa,
+	uint64_t size, unsigned long *iova_p, phys_addr_t *pa_p, u32 *size_p)
+{
+	*iova_p = rounddown(iova, PAGE_SIZE);
+	*pa_p = rounddown(pa, PAGE_SIZE);
+	*size_p = roundup(size + pa - *pa_p, PAGE_SIZE);
+}
+
+
+static int __ipa_mpm_configure_mhi_device(struct ipa_mpm_channel *ch,
+	int mhi_idx, int dir)
+{
+	struct mhi_buf ch_config[2];
+	int ret;
+
+	IPA_MPM_FUNC_ENTRY();
+
+	if (ch == NULL) {
+		IPA_MPM_ERR("ch config is NULL\n");
+		return -EINVAL;
+	}
+
+	/* Populate CCA */
+	ch_config[0].buf = &ch->chan_props.ch_ctx;
+	ch_config[0].len = sizeof(ch->chan_props.ch_ctx);
+	ch_config[0].name = "CCA";
+
+	/* populate ECA */
+	ch_config[1].buf = &ch->evt_props.ev_ctx;
+	ch_config[1].len = sizeof(ch->evt_props.ev_ctx);
+	ch_config[1].name = "ECA";
+
+	IPA_MPM_DBG("Configuring MHI PRIME device for mhi_idx %d\n", mhi_idx);
+
+	ret = mhi_device_configure(ipa_mpm_ctx->md[mhi_idx].mhi_dev, dir,
+			ch_config, 2);
+	if (ret) {
+		IPA_MPM_ERR("mhi_device_configure failed\n");
+		return -EINVAL;
+	}
+
+	IPA_MPM_FUNC_EXIT();
+
+	return 0;
+}
+
+static void ipa_mpm_mhip_shutdown(void)
+{
+	int mhip_idx;
+	enum ipa_client_type ul_chan, dl_chan;
+
+	IPA_MPM_FUNC_ENTRY();
+
+	for (mhip_idx = 0; mhip_idx < IPA_MPM_MHIP_CH_ID_MAX; mhip_idx++) {
+		if (ipa_mpm_ctx->md[mhip_idx].gsi_state >= GSI_ALLOCATED) {
+			get_ipa3_client(mhip_idx, &ul_chan, &dl_chan);
+			IPA_MPM_DBG("Stopping chan = %d\n", mhip_idx);
+			/* MHIP PROD: Enable HOLB and Stop the GSI UL channel */
+			ipa_mpm_start_stop_mhip_data_path(mhip_idx, STOP);
+			ipa_mpm_start_stop_mhip_chan(IPA_MPM_MHIP_CHAN_UL,
+							mhip_idx, STOP);
+			ipa_mpm_start_stop_mhip_chan(IPA_MPM_MHIP_CHAN_DL,
+							mhip_idx, STOP);
+
+			/* Clean up the GSI UL and DL channels */
+			if (ipa_mpm_ctx->dev_info.ipa_smmu_enabled &&
+				ipa_mpm_ctx->dev_info.pcie_smmu_enabled) {
+				IPA_MPM_DBG("Cleaning SMMU entries..\n");
+			}
+
+			ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, mhip_idx);
+			ipa_mpm_vote_unvote_ipa_clk(CLK_OFF);
+			if (ul_chan != IPA_CLIENT_MAX)
+				ipa_mpm_clean_mhip_chan(mhip_idx, ul_chan);
+			if (dl_chan != IPA_CLIENT_MAX)
+				ipa_mpm_clean_mhip_chan(mhip_idx, dl_chan);
+		}
+	}
+	IPA_MPM_FUNC_EXIT();
+}
+
+/*
+ * Turning on/OFF PCIE Clock is done once for all clients.
+ * Always vote for Probe_ID 0 as a standard.
+ */
+static int ipa_mpm_vote_unvote_pcie_clk(enum ipa_mpm_clk_vote_type vote,
+	int probe_id)
+{
+	int result = 0;
+
+	if (probe_id >= IPA_MPM_MHIP_CH_ID_MAX) {
+		IPA_MPM_ERR("probe_id not found\n");
+		return -EINVAL;
+	}
+
+	if (vote > CLK_OFF) {
+		IPA_MPM_ERR("Invalid vote\n");
+		return -EINVAL;
+	}
+
+	if (ipa_mpm_ctx->md[probe_id].mhi_dev == NULL) {
+		IPA_MPM_ERR("MHI not initialized yet\n");
+		return 0;
+	}
+	if (vote == CLK_ON) {
+		if ((atomic_read(&ipa_mpm_ctx->pcie_clk_ref_cnt) == 0)) {
+			result = mhi_device_get_sync(
+				ipa_mpm_ctx->md[probe_id].mhi_dev);
+			if (result) {
+				IPA_MPM_ERR("mhi_sync_get failed %d\n",
+					result);
+				return result;
+			}
+			IPA_MPM_DBG("PCIE clock now ON\n");
+		}
+		atomic_inc(&ipa_mpm_ctx->pcie_clk_ref_cnt);
+	} else {
+		if ((atomic_read(&ipa_mpm_ctx->pcie_clk_ref_cnt) == 1)) {
+			mhi_device_put(ipa_mpm_ctx->md[probe_id].mhi_dev);
+			IPA_MPM_DBG("PCIE clock off ON\n");
+		}
+		atomic_dec(&ipa_mpm_ctx->pcie_clk_ref_cnt);
+	}
+
+	return result;
+}
+
+/*
+ * Turning on/OFF IPA Clock is done only once- for all clients
+ */
+static void ipa_mpm_vote_unvote_ipa_clk(enum ipa_mpm_clk_vote_type vote)
+{
+	if (vote > CLK_OFF)
+		return;
+
+	if (vote == CLK_ON) {
+		if ((!atomic_read(&ipa_mpm_ctx->ipa_clk_ref_cnt))) {
+			IPA_ACTIVE_CLIENTS_INC_SPECIAL("ipa_mpm");
+			IPA_MPM_DBG("IPA clock now ON\n");
+		}
+		atomic_inc(&ipa_mpm_ctx->ipa_clk_ref_cnt);
+	} else {
+		if ((atomic_read(&ipa_mpm_ctx->ipa_clk_ref_cnt) == 1)) {
+			IPA_ACTIVE_CLIENTS_DEC_SPECIAL("ipa_mpm");
+			IPA_MPM_DBG("IPA clock now OFF\n");
+		}
+		atomic_dec(&ipa_mpm_ctx->ipa_clk_ref_cnt);
+	}
+}
+
+static enum mhip_status_type ipa_mpm_start_stop_mhip_chan(
+	enum ipa_mpm_mhip_chan mhip_chan,
+	int probe_id,
+	enum ipa_mpm_start_stop_type start_stop)
+{
+	int ipa_ep_idx;
+	struct ipa3_ep_context *ep;
+	bool is_start;
+	enum ipa_client_type ul_chan, dl_chan;
+	u32 source_pipe_bitmask = 0;
+	enum gsi_status gsi_res = GSI_STATUS_SUCCESS;
+	int result;
+
+	IPA_MPM_FUNC_ENTRY();
+
+	if (mhip_chan > IPA_MPM_MHIP_CHAN_BOTH) {
+		IPA_MPM_ERR("MHI not initialized yet\n");
+		return MHIP_STATUS_FAIL;
+	}
+
+	if (probe_id >= IPA_MPM_MHIP_CH_ID_MAX) {
+		IPA_MPM_ERR("MHI not initialized yet\n");
+		return MHIP_STATUS_FAIL;
+	}
+
+	get_ipa3_client(probe_id, &ul_chan, &dl_chan);
+
+	if (mhip_chan == IPA_MPM_MHIP_CHAN_UL) {
+		ipa_ep_idx = ipa3_get_ep_mapping(ul_chan);
+	} else if (mhip_chan == IPA_MPM_MHIP_CHAN_DL) {
+		ipa_ep_idx = ipa3_get_ep_mapping(dl_chan);
+	} else if (mhip_chan == IPA_MPM_MHIP_CHAN_BOTH) {
+		ipa_ep_idx = ipa3_get_ep_mapping(ul_chan);
+		ipa_ep_idx = ipa3_get_ep_mapping(dl_chan);
+	}
+
+	if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) {
+		IPA_MPM_ERR("fail to get EP# for idx %d\n", ipa_ep_idx);
+		return MHIP_STATUS_EP_NOT_FOUND;
+	}
+	ep = &ipa3_ctx->ep[ipa_ep_idx];
+
+	IPA_MPM_DBG("current GSI state = %d, action = %d\n",
+		ipa_mpm_ctx->md[probe_id].gsi_state, start_stop);
+
+	if (ipa_mpm_ctx->md[probe_id].gsi_state < GSI_ALLOCATED) {
+		IPA_MPM_ERR("GSI chan is not allocated yet..\n");
+		return MHIP_STATUS_EP_NOT_READY;
+	}
+
+	is_start = (start_stop == START) ? true : false;
+
+	if (is_start) {
+		if (ipa_mpm_ctx->md[probe_id].gsi_state == GSI_STARTED) {
+			IPA_MPM_ERR("GSI chan is already started\n");
+			return MHIP_STATUS_NO_OP;
+		}
+
+		/* Start GSI channel */
+		gsi_res = ipa3_start_gsi_channel(ipa_ep_idx);
+		if (gsi_res != GSI_STATUS_SUCCESS) {
+			IPA_MPM_ERR("Error starting channel: err = %d\n",
+					gsi_res);
+			goto gsi_chan_fail;
+		} else {
+			ipa_mpm_change_gsi_state(probe_id, GSI_STARTED);
+		}
+	} else {
+		if (ipa_mpm_ctx->md[probe_id].gsi_state == GSI_STOPPED) {
+			IPA_MPM_ERR("GSI chan is already stopped\n");
+			return MHIP_STATUS_NO_OP;
+		} else if (ipa_mpm_ctx->md[probe_id].gsi_state !=
+							GSI_STARTED) {
+			IPA_MPM_ERR("GSI chan is not previously started\n");
+			return MHIP_STATUS_BAD_STATE;
+		}
+
+		if (mhip_chan == IPA_MPM_MHIP_CHAN_UL) {
+			source_pipe_bitmask = 1 <<
+				ipa3_get_ep_mapping(ep->client);
+
+			/* First Stop UL GSI channel before unvote PCIe clock */
+			result = ipa3_stop_gsi_channel(ipa_ep_idx);
+
+			if (result) {
+				IPA_MPM_ERR("UL chan stop failed\n");
+				goto gsi_chan_fail;
+			} else {
+				ipa_mpm_change_gsi_state(probe_id,
+							GSI_STARTED);
+			}
+		}
+
+		if (mhip_chan == IPA_MPM_MHIP_CHAN_DL) {
+			result = ipa3_stop_gsi_channel(ipa_ep_idx);
+			if (result) {
+				IPA_MPM_ERR("Fail to stop DL channel\n");
+				goto gsi_chan_fail;
+			} else {
+				ipa_mpm_change_gsi_state(probe_id, GSI_STOPPED);
+			}
+		}
+	}
+	IPA_MPM_FUNC_EXIT();
+
+	return MHIP_STATUS_SUCCESS;
+gsi_chan_fail:
+	ipa3_disable_data_path(ipa_ep_idx);
+	ipa_mpm_change_gsi_state(probe_id, GSI_ERR);
+	ipa_assert();
+
+	return MHIP_STATUS_FAIL;
+}
+
+int ipa_mpm_notify_wan_state(void)
+{
+	int probe_id = IPA_MPM_MHIP_CH_ID_MAX;
+	int i;
+	static enum mhip_status_type status;
+	int ret = 0;
+	enum ipa_client_type ul_chan, dl_chan;
+	enum ipa_mpm_mhip_client_type mhip_client = IPA_MPM_MHIP_TETH;
+
+	if (!ipa3_is_mhip_offload_enabled())
+		return -EPERM;
+
+	for (i = 0; i < IPA_MPM_MHIP_CH_ID_MAX; i++) {
+		if (ipa_mpm_pipes[i].mhip_client == mhip_client) {
+			probe_id = i;
+			break;
+		}
+	}
+
+	if (probe_id == IPA_MPM_MHIP_CH_ID_MAX) {
+		IPA_MPM_ERR("Unknown probe_id\n");
+		return -EPERM;
+	}
+
+	IPA_MPM_DBG("WAN backhaul available for probe_id = %d\n", probe_id);
+	get_ipa3_client(probe_id, &ul_chan, &dl_chan);
+
+	/* Start UL MHIP channel for offloading the tethering connection */
+	ret = ipa_mpm_vote_unvote_pcie_clk(CLK_ON, probe_id);
+
+	if (ret) {
+		IPA_MPM_ERR("Error cloking on PCIe clk, err = %d\n", ret);
+		return ret;
+	}
+
+	status = ipa_mpm_start_stop_mhip_chan(
+				IPA_MPM_MHIP_CHAN_UL, probe_id, START);
+	switch (status) {
+	case MHIP_STATUS_SUCCESS:
+	case MHIP_STATUS_NO_OP:
+		ipa_mpm_change_teth_state(probe_id, IPA_MPM_TETH_CONNECTED);
+		ret = ipa_mpm_start_stop_mhip_data_path(probe_id, START);
+
+		if (ret) {
+			IPA_MPM_ERR("Couldnt start UL GSI channel");
+			ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id);
+			return ret;
+		}
+
+		if (status == MHIP_STATUS_NO_OP) {
+			/* Channels already have been started,
+			 * we can devote for pcie clocks
+			 */
+			ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id);
+		}
+		break;
+	case MHIP_STATUS_EP_NOT_READY:
+		ipa_mpm_change_teth_state(probe_id, IPA_MPM_TETH_INPROGRESS);
+		break;
+	case MHIP_STATUS_FAIL:
+	case MHIP_STATUS_BAD_STATE:
+	case MHIP_STATUS_EP_NOT_FOUND:
+		IPA_MPM_ERR("UL chan cant be started err =%d\n", status);
+		ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id);
+		ret = -EFAULT;
+		break;
+	default:
+		IPA_MPM_ERR("Err not found\n");
+		break;
+	}
+
+	return ret;
+}
+
+static void ipa_mpm_change_gsi_state(int probe_id,
+	enum ipa_mpm_gsi_state next_state)
+{
+	if (probe_id >= IPA_MPM_MHIP_CH_ID_MAX)
+		return;
+
+	mutex_lock(&ipa_mpm_ctx->md[probe_id].mutex);
+	ipa_mpm_ctx->md[probe_id].gsi_state = next_state;
+	IPA_MPM_DBG("GSI next_state = %d\n",
+		ipa_mpm_ctx->md[probe_id].gsi_state);
+	mutex_unlock(&ipa_mpm_ctx->md[probe_id].mutex);
+}
+
+static void ipa_mpm_change_teth_state(int probe_id,
+	enum ipa_mpm_teth_state next_state)
+{
+	enum ipa_mpm_teth_state curr_state;
+
+	if (probe_id >= IPA_MPM_MHIP_CH_ID_MAX) {
+		IPA_MPM_ERR("Unknown probe_id\n");
+		return;
+	}
+
+	curr_state = ipa_mpm_ctx->md[probe_id].teth_state;
+
+	IPA_MPM_DBG("curr_state = %d, ip_state = %d mhip_s\n",
+		curr_state, next_state);
+
+	switch (curr_state) {
+	case IPA_MPM_TETH_INIT:
+		if (next_state == IPA_MPM_TETH_CONNECTED)
+			next_state = IPA_MPM_TETH_INPROGRESS;
+		break;
+	case IPA_MPM_TETH_INPROGRESS:
+		break;
+	case IPA_MPM_TETH_CONNECTED:
+		break;
+	default:
+		IPA_MPM_ERR("No change in state\n");
+		break;
+	}
+
+	ipa_mpm_ctx->md[probe_id].teth_state = next_state;
+	IPA_MPM_DBG("next_state = %d\n", next_state);
+}
+
+static void ipa_mpm_read_channel(enum ipa_client_type chan)
+{
+	struct gsi_chan_info chan_info;
+	int ipa_ep_idx;
+	struct ipa3_ep_context *ep;
+	int res;
+
+	ipa_ep_idx = ipa3_get_ep_mapping(chan);
+
+	if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) {
+		IPAERR("failed to get idx");
+		return;
+	}
+
+	ep = &ipa3_ctx->ep[ipa_ep_idx];
+
+	IPA_MPM_ERR("Reading channel for chan %d, ep = %d, gsi_chan_hdl = %d\n",
+		chan, ep, ep->gsi_chan_hdl);
+
+	res = ipa3_get_gsi_chan_info(&chan_info, ep->gsi_chan_hdl);
+	if (res)
+		IPA_MPM_ERR("Reading of channel failed for ep %d\n", ep);
+}
+
+static int ipa_mpm_start_stop_mhip_data_path(int probe_id,
+	enum ipa_mpm_start_stop_type start)
+{
+	int ipa_ep_idx;
+	int res = 0;
+	enum ipa_client_type ul_chan, dl_chan;
+
+	if (probe_id >= IPA_MPM_MHIP_CH_ID_MAX) {
+		IPA_MPM_ERR("Unknown probe_id\n");
+		return 0;
+	}
+	get_ipa3_client(probe_id, &ul_chan, &dl_chan);
+	IPA_MPM_DBG("Start/Stop Data Path ? = %d\n", start);
+
+	/* Defensive check to make sure start/stop MHIP channels only if
+	 *  MHIP channels are allocated.
+	 */
+
+	if (ipa_mpm_ctx->md[probe_id].gsi_state < GSI_ALLOCATED) {
+		IPA_MPM_ERR("Cant start/stop data, GSI state = %d\n",
+			ipa_mpm_ctx->md[probe_id].gsi_state);
+		return -EFAULT;
+	}
+
+	/* MHIP Start Data path:
+	 * IPA MHIP Producer: remove HOLB
+	 * IPA MHIP Consumer : no op as there is no delay on these pipes.
+	 */
+	if (start) {
+		IPA_MPM_DBG("Enabling data path\n");
+		if (ul_chan != IPA_CLIENT_MAX) {
+			/* Remove HOLB on the producer pipe */
+			IPA_MPM_DBG("Removing HOLB on ep = %s\n",
+				__stringify(ul_chan));
+			ipa_ep_idx = ipa3_get_ep_mapping(ul_chan);
+
+			if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) {
+				IPAERR("failed to get idx");
+				return ipa_ep_idx;
+			}
+
+			res = ipa3_enable_data_path(ipa_ep_idx);
+			if (res)
+				IPA_MPM_ERR("Enable data path failed res=%d\n",
+					res);
+		}
+	} else {
+		IPA_MPM_DBG("Disabling data path\n");
+		if (ul_chan != IPA_CLIENT_MAX) {
+			/* Set HOLB on the producer pipe */
+			ipa_ep_idx = ipa3_get_ep_mapping(ul_chan);
+
+			if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) {
+				IPAERR("failed to get idx");
+				return ipa_ep_idx;
+			}
+
+			res = ipa3_disable_data_path(ipa_ep_idx);
+			if (res)
+				IPA_MPM_ERR("disable data path failed res=%d\n",
+					res);
+		}
+	}
+
+	return res;
+}
+
+/* ipa_mpm_mhi_probe_cb is received for each MHI'/MHI channel
+ * Currently we have 4 MHI channels.
+ */
+static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev,
+	const struct mhi_device_id *mhi_id)
+{
+	struct ipa_mpm_channel *ch;
+	int ret;
+	enum ipa_client_type ul_prod, dl_cons;
+	int probe_id;
+	struct ipa_req_chan_out_params ul_out_params, dl_out_params;
+	void __iomem  *db_addr;
+	int ipa_ep_idx;
+	struct ipa3_ep_context *ep;
+	u32 evt_ring_db_addr_low, evt_ring_db_addr_high;
+	u32 wp_addr;
+
+	IPA_MPM_FUNC_ENTRY();
+
+	if (ipa_mpm_ctx == NULL) {
+		IPA_MPM_ERR("ipa_mpm_ctx is NULL not expected, returning..\n");
+		return -ENOMEM;
+	}
+
+	probe_id = get_idx_from_id(mhi_id);
+
+	if (probe_id >= IPA_MPM_MHIP_CH_ID_MAX) {
+		IPA_MPM_ERR("chan=%s is not supported for now\n", mhi_id);
+		return -EPERM;
+	}
+
+	if (ipa_mpm_ctx->md[probe_id].init_complete) {
+		IPA_MPM_ERR("Probe initialization already done, returning\n");
+		return -EPERM;
+	}
+
+	IPA_MPM_DBG("Received probe for id=%d\n", probe_id);
+
+	if (probe_id == IPA_MPM_MHIP_CH_ID_2) {
+		/* NOTE :: DPL not supported yet , remove later */
+		IPA_MPM_DBG("DPL not supported yet - returning for DPL..\n");
+		return 0;
+	}
+
+	get_ipa3_client(probe_id, &ul_prod, &dl_cons);
+
+	/* Vote for IPA clock for first time in initialization seq.
+	 * IPA clock will be devoted when MHI enters LPM
+	 * PCIe clock will be voted / devoted with every channel probe
+	 * we receive.
+	 * ul_prod = Host -> Device
+	 * dl_cons = Device -> Host
+	 */
+	ipa_mpm_ctx->md[probe_id].mhi_dev = mhi_dev;
+
+	ipa_mpm_vote_unvote_pcie_clk(CLK_ON, probe_id);
+	ipa_mpm_vote_unvote_ipa_clk(CLK_ON);
+	/* NOTE :: Duplicate IPA vote - just for BU, remove later */
+	ipa_mpm_vote_unvote_ipa_clk(CLK_ON);
+
+	IPA_MPM_DBG("ul chan = %d, dl_chan = %d\n", ul_prod, dl_cons);
+
+	/*
+	 * Set up MHI' pipes for Device IPA filling in
+	 * Channel Context and Event Context.
+	 * These params will be sent to Device side.
+	 * UL CHAN = HOST -> Device
+	 * DL CHAN = Device -> HOST
+	 * per channel a TRE and EV is allocated.
+	 * for a UL channel -
+	 * IPA HOST PROD TRE -> IPA DEVICE CONS EV
+	 * IPA HOST PROD EV ->  IPA DEVICE CONS TRE
+	 * for a DL channel -
+	 * IPA Device PROD TRE -> IPA HOST CONS EV
+	 * IPA Device PROD EV ->  IPA HOST CONS TRE
+	 */
+	if (probe_id != IPA_MPM_MHIP_CH_ID_2) {
+		if (ul_prod != IPA_CLIENT_MAX) {
+			/* store UL properties */
+			ch = &ipa_mpm_ctx->md[probe_id].ul_prod;
+			/* Store Channel properties */
+			ch->chan_props.id = mhi_dev->ul_chan_id;
+			ch->chan_props.device_db =
+				ipa_mpm_ctx->dev_info.chdb_base +
+				ch->chan_props.id * 8;
+			/* Fill Channel Conext to be sent to Device side */
+			ch->chan_props.ch_ctx.chtype =
+				IPA_MPM_MHI_HOST_UL_CHANNEL;
+			ch->chan_props.ch_ctx.erindex =
+				mhi_dev->ul_event_id;
+			ch->chan_props.ch_ctx.rlen = (IPA_MPM_RING_LEN) *
+				GSI_EVT_RING_RE_SIZE_16B;
+			/* Store Event properties */
+			ch->evt_props.ev_ctx.update_rp_modc = 0;
+			ch->evt_props.ev_ctx.update_rp_intmodt = 0;
+			ch->evt_props.ev_ctx.ertype = 1;
+			ch->evt_props.ev_ctx.rlen = (IPA_MPM_RING_LEN) *
+				GSI_EVT_RING_RE_SIZE_16B;
+			ch->evt_props.ev_ctx.buff_size = TRE_BUFF_SIZE;
+			ch->evt_props.device_db =
+				ipa_mpm_ctx->dev_info.erdb_base +
+				ch->chan_props.ch_ctx.erindex * 8;
+		}
+	}
+	if (dl_cons != IPA_CLIENT_MAX) {
+		/* store DL channel properties */
+		ch = &ipa_mpm_ctx->md[probe_id].dl_cons;
+		/* Store Channel properties */
+		ch->chan_props.id = mhi_dev->dl_chan_id;
+		ch->chan_props.device_db =
+			ipa_mpm_ctx->dev_info.chdb_base +
+			ch->chan_props.id * 8;
+		/* Fill Channel Conext to be be sent to Dev side */
+		ch->chan_props.ch_ctx.chstate = 1;
+		ch->chan_props.ch_ctx.chtype =
+			IPA_MPM_MHI_HOST_DL_CHANNEL;
+		ch->chan_props.ch_ctx.erindex = mhi_dev->dl_event_id;
+		ch->chan_props.ch_ctx.rlen = (IPA_MPM_RING_LEN) *
+			GSI_EVT_RING_RE_SIZE_16B;
+		/* Store Event properties */
+		ch->evt_props.ev_ctx.update_rp_modc = 0;
+		ch->evt_props.ev_ctx.update_rp_intmodt = 0;
+		ch->evt_props.ev_ctx.ertype = 1;
+		ch->evt_props.ev_ctx.rlen = (IPA_MPM_RING_LEN) *
+			GSI_EVT_RING_RE_SIZE_16B;
+		ch->evt_props.ev_ctx.buff_size = TRE_BUFF_SIZE;
+		ch->evt_props.device_db =
+			ipa_mpm_ctx->dev_info.erdb_base +
+			ch->chan_props.ch_ctx.erindex * 8;
+	}
+	/* connect Host GSI pipes with MHI' protocol */
+	if (probe_id != IPA_MPM_MHIP_CH_ID_2)  {
+		ret = ipa_mpm_connect_mhip_gsi_pipe(ul_prod,
+			probe_id, &ul_out_params);
+		if (ret) {
+			IPA_MPM_ERR("failed connecting MPM client %d\n",
+					ul_prod);
+			goto fail_gsi_setup;
+		}
+	}
+	ret = ipa_mpm_connect_mhip_gsi_pipe(dl_cons, probe_id, &dl_out_params);
+	if (ret) {
+		IPA_MPM_ERR("connecting MPM client = %d failed\n",
+			dl_cons);
+		goto fail_gsi_setup;
+	}
+	if (probe_id != IPA_MPM_MHIP_CH_ID_2)  {
+		if (ul_prod != IPA_CLIENT_MAX) {
+			ch = &ipa_mpm_ctx->md[probe_id].ul_prod;
+			ch->evt_props.ev_ctx.update_rp_addr =
+				ipa_mpm_smmu_map_doorbell(
+					MHIP_SMMU_DOMAIN_PCIE,
+					ul_out_params.db_reg_phs_addr_lsb);
+
+			if (ch->evt_props.ev_ctx.update_rp_addr == 0)
+				ipa_assert();
+
+			ret = __ipa_mpm_configure_mhi_device(
+					ch, probe_id, DMA_TO_HIPA);
+			if (ret) {
+				IPA_MPM_ERR("configure_mhi_dev fail %d\n",
+						ret);
+				goto fail_smmu;
+			}
+		}
+	}
+
+	if (dl_cons != IPA_CLIENT_MAX) {
+		ch = &ipa_mpm_ctx->md[probe_id].dl_cons;
+		ch->evt_props.ev_ctx.update_rp_addr =
+			ipa_mpm_smmu_map_doorbell(
+					MHIP_SMMU_DOMAIN_PCIE,
+					dl_out_params.db_reg_phs_addr_lsb);
+
+		if (ch->evt_props.ev_ctx.update_rp_addr == 0)
+			ipa_assert();
+
+		ret = __ipa_mpm_configure_mhi_device(ch, probe_id,
+					DMA_FROM_HIPA);
+		if (ret) {
+			IPA_MPM_ERR("mpm_config_mhi_dev failed %d\n", ret);
+			goto fail_smmu;
+		}
+	}
+
+	ret = mhi_prepare_for_transfer(ipa_mpm_ctx->md[probe_id].mhi_dev);
+	if (ret) {
+		IPA_MPM_ERR("mhi_prepare_for_transfer failed %d\n", ret);
+		goto fail_smmu;
+	}
+
+	/*
+	 * Ring initial channel db - Host Side UL and Device side DL channel.
+	 * To ring doorbell, write "WP" into doorbell register.
+	 * This WP should be set to 1 element less than ring max.
+	 */
+
+	/* Ring UL PRODUCER TRANSFER RING (HOST IPA -> DEVICE IPA) Doorbell */
+	if (ul_prod != IPA_CLIENT_MAX) {
+		IPA_MPM_DBG("Host UL TR PA DB = 0X%0x\n",
+			ul_out_params.db_reg_phs_addr_lsb);
+
+		db_addr = ioremap(
+			(phys_addr_t)(ul_out_params.db_reg_phs_addr_lsb), 4);
+
+		wp_addr = ipa_mpm_ctx->md[probe_id].ul_prod_ring.tr_pa +
+			((IPA_MPM_RING_LEN - 1) * GSI_CHAN_RE_SIZE_16B);
+
+		iowrite32(wp_addr, db_addr);
+
+		IPA_MPM_DBG("Host UL TR  DB = 0X%0x, wp_addr = 0X%0x",
+			db_addr, wp_addr);
+
+		iounmap(db_addr);
+		ipa_mpm_read_channel(ul_prod);
+	}
+
+	/* Ring UL PRODUCER EVENT RING (HOST IPA -> DEVICE IPA) Doorbell
+	 * Ring the event DB to a value outside the
+	 * ring range such that rp and wp never meet.
+	 */
+	if (ul_prod != IPA_CLIENT_MAX) {
+		ipa_ep_idx = ipa3_get_ep_mapping(ul_prod);
+
+		if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) {
+			IPA_MPM_ERR("fail to alloc EP.\n");
+			goto fail_start_channel;
+		}
+
+		ep = &ipa3_ctx->ep[ipa_ep_idx];
+
+		IPA_MPM_DBG("for ep_idx %d , gsi_evt_ring_hdl = %d\n",
+			ipa_ep_idx, ep->gsi_evt_ring_hdl);
+		gsi_query_evt_ring_db_addr(ep->gsi_evt_ring_hdl,
+			&evt_ring_db_addr_low, &evt_ring_db_addr_high);
+
+		IPA_MPM_DBG("Host UL ER PA DB = 0X%0x\n",
+			evt_ring_db_addr_low);
+
+		db_addr = ioremap((phys_addr_t)(evt_ring_db_addr_low), 4);
+
+		wp_addr = ipa_mpm_ctx->md[probe_id].ul_prod_ring.er_pa +
+			((IPA_MPM_RING_LEN + 1) * GSI_EVT_RING_RE_SIZE_16B);
+		IPA_MPM_DBG("Host UL ER  DB = 0X%0x, wp_addr = 0X%0x",
+			db_addr, wp_addr);
+
+		iowrite32(wp_addr, db_addr);
+		iounmap(db_addr);
+	}
+
+	/* Ring DEVICE IPA DL CONSUMER Event Doorbell */
+	if (ul_prod != IPA_CLIENT_MAX) {
+		db_addr = ioremap((phys_addr_t)
+			(ipa_mpm_ctx->md[probe_id].ul_prod.evt_props.device_db),
+			4);
+
+		wp_addr = ipa_mpm_ctx->md[probe_id].ul_prod_ring.tr_pa +
+			((IPA_MPM_RING_LEN + 1) * GSI_EVT_RING_RE_SIZE_16B);
+
+		iowrite32(wp_addr, db_addr);
+		iounmap(db_addr);
+	}
+
+	/* Ring DL PRODUCER (DEVICE IPA -> HOST IPA) Doorbell */
+	if (dl_cons != IPA_CLIENT_MAX) {
+		db_addr = ioremap((phys_addr_t)
+		(ipa_mpm_ctx->md[probe_id].dl_cons.chan_props.device_db),
+		4);
+
+		wp_addr = ipa_mpm_ctx->md[probe_id].dl_prod_ring.tr_pa +
+			((IPA_MPM_RING_LEN - 1) * GSI_CHAN_RE_SIZE_16B);
+
+		IPA_MPM_DBG("Device DL TR  DB = 0X%0X, wp_addr = 0X%0x",
+			db_addr, wp_addr);
+
+		iowrite32(wp_addr, db_addr);
+
+		iounmap(db_addr);
+	}
+
+	/*
+	 * Ring event ring DB on Device side.
+	 * ipa_mpm should ring the event DB to a value outside the
+	 * ring range such that rp and wp never meet.
+	 */
+	if (dl_cons != IPA_CLIENT_MAX) {
+		db_addr =
+		ioremap(
+		(phys_addr_t)
+		(ipa_mpm_ctx->md[probe_id].dl_cons.evt_props.device_db),
+		4);
+
+		wp_addr = ipa_mpm_ctx->md[probe_id].dl_prod_ring.er_pa +
+			((IPA_MPM_RING_LEN + 1) * GSI_EVT_RING_RE_SIZE_16B);
+
+		iowrite32(wp_addr, db_addr);
+		IPA_MPM_DBG("Device  UL ER  DB = 0X%0X,wp_addr = 0X%0x",
+			db_addr, wp_addr);
+		iounmap(db_addr);
+	}
+
+	/* Ring DL EVENT RING CONSUMER (DEVICE IPA CONSUMER) Doorbell */
+	if (dl_cons != IPA_CLIENT_MAX) {
+		ipa_ep_idx = ipa3_get_ep_mapping(dl_cons);
+
+		if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED) {
+			IPA_MPM_ERR("fail to alloc EP.\n");
+			goto fail_start_channel;
+		}
+		ep = &ipa3_ctx->ep[ipa_ep_idx];
+		gsi_query_evt_ring_db_addr(ep->gsi_evt_ring_hdl,
+			&evt_ring_db_addr_low, &evt_ring_db_addr_high);
+		IPA_MPM_DBG("Host DL ER PA DB = 0X%0x\n",
+				evt_ring_db_addr_low);
+		db_addr = ioremap((phys_addr_t)(evt_ring_db_addr_low), 4);
+
+		wp_addr = ipa_mpm_ctx->md[probe_id].dl_prod_ring.tr_pa +
+			((IPA_MPM_RING_LEN + 1) * GSI_EVT_RING_RE_SIZE_16B);
+		iowrite32(wp_addr, db_addr);
+		IPA_MPM_DBG("Host  DL ER  DB = 0X%0X, wp_addr = 0X%0x",
+			db_addr, wp_addr);
+		iounmap(db_addr);
+	}
+
+	/* Check if TETH connection is in progress, no op
+	 * if no then Stop UL channel.
+	 */
+	switch (ipa_mpm_ctx->md[probe_id].teth_state) {
+	case IPA_MPM_TETH_INIT:
+		/* No teth started yet, disable UL channel */
+		ipa_mpm_start_stop_mhip_chan(IPA_MPM_MHIP_CHAN_UL,
+						probe_id, STOP);
+
+		/* Disable data path */
+		if (ipa_mpm_start_stop_mhip_data_path(probe_id, STOP)) {
+			IPA_MPM_ERR("MHIP Enable data path failed\n");
+			goto fail_start_channel;
+		}
+		break;
+	case IPA_MPM_TETH_INPROGRESS:
+	case IPA_MPM_TETH_CONNECTED:
+		IPA_MPM_DBG("UL channel is already started, continue\n");
+		ipa_mpm_change_teth_state(probe_id, IPA_MPM_TETH_CONNECTED);
+
+		/* Enable data path */
+		if (ipa_mpm_start_stop_mhip_data_path(probe_id, START)) {
+			IPA_MPM_ERR("MHIP Enable data path failed\n");
+			goto fail_start_channel;
+		}
+
+		/* Lyft the delay for rmnet USB prod pipe */
+		ipa3_set_reset_client_prod_pipe_delay(false,
+			IPA_CLIENT_USB_PROD);
+		break;
+	default:
+		IPA_MPM_DBG("No op for UL channel, in teth state = %d");
+		break;
+	}
+
+	IPA_MPM_FUNC_EXIT();
+	return 0;
+
+fail_gsi_setup:
+fail_start_channel:
+fail_smmu:
+	if (ipa_mpm_ctx->dev_info.ipa_smmu_enabled)
+		IPA_MPM_DBG("SMMU failed\n");
+	ipa_assert();
+	return ret;
+}
+
+static void ipa_mpm_init_mhip_channel_info(void)
+{
+	/* IPA_MPM_MHIP_CH_ID_0 => MHIP TETH PIPES  */
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_0].dl_cons.ipa_client =
+		IPA_CLIENT_MHI_PRIME_TETH_PROD;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_0].dl_cons.ep_cfg =
+		mhip_dl_teth_ep_cfg;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_0].ul_prod.ipa_client =
+		IPA_CLIENT_MHI_PRIME_TETH_CONS;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_0].ul_prod.ep_cfg =
+		mhip_ul_teth_ep_cfg;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_0].mhip_client =
+		IPA_MPM_MHIP_TETH;
+
+	/* IPA_MPM_MHIP_CH_ID_1 => MHIP RMNET PIPES */
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_1].dl_cons.ipa_client =
+		IPA_CLIENT_MHI_PRIME_RMNET_PROD;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_1].dl_cons.ep_cfg =
+		mhip_dl_rmnet_ep_cfg;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_1].ul_prod.ipa_client =
+		IPA_CLIENT_MHI_PRIME_RMNET_CONS;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_1].ul_prod.ep_cfg =
+		mhip_ul_rmnet_ep_cfg;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_1].mhip_client =
+		IPA_MPM_MHIP_USB_RMNET;
+
+	/* IPA_MPM_MHIP_CH_ID_2 => MHIP ADPL PIPE */
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_2].dl_cons.ipa_client =
+		IPA_CLIENT_MHI_PRIME_DPL_PROD;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_2].dl_cons.ep_cfg =
+		mhip_dl_dpl_ep_cfg;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_2].ul_prod.ipa_client =
+		IPA_CLIENT_MAX;
+	ipa_mpm_pipes[IPA_MPM_MHIP_CH_ID_2].mhip_client =
+	IPA_MPM_MHIP_USB_DPL;
+}
+
+static void ipa_mpm_mhi_remove_cb(struct mhi_device *mhi_dev)
+{
+	IPA_MPM_FUNC_ENTRY();
+	ipa_mpm_mhip_shutdown();
+	IPA_MPM_FUNC_EXIT();
+}
+
+static void ipa_mpm_mhi_status_cb(struct mhi_device *mhi_dev,
+				enum MHI_CB mhi_cb)
+{
+	int mhip_idx;
+	enum mhip_status_type status;
+
+	IPA_MPM_DBG("%d\n", mhi_cb);
+
+	for (mhip_idx = 0; mhip_idx < IPA_MPM_MHIP_CH_ID_MAX; mhip_idx++) {
+		if (mhi_dev == ipa_mpm_ctx->md[mhip_idx].mhi_dev)
+			break;
+	}
+	if (mhip_idx >= IPA_MPM_MHIP_CH_ID_MAX) {
+		IPA_MPM_DBG("ignoring secondary callbacks\n");
+		return;
+	}
+	switch (mhi_cb) {
+	case MHI_CB_IDLE:
+		break;
+	case MHI_CB_LPM_ENTER:
+		status = ipa_mpm_start_stop_mhip_chan(IPA_MPM_MHIP_CHAN_DL,
+							mhip_idx, STOP);
+		IPA_MPM_DBG("status = %d\n", status);
+		ipa_mpm_vote_unvote_ipa_clk(CLK_OFF);
+		break;
+	case MHI_CB_LPM_EXIT:
+		status = ipa_mpm_start_stop_mhip_chan(IPA_MPM_MHIP_CHAN_DL,
+							mhip_idx, START);
+		ipa_mpm_vote_unvote_ipa_clk(CLK_ON);
+		break;
+	case MHI_CB_EE_RDDM:
+	case MHI_CB_PENDING_DATA:
+	case MHI_CB_SYS_ERROR:
+	case MHI_CB_FATAL_ERROR:
+		IPA_MPM_ERR("unexpected event %d\n", mhi_cb);
+		break;
+	}
+}
+
+static int ipa_mpm_set_dma_mode(enum ipa_client_type src_pipe,
+	enum ipa_client_type dst_pipe)
+{
+	int result = 0;
+	struct ipa_ep_cfg ep_cfg = { { 0 } };
+
+	IPA_MPM_FUNC_ENTRY();
+	IPA_MPM_DBG("DMA from %d to %d\n", src_pipe, dst_pipe);
+
+	/* Set USB PROD PIPE DMA to MHIP PROD PIPE */
+	ep_cfg.mode.mode = IPA_DMA;
+	ep_cfg.mode.dst = dst_pipe;
+	ep_cfg.seq.set_dynamic = true;
+
+	result = ipa_cfg_ep(ipa_get_ep_mapping(src_pipe), &ep_cfg);
+	IPA_MPM_FUNC_EXIT();
+
+	return result;
+}
+
+static int ipa_mpm_reset_dma_mode(enum ipa_client_type src_pipe,
+	enum ipa_client_type dst_pipe)
+{
+	int result = 0;
+	struct ipa_ep_cfg ep_cfg = { { 0 } };
+
+	IPA_MPM_FUNC_ENTRY();
+	IPA_MPM_DBG("DMA from %d to %d\n", src_pipe, dst_pipe);
+
+	/* Set USB PROD PIPE DMA to MHIP PROD PIPE */
+	ep_cfg.mode.mode = IPA_BASIC;
+	ep_cfg.mode.dst = IPA_CLIENT_APPS_LAN_CONS;
+	ep_cfg.seq.set_dynamic = true;
+
+	result = ipa_cfg_ep(ipa_get_ep_mapping(src_pipe), &ep_cfg);
+	IPA_MPM_FUNC_EXIT();
+
+	return result;
+}
+
+static void ipa_mpm_mhip_map_prot(enum ipa_usb_teth_prot prot,
+	enum ipa_mpm_mhip_client_type *mhip_client)
+{
+	switch (prot) {
+	case IPA_USB_RNDIS:
+		*mhip_client = IPA_MPM_MHIP_TETH;
+		break;
+	case IPA_USB_RMNET:
+		*mhip_client = IPA_MPM_MHIP_USB_RMNET;
+		break;
+	case IPA_USB_DIAG:
+		*mhip_client = IPA_MPM_MHIP_USB_DPL;
+		break;
+	default:
+		*mhip_client = IPA_MPM_MHIP_NONE;
+		break;
+	}
+	IPA_MPM_DBG("Mapped xdci prot %d -> MHIP prot %d\n", prot,
+		*mhip_client);
+}
+
+int ipa_mpm_mhip_xdci_pipe_enable(enum ipa_usb_teth_prot xdci_teth_prot)
+{
+	int probe_id = IPA_MPM_MHIP_CH_ID_MAX;
+	int i;
+	enum ipa_mpm_mhip_client_type mhip_client;
+	enum mhip_status_type status;
+	int ret = 0;
+
+	if (ipa_mpm_ctx == NULL) {
+		IPA_MPM_ERR("MPM not platform probed yet, returning ..\n");
+		return 0;
+	}
+
+	ipa_mpm_mhip_map_prot(xdci_teth_prot, &mhip_client);
+
+	for (i = 0; i < IPA_MPM_MHIP_CH_ID_MAX; i++) {
+		if (ipa_mpm_pipes[i].mhip_client == mhip_client) {
+			probe_id = i;
+			break;
+		}
+	}
+
+	if (probe_id == IPA_MPM_MHIP_CH_ID_MAX) {
+		IPA_MPM_ERR("Unknown probe_id\n");
+		return 0;
+	}
+
+	IPA_MPM_DBG("Connect xdci prot %d -> mhip_client = %d probe_id = %d\n",
+		xdci_teth_prot, mhip_client, probe_id);
+
+	ipa_mpm_ctx->md[probe_id].mhip_client = mhip_client;
+
+	switch (mhip_client) {
+	case IPA_MPM_MHIP_USB_RMNET:
+		ipa_mpm_set_dma_mode(IPA_CLIENT_USB_PROD,
+			IPA_CLIENT_MHI_PRIME_RMNET_CONS);
+		break;
+	case IPA_MPM_MHIP_TETH:
+	case IPA_MPM_MHIP_USB_DPL:
+		IPA_MPM_DBG("Teth connecting for prot %d\n", mhip_client);
+		return 0;
+	default:
+		IPA_MPM_ERR("mhip_client = %d not supported\n", mhip_client);
+		ret = 0;
+		break;
+	}
+
+	/* Start UL MHIP channel for offloading the tethering connection */
+	ret = ipa_mpm_vote_unvote_pcie_clk(CLK_ON, probe_id);
+
+	if (ret) {
+		IPA_MPM_ERR("Error cloking on PCIe clk, err = %d\n", ret);
+		return ret;
+	}
+
+	status = ipa_mpm_start_stop_mhip_chan(IPA_MPM_MHIP_CHAN_UL,
+						probe_id, START);
+
+	switch (status) {
+	case MHIP_STATUS_SUCCESS:
+	case MHIP_STATUS_NO_OP:
+		ipa_mpm_change_teth_state(probe_id, IPA_MPM_TETH_CONNECTED);
+		ipa_mpm_start_stop_mhip_data_path(probe_id, START);
+		/* Lift the delay for rmnet USB prod pipe */
+		ipa3_set_reset_client_prod_pipe_delay(false,
+			IPA_CLIENT_USB_PROD);
+		if (status == MHIP_STATUS_NO_OP) {
+			/* Channels already have been started,
+			 * we can devote for pcie clocks
+			 */
+			ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id);
+		}
+		break;
+	case MHIP_STATUS_EP_NOT_READY:
+		ipa_mpm_change_teth_state(probe_id, IPA_MPM_TETH_INPROGRESS);
+		break;
+	case MHIP_STATUS_FAIL:
+	case MHIP_STATUS_BAD_STATE:
+	case MHIP_STATUS_EP_NOT_FOUND:
+		IPA_MPM_ERR("UL chan cant be started err =%d\n", status);
+		ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id);
+		ret = -EFAULT;
+		break;
+	default:
+		IPA_MPM_ERR("Err not found\n");
+		break;
+	}
+	return ret;
+}
+
+int ipa_mpm_mhip_ul_data_stop(enum ipa_usb_teth_prot xdci_teth_prot)
+{
+	int probe_id = IPA_MPM_MHIP_CH_ID_MAX;
+	int i;
+	enum ipa_mpm_mhip_client_type mhip_client;
+	int ret = 0;
+
+	if (ipa_mpm_ctx == NULL) {
+		IPA_MPM_ERR("MPM not platform probed, returning ..\n");
+		return 0;
+	}
+
+	ipa_mpm_mhip_map_prot(xdci_teth_prot, &mhip_client);
+
+	for (i = 0; i < IPA_MPM_MHIP_CH_ID_MAX; i++) {
+		if (ipa_mpm_pipes[i].mhip_client == mhip_client) {
+			probe_id = i;
+			break;
+		}
+	}
+
+	if (probe_id == IPA_MPM_MHIP_CH_ID_MAX) {
+		IPA_MPM_ERR("Invalid probe_id\n");
+		return 0;
+	}
+
+	IPA_MPM_DBG("Map xdci prot %d to mhip_client = %d probe_id = %d\n",
+		xdci_teth_prot, mhip_client, probe_id);
+
+	ret = ipa_mpm_start_stop_mhip_data_path(probe_id, STOP);
+
+	if (ret)
+		IPA_MPM_ERR("Error stopping UL path, err = %d\n", ret);
+
+	return ret;
+}
+
+int ipa_mpm_mhip_xdci_pipe_disable(enum ipa_usb_teth_prot xdci_teth_prot)
+{
+	int probe_id = IPA_MPM_MHIP_CH_ID_MAX;
+	int i;
+	enum ipa_mpm_mhip_client_type mhip_client;
+	enum mhip_status_type status;
+	int ret = 0;
+
+	if (ipa_mpm_ctx == NULL) {
+		IPA_MPM_ERR("MPM not platform probed, returning ..\n");
+		return 0;
+	}
+
+	ipa_mpm_mhip_map_prot(xdci_teth_prot, &mhip_client);
+
+	for (i = 0; i < IPA_MPM_MHIP_CH_ID_MAX; i++) {
+		if (ipa_mpm_pipes[i].mhip_client == mhip_client) {
+			probe_id = i;
+			break;
+		}
+	}
+
+	if (probe_id == IPA_MPM_MHIP_CH_ID_MAX) {
+		IPA_MPM_ERR("Invalid probe_id\n");
+		return 0;
+	}
+
+	IPA_MPM_DBG("xdci disconnect prot %d mhip_client = %d probe_id = %d\n",
+			xdci_teth_prot, mhip_client, probe_id);
+
+	switch (mhip_client) {
+	case IPA_MPM_MHIP_USB_RMNET:
+		ipa_mpm_reset_dma_mode(IPA_CLIENT_USB_PROD,
+			IPA_CLIENT_MHI_PRIME_RMNET_CONS);
+		break;
+	case IPA_MPM_MHIP_TETH:
+	case IPA_MPM_MHIP_USB_DPL:
+		IPA_MPM_DBG("Teth Disconnecting for prot %d\n", mhip_client);
+		return 0;
+	default:
+		IPA_MPM_ERR("mhip_client = %d not supported\n", mhip_client);
+		return 0;
+	}
+
+	status = ipa_mpm_start_stop_mhip_chan(IPA_MPM_MHIP_CHAN_UL,
+		probe_id, STOP);
+
+	switch (status) {
+	case MHIP_STATUS_SUCCESS:
+	case MHIP_STATUS_NO_OP:
+	case MHIP_STATUS_EP_NOT_READY:
+		ipa_mpm_change_teth_state(probe_id, IPA_MPM_TETH_INIT);
+		ipa_mpm_start_stop_mhip_data_path(probe_id, STOP);
+		break;
+	case MHIP_STATUS_FAIL:
+	case MHIP_STATUS_BAD_STATE:
+	case MHIP_STATUS_EP_NOT_FOUND:
+		IPA_MPM_ERR("UL chan cant be started err =%d\n", status);
+		ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id);
+		ret = -EFAULT;
+		break;
+	default:
+		IPA_MPM_ERR("Err not found\n");
+		break;
+	}
+
+	ret = ipa_mpm_vote_unvote_pcie_clk(CLK_OFF, probe_id);
+
+	if (ret) {
+		IPA_MPM_ERR("Error cloking off PCIe clk, err = %d\n", ret);
+		return ret;
+	}
+
+	ipa_mpm_ctx->md[probe_id].mhip_client = IPA_MPM_MHIP_NONE;
+
+	return ret;
+}
+
+static int ipa_mpm_populate_smmu_info(struct platform_device *pdev)
+{
+	struct ipa_smmu_in_params smmu_in;
+	struct ipa_smmu_out_params smmu_out;
+	u32 carved_iova_ap_mapping[2];
+	struct ipa_smmu_cb_ctx *cb;
+	struct ipa_smmu_cb_ctx *ap_cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
+	int ret = 0;
+
+	if (ipa_mpm_ctx->carved_smmu_cb.valid) {
+		IPA_MPM_DBG("SMMU Context allocated, returning ..\n");
+		return ret;
+	}
+
+	cb = &ipa_mpm_ctx->carved_smmu_cb;
+
+	/* get IPA SMMU enabled status */
+	smmu_in.smmu_client = IPA_SMMU_AP_CLIENT;
+	if (ipa_get_smmu_params(&smmu_in, &smmu_out))
+		ipa_mpm_ctx->dev_info.ipa_smmu_enabled = false;
+	else
+		ipa_mpm_ctx->dev_info.ipa_smmu_enabled =
+		smmu_out.smmu_enable;
+
+	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,iova-mapping",
+		carved_iova_ap_mapping, 2)) {
+		IPA_MPM_ERR("failed to read of_node %s\n",
+			"qcom,mpm-iova-mapping");
+		return -EINVAL;
+	}
+	ipa_mpm_ctx->dev_info.pcie_smmu_enabled = true;
+
+	if (ipa_mpm_ctx->dev_info.ipa_smmu_enabled !=
+		ipa_mpm_ctx->dev_info.pcie_smmu_enabled) {
+		IPA_MPM_DBG("PCIE/IPA SMMU config mismatch\n");
+		return -EINVAL;
+	}
+
+	cb->va_start = carved_iova_ap_mapping[0];
+	cb->va_size = carved_iova_ap_mapping[1];
+	cb->va_end = cb->va_start + cb->va_size;
+
+	if (cb->va_start >= ap_cb->va_start && cb->va_start < ap_cb->va_end) {
+		IPA_MPM_ERR("MPM iommu and AP overlap addr 0x%lx\n",
+				cb->va_start);
+		ipa_assert();
+		return -EFAULT;
+	}
+
+	cb->dev = ipa_mpm_ctx->dev_info.dev;
+	cb->valid = true;
+	cb->next_addr = cb->va_start;
+
+	if (dma_set_mask_and_coherent(ipa_mpm_ctx->dev_info.dev,
+		DMA_BIT_MASK(64))) {
+		IPA_MPM_ERR("setting DMA mask to 64 failed.\n");
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int ipa_mpm_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	int i = 0;
+	int idx = 0;
+
+	IPA_MPM_FUNC_ENTRY();
+
+	if (ipa_mpm_ctx) {
+		IPA_MPM_DBG("MPM is already probed, returning\n");
+		return 0;
+	}
+
+	ret = ipa_register_ipa_ready_cb(ipa_mpm_ipa3_ready_cb, (void *)pdev);
+	/*
+	 * If we received -EEXIST, IPA has initialized. So we need
+	 * to continue the probing process.
+	 */
+	if (!ret) {
+		IPA_MPM_DBG("IPA not ready yet, registering callback\n");
+		return ret;
+	}
+	IPA_MPM_DBG("IPA is ready, continue with probe\n");
+
+	ipa_mpm_ctx = kzalloc(sizeof(*ipa_mpm_ctx), GFP_KERNEL);
+
+	if (!ipa_mpm_ctx)
+		return -ENOMEM;
+
+	for (i = 0; i < IPA_MPM_MHIP_CH_ID_MAX; i++)
+		mutex_init(&ipa_mpm_ctx->md[i].mutex);
+	ipa_mpm_ctx->dev_info.pdev = pdev;
+	ipa_mpm_ctx->dev_info.dev = &pdev->dev;
+
+	ipa_mpm_init_mhip_channel_info();
+
+	if (of_property_read_u32(pdev->dev.of_node, "qcom,mhi-chdb-base",
+		&ipa_mpm_ctx->dev_info.chdb_base)) {
+		IPA_MPM_ERR("failed to read qcom,mhi-chdb-base\n");
+		goto fail_probe;
+	}
+	IPA_MPM_DBG("chdb-base=0x%x\n", ipa_mpm_ctx->dev_info.chdb_base);
+
+	if (of_property_read_u32(pdev->dev.of_node, "qcom,mhi-erdb-base",
+		&ipa_mpm_ctx->dev_info.erdb_base)) {
+		IPA_MPM_ERR("failed to read qcom,mhi-erdb-base\n");
+		goto fail_probe;
+	}
+	IPA_MPM_DBG("erdb-base=0x%x\n", ipa_mpm_ctx->dev_info.erdb_base);
+
+	ret = ipa_mpm_populate_smmu_info(pdev);
+
+	if (ret) {
+		IPA_MPM_DBG("SMMU Config failed\n");
+		goto fail_probe;
+	}
+
+	atomic_set(&ipa_mpm_ctx->ipa_clk_ref_cnt, 0);
+	atomic_set(&ipa_mpm_ctx->pcie_clk_ref_cnt, 0);
+
+	for (idx = 0; idx < IPA_MPM_MHIP_CH_ID_MAX; idx++)
+		ipa_mpm_ctx->md[idx].gsi_state = GSI_INIT;
+
+	ret = mhi_driver_register(&mhi_driver);
+	if (ret) {
+		IPA_MPM_ERR("mhi_driver_register failed %d\n", ret);
+		goto fail_probe;
+	}
+	IPA_MPM_FUNC_EXIT();
+	return 0;
+
+fail_probe:
+	kfree(ipa_mpm_ctx);
+	ipa_mpm_ctx = NULL;
+	return -EFAULT;
+}
+
+static int ipa_mpm_remove(struct platform_device *pdev)
+{
+	IPA_MPM_FUNC_ENTRY();
+
+	mhi_driver_unregister(&mhi_driver);
+	IPA_MPM_FUNC_EXIT();
+	return 0;
+}
+
+static const struct of_device_id ipa_mpm_dt_match[] = {
+	{ .compatible = "qcom,ipa-mpm" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ipa_mpm_dt_match);
+
+static struct platform_driver ipa_ipa_mpm_driver = {
+	.driver = {
+		.name = "ipa_mpm",
+		.of_match_table = ipa_mpm_dt_match,
+	},
+	.probe = ipa_mpm_probe,
+	.remove = ipa_mpm_remove,
+};
+
+/**
+ * ipa_mpm_init() - Registers ipa_mpm as a platform device for a APQ
+ *
+ * This function is called after bootup for APQ device.
+ * ipa_mpm will register itself as a platform device, and probe
+ * function will get called.
+ *
+ * Return: None
+ */
+static int __init ipa_mpm_init(void)
+{
+	IPA_MPM_DBG("register ipa_mpm platform device\n");
+	return platform_driver_register(&ipa_ipa_mpm_driver);
+}
+
+/**
+ * ipa3_is_mhip_offload_enabled() - check if IPA MPM module was initialized
+ * successfully. If it is initialized, MHIP is enabled for teth
+ *
+ * Return value: 1 for yes; 0 for no
+ */
+int ipa3_is_mhip_offload_enabled(void)
+{
+	if (ipa_mpm_ctx == NULL)
+		return 0;
+	else
+		return 1;
+}
+
+late_initcall(ipa_mpm_init);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MHI Proxy Manager Driver");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
index 35a7d87..c570c22 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
@@ -803,7 +803,7 @@ int ipa3_qmi_ul_filter_request_send(
 {
 	struct ipa_configure_ul_firewall_rules_resp_msg_v01 resp;
 	struct ipa_msg_desc req_desc, resp_desc;
-	int rc;
+	int rc, i;
 
 	IPAWANDBG("IPACM pass %u rules to Q6\n",
 		req->firewall_rules_list_len);
@@ -823,6 +823,37 @@ int ipa3_qmi_ul_filter_request_send(
 	}
 	mutex_unlock(&ipa3_qmi_lock);
 
+	/* check if modem is up */
+	if (!ipa3_qmi_indication_fin ||
+		!ipa3_qmi_modem_init_fin ||
+		!ipa_q6_clnt) {
+		IPAWANDBG("modem QMI service is not up yet\n");
+		return -EINVAL;
+	}
+
+	/* Passing 0 rules means that firewall is disabled */
+	if (req->firewall_rules_list_len == 0)
+		IPAWANDBG("IPACM passed 0 rules to Q6\n");
+
+	if (req->firewall_rules_list_len >= QMI_IPA_MAX_UL_FIREWALL_RULES_V01) {
+		IPAWANERR(
+		"Number of rules passed by IPACM, %d, exceed limit %d\n",
+			req->firewall_rules_list_len,
+			QMI_IPA_MAX_UL_FIREWALL_RULES_V01);
+		return -EINVAL;
+	}
+
+	/* Check for valid IP type */
+	for (i = 0; i < req->firewall_rules_list_len; i++) {
+		if (req->firewall_rules_list[i].ip_type !=
+				QMI_IPA_IP_TYPE_V4_V01 &&
+			req->firewall_rules_list[i].ip_type !=
+				QMI_IPA_IP_TYPE_V6_V01)
+			IPAWANERR("Invalid IP type %d\n",
+					req->firewall_rules_list[i].ip_type);
+		return -EINVAL;
+	}
+
 	req_desc.max_msg_len =
 		QMI_IPA_INSTALL_UL_FIREWALL_RULES_REQ_MAX_MSG_LEN_V01;
 	req_desc.msg_id = QMI_IPA_INSTALL_UL_FIREWALL_RULES_REQ_V01;
@@ -836,7 +867,6 @@ int ipa3_qmi_ul_filter_request_send(
 	resp_desc.msg_id = QMI_IPA_INSTALL_UL_FIREWALL_RULES_RESP_V01;
 	resp_desc.ei_array =
 		ipa3_configure_ul_firewall_rules_resp_msg_data_v01_ei;
-
 	rc = ipa3_qmi_send_req_wait(ipa_q6_clnt,
 		&req_desc, req,
 		&resp_desc, &resp,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service_v01.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service_v01.c
index 5a544be..df1906d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service_v01.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service_v01.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
@@ -1402,6 +1402,329 @@ struct qmi_elem_info ipa3_master_driver_init_complt_ind_msg_data_v01_ei[] = {
 	},
 };
 
+static struct qmi_elem_info ipa_filter_rule_req2_type_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_2_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u16),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   rule_eq_bitmap),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   pure_ack_eq_present),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   pure_ack_eq),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   protocol_eq_present),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   protocol_eq),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   num_ihl_offset_range_16),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS_V01,
+		.elem_size      = sizeof(
+			struct ipa_ipfltr_range_eq_16_type_v01),
+		.is_array       = STATIC_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   ihl_offset_range_16),
+		.ei_array      = ipa3_ipfltr_range_eq_16_type_data_v01_ei,
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   num_offset_meq_32),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_IPFLTR_NUM_MEQ_32_EQNS_V01,
+		.elem_size      = sizeof(struct ipa_ipfltr_mask_eq_32_type_v01),
+		.is_array       = STATIC_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   offset_meq_32),
+		.ei_array      = ipa3_ipfltr_mask_eq_32_type_data_v01_ei,
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   tc_eq_present),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   tc_eq),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   flow_eq_present),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   flow_eq),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   ihl_offset_eq_16_present),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct ipa_ipfltr_eq_16_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   ihl_offset_eq_16),
+		.ei_array      = ipa3_ipfltr_eq_16_type_data_v01_ei,
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   ihl_offset_eq_32_present),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct ipa_ipfltr_eq_32_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   ihl_offset_eq_32),
+		.ei_array      = ipa3_ipfltr_eq_32_type_data_v01_ei,
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   num_ihl_offset_meq_32),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS_V01,
+		.elem_size      = sizeof(struct ipa_ipfltr_mask_eq_32_type_v01),
+		.is_array       = STATIC_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   ihl_offset_meq_32),
+		.ei_array      = ipa3_ipfltr_mask_eq_32_type_data_v01_ei,
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   num_offset_meq_128),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_IPFLTR_NUM_MEQ_128_EQNS_V01,
+		.elem_size      = sizeof(
+			struct ipa_ipfltr_mask_eq_128_type_v01),
+		.is_array       = STATIC_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   offset_meq_128),
+		.ei_array      = ipa3_ipfltr_mask_eq_128_type_data_v01_ei,
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   metadata_meq32_present),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct ipa_ipfltr_mask_eq_32_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   metadata_meq32),
+		.ei_array      = ipa3_ipfltr_mask_eq_32_type_data_v01_ei,
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_rule_req2_type_v01,
+					   ipv4_frag_eq_present),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+static struct qmi_elem_info ipa_filter_spec_ex2_type_v01_ei[] = {
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum ipa_ip_type_enum_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_spec_ex2_type_v01,
+					   ip_type),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct ipa_filter_rule_req2_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_spec_ex2_type_v01,
+					   filter_rule),
+		.ei_array      = ipa_filter_rule_req2_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum ipa_filter_action_enum_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_spec_ex2_type_v01,
+					   filter_action),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_spec_ex2_type_v01,
+					   is_routing_table_index_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_spec_ex2_type_v01,
+					   route_table_index),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_spec_ex2_type_v01,
+					   is_mux_id_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_spec_ex2_type_v01,
+					   mux_id),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_spec_ex2_type_v01,
+					   rule_id),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_filter_spec_ex2_type_v01,
+					   is_rule_hashable),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
 struct qmi_elem_info ipa3_install_fltr_rule_req_msg_data_v01_ei[] = {
 	{
 		.data_type	= QMI_OPT_FLAG,
@@ -1556,6 +1879,37 @@ struct qmi_elem_info ipa3_install_fltr_rule_req_msg_data_v01_ei[] = {
 		.ei_array	= ipa_filter_spec_ex_type_data_v01_ei,
 	},
 	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x16,
+		.offset         = offsetof(
+			struct ipa_install_fltr_rule_req_msg_v01,
+			filter_spec_ex2_list_valid),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x16,
+		.offset         = offsetof(
+			struct ipa_install_fltr_rule_req_msg_v01,
+			filter_spec_ex2_list_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_MAX_FILTERS_V01,
+		.elem_size      = sizeof(struct ipa_filter_spec_ex2_type_v01),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x16,
+		.offset         = offsetof(
+			struct ipa_install_fltr_rule_req_msg_v01,
+			filter_spec_ex2_list),
+		.ei_array      = ipa_filter_spec_ex2_type_v01_ei,
+	},
+	{
 		.data_type	= QMI_EOTI,
 		.is_array	= NO_ARRAY,
 		.tlv_type	= QMI_COMMON_TLV_TYPE,
@@ -3001,6 +3355,37 @@ struct qmi_elem_info ipa3_install_fltr_rule_req_ex_msg_data_v01_ei[] = {
 			struct ipa_install_fltr_rule_req_ex_msg_v01,
 			xlat_filter_indices_list),
 	},
+		{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x15,
+		.offset         = offsetof(
+			struct ipa_install_fltr_rule_req_ex_msg_v01,
+			filter_spec_ex2_list_valid),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x15,
+		.offset         = offsetof(
+			struct ipa_install_fltr_rule_req_ex_msg_v01,
+			filter_spec_ex2_list_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_MAX_FILTERS_V01,
+		.elem_size      = sizeof(struct ipa_filter_spec_ex2_type_v01),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x15,
+		.offset         = offsetof(
+			struct ipa_install_fltr_rule_req_ex_msg_v01,
+			filter_spec_ex2_list),
+		.ei_array      = ipa_filter_spec_ex2_type_v01_ei,
+	},
 	{
 		.data_type	= QMI_EOTI,
 		.is_array	= NO_ARRAY,
@@ -4050,3 +4435,474 @@ struct qmi_elem_info ipa_mhi_cleanup_resp_msg_v01_ei[] = {
 		.is_array = QMI_COMMON_TLV_TYPE,
 	},
 };
+
+static struct qmi_elem_info ipa_ep_id_type_v01_ei[] = {
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum ipa_ic_type_enum_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_ep_id_type_v01,
+					   ic_type),
+	},
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum ipa_ep_desc_type_enum_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_ep_id_type_v01,
+					   ep_type),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_ep_id_type_v01,
+					   ep_id),
+	},
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum ipa_ep_status_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct ipa_ep_id_type_v01,
+					   ep_status),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info ipa_endp_desc_indication_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_endp_desc_indication_msg_v01,
+			ep_info_valid),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_endp_desc_indication_msg_v01,
+			ep_info_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_ENDP_DESC_NUM_MAX_V01,
+		.elem_size      = sizeof(struct ipa_ep_id_type_v01),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_endp_desc_indication_msg_v01,
+			ep_info),
+		.ei_array      = ipa_ep_id_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x11,
+		.offset         = offsetof(
+			struct ipa_endp_desc_indication_msg_v01,
+			num_eps_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x11,
+		.offset         = offsetof(
+			struct ipa_endp_desc_indication_msg_v01,
+			num_eps),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+static struct qmi_elem_info ipa_mhi_prime_aggr_info_type_v01_ei[] = {
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum ipa_ic_type_enum_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_type_v01,
+			ic_type),
+	},
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum ipa_ep_desc_type_enum_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_type_v01,
+			ep_type),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_type_v01,
+			bytes_count),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_type_v01,
+			pkt_count),
+	},
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum ipa_aggr_enum_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_type_v01,
+			aggr_type),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info ipa_mhi_prime_aggr_info_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_req_msg_v01,
+			aggr_info_valid),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_req_msg_v01,
+			aggr_info_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_ENDP_DESC_NUM_MAX_V01,
+		.elem_size      = sizeof(
+			struct ipa_mhi_prime_aggr_info_type_v01),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_req_msg_v01,
+			aggr_info),
+		.ei_array      = ipa_mhi_prime_aggr_info_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x11,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_req_msg_v01,
+			num_eps_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x11,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_req_msg_v01,
+			num_eps),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info ipa_mhi_prime_aggr_info_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(
+			struct ipa_mhi_prime_aggr_info_resp_msg_v01,
+			resp),
+		.ei_array      = qmi_response_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info ipa_add_offload_connection_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_req_msg_v01,
+			num_ipv4_filters_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_req_msg_v01,
+			num_ipv4_filters),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x11,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_req_msg_v01,
+			num_ipv6_filters_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x11,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_req_msg_v01,
+			num_ipv6_filters),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x12,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_req_msg_v01,
+			xlat_filter_indices_list_valid),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x12,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_req_msg_v01,
+			xlat_filter_indices_list_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = QMI_IPA_MAX_FILTERS_V01,
+		.elem_size      = sizeof(u32),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x12,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_req_msg_v01,
+			xlat_filter_indices_list),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x13,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_req_msg_v01,
+			filter_spec_ex2_list_valid),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x13,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_req_msg_v01,
+			filter_spec_ex2_list_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_MAX_FILTERS_V01,
+		.elem_size      = sizeof(struct ipa_filter_spec_ex2_type_v01),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x13,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_req_msg_v01,
+			filter_spec_ex2_list),
+		.ei_array      = ipa_filter_spec_ex2_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info ipa_add_offload_connection_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_resp_msg_v01,
+			resp),
+		.ei_array      = qmi_response_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_resp_msg_v01,
+			filter_handle_list_valid),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_resp_msg_v01,
+			filter_handle_list_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_MAX_FILTERS_V01,
+		.elem_size      = sizeof(
+			struct ipa_filter_rule_identifier_to_handle_map_v01),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_add_offload_connection_resp_msg_v01,
+			filter_handle_list),
+		.ei_array      =
+			ipa3_filter_rule_identifier_to_handle_map_data_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info ipa_remove_offload_connection_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_remove_offload_connection_req_msg_v01,
+			filter_handle_list_valid),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_remove_offload_connection_req_msg_v01,
+			filter_handle_list_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = QMI_IPA_MAX_FILTERS_V01,
+		.elem_size      = sizeof(
+			struct ipa_filter_rule_identifier_to_handle_map_v01),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(
+			struct ipa_remove_offload_connection_req_msg_v01,
+			filter_handle_list),
+		.ei_array      =
+			ipa3_filter_rule_identifier_to_handle_map_data_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info ipa_remove_offload_connection_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(
+			struct ipa_remove_offload_connection_resp_msg_v01,
+			resp_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(
+			struct ipa_remove_offload_connection_resp_msg_v01,
+			resp),
+		.ei_array      = qmi_response_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index a07e5f2..33eeff5 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.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
@@ -1590,6 +1590,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only)
 					hdr_entry->cookie != IPA_HDR_COOKIE) {
 						IPAERR_RL(
 						"Header already deleted\n");
+						mutex_unlock(&ipa3_ctx->lock);
 						return -EINVAL;
 					}
 				} else if (rule->proc_ctx) {
@@ -1601,6 +1602,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only)
 							IPA_PROC_HDR_COOKIE) {
 						IPAERR_RL(
 						"Proc entry already deleted\n");
+						mutex_unlock(&ipa3_ctx->lock);
 						return -EINVAL;
 					}
 				}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
index 9e06dcf..386c786 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
@@ -499,6 +499,16 @@ static void ipa3_uc_response_hdlr(enum ipa_irq_type interrupt,
 		 */
 		ipa3_proxy_clk_unvote();
 
+		/*
+		 * To enable ipa power collapse we need to enable rpmh and uc
+		 * handshake So that uc can do register retention. To enable
+		 * this handshake we need to send the below message to rpmh.
+		 * For APQ only target, we do it here once uC loading is
+		 * completed.
+		 */
+		if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_APQ)
+			ipa_pc_qmp_enable();
+
 		for (i = 0; i < IPA_HW_NUM_FEATURES; i++) {
 			if (ipa3_uc_hdlrs[i].ipa_uc_loaded_hdlr)
 				ipa3_uc_hdlrs[i].ipa_uc_loaded_hdlr();
@@ -543,10 +553,12 @@ static void ipa3_uc_wigig_misc_int_handler(enum ipa_irq_type interrupt,
 void ipa3_uc_map_cntr_reg_notify(void)
 {
 	IPAWANDBG("complete the mapping of G_RD_CNTR register\n");
+	IPA_ACTIVE_CLIENTS_INC_SPECIAL("QMI_IPA_UC");
 	ipa3_uc_send_cmd(0,
 		IPA_CPU_2_HW_CMD_DEBUG_GET_INFO,
 		IPA_HW_2_CPU_RESPONSE_CMD_COMPLETED,
 		false, 6*HZ);
+	IPA_ACTIVE_CLIENTS_DEC_SPECIAL("QMI_IPA_UC");
 }
 
 static int ipa3_uc_send_cmd_64b_param(u32 cmd_lo, u32 cmd_hi, u32 opcode,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
index c78ab22..b9a4641 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.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
@@ -503,6 +503,38 @@ int ipa3_wdi_init(void)
 	return 0;
 }
 
+static int ipa_create_ap_smmu_mapping_pa(phys_addr_t pa, size_t len,
+		bool device, unsigned long *iova)
+{
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
+	unsigned long va = roundup(cb->next_addr, PAGE_SIZE);
+	int prot = IOMMU_READ | IOMMU_WRITE;
+	size_t true_len = roundup(len + pa - rounddown(pa, PAGE_SIZE),
+			PAGE_SIZE);
+	int ret;
+
+	if (!cb->valid) {
+		IPAERR("No SMMU CB setup\n");
+		return -EINVAL;
+	}
+
+	if (len > PAGE_SIZE)
+		va = roundup(cb->next_addr, len);
+
+	ret = ipa3_iommu_map(cb->mapping->domain, va, rounddown(pa, PAGE_SIZE),
+			true_len,
+			device ? (prot | IOMMU_MMIO) : prot);
+	if (ret) {
+		IPAERR("iommu map failed for pa=%pa len=%zu\n", &pa, true_len);
+		return -EINVAL;
+	}
+
+	ipa3_ctx->wdi_map_cnt++;
+	cb->next_addr = va + true_len;
+	*iova = va + pa - rounddown(pa, PAGE_SIZE);
+	return 0;
+}
+
 static int ipa_create_uc_smmu_mapping_pa(phys_addr_t pa, size_t len,
 		bool device, unsigned long *iova)
 {
@@ -532,6 +564,67 @@ static int ipa_create_uc_smmu_mapping_pa(phys_addr_t pa, size_t len,
 	return 0;
 }
 
+static int ipa_create_ap_smmu_mapping_sgt(struct sg_table *sgt,
+		unsigned long *iova)
+{
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
+	unsigned long va = roundup(cb->next_addr, PAGE_SIZE);
+	int prot = IOMMU_READ | IOMMU_WRITE;
+	int ret, i;
+	struct scatterlist *sg;
+	unsigned long start_iova = va;
+	phys_addr_t phys;
+	size_t len = 0;
+	int count = 0;
+
+	if (!cb->valid) {
+		IPAERR("No SMMU CB setup\n");
+		return -EINVAL;
+	}
+	if (!sgt) {
+		IPAERR("Bad parameters, scatter / gather list is NULL\n");
+		return -EINVAL;
+	}
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		/* directly get sg_tbl PA from wlan-driver */
+		len += PAGE_ALIGN(sg->offset + sg->length);
+	}
+
+	if (len > PAGE_SIZE) {
+		va = roundup(cb->next_addr,
+				roundup_pow_of_two(len));
+		start_iova = va;
+	}
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		/* directly get sg_tbl PA from wlan-driver */
+		phys = sg->dma_address;
+		len = PAGE_ALIGN(sg->offset + sg->length);
+
+		ret = ipa3_iommu_map(cb->mapping->domain, va, phys, len, prot);
+		if (ret) {
+			IPAERR("iommu map failed for pa=%pa len=%zu\n",
+					&phys, len);
+			goto bad_mapping;
+		}
+		va += len;
+		ipa3_ctx->wdi_map_cnt++;
+		count++;
+	}
+	cb->next_addr = va;
+	*iova = start_iova;
+
+	return 0;
+
+bad_mapping:
+	for_each_sg(sgt->sgl, sg, count, i)
+		iommu_unmap(cb->mapping->domain, sg_dma_address(sg),
+				sg_dma_len(sg));
+	return -EINVAL;
+}
+
+
 static int ipa_create_uc_smmu_mapping_sgt(struct sg_table *sgt,
 		unsigned long *iova)
 {
@@ -582,6 +675,43 @@ static int ipa_create_uc_smmu_mapping_sgt(struct sg_table *sgt,
 	return -EINVAL;
 }
 
+static void ipa_release_ap_smmu_mappings(enum ipa_client_type client)
+{
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
+	int i, j, start, end;
+
+	if (IPA_CLIENT_IS_CONS(client)) {
+		start = IPA_WDI_TX_RING_RES;
+		if (ipa3_ctx->ipa_wdi3_over_gsi)
+			end = IPA_WDI_TX_DB_RES;
+		else
+			end = IPA_WDI_CE_DB_RES;
+	} else {
+		start = IPA_WDI_RX_RING_RES;
+		if (ipa3_ctx->ipa_wdi2 ||
+			ipa3_ctx->ipa_wdi3_over_gsi)
+			end = IPA_WDI_RX_COMP_RING_WP_RES;
+		else
+			end = IPA_WDI_RX_RING_RP_RES;
+	}
+
+	for (i = start; i <= end; i++) {
+		if (wdi_res[i].valid) {
+			for (j = 0; j < wdi_res[i].nents; j++) {
+				iommu_unmap(cb->mapping->domain,
+					wdi_res[i].res[j].iova,
+					wdi_res[i].res[j].size);
+				ipa3_ctx->wdi_map_cnt--;
+			}
+			kfree(wdi_res[i].res);
+			wdi_res[i].valid = false;
+		}
+	}
+
+	if (ipa3_ctx->wdi_map_cnt == 0)
+		cb->next_addr = cb->va_end;
+}
+
 static void ipa_release_uc_smmu_mappings(enum ipa_client_type client)
 {
 	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
@@ -757,9 +887,11 @@ int ipa_create_gsi_smmu_mapping(int res_idx, bool wlan_smmu_en,
 
 	/* no SMMU on WLAN but SMMU on IPA */
 	if (!wlan_smmu_en && !ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_AP]) {
-		if (ipa3_smmu_map_peer_buff(*iova, pa, len,
-						sgt, IPA_SMMU_CB_WLAN)) {
-			IPAERR("Fail to create mapping res %d\n", res_idx);
+		if (ipa_create_ap_smmu_mapping_pa(pa, len,
+				(res_idx == IPA_WDI_CE_DB_RES) ? true : false,
+					iova)) {
+			IPAERR("Fail to create mapping res %d\n",
+					res_idx);
 			return -EFAULT;
 		}
 		ipa_save_uc_smmu_mapping_pa(res_idx, pa, *iova, len);
@@ -771,10 +903,12 @@ int ipa_create_gsi_smmu_mapping(int res_idx, bool wlan_smmu_en,
 		case IPA_WDI_RX_RING_RP_RES:
 		case IPA_WDI_RX_COMP_RING_WP_RES:
 		case IPA_WDI_CE_DB_RES:
-			if (ipa3_smmu_map_peer_buff(*iova, pa, len, sgt,
-							IPA_SMMU_CB_WLAN)) {
+		case IPA_WDI_TX_DB_RES:
+			if (ipa_create_ap_smmu_mapping_pa(pa, len,
+				(res_idx == IPA_WDI_CE_DB_RES) ? true : false,
+						iova)) {
 				IPAERR("Fail to create mapping res %d\n",
-					res_idx);
+						res_idx);
 				return -EFAULT;
 			}
 			ipa_save_uc_smmu_mapping_pa(res_idx, pa, *iova, len);
@@ -783,10 +917,9 @@ int ipa_create_gsi_smmu_mapping(int res_idx, bool wlan_smmu_en,
 		case IPA_WDI_RX_COMP_RING_RES:
 		case IPA_WDI_TX_RING_RES:
 		case IPA_WDI_CE_RING_RES:
-			if (ipa3_smmu_map_peer_reg(pa, true,
-							IPA_SMMU_CB_WLAN)) {
+			if (ipa_create_ap_smmu_mapping_sgt(sgt, iova)) {
 				IPAERR("Fail to create mapping res %d\n",
-					res_idx);
+						res_idx);
 				return -EFAULT;
 			}
 			ipa_save_uc_smmu_mapping_sgt(res_idx, sgt, *iova);
@@ -1310,7 +1443,7 @@ int ipa3_connect_gsi_wdi_pipe(struct ipa_wdi_in_params *in,
 ipa_cfg_ep_fail:
 	memset(&ipa3_ctx->ep[ipa_ep_idx], 0, sizeof(struct ipa3_ep_context));
 gsi_timeout:
-	ipa_release_uc_smmu_mappings(in->sys.client);
+	ipa_release_ap_smmu_mappings(in->sys.client);
 	IPA_ACTIVE_CLIENTS_DEC_EP(in->sys.client);
 fail:
 	return result;
@@ -1870,7 +2003,7 @@ int ipa3_disconnect_gsi_wdi_pipe(u32 clnt_hdl)
 				result);
 		goto fail_dealloc_channel;
 	}
-	ipa_release_uc_smmu_mappings(clnt_hdl);
+	ipa_release_ap_smmu_mappings(clnt_hdl);
 
 	/* for AP+STA stats update */
 	if (ipa3_ctx->uc_wdi_ctx.stats_notify)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 4b29342..338fd39 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -46,6 +46,11 @@
 #define IPA_V4_0_CLK_RATE_NOMINAL (220 * 1000 * 1000UL)
 #define IPA_V4_0_CLK_RATE_TURBO (250 * 1000 * 1000UL)
 
+#define IPA_V4_2_CLK_RATE_SVS2 (50 * 1000 * 1000UL)
+#define IPA_V4_2_CLK_RATE_SVS (100 * 1000 * 1000UL)
+#define IPA_V4_2_CLK_RATE_NOMINAL (201 * 1000 * 1000UL)
+#define IPA_V4_2_CLK_RATE_TURBO (240 * 1000 * 1000UL)
+
 #define IPA_V3_0_MAX_HOLB_TMR_VAL (4294967296 - 1)
 
 #define IPA_V3_0_BW_THRESHOLD_TURBO_MBPS (1000)
@@ -174,8 +179,7 @@
 #define IPA_v4_2_DST_GROUP_MAX		(1)
 
 #define IPA_v4_5_MHI_GROUP_PCIE		(0)
-#define IPA_v4_5_GROUP_UL_DL_DST	(0)
-#define IPA_v4_5_GROUP_UL_DL_SRC	(1)
+#define IPA_v4_5_GROUP_UL_DL		(1)
 #define IPA_v4_5_MHI_GROUP_DDR		(1)
 #define IPA_v4_5_MHI_GROUP_DMA		(2)
 #define IPA_v4_5_MHI_GROUP_QDSS		(3)
@@ -387,9 +391,9 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config
 		{5, 5}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} },
 	},
 	[IPA_4_5] = {
-		/* unused  UL_DL_SRC  unused  unused  UC_RX_Q N/A */
+		/* unused  UL_DL  unused  unused  UC_RX_Q N/A */
 		[IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = {
-		{0, 0}, {1, 63}, {0, 0}, {0, 0}, {1, 63}, {0, 0} },
+		{0, 0}, {1, 11}, {0, 0}, {0, 0}, {1, 63}, {0, 0} },
 		[IPA_v4_0_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = {
 		{0, 0}, {14, 14}, {0, 0}, {0, 0}, {3, 3}, {0, 0} },
 		[IPA_v4_0_RSRC_GRP_TYPE_SRC_DESCRIPTOR_BUFF] = {
@@ -400,7 +404,7 @@ static const struct rsrc_min_max ipa3_rsrc_src_grp_config
 		{0, 0}, {24, 24}, {0, 0}, {0, 0}, {8, 8}, {0, 0} },
 	},
 	[IPA_4_5_MHI] = {
-		/* PCIE  DDR  DMA  QDSS  unused  N/A  N/A */
+		/* PCIE  DDR  DMA  QDSS  unused  N/A */
 		[IPA_v4_0_RSRC_GRP_TYPE_SRC_PKT_CONTEXTS] = {
 		{3, 8}, {4, 11}, {1, 1}, {1, 1}, {0, 0}, {0, 0} },
 		[IPA_v4_0_RSRC_GRP_TYPE_SRS_DESCRIPTOR_LISTS] = {
@@ -482,11 +486,11 @@ static const struct rsrc_min_max ipa3_rsrc_dst_grp_config
 		{1, 63}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} },
 	},
 	[IPA_4_5] = {
-		/* UL/DL/DPL_DST unused unused unused uC N/A */
+		/* unused  UL/DL/DPL unused  unused  uC  N/A */
 		[IPA_v4_0_RSRC_GRP_TYPE_DST_DATA_SECTORS] = {
-		{16, 16}, {5, 5}, {2, 2}, {2, 2}, {0, 0}, {0, 0} },
+		{0, 0}, {16, 16}, {2, 2}, {2, 2}, {0, 0}, {0, 0} },
 		[IPA_v4_0_RSRC_GRP_TYPE_DST_DPS_DMARS] = {
-		{2, 63}, {1, 63}, {1, 2}, {1, 2}, {0, 2}, {0, 0} },
+		{0, 0}, {2, 63}, {1, 2}, {1, 2}, {0, 2}, {0, 0} },
 	},
 	[IPA_4_5_MHI] = {
 		/* PCIE/DPL  DDR  DMA/CV2X  QDSS  uC  N/A */
@@ -2021,6 +2025,39 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 31, 31, 8, 8, IPA_EE_AP } },
+	/* MHI PRIME PIPES - Client producer / IPA Consumer pipes */
+	[IPA_4_1_APQ][IPA_CLIENT_MHI_PRIME_DPL_PROD] = {
+			true, IPA_v4_0_MHI_GROUP_PCIE,
+			true,
+			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
+			QMB_MASTER_SELECT_DDR,
+			{7, 9, 8, 16, IPA_EE_AP } },
+	[IPA_4_1_APQ][IPA_CLIENT_MHI_PRIME_TETH_PROD] = {
+			true, IPA_v4_0_MHI_GROUP_PCIE,
+			true,
+			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
+			QMB_MASTER_SELECT_DDR,
+			{ 1, 0, 8, 16, IPA_EE_AP } },
+	[IPA_4_1_APQ][IPA_CLIENT_MHI_PRIME_RMNET_PROD] = {
+			true, IPA_v4_0_MHI_GROUP_PCIE,
+			true,
+			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
+			QMB_MASTER_SELECT_DDR,
+			{ 2, 3, 16, 32, IPA_EE_AP } },
+	/* MHI PRIME PIPES - Client Consumer / IPA Producer pipes */
+	[IPA_4_1_APQ][IPA_CLIENT_MHI_PRIME_TETH_CONS] = {
+			true, IPA_v4_0_MHI_GROUP_PCIE,
+			false,
+			IPA_DPS_HPS_SEQ_TYPE_INVALID,
+			QMB_MASTER_SELECT_DDR,
+			{ 20, 13, 9, 9, IPA_EE_AP } },
+	[IPA_4_1_APQ][IPA_CLIENT_MHI_PRIME_RMNET_CONS] = {
+			true, IPA_v4_0_MHI_GROUP_PCIE,
+			false,
+			IPA_DPS_HPS_SEQ_TYPE_INVALID,
+			QMB_MASTER_SELECT_DDR,
+			{ 21, 14, 9, 9, IPA_EE_AP } },
+
 
 	/* IPA_4_2 */
 	[IPA_4_2][IPA_CLIENT_WLAN1_PROD]          = {
@@ -2199,190 +2236,190 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 			{ 31, 31, 8, 8, IPA_EE_AP, GSI_USE_PREFETCH_BUFS} },
 
 	/* IPA_4_5 */
-	[IPA_4_5][IPA_CLIENT_WLAN1_PROD]          = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+	[IPA_4_5][IPA_CLIENT_WLAN2_PROD]          = {
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 9, 12, 8, 16, IPA_EE_AP, GSI_SMART_PRE_FETCH, 4 } },
+			{ 9, 12, 8, 16, IPA_EE_AP, GSI_FREE_PRE_FETCH, 2 } },
 	[IPA_4_5][IPA_CLIENT_USB_PROD]            = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 1, 0, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_APPS_LAN_PROD]	  = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 11, 14, 10, 16, IPA_EE_AP, GSI_SMART_PRE_FETCH, 2 } },
 	[IPA_4_5][IPA_CLIENT_APPS_WAN_PROD]	  = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 2, 7, 16, 32, IPA_EE_AP, GSI_SMART_PRE_FETCH, 8 } },
 	[IPA_4_5][IPA_CLIENT_APPS_CMD_PROD]	  = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 7, 9, 20, 24, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_ODU_PROD]            = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 10, 13, 8, 19, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_ETHERNET_PROD]	  = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 12, 0, 8, 16, IPA_EE_UC, GSI_SMART_PRE_FETCH, 4 } },
 	[IPA_4_5][IPA_CLIENT_Q6_WAN_PROD]         = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 5, 0, 16, 28, IPA_EE_Q6, GSI_SMART_PRE_FETCH, 8 } },
+			{ 5, 0, 16, 28, IPA_EE_Q6, GSI_SMART_PRE_FETCH, 2 } },
 	[IPA_4_5][IPA_CLIENT_Q6_CMD_PROD]	  = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 6, 1, 20, 24, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_Q6_DL_NLO_DATA_PROD] = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 2, 27, 32, IPA_EE_Q6, GSI_FREE_PRE_FETCH, 3 } },
 	[IPA_4_5][IPA_CLIENT_AQC_ETHERNET_PROD] = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 10, 13, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
 	/* Only for test purpose */
 	[IPA_4_5][IPA_CLIENT_TEST_PROD]           = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 1, 0, 8, 16, IPA_EE_AP } },
 	[IPA_4_5][IPA_CLIENT_TEST1_PROD]          = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 1, 0, 8, 16, IPA_EE_AP } },
 	[IPA_4_5][IPA_CLIENT_TEST2_PROD]          = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 3, 5, 8, 16, IPA_EE_AP } },
 	[IPA_4_5][IPA_CLIENT_TEST3_PROD]          = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 9, 12, 8, 16, IPA_EE_AP } },
 	[IPA_4_5][IPA_CLIENT_TEST4_PROD]          = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, IPA_v4_5_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 11, 14, 8, 16, IPA_EE_AP } },
 
-	[IPA_4_5][IPA_CLIENT_WLAN1_CONS]          = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+	[IPA_4_5][IPA_CLIENT_WLAN2_CONS]          = {
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 24, 3, 8, 14, IPA_EE_AP, GSI_SMART_PRE_FETCH, 4 } },
 	[IPA_4_5][IPA_CLIENT_USB_CONS]            = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 26, 17, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_USB_DPL_CONS]        = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 15, 15, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_ODL_DPL_CONS]        = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 22, 2, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_APPS_LAN_CONS]       = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 16, 10, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_APPS_WAN_COAL_CONS]       = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 13, 4, 8, 11, IPA_EE_AP, GSI_SMART_PRE_FETCH, 4 } },
 	[IPA_4_5][IPA_CLIENT_APPS_WAN_CONS]       = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 14, 1, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_ODU_EMB_CONS]        = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 23, 8, 9, 9, IPA_EE_AP, GSI_SMART_PRE_FETCH, 4 } },
 	[IPA_4_5][IPA_CLIENT_ETHERNET_CONS]	  = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 28, 1, 9, 9, IPA_EE_UC, GSI_SMART_PRE_FETCH, 4 } },
 	[IPA_4_5][IPA_CLIENT_Q6_LAN_CONS]         = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 17, 3, 9, 9, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_Q6_WAN_CONS]         = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 21, 7, 9, 9, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_Q6_UL_NLO_DATA_CONS] = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 19, 5, 5, 5, IPA_EE_Q6, GSI_SMART_PRE_FETCH, 2 } },
 	[IPA_4_5][IPA_CLIENT_Q6_UL_NLO_ACK_CONS]  = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 20, 6, 5, 5, IPA_EE_Q6, GSI_SMART_PRE_FETCH, 2 } },
 	[IPA_4_5][IPA_CLIENT_Q6_QBAP_STATUS_CONS] = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 18, 4, 9, 9, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY, 0 } },
 	[IPA_4_5][IPA_CLIENT_AQC_ETHERNET_CONS] = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
@@ -2390,38 +2427,38 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 	/* Only for test purpose */
 	/* MBIM aggregation test pipes should have the same QMB as USB_CONS */
 	[IPA_4_5][IPA_CLIENT_TEST_CONS]           = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 14, 1, 9, 9, IPA_EE_AP } },
 	[IPA_4_5][IPA_CLIENT_TEST1_CONS]          = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 14, 1, 9, 9, IPA_EE_AP } },
 	[IPA_4_5][IPA_CLIENT_TEST2_CONS]          = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 24, 3, 8, 14, IPA_EE_AP } },
 	[IPA_4_5][IPA_CLIENT_TEST3_CONS]          = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 26, 17, 9, 9, IPA_EE_AP } },
 	[IPA_4_5][IPA_CLIENT_TEST4_CONS]          = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 27, 18, 9, 9, IPA_EE_AP } },
 	/* Dummy consumer (pipe 31) is used in L2TP rt rule */
 	[IPA_4_5][IPA_CLIENT_DUMMY_CONS]          = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, IPA_v4_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
@@ -2439,7 +2476,7 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 5, 0, 16, 28, IPA_EE_Q6, GSI_SMART_PRE_FETCH, 8 } },
+			{ 5, 0, 16, 28, IPA_EE_Q6, GSI_SMART_PRE_FETCH, 2 } },
 	[IPA_4_5_MHI][IPA_CLIENT_Q6_CMD_PROD]		= {
 			true, IPA_v4_5_MHI_GROUP_PCIE,
 			false,
@@ -2478,7 +2515,7 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 			{ 10, 13, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
 	/* Only for test purpose */
 	[IPA_4_5_MHI][IPA_CLIENT_TEST_PROD]           = {
-			true, IPA_v4_5_GROUP_UL_DL_SRC,
+			true, QMB_MASTER_SELECT_DDR,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
@@ -2559,7 +2596,7 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 
 	/* Dummy consumer (pipe 31) is used in L2TP rt rule */
 	[IPA_4_5_MHI][IPA_CLIENT_DUMMY_CONS]          = {
-			true, IPA_v4_5_GROUP_UL_DL_DST,
+			true, QMB_MASTER_SELECT_DDR,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
@@ -5556,10 +5593,17 @@ int ipa3_controller_static_bind(struct ipa3_controller *ctrl,
 		enum ipa_hw_type hw_type)
 {
 	if (hw_type >= IPA_HW_v4_0) {
-		ctrl->ipa_clk_rate_turbo = IPA_V4_0_CLK_RATE_TURBO;
-		ctrl->ipa_clk_rate_nominal = IPA_V4_0_CLK_RATE_NOMINAL;
-		ctrl->ipa_clk_rate_svs = IPA_V4_0_CLK_RATE_SVS;
-		ctrl->ipa_clk_rate_svs2 = IPA_V4_0_CLK_RATE_SVS2;
+		if (hw_type == IPA_HW_v4_2) {
+			ctrl->ipa_clk_rate_turbo = IPA_V4_2_CLK_RATE_TURBO;
+			ctrl->ipa_clk_rate_nominal = IPA_V4_2_CLK_RATE_NOMINAL;
+			ctrl->ipa_clk_rate_svs = IPA_V4_2_CLK_RATE_SVS;
+			ctrl->ipa_clk_rate_svs2 = IPA_V4_2_CLK_RATE_SVS2;
+		} else {
+			ctrl->ipa_clk_rate_turbo = IPA_V4_0_CLK_RATE_TURBO;
+			ctrl->ipa_clk_rate_nominal = IPA_V4_0_CLK_RATE_NOMINAL;
+			ctrl->ipa_clk_rate_svs = IPA_V4_0_CLK_RATE_SVS;
+			ctrl->ipa_clk_rate_svs2 = IPA_V4_0_CLK_RATE_SVS2;
+		}
 	} else if (hw_type >= IPA_HW_v3_5) {
 		ctrl->ipa_clk_rate_turbo = IPA_V3_5_CLK_RATE_TURBO;
 		ctrl->ipa_clk_rate_nominal = IPA_V3_5_CLK_RATE_NOMINAL;
@@ -6379,7 +6423,10 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type,
 	api_ctrl->ipa_wigig_uc_msi_init = ipa3_wigig_uc_msi_init;
 	api_ctrl->ipa_enable_wigig_pipe_i = ipa3_enable_wigig_pipe_i;
 	api_ctrl->ipa_disable_wigig_pipe_i = ipa3_disable_wigig_pipe_i;
-
+	api_ctrl->ipa_register_client_callback =
+		ipa3_register_client_callback;
+	api_ctrl->ipa_deregister_client_callback =
+		ipa3_deregister_client_callback;
 	return 0;
 }
 
@@ -6596,7 +6643,7 @@ static void ipa3_write_rsrc_grp_type_reg(int group_index,
 		if (src) {
 			switch (group_index) {
 			case IPA_v4_5_MHI_GROUP_PCIE:
-			case IPA_v4_5_GROUP_UL_DL_SRC:
+			case IPA_v4_5_GROUP_UL_DL:
 				ipahal_write_reg_n_fields(
 					IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n,
 					n, val);
@@ -6620,8 +6667,8 @@ static void ipa3_write_rsrc_grp_type_reg(int group_index,
 			}
 		} else {
 			switch (group_index) {
-			case IPA_v4_5_GROUP_UL_DL_DST:
-			case IPA_v4_5_MHI_GROUP_DDR:
+			case IPA_v4_5_MHI_GROUP_PCIE:
+			case IPA_v4_5_GROUP_UL_DL:
 				ipahal_write_reg_n_fields(
 					IPA_DST_RSRC_GRP_01_RSRC_TYPE_n,
 					n, val);
@@ -7007,7 +7054,11 @@ void ipa3_suspend_apps_pipes(bool suspend)
 					IPAERR("failed to stop WAN channel\n");
 					ipa_assert();
 				}
-			} else {
+			} else if (!atomic_read(&ipa3_ctx->is_ssr)) {
+				/* If SSR was alreday started not required to
+				 * start WAN channel,Because in SSR will stop
+				 * channel and reset the channel.
+				 */
 				res = gsi_start_channel(ep->gsi_chan_hdl);
 				if (res) {
 					IPAERR("failed to start WAN channel\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c b/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c
index 053adc7..0822e98 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c
@@ -80,6 +80,7 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 	const struct ipa_gsi_ep_config *gsi_ep_info;
 	int result, len;
 	unsigned long va;
+	uint32_t addr_low, addr_high;
 
 	if (!info || !info_smmu || !ep) {
 		IPAERR("invalid input\n");
@@ -160,6 +161,10 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 	gsi_channel_props.re_size = GSI_CHAN_RE_SIZE_16B;
 	gsi_channel_props.use_db_eng = GSI_CHAN_DB_MODE;
 	gsi_channel_props.max_prefetch = GSI_ONE_PREFETCH_SEG;
+	gsi_channel_props.prefetch_mode =
+		gsi_ep_info->prefetch_mode;
+	gsi_channel_props.empty_lvl_threshold =
+		gsi_ep_info->prefetch_threshold;
 	gsi_channel_props.low_weight = 1;
 	gsi_channel_props.err_cb = ipa3_wdi3_gsi_chan_err_cb;
 
@@ -213,17 +218,104 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 		IPAERR("failed to write evt ring scratch\n");
 		goto fail_write_scratch;
 	}
-	/* write event ring db address */
+
+	if (!is_smmu_enabled) {
+		IPADBG("smmu disabled\n");
+		if (info->is_evt_rn_db_pcie_addr == true)
+			IPADBG_LOW("is_evt_rn_db_pcie_addr is PCIE addr\n");
+		else
+			IPADBG_LOW("is_evt_rn_db_pcie_addr is DDR addr\n");
+		IPADBG_LOW("LSB 0x%x\n", (u32)info->event_ring_doorbell_pa);
+		IPADBG_LOW("MSB 0x%x\n",
+			(u32)((u64)info->event_ring_doorbell_pa >> 32));
+	} else {
+		IPADBG("smmu enabled\n");
+		if (info_smmu->is_evt_rn_db_pcie_addr == true)
+			IPADBG_LOW("is_evt_rn_db_pcie_addr is PCIE addr\n");
+		else
+			IPADBG_LOW("is_evt_rn_db_pcie_addr is DDR addr\n");
+		IPADBG_LOW("LSB 0x%x\n",
+			(u32)info_smmu->event_ring_doorbell_pa);
+		IPADBG_LOW("MSB 0x%x\n",
+			(u32)((u64)info_smmu->event_ring_doorbell_pa >> 32));
+	}
+
+	if (!is_smmu_enabled) {
+		addr_low = (u32)info->event_ring_doorbell_pa;
+		addr_high = (u32)((u64)info->event_ring_doorbell_pa >> 32);
+	} else {
+		if (dir == IPA_WDI3_TX_DIR) {
+			if (ipa_create_gsi_smmu_mapping(IPA_WDI_CE_DB_RES,
+				true, info_smmu->event_ring_doorbell_pa,
+				NULL, 4, true, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				result = -EFAULT;
+				goto fail_write_scratch;
+			}
+		} else {
+			if (ipa_create_gsi_smmu_mapping(
+				IPA_WDI_RX_COMP_RING_WP_RES,
+				true, info_smmu->event_ring_doorbell_pa,
+				NULL, 4, true, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				result = -EFAULT;
+				goto fail_write_scratch;
+			}
+		}
+		addr_low = (u32)va;
+		addr_high = (u32)((u64)va >> 32);
+	}
+
+	/*
+	 * Arch specific:
+	 * pcie addr which are not via smmu, use pa directly!
+	 * pcie and DDR via 2 different port
+	 * assert bit 40 to indicate it is pcie addr
+	 * WDI-3.0, MSM --> pcie via smmu
+	 * WDI-3.0, MDM --> pcie not via smmu + dual port
+	 * assert bit 40 in case
+	 */
+	if (!ipa3_is_msm_device() &&
+		is_smmu_enabled) {
+		/*
+		 * Ir-respective of smmu enabled don't use IOVA addr
+		 * since pcie not via smmu in MDM's
+		 */
+		if (info_smmu->is_evt_rn_db_pcie_addr == true) {
+			addr_low = (u32)info_smmu->event_ring_doorbell_pa;
+			addr_high =
+				(u32)((u64)info_smmu->event_ring_doorbell_pa
+				>> 32);
+		}
+	}
+
+	/*
+	 * GSI recomendation to set bit-40 for (mdm targets && pcie addr)
+	 * from wdi-3.0 interface document
+	 */
+	if (!is_smmu_enabled) {
+		if (!ipa3_is_msm_device() &&
+			info->is_evt_rn_db_pcie_addr)
+			addr_high |= (1 << 8);
+	} else {
+		if (!ipa3_is_msm_device() &&
+			info_smmu->is_evt_rn_db_pcie_addr)
+			addr_high |= (1 << 8);
+	}
+
 	gsi_wdi3_write_evt_ring_db(ep->gsi_evt_ring_hdl,
-		(u32)info->event_ring_doorbell_pa,
-		(u32)((u64)info->event_ring_doorbell_pa >> 32));
+			addr_low,
+			addr_high);
 
 	/* write channel scratch */
 	memset(&ch_scratch, 0, sizeof(ch_scratch));
 	ch_scratch.wdi3.update_rp_moderation_threshold =
 		UPDATE_RP_MODERATION_THRESHOLD;
 	if (dir == IPA_WDI3_RX_DIR) {
-		ch_scratch.wdi3.rx_pkt_offset = info->pkt_offset;
+		if (!is_smmu_enabled)
+			ch_scratch.wdi3.rx_pkt_offset = info->pkt_offset;
+		else
+			ch_scratch.wdi3.rx_pkt_offset = info_smmu->pkt_offset;
 		/* this metadata reg offset need to be in words */
 		ch_scratch.wdi3.endp_metadata_reg_offset =
 			ipahal_get_reg_mn_ofst(IPA_ENDP_INIT_HDR_METADATA_n, 0,
@@ -231,6 +323,27 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 	}
 
 	if (!is_smmu_enabled) {
+		IPADBG_LOW("smmu disabled\n");
+		if (info->is_txr_rn_db_pcie_addr == true)
+			IPADBG_LOW("is_txr_rn_db_pcie_addr is PCIE addr\n");
+		else
+			IPADBG_LOW("is_txr_rn_db_pcie_addr is DDR addr\n");
+		IPADBG_LOW("LSB 0x%x\n", (u32)info->transfer_ring_doorbell_pa);
+		IPADBG_LOW("MSB 0x%x\n",
+			(u32)((u64)info->transfer_ring_doorbell_pa >> 32));
+	} else {
+		IPADBG_LOW("smmu eabled\n");
+		if (info_smmu->is_txr_rn_db_pcie_addr == true)
+			IPADBG_LOW("is_txr_rn_db_pcie_addr is PCIE addr\n");
+		else
+			IPADBG_LOW("is_txr_rn_db_pcie_addr is DDR addr\n");
+		IPADBG_LOW("LSB 0x%x\n",
+			(u32)info_smmu->transfer_ring_doorbell_pa);
+		IPADBG_LOW("MSB 0x%x\n",
+			(u32)((u64)info_smmu->transfer_ring_doorbell_pa >> 32));
+	}
+
+	if (!is_smmu_enabled) {
 		ch_scratch.wdi3.wifi_rp_address_low =
 			(u32)info->transfer_ring_doorbell_pa;
 		ch_scratch.wdi3.wifi_rp_address_high =
@@ -264,6 +377,49 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled,
 				(u32)((u64)va >> 32);
 		}
 	}
+
+	/*
+	 * Arch specific:
+	 * pcie addr which are not via smmu, use pa directly!
+	 * pcie and DDR via 2 different port
+	 * assert bit 40 to indicate it is pcie addr
+	 * WDI-3.0, MSM --> pcie via smmu
+	 * WDI-3.0, MDM --> pcie not via smmu + dual port
+	 * assert bit 40 in case
+	 */
+	if (!ipa3_is_msm_device() &&
+		is_smmu_enabled) {
+		/*
+		 * Ir-respective of smmu enabled don't use IOVA addr
+		 * since pcie not via smmu in MDM's
+		 */
+		if (info_smmu->is_txr_rn_db_pcie_addr == true) {
+			ch_scratch.wdi3.wifi_rp_address_low =
+				(u32)info_smmu->transfer_ring_doorbell_pa;
+			ch_scratch.wdi3.wifi_rp_address_high =
+				(u32)((u64)info_smmu->transfer_ring_doorbell_pa
+				>> 32);
+		}
+	}
+
+	/*
+	 * GSI recomendation to set bit-40 for(mdm targets && pcie addr)
+	 * from wdi-3.0 interface document
+	 */
+	if (!is_smmu_enabled) {
+		if (!ipa3_is_msm_device() &&
+			info->is_txr_rn_db_pcie_addr)
+			ch_scratch.wdi3.wifi_rp_address_high =
+			(u32)((u32)ch_scratch.wdi3.wifi_rp_address_high |
+			(1 << 8));
+	} else {
+		if (!ipa3_is_msm_device() &&
+			info_smmu->is_txr_rn_db_pcie_addr)
+			ch_scratch.wdi3.wifi_rp_address_high =
+			(u32)((u32)ch_scratch.wdi3.wifi_rp_address_high |
+			(1 << 8));
+	}
+
 	result = gsi_write_channel_scratch(ep->gsi_chan_hdl, ch_scratch);
 	if (result != GSI_STATUS_SUCCESS) {
 		IPAERR("failed to write evt ring scratch\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_wigig_i.c b/drivers/platform/msm/ipa/ipa_v3/ipa_wigig_i.c
index 71475b0..7a6189a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_wigig_i.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_wigig_i.c
@@ -476,6 +476,7 @@ static int ipa3_wigig_config_gsi(bool Rx,
 	channel_props.use_db_eng = GSI_CHAN_DB_MODE;
 	channel_props.max_prefetch = GSI_ONE_PREFETCH_SEG;
 	channel_props.prefetch_mode = ep_gsi->prefetch_mode;
+	channel_props.empty_lvl_threshold = ep_gsi->prefetch_threshold;
 	channel_props.low_weight = 1;
 	channel_props.err_cb = ipa_gsi_chan_err_cb;
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index 04deb09..f04a1e1 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.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
@@ -890,13 +890,15 @@ static void ipa_pkt_status_parse(
 	status->flt_hash = hw_status->flt_hash;
 	status->flt_global = hw_status->flt_hash;
 	status->flt_ret_hdr = hw_status->flt_ret_hdr;
-	status->flt_miss = ~(hw_status->flt_rule_id) ? false : true;
+	status->flt_miss = (hw_status->rt_rule_id ==
+		IPAHAL_PKT_STATUS_FLTRT_RULE_MISS_ID);
 	status->flt_rule_id = hw_status->flt_rule_id;
 	status->rt_local = hw_status->rt_local;
 	status->rt_hash = hw_status->rt_hash;
 	status->ucp = hw_status->ucp;
 	status->rt_tbl_idx = hw_status->rt_tbl_idx;
-	status->rt_miss = ~(hw_status->rt_rule_id) ? false : true;
+	status->rt_miss = (hw_status->rt_rule_id ==
+		IPAHAL_PKT_STATUS_FLTRT_RULE_MISS_ID);
 	status->rt_rule_id = hw_status->rt_rule_id;
 	status->nat_hit = hw_status->nat_hit;
 	status->nat_entry_idx = hw_status->nat_entry_idx;
@@ -1187,6 +1189,13 @@ static void ipahal_cp_hdr_to_hw_buff_v3(void *const base, u32 offset,
 	memcpy(base + offset, hdr, hdr_len);
 }
 
+/* Header address update logic. */
+#define IPAHAL_CP_PROC_CTX_HEADER_UPDATE(hdr_lsb, hdr_msb, addr) \
+	do { \
+		hdr_lsb = lower_32_bits(addr); \
+		hdr_msb = upper_32_bits(addr); \
+	} while (0)
+
 /*
  * ipahal_cp_proc_ctx_to_hw_buff_v3() - copy processing context to
  * base address and offset given.
@@ -1200,26 +1209,31 @@ static void ipahal_cp_hdr_to_hw_buff_v3(void *const base, u32 offset,
  * @hdr_base_addr: base address in table
  * @offset_entry: offset from hdr_base_addr in table
  * @l2tp_params: l2tp parameters
+ * @is_64: Indicates whether header base address/dma base address is 64 bit.
  */
 static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
 		void *const base, u32 offset,
 		u32 hdr_len, bool is_hdr_proc_ctx,
-		dma_addr_t phys_base, u32 hdr_base_addr,
+		dma_addr_t phys_base, u64 hdr_base_addr,
 		struct ipa_hdr_offset_entry *offset_entry,
-		struct ipa_l2tp_hdr_proc_ctx_params l2tp_params)
+		struct ipa_l2tp_hdr_proc_ctx_params l2tp_params, bool is_64)
 {
+	u64 hdr_addr;
+
 	if (type == IPA_HDR_PROC_NONE) {
 		struct ipa_hw_hdr_proc_ctx_add_hdr_seq *ctx;
 
 		ctx = (struct ipa_hw_hdr_proc_ctx_add_hdr_seq *)
 			(base + offset);
 		ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
-		ctx->hdr_add.tlv.length = 1;
+		ctx->hdr_add.tlv.length = is_64 ? 2 : 1;
 		ctx->hdr_add.tlv.value = hdr_len;
-		ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
+		hdr_addr = is_hdr_proc_ctx ? phys_base :
 			hdr_base_addr + offset_entry->offset;
-		IPAHAL_DBG("header address 0x%x\n",
-			ctx->hdr_add.hdr_addr);
+		IPAHAL_DBG("header address 0x%llx\n",
+			hdr_addr);
+		IPAHAL_CP_PROC_CTX_HEADER_UPDATE(ctx->hdr_add.hdr_addr,
+			ctx->hdr_add.hdr_addr_hi, hdr_addr);
 		ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
 		ctx->end.length = 0;
 		ctx->end.value = 0;
@@ -1229,12 +1243,14 @@ static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
 		ctx = (struct ipa_hw_hdr_proc_ctx_add_l2tp_hdr_cmd_seq *)
 			(base + offset);
 		ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
-		ctx->hdr_add.tlv.length = 1;
+		ctx->hdr_add.tlv.length = is_64 ? 2 : 1;
 		ctx->hdr_add.tlv.value = hdr_len;
-		ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
+		hdr_addr = is_hdr_proc_ctx ? phys_base :
 			hdr_base_addr + offset_entry->offset;
-		IPAHAL_DBG("header address 0x%x\n",
-			ctx->hdr_add.hdr_addr);
+		IPAHAL_DBG("header address 0x%llx\n",
+			hdr_addr);
+		IPAHAL_CP_PROC_CTX_HEADER_UPDATE(ctx->hdr_add.hdr_addr,
+			ctx->hdr_add.hdr_addr_hi, hdr_addr);
 		ctx->l2tp_params.tlv.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
 		ctx->l2tp_params.tlv.length = 1;
 		ctx->l2tp_params.tlv.value =
@@ -1256,12 +1272,14 @@ static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
 		ctx = (struct ipa_hw_hdr_proc_ctx_remove_l2tp_hdr_cmd_seq *)
 			(base + offset);
 		ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
-		ctx->hdr_add.tlv.length = 1;
+		ctx->hdr_add.tlv.length = is_64 ? 2 : 1;
 		ctx->hdr_add.tlv.value = hdr_len;
-		ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
+		hdr_addr = is_hdr_proc_ctx ? phys_base :
 			hdr_base_addr + offset_entry->offset;
-		IPAHAL_DBG("header address 0x%x length %d\n",
-			ctx->hdr_add.hdr_addr, ctx->hdr_add.tlv.value);
+		IPAHAL_DBG("header address 0x%llx length %d\n",
+			hdr_addr, ctx->hdr_add.tlv.value);
+		IPAHAL_CP_PROC_CTX_HEADER_UPDATE(ctx->hdr_add.hdr_addr,
+			ctx->hdr_add.hdr_addr_hi, hdr_addr);
 		ctx->l2tp_params.tlv.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
 		ctx->l2tp_params.tlv.length = 1;
 		ctx->l2tp_params.tlv.value =
@@ -1292,12 +1310,14 @@ static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
 		ctx = (struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq *)
 			(base + offset);
 		ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
-		ctx->hdr_add.tlv.length = 1;
+		ctx->hdr_add.tlv.length = is_64 ? 2 : 1;
 		ctx->hdr_add.tlv.value = hdr_len;
-		ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
+		hdr_addr = is_hdr_proc_ctx ? phys_base :
 			hdr_base_addr + offset_entry->offset;
-		IPAHAL_DBG("header address 0x%x\n",
-			ctx->hdr_add.hdr_addr);
+		IPAHAL_DBG("header address 0x%llx\n",
+			hdr_addr);
+		IPAHAL_CP_PROC_CTX_HEADER_UPDATE(ctx->hdr_add.hdr_addr,
+			ctx->hdr_add.hdr_addr_hi, hdr_addr);
 		ctx->cmd.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
 		ctx->cmd.length = 0;
 		switch (type) {
@@ -1353,9 +1373,10 @@ struct ipahal_hdr_funcs {
 	int (*ipahal_cp_proc_ctx_to_hw_buff)(enum ipa_hdr_proc_type type,
 			void *const base, u32 offset, u32 hdr_len,
 			bool is_hdr_proc_ctx, dma_addr_t phys_base,
-			u32 hdr_base_addr,
+			u64 hdr_base_addr,
 			struct ipa_hdr_offset_entry *offset_entry,
-			struct ipa_l2tp_hdr_proc_ctx_params l2tp_params);
+			struct ipa_l2tp_hdr_proc_ctx_params l2tp_params,
+			bool is_64);
 
 	int (*ipahal_get_proc_ctx_needed_len)(enum ipa_hdr_proc_type type);
 };
@@ -1421,17 +1442,18 @@ void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *const hdr,
  * @hdr_base_addr: base address in table
  * @offset_entry: offset from hdr_base_addr in table
  * @l2tp_params: l2tp parameters
+ * @is_64: Indicates whether header base address/dma base address is 64 bit.
  */
 int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
 		void *const base, u32 offset, u32 hdr_len,
 		bool is_hdr_proc_ctx, dma_addr_t phys_base,
-		u32 hdr_base_addr, struct ipa_hdr_offset_entry *offset_entry,
-		struct ipa_l2tp_hdr_proc_ctx_params l2tp_params)
+		u64 hdr_base_addr, struct ipa_hdr_offset_entry *offset_entry,
+		struct ipa_l2tp_hdr_proc_ctx_params l2tp_params, bool is_64)
 {
 	IPAHAL_DBG(
-		"type %d, base %pK, offset %d, hdr_len %d, is_hdr_proc_ctx %d, hdr_base_addr %d, offset_entry %pK\n"
+		"type %d, base %pK, offset %d, hdr_len %d, is_hdr_proc_ctx %d, hdr_base_addr %llu, offset_entry %pK, bool %d\n"
 			, type, base, offset, hdr_len, is_hdr_proc_ctx,
-			hdr_base_addr, offset_entry);
+			hdr_base_addr, offset_entry, is_64);
 
 	if (!base ||
 		!hdr_len ||
@@ -1439,7 +1461,7 @@ int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
 		(!is_hdr_proc_ctx && !offset_entry) ||
 		(!is_hdr_proc_ctx && !hdr_base_addr)) {
 		IPAHAL_ERR(
-			"invalid input: hdr_len:%u phys_base:%pad hdr_base_addr:%u is_hdr_proc_ctx:%d offset_entry:%pK\n"
+			"invalid input: hdr_len:%u phys_base:%pad hdr_base_addr:%llu is_hdr_proc_ctx:%d offset_entry:%pK\n"
 			, hdr_len, &phys_base, hdr_base_addr
 			, is_hdr_proc_ctx, offset_entry);
 		return -EINVAL;
@@ -1447,7 +1469,7 @@ int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
 
 	return hdr_funcs.ipahal_cp_proc_ctx_to_hw_buff(type, base, offset,
 			hdr_len, is_hdr_proc_ctx, phys_base,
-			hdr_base_addr, offset_entry, l2tp_params);
+			hdr_base_addr, offset_entry, l2tp_params, is_64);
 }
 
 /*
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
index 7449eb4..b999ded 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
@@ -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
@@ -637,13 +637,14 @@ void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *hdr, u32 hdr_len);
  * @hdr_base_addr: base address in table
  * @offset_entry: offset from hdr_base_addr in table
  * @l2tp_params: l2tp parameters
+ * @is_64: Indicates whether header base address/dma base address is 64 bit.
  */
 int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
 		void *base, u32 offset, u32 hdr_len,
 		bool is_hdr_proc_ctx, dma_addr_t phys_base,
-		u32 hdr_base_addr,
+		u64 hdr_base_addr,
 		struct ipa_hdr_offset_entry *offset_entry,
-		struct ipa_l2tp_hdr_proc_ctx_params l2tp_params);
+		struct ipa_l2tp_hdr_proc_ctx_params l2tp_params, bool is_64);
 
 /*
  * ipahal_get_proc_ctx_needed_len() - calculates the needed length for addition
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c
index db4eb65..ddf9aa9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.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
@@ -1860,7 +1860,8 @@ static int ipa_fltrt_generate_hw_rule_bdy_from_eq(
 	if (attrib->fl_eq_present)
 		rest = ipa_write_32(attrib->fl_eq & 0xFFFFF, rest);
 
-	extra = ipa_pad_to_64(extra);
+	if (extra)
+		extra = ipa_pad_to_64(extra);
 	rest = ipa_pad_to_64(rest);
 	*buf = rest;
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
index 833b549..a2eb6f9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
@@ -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
@@ -74,6 +74,8 @@
 
 #define IPAHAL_IPC_LOG_PAGES 50
 
+#define IPAHAL_PKT_STATUS_FLTRT_RULE_MISS_ID 0x3ff
+
 /*
  * struct ipahal_context - HAL global context data
  * @hw_type: IPA H/W type/version.
@@ -656,7 +658,8 @@ struct ipa_hw_hdr_proc_ctx_tlv {
  */
 struct ipa_hw_hdr_proc_ctx_hdr_add {
 	struct ipa_hw_hdr_proc_ctx_tlv tlv;
-	u64 hdr_addr;
+	u32 hdr_addr;
+	u32 hdr_addr_hi;
 };
 
 /**
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
index 48187e6..89ce21a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.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
@@ -17,7 +17,6 @@
 
 #define IPA_64_LOW_32_MASK (0xFFFFFFFF)
 #define IPA_64_HIGH_32_MASK (0xFFFFFFFF00000000ULL)
-#define IPAHAL_NAT_INVALID_PROTOCOL (0xFF)
 
 static const char *ipahal_nat_type_to_str[IPA_NAT_MAX] = {
 	__stringify(IPAHAL_NAT_IPV4),
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index f427140..08c2c9c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -165,6 +165,7 @@ struct rmnet_ipa3_context {
 	struct ipa_tether_device_info
 		tether_device
 		[IPACM_MAX_CLIENT_DEVICE_TYPES];
+	bool dl_csum_offload_enabled;
 };
 
 static struct rmnet_ipa3_context *rmnet_ipa3_ctx;
@@ -198,21 +199,22 @@ static int ipa3_setup_a7_qmap_hdr(void)
 
 	strlcpy(hdr_entry->name, IPA_A7_QMAP_HDR_NAME,
 				IPA_RESOURCE_NAME_MAX);
-	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) {
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5 &&
+		rmnet_ipa3_ctx->dl_csum_offload_enabled) {
 		hdr_entry->hdr_len = IPA_DL_CHECKSUM_LENGTH; /* 8 bytes */
 		/* new DL QMAP header format */
-		hdr->hdr[0].hdr[0] = 0x40;
-		hdr->hdr[0].hdr[1] = 0;
-		hdr->hdr[0].hdr[2] = 0;
-		hdr->hdr[0].hdr[3] = 0;
-		hdr->hdr[0].hdr[4] = 0x4;
+		hdr_entry->hdr[0] = 0x40;
+		hdr_entry->hdr[1] = 0;
+		hdr_entry->hdr[2] = 0;
+		hdr_entry->hdr[3] = 0;
+		hdr_entry->hdr[4] = 0x4;
 		/*
 		 * Need to set csum required/valid bit on which will be replaced
 		 * by HW if checksum is incorrect after validation
 		 */
-		hdr->hdr[0].hdr[5] = 0x80;
-		hdr->hdr[0].hdr[6] = 0;
-		hdr->hdr[0].hdr[7] = 0;
+		hdr_entry->hdr[5] = 0x80;
+		hdr_entry->hdr[6] = 0;
+		hdr_entry->hdr[7] = 0;
 	} else
 		hdr_entry->hdr_len = IPA_QMAP_HEADER_LENGTH; /* 4 bytes */
 
@@ -334,8 +336,27 @@ static int ipa3_add_qmap_hdr(uint32_t mux_id, uint32_t *hdr_hdl)
 	 strlcpy(hdr_entry->name, hdr_name,
 				IPA_RESOURCE_NAME_MAX);
 
-	hdr_entry->hdr_len = IPA_QMAP_HEADER_LENGTH; /* 4 bytes */
-	hdr_entry->hdr[1] = (uint8_t) mux_id;
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5 &&
+		rmnet_ipa3_ctx->dl_csum_offload_enabled) {
+		hdr_entry->hdr_len = IPA_DL_CHECKSUM_LENGTH; /* 8 bytes */
+		/* new DL QMAP header format */
+		hdr_entry->hdr[0] = 0x40;
+		hdr_entry->hdr[1] = (uint8_t) mux_id;
+		hdr_entry->hdr[2] = 0;
+		hdr_entry->hdr[3] = 0;
+		hdr_entry->hdr[4] = 0x4;
+		/*
+		 * Need to set csum required/valid bit on which will be replaced
+		 * by HW if checksum is incorrect after validation
+		 */
+		hdr_entry->hdr[5] = 0x80;
+		hdr_entry->hdr[6] = 0;
+		hdr_entry->hdr[7] = 0;
+	} else {
+		hdr_entry->hdr_len = IPA_QMAP_HEADER_LENGTH; /* 4 bytes */
+		hdr_entry->hdr[1] = (uint8_t) mux_id;
+	}
+
 	IPAWANDBG("header (%s) with mux-id: (%d)\n",
 		hdr_name,
 		hdr_entry->hdr[1]);
@@ -454,12 +475,19 @@ static void ipa3_del_dflt_wan_rt_tables(void)
 
 static void ipa3_copy_qmi_flt_rule_ex(
 	struct ipa_ioc_ext_intf_prop *q6_ul_flt_rule_ptr,
-	struct ipa_filter_spec_ex_type_v01 *flt_spec_ptr)
+	void *flt_spec_ptr_void)
 {
 	int j;
+	struct ipa_filter_spec_ex_type_v01 *flt_spec_ptr;
 	struct ipa_ipfltr_range_eq_16 *q6_ul_filter_nat_ptr;
 	struct ipa_ipfltr_range_eq_16_type_v01 *filter_spec_nat_ptr;
 
+	/*
+	 * pure_ack and tos has the same size and type and we will treat tos
+	 * field as pure_ack in ipa4.5 version
+	 */
+	flt_spec_ptr = (struct ipa_filter_spec_ex_type_v01 *) flt_spec_ptr_void;
+
 	q6_ul_flt_rule_ptr->ip = flt_spec_ptr->ip_type;
 	q6_ul_flt_rule_ptr->action = flt_spec_ptr->filter_action;
 	if (flt_spec_ptr->is_routing_table_index_valid == true)
@@ -571,7 +599,6 @@ static void ipa3_copy_qmi_flt_rule_ex(
 		flt_spec_ptr->filter_rule.ipv4_frag_eq_present;
 }
 
-
 int ipa3_copy_ul_filter_rule_to_ipa(struct ipa_install_fltr_rule_req_msg_v01
 		*rule_req)
 {
@@ -579,14 +606,25 @@ int ipa3_copy_ul_filter_rule_to_ipa(struct ipa_install_fltr_rule_req_msg_v01
 
 	/* prevent multi-threads accessing rmnet_ipa3_ctx->num_q6_rules */
 	mutex_lock(&rmnet_ipa3_ctx->add_mux_channel_lock);
-	if (rule_req->filter_spec_ex_list_valid == true) {
+	if (rule_req->filter_spec_ex_list_valid == true &&
+		rule_req->filter_spec_ex2_list_valid == false) {
 		rmnet_ipa3_ctx->num_q6_rules =
 			rule_req->filter_spec_ex_list_len;
-		IPAWANDBG("Received (%d) install_flt_req\n",
+		IPAWANDBG("Received (%d) install_flt_req_ex_list\n",
+			rmnet_ipa3_ctx->num_q6_rules);
+	} else if (rule_req->filter_spec_ex2_list_valid == true &&
+		rule_req->filter_spec_ex_list_valid == false) {
+		rmnet_ipa3_ctx->num_q6_rules =
+			rule_req->filter_spec_ex2_list_len;
+		IPAWANDBG("Received (%d) install_flt_req_ex2_list\n",
 			rmnet_ipa3_ctx->num_q6_rules);
 	} else {
 		rmnet_ipa3_ctx->num_q6_rules = 0;
-		IPAWANERR("got no UL rules from modem\n");
+		if (rule_req->filter_spec_ex2_list_valid == true)
+			IPAWANERR(
+			"both ex and ex2 flt rules are set to valid\n");
+		else
+			IPAWANERR("got no UL rules from modem\n");
 		mutex_unlock(
 			&rmnet_ipa3_ctx->add_mux_channel_lock);
 		return -EINVAL;
@@ -602,8 +640,14 @@ int ipa3_copy_ul_filter_rule_to_ipa(struct ipa_install_fltr_rule_req_msg_v01
 				rmnet_ipa3_ctx->num_q6_rules);
 			goto failure;
 		}
-		ipa3_copy_qmi_flt_rule_ex(&ipa3_qmi_ctx->q6_ul_filter_rule[i],
-			&rule_req->filter_spec_ex_list[i]);
+		if (rule_req->filter_spec_ex_list_valid == true)
+			ipa3_copy_qmi_flt_rule_ex(
+				&ipa3_qmi_ctx->q6_ul_filter_rule[i],
+				&rule_req->filter_spec_ex_list[i]);
+		else if (rule_req->filter_spec_ex2_list_valid == true)
+			ipa3_copy_qmi_flt_rule_ex(
+				&ipa3_qmi_ctx->q6_ul_filter_rule[i],
+				&rule_req->filter_spec_ex2_list[i]);
 	}
 
 	if (rule_req->xlat_filter_indices_list_valid) {
@@ -1357,10 +1401,14 @@ static int handle3_ingress_format(struct net_device *dev,
 	}
 
 	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5 &&
-		(in->u.data) & RMNET_IOCTL_INGRESS_FORMAT_CHECKSUM)
+		(in->u.data) & RMNET_IOCTL_INGRESS_FORMAT_CHECKSUM) {
 		ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_len = 8;
-	else
+		rmnet_ipa3_ctx->dl_csum_offload_enabled = true;
+	} else {
 		ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_len = 4;
+		rmnet_ipa3_ctx->dl_csum_offload_enabled = false;
+	}
+
 	ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
 	ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata = 1;
 	ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
@@ -1398,7 +1446,19 @@ static int handle3_ingress_format(struct net_device *dev,
 	   &rmnet_ipa3_ctx->ipa3_to_apps_hdl);
 
 	mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard);
+	if (ret)
+		goto end;
 
+	/* construct default WAN RT tbl for IPACM */
+	ret = ipa3_setup_a7_qmap_hdr();
+	if (ret)
+		goto end;
+
+	ret = ipa3_setup_dflt_wan_rt_tables();
+	if (ret)
+		ipa3_del_a7_qmap_hdr();
+
+end:
 	if (ret)
 		IPAWANERR("failed to configure ingress\n");
 
@@ -2487,20 +2547,13 @@ static int ipa3_wwan_probe(struct platform_device *pdev)
 	if (ipa3_rmnet_res.is_platform_type_msm)
 		/* Android platform loads uC */
 		ipa3_qmi_service_init(QMI_IPA_PLATFORM_TYPE_MSM_ANDROID_V01);
+	else if (ipa3_ctx->ipa_config_is_mhi)
+		/* LE MHI platform */
+		ipa3_qmi_service_init(QMI_IPA_PLATFORM_TYPE_LE_MHI_V01);
 	else
 		/* LE platform not loads uC */
 		ipa3_qmi_service_init(QMI_IPA_PLATFORM_TYPE_LE_V01);
 
-	/* construct default WAN RT tbl for IPACM */
-	if (wan_cons_ep != IPA_EP_NOT_ALLOCATED) {
-		ret = ipa3_setup_a7_qmap_hdr();
-		if (ret)
-			goto setup_a7_qmap_hdr_err;
-		ret = ipa3_setup_dflt_wan_rt_tables();
-		if (ret)
-			goto setup_dflt_wan_rt_tables_err;
-	}
-
 	if (!atomic_read(&rmnet_ipa3_ctx->is_ssr)) {
 		/* Start transport-driver fd ioctl for ipacm for first init */
 		ret = ipa3_wan_ioctl_init();
@@ -2589,6 +2642,7 @@ static int ipa3_wwan_probe(struct platform_device *pdev)
 		ipa3_proxy_clk_unvote();
 	}
 	atomic_set(&rmnet_ipa3_ctx->is_ssr, 0);
+	ipa3_update_ssr_state(false);
 
 	IPAWANERR("rmnet_ipa completed initialization\n");
 	return 0;
@@ -2615,12 +2669,6 @@ static int ipa3_wwan_probe(struct platform_device *pdev)
 alloc_netdev_err:
 	ipa3_wan_ioctl_deinit();
 wan_ioctl_init_err:
-	if (wan_cons_ep != IPA_EP_NOT_ALLOCATED)
-		ipa3_del_dflt_wan_rt_tables();
-setup_dflt_wan_rt_tables_err:
-	if (wan_cons_ep != IPA_EP_NOT_ALLOCATED)
-		ipa3_del_a7_qmap_hdr();
-setup_a7_qmap_hdr_err:
 	ipa3_qmi_service_exit();
 	atomic_set(&rmnet_ipa3_ctx->is_ssr, 0);
 	return ret;
@@ -2667,6 +2715,8 @@ static int ipa3_wwan_remove(struct platform_device *pdev)
 	if (ipa3_qmi_ctx->modem_cfg_emb_pipe_flt == false)
 		ipa3_wwan_del_ul_flt_rule_to_ipa();
 	ipa3_cleanup_deregister_intf();
+	/* reset dl_csum_offload_enabled */
+	rmnet_ipa3_ctx->dl_csum_offload_enabled = false;
 	atomic_set(&rmnet_ipa3_ctx->is_initialized, 0);
 	IPAWANINFO("rmnet_ipa completed deinitialization\n");
 	return 0;
@@ -2855,14 +2905,20 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this,
 		if (atomic_read(&rmnet_ipa3_ctx->is_ssr) &&
 			ipa3_ctx->ipa_hw_type < IPA_HW_v4_0)
 			ipa3_q6_post_shutdown_cleanup();
+
+		if (ipa3_ctx->ipa_endp_delay_wa)
+			ipa3_client_prod_post_shutdown_cleanup();
+
 		IPAWANINFO("IPA AFTER_SHUTDOWN handling is complete\n");
 		break;
 	case SUBSYS_BEFORE_POWERUP:
 		IPAWANINFO("IPA received MPSS BEFORE_POWERUP\n");
-		if (atomic_read(&rmnet_ipa3_ctx->is_ssr))
+		if (atomic_read(&rmnet_ipa3_ctx->is_ssr)) {
 			/* clean up cached QMI msg/handlers */
 			ipa3_qmi_service_exit();
-		/*hold a proxy vote for the modem*/
+			ipa3_q6_pre_powerup_cleanup();
+		}
+		/* hold a proxy vote for the modem. */
 		ipa3_proxy_clk_vote();
 		ipa3_reset_freeze_vote();
 		IPAWANINFO("IPA BEFORE_POWERUP handling is complete\n");
@@ -4109,6 +4165,15 @@ int rmnet_ipa3_send_lan_client_msg(
 		IPAWANERR("Can't allocate memory for tether_info\n");
 		return -ENOMEM;
 	}
+
+	if (data->client_event != IPA_PER_CLIENT_STATS_CONNECT_EVENT &&
+		data->client_event != IPA_PER_CLIENT_STATS_DISCONNECT_EVENT) {
+		IPAWANERR("Wrong event given. Event:- %d\n",
+			data->client_event);
+		kfree(lan_client);
+		return -EINVAL;
+	}
+	data->lan_client.lanIface[IPA_RESOURCE_NAME_MAX-1] = '\0';
 	memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
 	memcpy(lan_client, &data->lan_client,
 		sizeof(struct ipa_lan_client_msg));
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
index 40a0a82..7661558 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.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
@@ -19,6 +19,7 @@
 #include <linux/uaccess.h>
 #include <linux/rmnet_ipa_fd_ioctl.h>
 #include "ipa_qmi_service.h"
+#include "ipa_i.h"
 
 #define DRIVER_NAME "wwan_ioctl"
 
@@ -389,6 +390,10 @@ static long ipa3_wan_ioctl(struct file *filp,
 			break;
 		}
 
+		if (ipa_mpm_notify_wan_state()) {
+			IPAWANERR("WAN_IOC_NOTIFY_WAN_STATE failed\n");
+			retval = -EPERM;
+		}
 		break;
 	case WAN_IOC_ENABLE_PER_CLIENT_STATS:
 		IPAWANDBG_LOW("got WAN_IOC_ENABLE_PER_CLIENT_STATS :>>>\n");
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index 05d5db5..218be64 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -46,7 +46,7 @@
 #define MHI_RING_PRIMARY_EVT_ID		1
 #define MHI_1K_SIZE			0x1000
 /* Updated Specification for event start is NER - 2 and end - NER -1 */
-#define MHI_HW_ACC_EVT_RING_START	2
+#define MHI_HW_ACC_EVT_RING_START	3
 #define MHI_HW_ACC_EVT_RING_END		1
 
 #define MHI_HOST_REGION_NUM             2
@@ -66,6 +66,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;
@@ -843,7 +844,9 @@ static int mhi_hwc_chcmd(struct mhi_dev *mhi, uint chid,
 	case MHI_DEV_RING_EL_START:
 		connect_params.channel_id = chid;
 		connect_params.sys.skip_ep_cfg = true;
-		if ((chid % 2) == 0x0)
+		if (chid == MHI_CLIENT_ADPL_IN)
+			connect_params.sys.client = IPA_CLIENT_MHI_DPL_CONS;
+		else if ((chid % 2) == 0x0)
 			connect_params.sys.client = IPA_CLIENT_MHI_PROD;
 		else
 			connect_params.sys.client = IPA_CLIENT_MHI_CONS;
@@ -1241,8 +1244,6 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
 	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};
 	union mhi_dev_ring_ctx *evt_ctx;
 
 	ch_id = el->generic.chid;
@@ -1347,9 +1348,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
 		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) {
@@ -1403,9 +1402,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
 
 			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:
@@ -1479,9 +1479,9 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
 				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:
@@ -1600,7 +1600,7 @@ static void mhi_dev_queue_channel_db(struct mhi_dev *mhi,
 			ring = &mhi->ring[ch_num + mhi->ch_ring_start];
 			if (ring->state == RING_STATE_UINT) {
 				pr_debug("Channel not opened for %d\n", ch_num);
-				break;
+				continue;
 			}
 			mhi_ring_set_state(ring, RING_STATE_PENDING);
 			list_add(&ring->list, &mhi->process_ring_list);
@@ -1644,13 +1644,28 @@ static void mhi_dev_check_channel_interrupt(struct mhi_dev *mhi)
 	}
 }
 
+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++) {
@@ -1664,19 +1679,9 @@ static int mhi_dev_abort(struct mhi_dev *mhi)
 		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);
@@ -1751,7 +1756,7 @@ static void mhi_dev_transfer_completion_cb(void *mreq)
 	ch = client->channel;
 	mhi = ch->ring->mhi_dev;
 	el = req->el;
-	transfer_len = req->len;
+	transfer_len = req->transfer_len;
 	snd_cmpl = req->snd_cmpl;
 	rd_offset = req->rd_offset;
 	ch->curr_ereq->context = ch;
@@ -1816,8 +1821,7 @@ static void mhi_dev_scheduler(struct work_struct *work)
 	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 */
@@ -1826,6 +1830,10 @@ static void mhi_dev_scheduler(struct work_struct *work)
 	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__);
@@ -1855,10 +1863,6 @@ static void mhi_dev_scheduler(struct work_struct *work)
 			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) {
@@ -2290,6 +2294,8 @@ int mhi_dev_channel_isempty(struct mhi_dev_client *handle)
 	int rc;
 
 	ch = handle->channel;
+	if (!ch)
+		return -EINVAL;
 
 	rc = ch->ring->rd_offset == ch->ring->wr_offset;
 
@@ -2448,7 +2454,7 @@ int mhi_dev_read_channel(struct mhi_req *mreq)
 			(mreq->len - usr_buf_remaining);
 		ch->tre_bytes_left -= bytes_to_read;
 		mreq->el = el;
-		mreq->actual_len = bytes_read;
+		mreq->transfer_len = bytes_to_read;
 		mreq->rd_offset = ring->rd_offset;
 		mhi_log(MHI_MSG_VERBOSE, "reading %d bytes from chan %d\n",
 				bytes_to_read, mreq->chan);
@@ -2612,6 +2618,7 @@ int mhi_dev_write_channel(struct mhi_req *wreq)
 		write_to_loc = el->tre.data_buf_ptr;
 		wreq->rd_offset = ring->rd_offset;
 		wreq->el = el;
+		wreq->transfer_len = bytes_to_write;
 		rc = mhi_ctx->device_to_host(write_to_loc,
 						(void *) read_from_loc,
 						bytes_to_write,
@@ -2668,13 +2675,85 @@ int mhi_dev_write_channel(struct mhi_req *wreq)
 }
 EXPORT_SYMBOL(mhi_dev_write_channel);
 
+static int mhi_dev_recover(struct mhi_dev *mhi)
+{
+	int rc = 0;
+	uint32_t syserr, max_cnt = 0, bhi_intvec = 0;
+	u32 mhi_reset;
+	enum mhi_dev_state state;
+
+	/* Check if MHI is in syserr */
+	mhi_dev_mmio_masked_read(mhi, MHISTATUS,
+				MHISTATUS_SYSERR_MASK,
+				MHISTATUS_SYSERR_SHIFT, &syserr);
+
+	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;
+
+		if (bhi_intvec != 0xffffffff) {
+			/* Indicate the host that the device is ready */
+			rc = ep_pcie_trigger_msi(mhi->phandle, bhi_intvec);
+			if (rc) {
+				pr_err("%s: error sending msi\n", __func__);
+				return rc;
+			}
+		}
+
+		/* 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);
+
+		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,
+								&mhi_reset);
+			if (rc) {
+				pr_err("%s: get mhi state failed\n", __func__);
+				return rc;
+			}
+			max_cnt++;
+		}
+
+		if (!mhi_reset) {
+			mhi_log(MHI_MSG_VERBOSE, "Host failed to set reset\n");
+			return -EINVAL;
+		}
+	}
+	/*
+	 * Now mask the interrupts so that the state machine moves
+	 * only after IPA is ready
+	 */
+	mhi_dev_mmio_mask_interrupts(mhi);
+	return 0;
+}
+
 static void mhi_dev_enable(struct work_struct *work)
 {
 	int rc = 0;
 	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;
 
@@ -2999,11 +3078,7 @@ static int mhi_deinit(struct mhi_dev *mhi)
 			ring->ring_cache_dma_handle);
 	}
 
-	for (i = 0; i < mhi->cfg.channels; i++)
-		mutex_destroy(&mhi->ch[i].ch_lock);
-
 	devm_kfree(&pdev->dev, mhi->mmio_backup);
-	devm_kfree(&pdev->dev, mhi->ch);
 	devm_kfree(&pdev->dev, mhi->ring);
 
 	mhi_dev_sm_exit(mhi);
@@ -3031,14 +3106,20 @@ static int mhi_init(struct mhi_dev *mhi)
 	if (!mhi->ring)
 		return -ENOMEM;
 
-	mhi->ch = devm_kzalloc(&pdev->dev,
+	/*
+	 * mhi_init is also called during device reset, in
+	 * which case channel mem will already be allocated.
+	 */
+	if (!mhi->ch) {
+		mhi->ch = devm_kzalloc(&pdev->dev,
 			(sizeof(struct mhi_dev_channel) *
 			(mhi->cfg.channels)), GFP_KERNEL);
-	if (!mhi->ch)
-		return -ENOMEM;
+		if (!mhi->ch)
+			return -ENOMEM;
 
-	for (i = 0; i < mhi->cfg.channels; i++)
-		mutex_init(&mhi->ch[i].ch_lock);
+		for (i = 0; i < mhi->cfg.channels; i++)
+			mutex_init(&mhi->ch[i].ch_lock);
+	}
 
 	spin_lock_init(&mhi->lock);
 	mhi->mmio_backup = devm_kzalloc(&pdev->dev,
@@ -3070,8 +3151,9 @@ static int mhi_dev_resume_mmio_mhi_reinit(struct mhi_dev *mhi_ctx)
 		EP_PCIE_EVENT_PM_D3_COLD |
 		EP_PCIE_EVENT_PM_D0 |
 		EP_PCIE_EVENT_PM_RST_DEAST |
-		EP_PCIE_EVENT_MHI_A7 |
 		EP_PCIE_EVENT_LINKDOWN;
+	if (!mhi_ctx->mhi_int)
+		mhi_ctx->event_reg.events |= EP_PCIE_EVENT_MHI_A7;
 	mhi_ctx->event_reg.user = mhi_ctx;
 	mhi_ctx->event_reg.mode = EP_PCIE_TRIGGER_CALLBACK;
 	mhi_ctx->event_reg.callback = mhi_dev_sm_pcie_handler;
@@ -3150,6 +3232,15 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx)
 	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);
@@ -3179,6 +3270,18 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx)
 	mutex_init(&mhi_ctx->mhi_event_lock);
 	mutex_init(&mhi_ctx->mhi_write_test);
 
+	mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id);
+	if (!mhi_ctx->phandle) {
+		pr_err("PCIe driver get handle failed.\n");
+		return -EINVAL;
+	}
+
+	rc = mhi_dev_recover(mhi_ctx);
+	if (rc) {
+		pr_err("%s: get mhi state failed\n", __func__);
+		return rc;
+	}
+
 	rc = mhi_init(mhi_ctx);
 	if (rc)
 		return rc;
@@ -3208,19 +3311,13 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx)
 		pr_err("Failed to update the MHI version\n");
 		return rc;
 	}
-
-	mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id);
-	if (!mhi_ctx->phandle) {
-		pr_err("PCIe driver get handle failed.\n");
-		return -EINVAL;
-	}
-
 	mhi_ctx->event_reg.events = EP_PCIE_EVENT_PM_D3_HOT |
 		EP_PCIE_EVENT_PM_D3_COLD |
 		EP_PCIE_EVENT_PM_D0 |
 		EP_PCIE_EVENT_PM_RST_DEAST |
-		EP_PCIE_EVENT_MHI_A7 |
 		EP_PCIE_EVENT_LINKDOWN;
+	if (!mhi_ctx->mhi_int)
+		mhi_ctx->event_reg.events |= EP_PCIE_EVENT_MHI_A7;
 	mhi_ctx->event_reg.user = mhi_ctx;
 	mhi_ctx->event_reg.mode = EP_PCIE_TRIGGER_CALLBACK;
 	mhi_ctx->event_reg.callback = mhi_dev_sm_pcie_handler;
@@ -3276,6 +3373,8 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx)
 	if (mhi_ctx->use_edma)
 		mhi_ring_init_cb(mhi_ctx);
 
+	mhi_ctx->init_done = true;
+
 	return 0;
 }
 
@@ -3457,7 +3556,7 @@ static int __init mhi_dev_init(void)
 {
 	return platform_driver_register(&mhi_dev_driver);
 }
-module_init(mhi_dev_init);
+subsys_initcall(mhi_dev_init);
 
 static void __exit mhi_dev_exit(void)
 {
diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h
index 0bb3022..f792e3d 100644
--- a/drivers/platform/msm/mhi_dev/mhi.h
+++ b/drivers/platform/msm/mhi_dev/mhi.h
@@ -567,6 +567,9 @@ struct mhi_dev {
 	/* 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;
 
@@ -606,6 +609,7 @@ enum mhi_msg_level {
 	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;
@@ -616,7 +620,7 @@ extern void *mhi_ipc_log;
 	} \
 	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)
 
@@ -883,6 +887,12 @@ int mhi_dev_mmio_mask_erdb_interrupts(struct mhi_dev *dev);
 int mhi_dev_mmio_read_erdb_status_interrupts(struct mhi_dev *dev);
 
 /**
+ * mhi_dev_mmio_mask_interrupts() - Mask all MHI interrupts.
+ * @dev:	MHI device structure.
+ */
+void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev);
+
+/**
  * mhi_dev_mmio_clear_interrupts() - Clear all doorbell interrupts.
  * @dev:	MHI device structure.
  */
@@ -953,7 +963,7 @@ int mhi_dev_get_mhi_addr(struct mhi_dev *dev);
  * @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
@@ -1063,5 +1073,17 @@ int mhi_dev_net_interface_init(void);
 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_dev_net.c b/drivers/platform/msm/mhi_dev/mhi_dev_net.c
index e72beb3..d76c65a 100644
--- a/drivers/platform/msm/mhi_dev/mhi_dev_net.c
+++ b/drivers/platform/msm/mhi_dev/mhi_dev_net.c
@@ -246,10 +246,10 @@ static void mhi_dev_net_read_completion_cb(void *req)
 	struct sk_buff *skb = mreq->context;
 	unsigned long   flags;
 
-	skb->len = mreq->actual_len;
+	skb->len = mreq->transfer_len;
 	skb->protocol =
 		mhi_dev_net_eth_type_trans(skb);
-	skb_put(skb, mreq->actual_len);
+	skb_put(skb, mreq->transfer_len);
 	net_handle->dev->stats.rx_packets++;
 	skb->dev = net_handle->dev;
 	netif_rx(skb);
diff --git a/drivers/platform/msm/mhi_dev/mhi_mmio.c b/drivers/platform/msm/mhi_dev/mhi_mmio.c
index 1f8ade6..67868f9 100644
--- a/drivers/platform/msm/mhi_dev/mhi_mmio.c
+++ b/drivers/platform/msm/mhi_dev/mhi_mmio.c
@@ -190,7 +190,7 @@ int mhi_dev_mmio_disable_erdb_a7(struct mhi_dev *dev, uint32_t erdb_id)
 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;
 
@@ -203,9 +203,12 @@ int mhi_dev_mmio_get_mhi_state(struct mhi_dev *dev, enum mhi_dev_state *state,
 	mhi_dev_mmio_read(dev, MHICTRL, &reg_value);
 
 	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;
 }
@@ -389,7 +392,7 @@ int mhi_dev_mmio_disable_cmdb_interrupt(struct mhi_dev *dev)
 }
 EXPORT_SYMBOL(mhi_dev_mmio_disable_cmdb_interrupt);
 
-static void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev)
+void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev)
 {
 	mhi_dev_mmio_disable_ctrl_interrupt(dev);
 
@@ -399,6 +402,7 @@ static void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev)
 
 	mhi_dev_mmio_mask_erdb_interrupts(dev);
 }
+EXPORT_SYMBOL(mhi_dev_mmio_mask_interrupts);
 
 int mhi_dev_mmio_clear_interrupts(struct mhi_dev *dev)
 {
diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c
index 50126e9..ee78f32 100644
--- a/drivers/platform/msm/mhi_dev/mhi_sm.c
+++ b/drivers/platform/msm/mhi_dev/mhi_sm.c
@@ -1190,7 +1190,7 @@ void mhi_dev_sm_pcie_handler(struct ep_pcie_notify *notify)
 		spin_lock_irqsave(&mhi_sm_ctx->mhi_dev->lock, flags);
 		if ((mhi_sm_ctx->mhi_dev->mhi_int) &&
 				(mhi_sm_ctx->mhi_dev->mhi_int_en)) {
-			disable_irq(mhi_sm_ctx->mhi_dev->mhi_irq);
+			disable_irq_nosync(mhi_sm_ctx->mhi_dev->mhi_irq);
 			mhi_sm_ctx->mhi_dev->mhi_int_en = false;
 			MHI_SM_DBG("Disable MHI IRQ during D3 HOT");
 		}
diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c
index cfbdece..28778086 100644
--- a/drivers/platform/msm/mhi_dev/mhi_uci.c
+++ b/drivers/platform/msm/mhi_dev/mhi_uci.c
@@ -37,10 +37,13 @@
 #define MAX_UCI_WR_REQ			10
 #define MAX_NR_TRBS_PER_CHAN		9
 #define MHI_QTI_IFACE_ID		4
+#define MHI_ADPL_IFACE_ID		5
 #define DEVICE_NAME			"mhi"
 #define MAX_DEVICE_NAME_SIZE		80
 
 #define MHI_UCI_ASYNC_READ_TIMEOUT	msecs_to_jiffies(100)
+#define MHI_UCI_ASYNC_WRITE_TIMEOUT	msecs_to_jiffies(100)
+#define MHI_UCI_AT_CTRL_READ_TIMEOUT	msecs_to_jiffies(1000)
 
 enum uci_dbg_level {
 	UCI_DBG_VERBOSE = 0x0,
@@ -73,12 +76,23 @@ struct chan_attr {
 	u32 nr_trbs;
 	/* direction of the channel, see enum mhi_chan_dir */
 	enum mhi_chan_dir dir;
-	/* need to register mhi channel state change callback */
-	bool register_cb;
+	/* Optional mhi channel state change callback func pointer */
+	void (*chan_state_cb)(struct mhi_dev_client_cb_data *cb_data);
 	/* Name of char device */
 	char *device_name;
+	/* Client-specific TRE handler */
+	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;
+
 };
 
+static void mhi_uci_adb_client_cb(struct mhi_dev_client_cb_data *cb_data);
+static void mhi_uci_at_ctrl_client_cb(struct mhi_dev_client_cb_data *cb_data);
+static void mhi_uci_at_ctrl_tre_cb(struct mhi_dev_client_cb_reason *reason);
+
 /* UCI channel attributes table */
 static const struct chan_attr uci_chan_attr_table[] = {
 	{
@@ -86,7 +100,7 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -94,7 +108,7 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -102,7 +116,7 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -110,7 +124,7 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -118,7 +132,7 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -126,7 +140,7 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -134,15 +148,18 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
+		NULL,
+		NULL,
+		NULL,
 		false,
-		NULL
+		true
 	},
 	{
 		MHI_CLIENT_MBIM_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -150,15 +167,18 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
+		NULL,
+		NULL,
+		NULL,
 		false,
-		NULL
+		true
 	},
 	{
 		MHI_CLIENT_QMI_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -166,7 +186,7 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -174,7 +194,7 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -182,23 +202,26 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false,
-		NULL
+		mhi_uci_at_ctrl_client_cb,
+		NULL,
+		mhi_uci_at_ctrl_tre_cb
 	},
 	{
 		MHI_CLIENT_IP_CTRL_1_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false,
-		NULL
+		mhi_uci_at_ctrl_client_cb,
+		NULL,
+		NULL,
+		true
 	},
 	{
 		MHI_CLIENT_DUN_OUT,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -206,7 +229,7 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false,
+		NULL,
 		NULL
 	},
 	{
@@ -214,7 +237,7 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		true,
+		mhi_uci_adb_client_cb,
 		NULL
 	},
 	{
@@ -222,11 +245,33 @@ static const struct chan_attr uci_chan_attr_table[] = {
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		true,
+		mhi_uci_adb_client_cb,
 		"android_adb"
 	},
 };
 
+/* Defines for AT messages */
+#define MHI_UCI_CTRL_MSG_MAGIC		(0x4354524C)
+#define MHI_UCI_CTRL_MSG_DTR		BIT(0)
+#define MHI_UCI_CTRL_MSG_RTS		BIT(1)
+#define MHI_UCI_CTRL_MSG_DCD		BIT(0)
+#define MHI_UCI_CTRL_MSG_DSR		BIT(1)
+#define MHI_UCI_CTRL_MSG_RI		BIT(3)
+
+#define MHI_UCI_CTRL_MSGID_SET_CTRL_LINE	0x10
+#define MHI_UCI_CTRL_MSGID_SERIAL_STATE		0x11
+#define MHI_UCI_TIOCM_GET			TIOCMGET
+#define MHI_UCI_TIOCM_SET			TIOCMSET
+
+/* AT message format */
+struct __packed mhi_uci_ctrl_msg {
+	u32 preamble;
+	u32 msg_id;
+	u32 dest_id;
+	u32 size;
+	u32 msg;
+};
+
 struct uci_ctrl {
 	wait_queue_head_t	ctrl_wq;
 	struct mhi_uci_ctxt_t	*uci_ctxt;
@@ -262,8 +307,12 @@ struct uci_client {
 	struct mhi_req *wreqs;
 	struct list_head wr_req_list;
 	struct completion read_done;
+	struct completion at_ctrl_read_done;
+	struct completion *write_done;
 	int (*send)(struct uci_client*, void*, u32);
 	int (*read)(struct uci_client*, struct mhi_req*, int*);
+	unsigned int tiocm;
+	unsigned int at_ctrl_mask;
 };
 
 struct mhi_uci_ctxt_t {
@@ -278,6 +327,8 @@ struct mhi_uci_ctxt_t {
 	struct class *mhi_uci_class;
 	atomic_t mhi_disabled;
 	atomic_t mhi_enable_notif_wq_active;
+	struct workqueue_struct *at_ctrl_wq;
+	struct work_struct at_ctrl_work;
 };
 
 #define CHAN_TO_CLIENT(_CHAN_NR) (_CHAN_NR / 2)
@@ -375,6 +426,9 @@ static void mhi_uci_write_completion_cb(void *req)
 	spin_lock_irqsave(&uci_handle->wr_req_lock, flags);
 	list_add_tail(&ureq->list, &uci_handle->wr_req_list);
 	spin_unlock_irqrestore(&uci_handle->wr_req_lock, flags);
+
+	if (uci_handle->write_done)
+		complete(uci_handle->write_done);
 }
 
 static void mhi_uci_read_completion_cb(void *req)
@@ -400,7 +454,8 @@ static int mhi_uci_send_sync(struct uci_client *uci_handle,
 
 	ret_val = mhi_dev_write_channel(&ureq);
 
-	kfree(data_loc);
+	if (ret_val == size)
+		kfree(data_loc);
 	return ret_val;
 }
 
@@ -441,7 +496,6 @@ static int mhi_uci_send_async(struct uci_client *uci_handle,
 	return bytes_to_write;
 
 error_async_transfer:
-	kfree(data_loc);
 	ureq->buf = NULL;
 	spin_lock_irq(&uci_handle->wr_req_lock);
 	list_add_tail(&ureq->list, &uci_handle->wr_req_list);
@@ -450,41 +504,42 @@ static int mhi_uci_send_async(struct uci_client *uci_handle,
 	return bytes_to_write;
 }
 
-static int mhi_uci_send_packet(struct mhi_dev_client **client_handle,
-		const char __user *buf, u32 size)
+static int mhi_uci_send_packet(struct uci_client *uci_handle, void *data_loc,
+				u32 size)
 {
-	void *data_loc;
-	unsigned long memcpy_result;
-	struct uci_client *uci_handle;
+	int ret_val;
 
-	if (!client_handle || !buf || !size)
-		return -EINVAL;
+	mutex_lock(&uci_handle->out_chan_lock);
+	do {
+		ret_val = uci_handle->send(uci_handle, data_loc, size);
+		if (ret_val < 0) {
+			uci_log(UCI_DBG_ERROR,
+				"Err sending data: chan %d, buf %pK, size %d\n",
+				uci_handle->out_chan, data_loc, size);
+			ret_val = -EIO;
+			break;
+		}
+		if (!ret_val) {
+			uci_log(UCI_DBG_VERBOSE,
+				"No descriptors available, did we poll, chan %d?\n",
+				uci_handle->out_chan);
+			mutex_unlock(&uci_handle->out_chan_lock);
+			if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY))
+				return -EAGAIN;
+			ret_val = wait_event_interruptible(uci_handle->write_wq,
+					!mhi_dev_channel_isempty(
+					uci_handle->out_handle));
+			if (-ERESTARTSYS == ret_val) {
+				uci_log(UCI_DBG_WARNING,
+					"Waitqueue cancelled by system\n");
+				return ret_val;
+			}
+			mutex_lock(&uci_handle->out_chan_lock);
+		}
+	} while (!ret_val);
+	mutex_unlock(&uci_handle->out_chan_lock);
 
-	if (size > TRB_MAX_DATA_SIZE) {
-		uci_log(UCI_DBG_ERROR,
-			"Too big write size: %d, max supported size is %d\n",
-			size, TRB_MAX_DATA_SIZE);
-		return -EFBIG;
-	}
-
-	uci_handle = container_of(client_handle, struct uci_client,
-					out_handle);
-	data_loc = kmalloc(size, GFP_KERNEL);
-	if (!data_loc) {
-		uci_log(UCI_DBG_ERROR,
-		"Failed to allocate kernel buf for user requested size 0x%x\n",
-			size);
-		return -ENOMEM;
-	}
-	memcpy_result = copy_from_user(data_loc, buf, size);
-	if (memcpy_result)
-		goto error_memcpy;
-
-	return uci_handle->send(uci_handle, data_loc, size);
-
-error_memcpy:
-	kfree(data_loc);
-	return -EFAULT;
+	return ret_val;
 }
 
 static unsigned int mhi_uci_ctrl_poll(struct file *file, poll_table *wait)
@@ -523,6 +578,7 @@ static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait)
 
 	poll_wait(file, &uci_handle->read_wq, wait);
 	poll_wait(file, &uci_handle->write_wq, wait);
+	mask = uci_handle->at_ctrl_mask;
 	if (!atomic_read(&uci_ctxt.mhi_disabled) &&
 		!mhi_dev_channel_isempty(uci_handle->in_handle)) {
 		uci_log(UCI_DBG_VERBOSE,
@@ -608,7 +664,7 @@ static int mhi_uci_read_async(struct uci_client *uci_handle,
 			"wk up Read completed on ch %d\n", ureq->chan);
 
 		uci_handle->pkt_loc = (void *)ureq->buf;
-		uci_handle->pkt_size = ureq->actual_len;
+		uci_handle->pkt_size = ureq->transfer_len;
 
 		uci_log(UCI_DBG_VERBOSE,
 			"Got pkt of sz 0x%x at adr %pK, ch %d\n",
@@ -641,7 +697,7 @@ static int mhi_uci_read_sync(struct uci_client *uci_handle,
 
 	if (*bytes_avail > 0) {
 		uci_handle->pkt_loc = (void *)ureq->buf;
-		uci_handle->pkt_size = ureq->actual_len;
+		uci_handle->pkt_size = ureq->transfer_len;
 
 		uci_log(UCI_DBG_VERBOSE,
 			"Got pkt of sz 0x%x at adr %pK, ch %d\n",
@@ -919,81 +975,62 @@ static ssize_t mhi_uci_ctrl_client_read(struct file *file,
 	return size;
 }
 
-static ssize_t mhi_uci_client_read(struct file *file, char __user *ubuf,
-		size_t uspace_buf_size, loff_t *bytes_pending)
+static int __mhi_uci_client_read(struct uci_client *uci_handle,
+		int *bytes_avail)
 {
-	struct uci_client *uci_handle = NULL;
-	struct mhi_dev_client *client_handle = NULL;
-	int bytes_avail = 0;
 	int ret_val = 0;
-	struct mutex *mutex;
-	ssize_t bytes_copied = 0;
-	u32 addr_offset = 0;
+	struct mhi_dev_client *client_handle;
 	struct mhi_req ureq;
 
-	if (!file || !ubuf || !uspace_buf_size ||
-			!file->private_data)
-		return -EINVAL;
-
-	uci_handle = file->private_data;
 	client_handle = uci_handle->in_handle;
-	mutex = &uci_handle->in_chan_lock;
 	ureq.chan = uci_handle->in_chan;
-
-	mutex_lock(mutex);
 	ureq.client = client_handle;
 	ureq.buf = uci_handle->in_buf_list[0].addr;
 	ureq.len = uci_handle->in_buf_list[0].buf_size;
 
-
-	uci_log(UCI_DBG_VERBOSE, "Client attempted read on chan %d\n",
-			ureq.chan);
 	do {
 		if (!uci_handle->pkt_loc &&
 			!atomic_read(&uci_ctxt.mhi_disabled)) {
 			ret_val = uci_handle->read(uci_handle, &ureq,
-							&bytes_avail);
+				bytes_avail);
 			if (ret_val)
-				goto error;
-			if (bytes_avail > 0)
-				*bytes_pending = (loff_t)uci_handle->pkt_size;
+				return ret_val;
 		}
-		if (bytes_avail == 0) {
+		if (*bytes_avail == 0) {
 
 			/* If nothing was copied yet, wait for data */
 			uci_log(UCI_DBG_VERBOSE,
 				"No data read_data_ready %d, chan %d\n",
 				atomic_read(&uci_handle->read_data_ready),
 				ureq.chan);
-			if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY)) {
-				ret_val = -EAGAIN;
-				goto error;
-			}
+			if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY))
+				return -EAGAIN;
+
 			ret_val = wait_event_interruptible(uci_handle->read_wq,
 				(!mhi_dev_channel_isempty(client_handle)));
 
 			if (ret_val == -ERESTARTSYS) {
 				uci_log(UCI_DBG_ERROR, "Exit signal caught\n");
-				goto error;
+				return ret_val;
 			}
+
 			uci_log(UCI_DBG_VERBOSE,
 				"wk up Got data on ch %d read_data_ready %d\n",
 				ureq.chan,
 				atomic_read(&uci_handle->read_data_ready));
-
+		} else if (*bytes_avail > 0) {
 			/* A valid packet was returned from MHI */
-		} else if (bytes_avail > 0) {
 			uci_log(UCI_DBG_VERBOSE,
 				"Got packet: avail pkts %d phy_adr %pK, ch %d\n",
 				atomic_read(&uci_handle->read_data_ready),
 				ureq.buf,
 				ureq.chan);
 			break;
+		} else {
 			/*
 			 * MHI did not return a valid packet, but we have one
 			 * which we did not finish returning to user
 			 */
-		} else {
 			uci_log(UCI_DBG_CRITICAL,
 				"chan %d err: avail pkts %d phy_adr %pK",
 				ureq.chan,
@@ -1003,10 +1040,36 @@ static ssize_t mhi_uci_client_read(struct file *file, char __user *ubuf,
 		}
 	} while (!uci_handle->pkt_loc);
 
+	return ret_val;
+}
+
+static ssize_t mhi_uci_client_read(struct file *file, char __user *ubuf,
+	size_t uspace_buf_size, loff_t *bytes_pending)
+{
+	struct uci_client *uci_handle = NULL;
+	int bytes_avail = 0, ret_val = 0;
+	struct mutex *mutex;
+	ssize_t bytes_copied = 0;
+	u32 addr_offset = 0;
+
+	uci_handle = file->private_data;
+	mutex = &uci_handle->in_chan_lock;
+	mutex_lock(mutex);
+
+	uci_log(UCI_DBG_VERBOSE, "Client attempted read on chan %d\n",
+		uci_handle->in_chan);
+
+	ret_val = __mhi_uci_client_read(uci_handle, &bytes_avail);
+	if (ret_val)
+		goto error;
+
+	if (bytes_avail > 0)
+		*bytes_pending = (loff_t)uci_handle->pkt_size;
+
 	if (uspace_buf_size >= *bytes_pending) {
 		addr_offset = uci_handle->pkt_size - *bytes_pending;
 		if (copy_to_user(ubuf, uci_handle->pkt_loc + addr_offset,
-							*bytes_pending)) {
+			*bytes_pending)) {
 			ret_val = -EIO;
 			goto error;
 		}
@@ -1014,50 +1077,51 @@ static ssize_t mhi_uci_client_read(struct file *file, char __user *ubuf,
 		bytes_copied = *bytes_pending;
 		*bytes_pending = 0;
 		uci_log(UCI_DBG_VERBOSE, "Copied 0x%x of 0x%x, chan %d\n",
-				bytes_copied, (u32)*bytes_pending, ureq.chan);
+			bytes_copied, (u32)*bytes_pending, uci_handle->in_chan);
 	} else {
 		addr_offset = uci_handle->pkt_size - *bytes_pending;
 		if (copy_to_user(ubuf, (void *) (uintptr_t)uci_handle->pkt_loc +
-					addr_offset, uspace_buf_size)) {
+			addr_offset, uspace_buf_size)) {
 			ret_val = -EIO;
 			goto error;
 		}
 		bytes_copied = uspace_buf_size;
 		*bytes_pending -= uspace_buf_size;
 		uci_log(UCI_DBG_VERBOSE, "Copied 0x%x of 0x%x,chan %d\n",
-				bytes_copied,
-				(u32)*bytes_pending,
-				ureq.chan);
+			bytes_copied,
+			(u32)*bytes_pending,
+			uci_handle->in_chan);
 	}
 	/* We finished with this buffer, map it back */
 	if (*bytes_pending == 0) {
 		uci_log(UCI_DBG_VERBOSE,
-				"All data consumed. Pkt loc %pK ,chan %d\n",
-				uci_handle->pkt_loc, ureq.chan);
+			"All data consumed. Pkt loc %p ,chan %d\n",
+			uci_handle->pkt_loc, uci_handle->in_chan);
 		uci_handle->pkt_loc = 0;
 		uci_handle->pkt_size = 0;
 	}
 	uci_log(UCI_DBG_VERBOSE,
-			"Returning 0x%x bytes, 0x%x bytes left\n",
-			bytes_copied, (u32)*bytes_pending);
+		"Returning 0x%x bytes, 0x%x bytes left\n",
+		bytes_copied, (u32)*bytes_pending);
 	mutex_unlock(mutex);
 	return bytes_copied;
 error:
 	mutex_unlock(mutex);
+
 	uci_log(UCI_DBG_ERROR, "Returning %d\n", ret_val);
 	return ret_val;
 }
 
 static ssize_t mhi_uci_client_write(struct file *file,
-		const char __user *buf,
-		size_t count, loff_t *offp)
+			const char __user *buf, size_t count, loff_t *offp)
 {
 	struct uci_client *uci_handle = NULL;
-	int ret_val = 0;
-	u32 chan = 0xFFFFFFFF;
+	void *data_loc;
+	unsigned long memcpy_result;
+	int rc;
 
 	if (file == NULL || buf == NULL ||
-			!count || file->private_data == NULL)
+		!count || file->private_data == NULL)
 		return -EINVAL;
 
 	uci_handle = file->private_data;
@@ -1068,40 +1132,98 @@ static ssize_t mhi_uci_client_write(struct file *file,
 			uci_handle->out_chan);
 		return -EIO;
 	}
-	chan = uci_handle->out_chan;
-	mutex_lock(&uci_handle->out_chan_lock);
-	while (!ret_val) {
-		ret_val = mhi_uci_send_packet(&uci_handle->out_handle,
-						buf, count);
-		if (ret_val < 0) {
-			uci_log(UCI_DBG_ERROR,
-				"Error while writing data to MHI, chan %d, buf %pK, size %d\n",
-				chan, (void *)buf, count);
-			ret_val = -EIO;
-			break;
-		}
-		if (!ret_val) {
-			uci_log(UCI_DBG_VERBOSE,
-				"No descriptors available, did we poll, chan %d?\n",
-				chan);
-			mutex_unlock(&uci_handle->out_chan_lock);
-			if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY))
-				return -EAGAIN;
-			ret_val = wait_event_interruptible(uci_handle->write_wq,
-				!mhi_dev_channel_isempty(
-					uci_handle->out_handle));
 
-			mutex_lock(&uci_handle->out_chan_lock);
-			if (-ERESTARTSYS == ret_val) {
-				uci_log(UCI_DBG_WARNING,
-					    "Waitqueue cancelled by system\n");
-				break;
-			}
+	if (count > TRB_MAX_DATA_SIZE) {
+		uci_log(UCI_DBG_ERROR,
+			"Too big write size: %d, max supported size is %d\n",
+			count, TRB_MAX_DATA_SIZE);
+		return -EFBIG;
+	}
+
+	data_loc = kmalloc(count, GFP_KERNEL);
+	if (!data_loc)
+		return -ENOMEM;
+
+	memcpy_result = copy_from_user(data_loc, buf, count);
+	if (memcpy_result) {
+		rc = -EFAULT;
+		goto error_memcpy;
+	}
+
+	rc = mhi_uci_send_packet(uci_handle, data_loc, count);
+	if (rc == count)
+		return rc;
+
+error_memcpy:
+	kfree(data_loc);
+	return rc;
+
+}
+
+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);
 		}
 	}
-	mutex_unlock(&uci_handle->out_chan_lock);
-	return ret_val;
 }
+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->out_chan_attr ||
+		!uci_handle->out_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)
 {
@@ -1126,13 +1248,18 @@ static void uci_event_notifier(struct mhi_dev_client_cb_reason *reason)
 	int client_index = 0;
 	struct uci_client *uci_handle = NULL;
 
-	if (reason->reason == MHI_DEV_TRE_AVAILABLE) {
-		client_index = reason->ch_id / 2;
-		uci_handle = &uci_ctxt.client_handles[client_index];
+	client_index = reason->ch_id / 2;
+	uci_handle = &uci_ctxt.client_handles[client_index];
+	/*
+	 * If this client has its own TRE event handler, call that
+	 * else use the default handler.
+	 */
+	if (uci_handle->out_chan_attr->tre_notif_cb) {
+		uci_handle->out_chan_attr->tre_notif_cb(reason);
+	} else if (reason->reason == MHI_DEV_TRE_AVAILABLE) {
 		uci_log(UCI_DBG_DBG,
 			"recived TRE available event for chan %d\n",
-					uci_handle->in_chan);
-
+			uci_handle->in_chan);
 		if (reason->ch_id % 2) {
 			atomic_set(&uci_handle->write_data_ready, 1);
 			wake_up(&uci_handle->write_wq);
@@ -1152,17 +1279,169 @@ static int mhi_register_client(struct uci_client *mhi_client, int index)
 	mutex_init(&mhi_client->in_chan_lock);
 	mutex_init(&mhi_client->out_chan_lock);
 	spin_lock_init(&mhi_client->wr_req_lock);
+	/* Init the completion event for AT ctrl read */
+	init_completion(&mhi_client->at_ctrl_read_done);
 
 	uci_log(UCI_DBG_DBG, "Registering chan %d.\n", mhi_client->out_chan);
 	return 0;
 }
 
+static int mhi_uci_ctrl_set_tiocm(struct uci_client *client,
+				unsigned int ser_state)
+{
+	unsigned int cur_ser_state;
+	unsigned long compl_ret;
+	struct mhi_uci_ctrl_msg *ctrl_msg;
+	int ret_val;
+	struct uci_client *ctrl_client =
+		&uci_ctxt.client_handles[CHAN_TO_CLIENT
+					(MHI_CLIENT_IP_CTRL_1_OUT)];
+	unsigned int info = 0;
+
+	uci_log(UCI_DBG_VERBOSE, "Rcvd ser_state = 0x%x\n", ser_state);
+
+	/* Check if the IP_CTRL channels were started by host */
+	mhi_ctrl_state_info(MHI_CLIENT_IP_CTRL_1_IN, &info);
+	if (info != MHI_STATE_CONNECTED) {
+		uci_log(UCI_DBG_VERBOSE,
+			"IP_CTRL channels not started by host yet\n");
+		return -EAGAIN;
+	}
+
+	cur_ser_state = client->tiocm & ~(TIOCM_DTR | TIOCM_RTS);
+	ser_state &= (TIOCM_CD | TIOCM_DSR | TIOCM_RI);
+
+	if (cur_ser_state == ser_state)
+		return 0;
+
+	ctrl_msg = kzalloc(sizeof(*ctrl_msg), GFP_KERNEL);
+	if (!ctrl_msg)
+		return -ENOMEM;
+
+	ctrl_msg->preamble = MHI_UCI_CTRL_MSG_MAGIC;
+	ctrl_msg->msg_id = MHI_UCI_CTRL_MSGID_SERIAL_STATE;
+	ctrl_msg->dest_id = client->out_chan;
+	ctrl_msg->size = sizeof(unsigned int);
+	if (ser_state & TIOCM_CD)
+		ctrl_msg->msg |= MHI_UCI_CTRL_MSG_DCD;
+	if (ser_state & TIOCM_DSR)
+		ctrl_msg->msg |= MHI_UCI_CTRL_MSG_DSR;
+	if (ser_state & TIOCM_RI)
+		ctrl_msg->msg |= MHI_UCI_CTRL_MSG_RI;
+
+	reinit_completion(ctrl_client->write_done);
+	ret_val = mhi_uci_send_packet(ctrl_client, ctrl_msg, sizeof(*ctrl_msg));
+	if (ret_val != sizeof(*ctrl_msg))
+		goto tiocm_error;
+	compl_ret = wait_for_completion_interruptible_timeout(
+			ctrl_client->write_done,
+			MHI_UCI_ASYNC_WRITE_TIMEOUT);
+	if (compl_ret == -ERESTARTSYS) {
+		uci_log(UCI_DBG_ERROR, "Exit signal caught\n");
+		ret_val = compl_ret;
+		goto tiocm_error;
+	} else if (compl_ret == 0) {
+		uci_log(UCI_DBG_ERROR, "Timed out trying to send ctrl msg\n");
+		ret_val = -EIO;
+		goto tiocm_error;
+	}
+
+	client->tiocm &= ~(TIOCM_CD | TIOCM_DSR | TIOCM_RI);
+	client->tiocm |= ser_state;
+	return 0;
+
+tiocm_error:
+	kfree(ctrl_msg);
+	return ret_val;
+}
+
+static void mhi_uci_at_ctrl_read(struct work_struct *work)
+{
+	int ret_val;
+	int msg_size = 0;
+	struct uci_client *ctrl_client =
+		&uci_ctxt.client_handles[CHAN_TO_CLIENT
+		(MHI_CLIENT_IP_CTRL_1_OUT)];
+	struct uci_client *tgt_client;
+	struct mhi_uci_ctrl_msg *ctrl_msg;
+	unsigned int chan;
+	unsigned long compl_ret;
+
+	while (!mhi_dev_channel_isempty(ctrl_client->in_handle)) {
+
+		ctrl_client->pkt_loc = NULL;
+		ctrl_client->pkt_size = 0;
+
+		ret_val = __mhi_uci_client_read(ctrl_client, &msg_size);
+		if (ret_val) {
+			uci_log(UCI_DBG_ERROR,
+				"Ctrl msg read failed, ret_val is %d\n",
+				ret_val);
+			return;
+		}
+		if (msg_size != sizeof(*ctrl_msg)) {
+			uci_log(UCI_DBG_ERROR, "Invalid ctrl msg size\n");
+			return;
+		}
+		if (!ctrl_client->pkt_loc) {
+			uci_log(UCI_DBG_ERROR, "ctrl msg pkt_loc null\n");
+			return;
+		}
+		ctrl_msg = ctrl_client->pkt_loc;
+		chan = ctrl_msg->dest_id;
+
+		if (chan >= MHI_MAX_SOFTWARE_CHANNELS) {
+			uci_log(UCI_DBG_ERROR,
+				"Invalid channel number in ctrl msg\n");
+			return;
+		}
+
+		uci_log(UCI_DBG_VERBOSE, "preamble: 0x%x\n",
+				ctrl_msg->preamble);
+		uci_log(UCI_DBG_VERBOSE, "msg_id: 0x%x\n", ctrl_msg->msg_id);
+		uci_log(UCI_DBG_VERBOSE, "dest_id: 0x%x\n", ctrl_msg->dest_id);
+		uci_log(UCI_DBG_VERBOSE, "size: 0x%x\n", ctrl_msg->size);
+		uci_log(UCI_DBG_VERBOSE, "msg: 0x%x\n", ctrl_msg->msg);
+
+		tgt_client = &uci_ctxt.client_handles[CHAN_TO_CLIENT(chan)];
+		tgt_client->tiocm &= (TIOCM_CD | TIOCM_DSR | TIOCM_RI);
+
+		if (ctrl_msg->msg & MHI_UCI_CTRL_MSG_DCD)
+			tgt_client->tiocm |= TIOCM_CD;
+		if (ctrl_msg->msg & MHI_UCI_CTRL_MSG_DSR)
+			tgt_client->tiocm |= TIOCM_DSR;
+		if (ctrl_msg->msg & MHI_UCI_CTRL_MSG_RI)
+			tgt_client->tiocm |= TIOCM_RI;
+
+		uci_log(UCI_DBG_VERBOSE, "Rcvd tiocm %d\n", tgt_client->tiocm);
+
+		/* Wait till client reads the new state */
+		reinit_completion(&tgt_client->at_ctrl_read_done);
+
+		tgt_client->at_ctrl_mask = POLLPRI;
+		wake_up(&tgt_client->read_wq);
+
+		uci_log(UCI_DBG_VERBOSE, "Waiting for at_ctrl_read_done");
+		compl_ret = wait_for_completion_interruptible_timeout(
+					&tgt_client->at_ctrl_read_done,
+					MHI_UCI_AT_CTRL_READ_TIMEOUT);
+		if (compl_ret == -ERESTARTSYS) {
+			uci_log(UCI_DBG_ERROR, "Exit signal caught\n");
+			return;
+		} else if (compl_ret == 0) {
+			uci_log(UCI_DBG_ERROR,
+			"Timed out waiting for client to read ctrl state\n");
+		}
+	}
+}
+
 static long mhi_uci_client_ioctl(struct file *file, unsigned int cmd,
 		unsigned long arg)
 {
 	struct uci_client *uci_handle = NULL;
 	int rc = 0;
 	struct ep_info epinfo;
+	unsigned int tiocm;
 
 	if (file == NULL || file->private_data == NULL)
 		return -EINVAL;
@@ -1195,6 +1474,44 @@ static long mhi_uci_client_ioctl(struct file *file, unsigned int cmd,
 			sizeof(epinfo));
 		if (rc)
 			uci_log(UCI_DBG_ERROR, "copying to user space failed");
+	} else if (cmd == MHI_UCI_TIOCM_GET) {
+		rc = copy_to_user((void __user *)arg, &uci_handle->tiocm,
+			sizeof(uci_handle->tiocm));
+		if (rc) {
+			uci_log(UCI_DBG_ERROR,
+				"copying ctrl state to user space failed");
+			rc = -EFAULT;
+		}
+		uci_handle->at_ctrl_mask = 0;
+		uci_log(UCI_DBG_VERBOSE, "Completing at_ctrl_read_done");
+		complete(&uci_handle->at_ctrl_read_done);
+	} else if (cmd == MHI_UCI_TIOCM_SET) {
+		rc = get_user(tiocm, (unsigned int __user *)arg);
+		if (rc)
+			return rc;
+		rc = mhi_uci_ctrl_set_tiocm(uci_handle, tiocm);
+	} else if (cmd == MHI_UCI_DPL_EP_LOOKUP) {
+		uci_log(UCI_DBG_DBG, "DPL EP_LOOKUP for client:%d\n",
+			uci_handle->client_index);
+		epinfo.ph_ep_info.ep_type = DATA_EP_TYPE_PCIE;
+		epinfo.ph_ep_info.peripheral_iface_id = MHI_ADPL_IFACE_ID;
+		epinfo.ipa_ep_pair.prod_pipe_num =
+			ipa_get_ep_mapping(IPA_CLIENT_MHI_DPL_CONS);
+		/* For DPL set cons pipe to -1 to indicate it is unused */
+		epinfo.ipa_ep_pair.cons_pipe_num = -1;
+
+		uci_log(UCI_DBG_DBG, "client:%d ep_type:%d intf:%d\n",
+			uci_handle->client_index,
+			epinfo.ph_ep_info.ep_type,
+			epinfo.ph_ep_info.peripheral_iface_id);
+
+		uci_log(UCI_DBG_DBG, "DPL ipa_prod_idx:%d\n",
+			epinfo.ipa_ep_pair.prod_pipe_num);
+
+		rc = copy_to_user((void __user *)arg, &epinfo,
+			sizeof(epinfo));
+		if (rc)
+			uci_log(UCI_DBG_ERROR, "copying to user space failed");
 	} else {
 		uci_log(UCI_DBG_ERROR, "wrong parameter:%d\n", cmd);
 		rc = -EINVAL;
@@ -1286,7 +1603,70 @@ static int uci_device_create(struct uci_client *client)
 	return r;
 }
 
-static void mhi_uci_client_cb(struct mhi_dev_client_cb_data *cb_data)
+static void mhi_uci_at_ctrl_tre_cb(struct mhi_dev_client_cb_reason *reason)
+{
+	int client_index;
+	struct uci_client *uci_handle;
+
+	client_index = reason->ch_id / 2;
+	uci_handle = &uci_ctxt.client_handles[client_index];
+
+	if (reason->reason == MHI_DEV_TRE_AVAILABLE) {
+		if (reason->ch_id % 2) {
+			atomic_set(&uci_handle->write_data_ready, 1);
+			wake_up(&uci_handle->write_wq);
+		} else {
+			queue_work(uci_ctxt.at_ctrl_wq, &uci_ctxt.at_ctrl_work);
+		}
+	}
+}
+
+static void mhi_uci_at_ctrl_client_cb(struct mhi_dev_client_cb_data *cb_data)
+{
+	struct uci_client *client = cb_data->user_data;
+	int rc;
+
+	uci_log(UCI_DBG_VERBOSE, " Rcvd MHI cb for channel %d, state %d\n",
+		cb_data->channel, cb_data->ctrl_info);
+
+	if (cb_data->ctrl_info == MHI_STATE_CONNECTED) {
+		/* Open the AT ctrl channels */
+		rc = open_client_mhi_channels(client);
+		if (rc) {
+			uci_log(UCI_DBG_INFO,
+				"Failed to open channels ret %d\n", rc);
+			return;
+		}
+		/* Init the completion event for AT ctrl writes */
+		init_completion(client->write_done);
+		/* Create a work queue to process AT commands */
+		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);
+	}
+}
+
+static void mhi_uci_adb_client_cb(struct mhi_dev_client_cb_data *cb_data)
 {
 	struct uci_client *client = cb_data->user_data;
 
@@ -1312,16 +1692,26 @@ static int uci_init_client_attributes(struct mhi_uci_ctxt_t *uci_ctxt)
 		client->in_chan_attr = ++chan_attrib;
 		client->in_chan = index * 2;
 		client->out_chan = index * 2 + 1;
+		client->at_ctrl_mask = 0;
 		client->in_buf_list =
 			kcalloc(chan_attrib->nr_trbs,
 			sizeof(struct mhi_dev_iov),
 			GFP_KERNEL);
 		if (!client->in_buf_list)
 			return -ENOMEM;
-		/* Register callback with MHI if requested */
-		if (client->out_chan_attr->register_cb)
-			mhi_register_state_cb(mhi_uci_client_cb, client,
-						client->out_chan);
+		/* Register channel state change cb with MHI if requested */
+		if (client->out_chan_attr->chan_state_cb)
+			mhi_register_state_cb(
+					client->out_chan_attr->chan_state_cb,
+					client,
+					client->out_chan);
+		if (client->in_chan_attr->wr_cmpl) {
+			client->write_done = kzalloc(
+					sizeof(*client->write_done),
+					GFP_KERNEL);
+			if (!client->write_done)
+				return -ENOMEM;
+		}
 	}
 	return 0;
 }
@@ -1403,7 +1793,7 @@ int mhi_uci_init(void)
 		 * this client's channels is called by the MHI driver,
 		 * if one is registered.
 		 */
-		if (mhi_client->in_chan_attr->register_cb)
+		if (mhi_client->in_chan_attr->chan_state_cb)
 			continue;
 		ret_val = uci_device_create(mhi_client);
 		if (ret_val)
diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c
index 982f642..9a0ed72f 100644
--- a/drivers/platform/msm/qcom-geni-se.c
+++ b/drivers/platform/msm/qcom-geni-se.c
@@ -39,6 +39,8 @@
 #define GENI_SE_DMA_PTR_H(ptr) 0
 #endif
 
+/* Convert BCM threshold to actual frequency x 4 */
+#define CONV_TO_BW(x) (x*20000*4)
 #define NUM_LOG_PAGES 2
 #define MAX_CLK_PERF_LEVEL 32
 static unsigned long default_bus_bw_set[] = {0, 19200000, 50000000,
@@ -330,6 +332,10 @@ static int geni_se_select_fifo_mode(void __iomem *base)
 	geni_write_reg(0xFFFFFFFF, base, SE_DMA_RX_IRQ_CLR);
 	geni_write_reg(0xFFFFFFFF, base, SE_IRQ_EN);
 
+	/* Clearing registers before reading */
+	geni_write_reg(0x00000000, base, SE_GENI_M_IRQ_EN);
+	geni_write_reg(0x00000000, base, SE_GENI_S_IRQ_EN);
+
 	common_geni_m_irq_en = geni_read_reg(base, SE_GENI_M_IRQ_EN);
 	common_geni_s_irq_en = geni_read_reg(base, SE_GENI_S_IRQ_EN);
 	geni_dma_mode = geni_read_reg(base, SE_GENI_DMA_MODE_EN);
@@ -349,9 +355,7 @@ static int geni_se_select_fifo_mode(void __iomem *base)
 
 static int geni_se_select_dma_mode(void __iomem *base)
 {
-	int proto = get_se_proto(base);
 	unsigned int geni_dma_mode = 0;
-	unsigned int common_geni_m_irq_en;
 
 	geni_write_reg(0, base, SE_GSI_EVENT_EN);
 	geni_write_reg(0xFFFFFFFF, base, SE_GENI_M_IRQ_CLEAR);
@@ -359,13 +363,9 @@ static int geni_se_select_dma_mode(void __iomem *base)
 	geni_write_reg(0xFFFFFFFF, base, SE_DMA_TX_IRQ_CLR);
 	geni_write_reg(0xFFFFFFFF, base, SE_DMA_RX_IRQ_CLR);
 	geni_write_reg(0xFFFFFFFF, base, SE_IRQ_EN);
+	geni_write_reg(0x00000000, base, SE_GENI_M_IRQ_EN);
+	geni_write_reg(0x00000000, base, SE_GENI_S_IRQ_EN);
 
-	common_geni_m_irq_en = geni_read_reg(base, SE_GENI_M_IRQ_EN);
-	if (proto != UART)
-		common_geni_m_irq_en &=
-			~(M_TX_FIFO_WATERMARK_EN | M_RX_FIFO_WATERMARK_EN);
-
-	geni_write_reg(common_geni_m_irq_en, base, SE_GENI_M_IRQ_EN);
 	geni_dma_mode = geni_read_reg(base, SE_GENI_DMA_MODE_EN);
 	geni_dma_mode |= GENI_DMA_MODE_EN;
 	geni_write_reg(geni_dma_mode, base, SE_GENI_DMA_MODE_EN);
@@ -734,9 +734,9 @@ static int geni_se_rmv_ab_ib(struct geni_se_device *geni_se_dev,
 
 	if (geni_se_dev->num_paths == 2) {
 		geni_se_dev->pdata->usecase[1].vectors[0].ab  =
-			geni_se_dev->cur_ab;
+			CONV_TO_BW(geni_se_dev->cur_ab);
 		geni_se_dev->pdata->usecase[1].vectors[0].ib  =
-			geni_se_dev->cur_ib;
+			CONV_TO_BW(geni_se_dev->cur_ib);
 	}
 
 	if (bus_bw_update && geni_se_dev->num_paths != 2)
@@ -881,9 +881,9 @@ static int geni_se_add_ab_ib(struct geni_se_device *geni_se_dev,
 
 	if (geni_se_dev->num_paths == 2) {
 		geni_se_dev->pdata->usecase[1].vectors[0].ab  =
-			geni_se_dev->cur_ab;
+			CONV_TO_BW(geni_se_dev->cur_ab);
 		geni_se_dev->pdata->usecase[1].vectors[0].ib  =
-			geni_se_dev->cur_ib;
+			CONV_TO_BW(geni_se_dev->cur_ib);
 	}
 
 	if (bus_bw_update && geni_se_dev->num_paths != 2)
@@ -1030,6 +1030,7 @@ EXPORT_SYMBOL(se_geni_resources_on);
 int geni_se_resources_init(struct se_geni_rsc *rsc,
 			   unsigned long ab, unsigned long ib)
 {
+	int ret = 0;
 	struct geni_se_device *geni_se_dev;
 
 	if (unlikely(!rsc || !rsc->wrapper_dev))
@@ -1051,7 +1052,8 @@ int geni_se_resources_init(struct se_geni_rsc *rsc,
 			}
 		}
 
-		rsc->ab = ab;
+		/* To reduce the higher ab values from individual drivers */
+		rsc->ab = ab/2;
 		rsc->ib = ab;
 		rsc->ab_noc = 0;
 		rsc->ib_noc = ib;
@@ -1077,8 +1079,11 @@ int geni_se_resources_init(struct se_geni_rsc *rsc,
 
 	INIT_LIST_HEAD(&rsc->ab_list);
 	INIT_LIST_HEAD(&rsc->ib_list);
-	geni_se_iommu_map_and_attach(geni_se_dev);
-	return 0;
+	ret = geni_se_iommu_map_and_attach(geni_se_dev);
+	if (ret)
+		GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL,
+			"%s: Error %d iommu_map_and_attach\n", __func__, ret);
+	return ret;
 }
 EXPORT_SYMBOL(geni_se_resources_init);
 
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index a6a3332..9c4b0d7 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -433,8 +433,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
 	{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
 	{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
 	{ KE_KEY, 0x32, { KEY_MUTE } },
-	{ KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */
-	{ KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */
+	{ KE_KEY, 0x35, { KEY_SCREENLOCK } },
 	{ KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
 	{ KE_KEY, 0x41, { KEY_NEXTSONG } },
 	{ KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 7440f65..3f662cd 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -2147,7 +2147,8 @@ static int asus_wmi_add(struct platform_device *pdev)
 		err = asus_wmi_backlight_init(asus);
 		if (err && err != -ENODEV)
 			goto fail_backlight;
-	}
+	} else
+		err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL);
 
 	status = wmi_install_notify_handler(asus->driver->event_guid,
 					    asus_wmi_notify, asus);
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index ba2e5fa..ba361d7 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.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
@@ -50,7 +50,7 @@
 #define SCM_DLOAD_BOTHDUMPS	(SCM_DLOAD_MINIDUMP | SCM_DLOAD_FULLDUMP)
 
 static int restart_mode;
-static void *restart_reason, *dload_type_addr;
+static void *restart_reason;
 static bool scm_pmic_arbiter_disable_supported;
 static bool scm_deassert_ps_hold_supported;
 /* Download mode master kill-switch */
@@ -64,7 +64,7 @@ static void scm_disable_sdi(void);
  * So the SDI cannot be re-enabled when it already by-passed.
  */
 static int download_mode = 1;
-static struct kobject dload_kobj;
+static bool force_warm_reboot;
 
 #ifdef CONFIG_QCOM_DLOAD_MODE
 #define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
@@ -74,8 +74,10 @@ static struct kobject dload_kobj;
 #endif
 
 static int in_panic;
+static struct kobject dload_kobj;
 static int dload_type = SCM_DLOAD_FULLDUMP;
 static void *dload_mode_addr;
+static void *dload_type_addr;
 static bool dload_mode_enabled;
 static void *emergency_dload_mode_addr;
 #ifdef CONFIG_RANDOMIZE_BASE
@@ -83,8 +85,6 @@ static void *kaslr_imem_addr;
 #endif
 static bool scm_dload_supported;
 
-static bool force_warm_reboot;
-
 static int dload_set(const char *val, const struct kernel_param *kp);
 /* interface for exporting attributes */
 struct reset_attribute {
@@ -190,6 +190,11 @@ static int dload_set(const char *val, const struct kernel_param *kp)
 
 	int old_val = download_mode;
 
+	if (!download_mode) {
+		pr_err("Error: SDI dynamic enablement is not supported\n");
+		return -EINVAL;
+	}
+
 	ret = param_set_int(val, kp);
 
 	if (ret)
@@ -203,6 +208,9 @@ static int dload_set(const char *val, const struct kernel_param *kp)
 
 	set_dload_mode(download_mode);
 
+	if (!download_mode)
+		scm_disable_sdi();
+
 	return 0;
 }
 #else
@@ -408,6 +416,7 @@ static void do_msm_poweroff(void)
 	pr_err("Powering off has failed\n");
 }
 
+#ifdef CONFIG_QCOM_DLOAD_MODE
 static ssize_t attr_show(struct kobject *kobj, struct attribute *attr,
 				char *buf)
 {
@@ -525,6 +534,7 @@ static size_t store_dload_mode(struct kobject *kobj, struct attribute *attr,
 }
 RESET_ATTR(dload_mode, 0644, show_dload_mode, store_dload_mode);
 #endif
+
 RESET_ATTR(emmc_dload, 0644, show_emmc_dload, store_emmc_dload);
 
 static struct attribute *reset_attrs[] = {
@@ -538,6 +548,7 @@ static struct attribute *reset_attrs[] = {
 static struct attribute_group reset_attr_group = {
 	.attrs = reset_attrs,
 };
+#endif
 
 static int msm_restart_probe(struct platform_device *pdev)
 {
diff --git a/drivers/power/supply/olpc_battery.c b/drivers/power/supply/olpc_battery.c
index 3bc2eea..6292680 100644
--- a/drivers/power/supply/olpc_battery.c
+++ b/drivers/power/supply/olpc_battery.c
@@ -427,14 +427,14 @@ static int olpc_bat_get_property(struct power_supply *psy,
 		if (ret)
 			return ret;
 
-		val->intval = (s16)be16_to_cpu(ec_word) * 100 / 256;
+		val->intval = (s16)be16_to_cpu(ec_word) * 10 / 256;
 		break;
 	case POWER_SUPPLY_PROP_TEMP_AMBIENT:
 		ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
 		if (ret)
 			return ret;
 
-		val->intval = (int)be16_to_cpu(ec_word) * 100 / 256;
+		val->intval = (int)be16_to_cpu(ec_word) * 10 / 256;
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
 		ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2);
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index e2b98ec..c5ab82a 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -393,6 +393,9 @@ static struct device_attribute power_supply_attrs[] = {
 	POWER_SUPPLY_ATTR(batt_age_level),
 	POWER_SUPPLY_ATTR(voltage_vph),
 	POWER_SUPPLY_ATTR(chip_version),
+	POWER_SUPPLY_ATTR(therm_icl_limit),
+	POWER_SUPPLY_ATTR(dc_reset),
+	POWER_SUPPLY_ATTR(scale_mode_en),
 	/* Charge pump properties */
 	POWER_SUPPLY_ATTR(cp_status1),
 	POWER_SUPPLY_ATTR(cp_status2),
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index 2bb6ee7..0dd51cc 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -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
@@ -174,6 +174,8 @@ enum fg_sram_param_id {
 	FG_SRAM_MONOTONIC_SOC,
 	FG_SRAM_VOLTAGE_PRED,
 	FG_SRAM_OCV,
+	FG_SRAM_VBAT_FLT,
+	FG_SRAM_VBAT_TAU,
 	FG_SRAM_VBAT_FINAL,
 	FG_SRAM_IBAT_FINAL,
 	FG_SRAM_ESR,
@@ -492,6 +494,8 @@ struct fg_dbgfs {
 	u32				addr;
 };
 
+extern int fg_decode_voltage_24b(struct fg_sram_param *sp,
+	enum fg_sram_param_id id, int val);
 extern int fg_decode_voltage_15b(struct fg_sram_param *sp,
 	enum fg_sram_param_id id, int val);
 extern int fg_decode_current_16b(struct fg_sram_param *sp,
diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c
index 82c453f..c697e13 100644
--- a/drivers/power/supply/qcom/fg-util.c
+++ b/drivers/power/supply/qcom/fg-util.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
@@ -25,9 +25,25 @@
 #define MAX_LINE_LENGTH			(ADDR_LEN + (ITEMS_PER_LINE *	\
 					CHARS_PER_ITEM) + 1)		\
 
-#define VOLTAGE_15BIT_MASK	GENMASK(14, 0)
 #define MAX_READ_TRIES		5
 
+#define VOLTAGE_24BIT_MSB_MASK	GENMASK(27, 16)
+#define VOLTAGE_24BIT_LSB_MASK	GENMASK(11, 0)
+int fg_decode_voltage_24b(struct fg_sram_param *sp,
+	enum fg_sram_param_id id, int value)
+{
+	int msb, lsb, val;
+
+	msb = value & VOLTAGE_24BIT_MSB_MASK;
+	lsb = value & VOLTAGE_24BIT_LSB_MASK;
+	val = (msb >> 4) | lsb;
+	sp[id].value = div_s64((s64)val * sp[id].denmtr, sp[id].numrtr);
+	pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
+			sp[id].value);
+	return sp[id].value;
+}
+
+#define VOLTAGE_15BIT_MASK	GENMASK(14, 0)
 int fg_decode_voltage_15b(struct fg_sram_param *sp,
 				enum fg_sram_param_id id, int value)
 {
diff --git a/drivers/power/supply/qcom/pmic-voter.c b/drivers/power/supply/qcom/pmic-voter.c
index e0a5150..0ae0b44 100644
--- a/drivers/power/supply/qcom/pmic-voter.c
+++ b/drivers/power/supply/qcom/pmic-voter.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017 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
@@ -20,7 +20,7 @@
 
 #include <linux/pmic-voter.h>
 
-#define NUM_MAX_CLIENTS		16
+#define NUM_MAX_CLIENTS		32
 #define DEBUG_FORCE_CLIENT	"DEBUG_FORCE_CLIENT"
 
 static DEFINE_SPINLOCK(votable_list_slock);
diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h
index 8932821..ec35ded 100644
--- a/drivers/power/supply/qcom/qg-core.h
+++ b/drivers/power/supply/qcom/qg-core.h
@@ -64,6 +64,7 @@ struct qg_dt {
 	bool			esr_disable;
 	bool			esr_discharge_enable;
 	bool			qg_ext_sense;
+	bool			use_s7_ocv;
 };
 
 struct qg_esr_data {
diff --git a/drivers/power/supply/qcom/qg-soc.c b/drivers/power/supply/qcom/qg-soc.c
index c76e2ff..4c227af 100644
--- a/drivers/power/supply/qcom/qg-soc.c
+++ b/drivers/power/supply/qcom/qg-soc.c
@@ -118,6 +118,8 @@ static void get_next_update_time(struct qpnp_qg *chip)
 
 static bool is_scaling_required(struct qpnp_qg *chip)
 {
+	bool input_present = is_input_present(chip);
+
 	if (!chip->profile_loaded)
 		return false;
 
@@ -134,10 +136,16 @@ static bool is_scaling_required(struct qpnp_qg *chip)
 		return false;
 
 
-	if (chip->catch_up_soc > chip->msoc && !is_input_present(chip))
+	if (chip->catch_up_soc > chip->msoc && !input_present)
 		/* input is not present and SOC has increased */
 		return false;
 
+	if (chip->catch_up_soc > chip->msoc && input_present &&
+			(chip->charge_status != POWER_SUPPLY_STATUS_CHARGING &&
+			chip->charge_status != POWER_SUPPLY_STATUS_FULL))
+		/* USB is present, but not charging */
+		return false;
+
 	return true;
 }
 
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c
index 9cee5ed..29308e0 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen4.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c
@@ -13,7 +13,9 @@
 #define pr_fmt(fmt)	"FG: %s: " fmt, __func__
 
 #include <linux/alarmtimer.h>
+#include <linux/irq.h>
 #include <linux/ktime.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_batterydata.h>
@@ -33,6 +35,12 @@
 #define FG_MEM_IF_PM8150B		0x0D
 #define FG_ADC_RR_PM8150B		0x13
 
+#define SDAM_COOKIE_OFFSET		0x80
+#define SDAM_CYCLE_COUNT_OFFSET		0x81
+#define SDAM_CAP_LEARN_OFFSET		0x91
+#define SDAM_COOKIE			0xA5
+#define SDAM_FG_PARAM_LENGTH		20
+
 #define FG_SRAM_LEN			972
 #define PROFILE_LEN			416
 #define PROFILE_COMP_LEN		24
@@ -159,12 +167,16 @@
 #define MONOTONIC_SOC_OFFSET		0
 
 /* v2 SRAM address and offset in ascending order */
+#define LOW_PASS_VBATT_WORD		3
+#define LOW_PASS_VBATT_OFFSET		0
 #define RSLOW_SCALE_FN_DISCHG_V2_WORD	281
 #define RSLOW_SCALE_FN_DISCHG_V2_OFFSET	0
 #define RSLOW_SCALE_FN_CHG_V2_WORD	285
 #define RSLOW_SCALE_FN_CHG_V2_OFFSET	0
 #define ACT_BATT_CAP_v2_WORD		287
 #define ACT_BATT_CAP_v2_OFFSET		0
+#define VBAT_FLT_WORD			326
+#define VBAT_FLT_OFFSET			0
 #define RSLOW_v2_WORD			371
 #define RSLOW_v2_OFFSET			0
 #define OCV_v2_WORD			425
@@ -196,11 +208,15 @@ struct fg_dt_props {
 	bool	multi_profile_load;
 	bool	esr_calib_dischg;
 	bool	soc_hi_res;
+	bool	soc_scale_mode;
 	int	cutoff_volt_mv;
 	int	empty_volt_mv;
+	int	sys_min_volt_mv;
 	int	cutoff_curr_ma;
 	int	sys_term_curr_ma;
 	int	delta_soc_thr;
+	int	vbatt_scale_thr_mv;
+	int	scale_timer_ms;
 	int	esr_timer_chg_fast[NUM_ESR_TIMERS];
 	int	esr_timer_chg_slow[NUM_ESR_TIMERS];
 	int	esr_timer_dischg_fast[NUM_ESR_TIMERS];
@@ -236,16 +252,20 @@ struct fg_gen4_chip {
 	struct cycle_counter	*counter;
 	struct cap_learning	*cl;
 	struct ttf		*ttf;
+	struct nvmem_device	*fg_nvmem;
 	struct votable		*delta_esr_irq_en_votable;
 	struct votable		*pl_disable_votable;
 	struct votable		*cp_disable_votable;
 	struct votable		*parallel_current_en_votable;
 	struct votable		*mem_attn_irq_en_votable;
 	struct work_struct	esr_calib_work;
+	struct work_struct	soc_scale_work;
 	struct alarm		esr_fast_cal_timer;
+	struct alarm		soc_scale_alarm_timer;
 	struct delayed_work	pl_enable_work;
-	struct delayed_work	pl_current_en_work;
+	struct work_struct	pl_current_en_work;
 	struct completion	mem_attn;
+	struct mutex		soc_scale_lock;
 	char			batt_profile[PROFILE_LEN];
 	enum slope_limit_status	slope_limit_sts;
 	int			ki_coeff_full_soc[2];
@@ -257,6 +277,14 @@ struct fg_gen4_chip {
 	int			esr_soh_cycle_count;
 	int			batt_age_level;
 	int			last_batt_age_level;
+	int			soc_scale_msoc;
+	int			prev_soc_scale_msoc;
+	int			soc_scale_slope;
+	int			vbatt_avg;
+	int			vbatt_now;
+	int			vbatt_res;
+	int			scale_timer;
+	int			current_now;
 	bool			first_profile_load;
 	bool			ki_coeff_dischg_en;
 	bool			slope_limit_en;
@@ -269,6 +297,8 @@ struct fg_gen4_chip {
 	bool			rslow_low;
 	bool			rapid_soc_dec_en;
 	bool			vbatt_low;
+	bool			soc_scale_mode;
+	bool			chg_term_good;
 };
 
 struct bias_config {
@@ -296,6 +326,8 @@ static int fg_restart_mp;
 static bool fg_sram_dump;
 static bool fg_esr_fast_cal_en;
 
+static int fg_gen4_validate_soc_scale_mode(struct fg_gen4_chip *chip);
+
 static struct fg_sram_param pm8150b_v1_sram_params[] = {
 	PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
 		fg_decode_default),
@@ -389,6 +421,8 @@ static struct fg_sram_param pm8150b_v1_sram_params[] = {
 };
 
 static struct fg_sram_param pm8150b_v2_sram_params[] = {
+	PARAM(VBAT_TAU, LOW_PASS_VBATT_WORD, LOW_PASS_VBATT_OFFSET, 1, 1, 1, 0,
+		NULL, NULL),
 	PARAM(BATT_SOC, BATT_SOC_v2_WORD, BATT_SOC_v2_OFFSET, 4, 1, 1, 0, NULL,
 		fg_decode_default),
 	PARAM(FULL_SOC, FULL_SOC_v2_WORD, FULL_SOC_v2_OFFSET, 2, 1, 1, 0,
@@ -399,6 +433,8 @@ static struct fg_sram_param pm8150b_v2_sram_params[] = {
 		1000, 244141, 0, NULL, fg_decode_voltage_15b),
 	PARAM(OCV, OCV_v2_WORD, OCV_v2_OFFSET, 2, 1000, 244141, 0, NULL,
 		fg_decode_voltage_15b),
+	PARAM(VBAT_FLT, VBAT_FLT_WORD, VBAT_FLT_OFFSET, 4, 10000, 19073, 0,
+		NULL, fg_decode_voltage_24b),
 	PARAM(VBAT_FINAL, VBAT_FINAL_WORD, VBAT_FINAL_OFFSET, 2, 1000, 244141,
 		0, NULL, fg_decode_voltage_15b),
 	PARAM(IBAT_FINAL, IBAT_FINAL_WORD, IBAT_FINAL_OFFSET, 2, 1000, 488282,
@@ -564,18 +600,26 @@ static int fg_gen4_get_learned_capacity(void *data, int64_t *learned_cap_uah)
 	struct fg_gen4_chip *chip = data;
 	struct fg_dev *fg;
 	int rc, act_cap_mah;
+	u8 buf[2];
 
 	if (!chip)
 		return -ENODEV;
 
 	fg = &chip->fg;
-	rc = fg_get_sram_prop(fg, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
+	if (chip->fg_nvmem)
+		rc = nvmem_device_read(chip->fg_nvmem, SDAM_CAP_LEARN_OFFSET, 2,
+					buf);
+	else
+		rc = fg_get_sram_prop(fg, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
 	if (rc < 0) {
-		pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
+		pr_err("Error in getting learned capacity, rc=%d\n", rc);
 		return rc;
 	}
 
-	*learned_cap_uah = act_cap_mah * 1000;
+	if (chip->fg_nvmem)
+		*learned_cap_uah = (buf[0] | buf[1] << 8) * 1000;
+	else
+		*learned_cap_uah = act_cap_mah * 1000;
 
 	fg_dbg(fg, FG_CAP_LEARN, "learned_cap_uah:%lld\n", *learned_cap_uah);
 	return 0;
@@ -818,14 +862,19 @@ static int fg_gen4_get_prop_capacity(struct fg_dev *fg, int *val)
 		return 0;
 	}
 
-	rc = fg_get_msoc(fg, &msoc);
-	if (rc < 0)
-		return rc;
-
-	if (chip->dt.linearize_soc && fg->delta_soc > 0)
-		*val = fg->maint_soc;
-	else
-		*val = msoc;
+	if (chip->soc_scale_mode) {
+		mutex_lock(&chip->soc_scale_lock);
+		*val = chip->soc_scale_msoc;
+		mutex_unlock(&chip->soc_scale_lock);
+	} else {
+		rc = fg_get_msoc(fg, &msoc);
+		if (rc < 0)
+			return rc;
+		if (chip->dt.linearize_soc && fg->delta_soc > 0)
+			*val = fg->maint_soc;
+		else
+			*val = msoc;
+	}
 
 	return 0;
 }
@@ -882,6 +931,76 @@ static inline void get_esr_meas_current(int curr_ma, u8 *val)
 	*val <<= ESR_PULL_DOWN_IVAL_SHIFT;
 }
 
+static int fg_gen4_get_power(struct fg_gen4_chip *chip, int *val, bool average)
+{
+	struct fg_dev *fg = &chip->fg;
+	int rc, v_min, v_pred, esr_uohms, rslow_uohms;
+	s64 power;
+
+	rc = fg_get_sram_prop(fg, FG_SRAM_VOLTAGE_PRED, &v_pred);
+	if (rc < 0)
+		return rc;
+
+	v_min = chip->dt.sys_min_volt_mv * 1000;
+	power = (s64)v_min * (v_pred - v_min);
+
+	rc = fg_get_sram_prop(fg, FG_SRAM_ESR_ACT, &esr_uohms);
+	if (rc < 0) {
+		pr_err("failed to get ESR_ACT, rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = fg_get_sram_prop(fg, FG_SRAM_RSLOW, &rslow_uohms);
+	if (rc < 0) {
+		pr_err("failed to get Rslow, rc=%d\n", rc);
+		return rc;
+	}
+
+	if (average)
+		power = div_s64(power, esr_uohms + rslow_uohms);
+	else
+		power = div_s64(power, esr_uohms);
+
+	pr_debug("V_min: %d V_pred: %d ESR: %d Rslow: %d power: %lld\n", v_min,
+		v_pred, esr_uohms, rslow_uohms, power);
+
+	*val = power;
+	return 0;
+}
+
+static int fg_gen4_get_prop_soc_scale(struct fg_gen4_chip *chip)
+{
+	struct fg_dev *fg = &chip->fg;
+	int rc;
+
+	rc = fg_get_sram_prop(fg, FG_SRAM_VBAT_FLT, &chip->vbatt_avg);
+	if (rc < 0) {
+		pr_err("Failed to get filtered battery voltage, rc = %d\n",
+			rc);
+		return rc;
+	}
+
+	rc = fg_get_battery_voltage(fg, &chip->vbatt_now);
+	if (rc < 0) {
+		pr_err("Failed to get battery voltage, rc =%d\n", rc);
+		return rc;
+	}
+
+	rc = fg_get_battery_current(fg, &chip->current_now);
+	if (rc < 0) {
+		pr_err("Failed to get battery current rc=%d\n", rc);
+		return rc;
+	}
+
+	chip->vbatt_now = DIV_ROUND_CLOSEST(chip->vbatt_now, 1000);
+	chip->vbatt_avg = DIV_ROUND_CLOSEST(chip->vbatt_avg, 1000);
+	chip->vbatt_res = chip->vbatt_avg - chip->dt.cutoff_volt_mv;
+	pr_debug("FVSS: Vbatt now=%d Vbatt avg=%d Vbatt res=%d\n",
+		chip->vbatt_now, chip->vbatt_avg, chip->vbatt_res);
+
+	return rc;
+}
+
 /* ALG callback functions below */
 
 static int fg_gen4_get_ttf_param(void *data, enum ttf_param param, int *val)
@@ -889,6 +1008,7 @@ static int fg_gen4_get_ttf_param(void *data, enum ttf_param param, int *val)
 	struct fg_gen4_chip *chip = data;
 	struct fg_dev *fg;
 	int rc = 0, act_cap_mah, full_soc;
+	u8 buf[2];
 
 	if (!chip)
 		return -ENODEV;
@@ -908,12 +1028,20 @@ static int fg_gen4_get_ttf_param(void *data, enum ttf_param param, int *val)
 		rc = fg_get_battery_current(fg, val);
 		break;
 	case TTF_FCC:
-		rc = fg_get_sram_prop(fg, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
+		if (chip->fg_nvmem)
+			rc = nvmem_device_read(chip->fg_nvmem,
+					SDAM_CAP_LEARN_OFFSET, 2, buf);
+		else
+			rc = fg_get_sram_prop(fg, FG_SRAM_ACT_BATT_CAP,
+					&act_cap_mah);
 		if (rc < 0) {
 			pr_err("Failed to get ACT_BATT_CAP rc=%d\n", rc);
 			break;
 		}
 
+		if (chip->fg_nvmem)
+			act_cap_mah = buf[0] | buf[1] << 8;
+
 		rc = fg_get_sram_prop(fg, FG_SRAM_FULL_SOC, &full_soc);
 		if (rc < 0) {
 			pr_err("Failed to get FULL_SOC rc=%d\n", rc);
@@ -962,6 +1090,7 @@ static int fg_gen4_store_learned_capacity(void *data, int64_t learned_cap_uah)
 	struct fg_dev *fg;
 	int16_t cc_mah;
 	int rc;
+	u8 cookie = SDAM_COOKIE;
 
 	if (!chip)
 		return -ENODEV;
@@ -979,6 +1108,23 @@ static int fg_gen4_store_learned_capacity(void *data, int64_t learned_cap_uah)
 		return rc;
 	}
 
+	if (chip->fg_nvmem) {
+		rc = nvmem_device_write(chip->fg_nvmem, SDAM_CAP_LEARN_OFFSET,
+					2, (u8 *)&cc_mah);
+		if (rc < 0) {
+			pr_err("Error in writing learned capacity to SDAM, rc=%d\n",
+				rc);
+			return rc;
+		}
+
+		rc = nvmem_device_write(chip->fg_nvmem, SDAM_COOKIE_OFFSET, 1,
+					&cookie);
+		if (rc < 0) {
+			pr_err("Error in writing cookie to SDAM, rc=%d\n", rc);
+			return rc;
+		}
+	}
+
 	fg_dbg(fg, FG_CAP_LEARN, "learned capacity %llduah/%dmah stored\n",
 		chip->cl->learned_cap_uah, cc_mah);
 	return 0;
@@ -1044,9 +1190,13 @@ static int fg_gen4_restore_count(void *data, u16 *buf, int length)
 		return -EINVAL;
 
 	for (id = 0; id < length; id++) {
-		rc = fg_sram_read(&chip->fg, CYCLE_COUNT_WORD + id,
-				CYCLE_COUNT_OFFSET, (u8 *)tmp, 2,
-				FG_IMA_DEFAULT);
+		if (chip->fg_nvmem)
+			rc = nvmem_device_read(chip->fg_nvmem,
+				SDAM_CYCLE_COUNT_OFFSET + (id * 2), 2, tmp);
+		else
+			rc = fg_sram_read(&chip->fg, CYCLE_COUNT_WORD + id,
+					CYCLE_COUNT_OFFSET, (u8 *)tmp, 2,
+					FG_IMA_DEFAULT);
 		if (rc < 0)
 			pr_err("failed to read bucket %d rc=%d\n", id, rc);
 		else
@@ -1068,8 +1218,13 @@ static int fg_gen4_store_count(void *data, u16 *buf, int id, int length)
 		id > BUCKET_COUNT - 1 || ((id * 2) + length) > BUCKET_COUNT * 2)
 		return -EINVAL;
 
-	rc = fg_sram_write(&chip->fg, CYCLE_COUNT_WORD + id, CYCLE_COUNT_OFFSET,
-			(u8 *)buf, length, FG_IMA_DEFAULT);
+	if (chip->fg_nvmem)
+		rc = nvmem_device_write(chip->fg_nvmem,
+			SDAM_CYCLE_COUNT_OFFSET + (id * 2), length, (u8 *)buf);
+	else
+		rc = fg_sram_write(&chip->fg, CYCLE_COUNT_WORD + id,
+				CYCLE_COUNT_OFFSET, (u8 *)buf, length,
+				FG_IMA_DEFAULT);
 	if (rc < 0)
 		pr_err("failed to write bucket rc=%d\n", rc);
 
@@ -1906,6 +2061,84 @@ static int qpnp_fg_gen4_load_profile(struct fg_gen4_chip *chip)
 	return 0;
 }
 
+static bool is_sdam_cookie_set(struct fg_gen4_chip *chip)
+{
+	struct fg_dev *fg = &chip->fg;
+	int rc;
+	u8 cookie;
+
+	rc = nvmem_device_read(chip->fg_nvmem, SDAM_COOKIE_OFFSET, 1,
+				&cookie);
+	if (rc < 0) {
+		pr_err("Error in reading SDAM_COOKIE rc=%d\n", rc);
+		return false;
+	}
+
+	fg_dbg(fg, FG_STATUS, "cookie: %x\n", cookie);
+	return (cookie == SDAM_COOKIE);
+}
+
+static void fg_gen4_clear_sdam(struct fg_gen4_chip *chip)
+{
+	struct fg_dev *fg = &chip->fg;
+	u8 buf[SDAM_FG_PARAM_LENGTH] = { 0 };
+	int rc;
+
+	/*
+	 * Clear all bytes of SDAM used to store FG parameters when it is first
+	 * profile load so that the junk values would not be used.
+	 */
+	rc = nvmem_device_write(chip->fg_nvmem, SDAM_CYCLE_COUNT_OFFSET,
+			SDAM_FG_PARAM_LENGTH, buf);
+	if (rc < 0)
+		pr_err("Error in clearing SDAM rc=%d\n", rc);
+	else
+		fg_dbg(fg, FG_STATUS, "Cleared SDAM\n");
+}
+
+static void fg_gen4_post_profile_load(struct fg_gen4_chip *chip)
+{
+	struct fg_dev *fg = &chip->fg;
+	int rc, act_cap_mah;
+	u8 buf[16];
+
+	/* If SDAM cookie is not set, read back from SRAM and load it in SDAM */
+	if (chip->fg_nvmem && !is_sdam_cookie_set(chip)) {
+		fg_gen4_clear_sdam(chip);
+		rc = fg_sram_read(&chip->fg, CYCLE_COUNT_WORD,
+					CYCLE_COUNT_OFFSET, buf, 16,
+					FG_IMA_DEFAULT);
+		if (rc < 0) {
+			pr_err("Error in reading cycle counters from SRAM rc=%d\n",
+				rc);
+		} else {
+			rc = nvmem_device_write(chip->fg_nvmem,
+				SDAM_CYCLE_COUNT_OFFSET, 16, (u8 *)buf);
+			if (rc < 0)
+				pr_err("Error in writing cycle counters to SDAM rc=%d\n",
+					rc);
+		}
+
+		rc = fg_get_sram_prop(fg, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
+		if (rc < 0) {
+			pr_err("Error in getting learned capacity, rc=%d\n",
+				rc);
+		} else {
+			rc = nvmem_device_write(chip->fg_nvmem,
+				SDAM_CAP_LEARN_OFFSET, 2, (u8 *)&act_cap_mah);
+			if (rc < 0)
+				pr_err("Error in writing learned capacity to SDAM, rc=%d\n",
+					rc);
+		}
+	}
+
+	/* Restore the cycle counters so that it would be valid at this point */
+	rc = restore_cycle_count(chip->counter);
+	if (rc < 0)
+		pr_err("Error in restoring cycle_count, rc=%d\n", rc);
+
+}
+
 static void profile_load_work(struct work_struct *work)
 {
 	struct fg_dev *fg = container_of(work,
@@ -1939,8 +2172,11 @@ static void profile_load_work(struct work_struct *work)
 	if (!is_profile_load_required(chip))
 		goto done;
 
-	if (!chip->dt.multi_profile_load)
+	if (!chip->dt.multi_profile_load) {
 		clear_cycle_count(chip->counter);
+		if (chip->fg_nvmem && !is_sdam_cookie_set(chip))
+			fg_gen4_clear_sdam(chip);
+	}
 
 	fg_dbg(fg, FG_STATUS, "profile loading started\n");
 
@@ -1965,9 +2201,8 @@ static void profile_load_work(struct work_struct *work)
 		pr_err("Error in reading %04x[%d] rc=%d\n", NOM_CAP_WORD,
 			NOM_CAP_OFFSET, rc);
 	} else {
-		rc = fg_sram_write(fg, fg->sp[FG_SRAM_ACT_BATT_CAP].addr_word,
-			fg->sp[FG_SRAM_ACT_BATT_CAP].addr_byte, buf,
-			fg->sp[FG_SRAM_ACT_BATT_CAP].len, FG_IMA_DEFAULT);
+		nom_cap_uah = (buf[0] | buf[1] << 8) * 1000;
+		rc = fg_gen4_store_learned_capacity(chip, nom_cap_uah);
 		if (rc < 0)
 			pr_err("Error in writing to ACT_BATT_CAP rc=%d\n", rc);
 	}
@@ -1979,6 +2214,8 @@ static void profile_load_work(struct work_struct *work)
 		chip->first_profile_load = true;
 	}
 
+	fg_gen4_post_profile_load(chip);
+
 	rc = fg_gen4_bp_params_config(fg);
 	if (rc < 0)
 		pr_err("Error in configuring battery profile params, rc:%d\n",
@@ -2008,6 +2245,10 @@ static void profile_load_work(struct work_struct *work)
 		pm_stay_awake(fg->dev);
 		schedule_work(&fg->status_change_work);
 	}
+
+	rc = fg_gen4_validate_soc_scale_mode(chip);
+	if (rc < 0)
+		pr_err("Failed to validate SOC scale mode, rc=%d\n", rc);
 }
 
 static void get_batt_psy_props(struct fg_dev *fg)
@@ -2260,8 +2501,16 @@ static int fg_gen4_adjust_recharge_soc(struct fg_gen4_chip *chip)
 				new_recharge_soc = msoc - (FULL_CAPACITY -
 								recharge_soc);
 				fg->recharge_soc_adjusted = true;
+				if (fg->health == POWER_SUPPLY_HEALTH_GOOD)
+					chip->chg_term_good = true;
 			} else {
-				/* adjusted already, do nothing */
+				/*
+				 * If charge termination happened properly then
+				 * do nothing.
+				 */
+				if (chip->chg_term_good)
+					return 0;
+
 				if (fg->health != POWER_SUPPLY_HEALTH_GOOD)
 					return 0;
 
@@ -2272,7 +2521,7 @@ static int fg_gen4_adjust_recharge_soc(struct fg_gen4_chip *chip)
 
 				new_recharge_soc = recharge_soc;
 				fg->recharge_soc_adjusted = false;
-				return 0;
+				chip->chg_term_good = false;
 			}
 		} else {
 			if (!fg->recharge_soc_adjusted)
@@ -2291,11 +2540,13 @@ static int fg_gen4_adjust_recharge_soc(struct fg_gen4_chip *chip)
 			/* Restore the default value */
 			new_recharge_soc = recharge_soc;
 			fg->recharge_soc_adjusted = false;
+			chip->chg_term_good = false;
 		}
 	} else {
 		/* Restore the default value */
 		new_recharge_soc = recharge_soc;
 		fg->recharge_soc_adjusted = false;
+		chip->chg_term_good = false;
 	}
 
 	if (recharge_soc_status == fg->recharge_soc_adjusted)
@@ -2637,6 +2888,193 @@ static int fg_gen4_esr_fast_calib_config(struct fg_gen4_chip *chip, bool en)
 	return 0;
 }
 
+#define IBATT_TAU_MASK	GENMASK(3, 0)
+static int fg_gen4_set_vbatt_tau(struct fg_gen4_chip *chip, u8 vbatt_tau)
+{
+	struct fg_dev *fg = &chip->fg;
+	int rc;
+	u8 buf;
+
+	rc = fg_sram_read(fg, fg->sp[FG_SRAM_VBAT_TAU].addr_word,
+			fg->sp[FG_SRAM_VBAT_TAU].addr_byte,
+			&buf, fg->sp[FG_SRAM_VBAT_TAU].len,
+			FG_IMA_DEFAULT);
+	if (rc < 0) {
+		pr_err("Error in reading Vbatt_tau, rc=%d\n", rc);
+		return rc;
+	}
+
+	buf &= IBATT_TAU_MASK;
+	buf |= vbatt_tau << 4;
+	rc = fg_sram_write(fg,
+			fg->sp[FG_SRAM_VBAT_TAU].addr_word,
+			fg->sp[FG_SRAM_VBAT_TAU].addr_byte,
+			&buf, fg->sp[FG_SRAM_VBAT_TAU].len,
+			FG_IMA_DEFAULT);
+	if (rc < 0)
+		pr_err("Error in writing Vbatt_tau, rc=%d\n", rc);
+
+	return rc;
+}
+
+static int fg_gen4_enter_soc_scale(struct fg_gen4_chip *chip)
+{
+	struct fg_dev *fg = &chip->fg;
+	int rc, soc;
+
+	rc = fg_gen4_get_prop_capacity(fg, &soc);
+	if (rc < 0) {
+		pr_err("Failed to get capacity, rc =%d\n", rc);
+		return rc;
+	}
+
+	/* Set entry FVS SOC equal to current H/W reported SOC */
+	chip->soc_scale_msoc = chip->prev_soc_scale_msoc = soc;
+	chip->scale_timer = chip->dt.scale_timer_ms;
+	/*
+	 * Calculate the FVS slope to linearly calculate SOC
+	 * based on filtered battery voltage.
+	 */
+	chip->soc_scale_slope =
+			DIV_ROUND_CLOSEST(chip->vbatt_res,
+					chip->soc_scale_msoc);
+	if (chip->soc_scale_slope <= 0) {
+		pr_err("Error in slope calculated = %d\n",
+			chip->soc_scale_slope);
+		return -EINVAL;
+	}
+
+	chip->soc_scale_mode = true;
+	pr_debug("FVSS: Enter FVSS mode, SOC=%d slope=%d timer=%d\n", soc,
+		chip->soc_scale_slope, chip->scale_timer);
+	alarm_start_relative(&chip->soc_scale_alarm_timer,
+				ms_to_ktime(chip->scale_timer));
+
+	return 0;
+}
+
+static void fg_gen4_write_scale_msoc(struct fg_gen4_chip *chip)
+{
+	struct fg_dev *fg = &chip->fg;
+	int soc_raw, rc;
+
+	if (!fg->charge_full) {
+		soc_raw = DIV_ROUND_CLOSEST(chip->soc_scale_msoc * 0xFFFF,
+						100);
+		rc = fg_sram_write(fg, fg->sp[FG_SRAM_MONOTONIC_SOC].addr_word,
+				fg->sp[FG_SRAM_MONOTONIC_SOC].addr_byte,
+				(u8 *)&soc_raw,
+				fg->sp[FG_SRAM_MONOTONIC_SOC].len,
+				FG_IMA_ATOMIC);
+		if (rc < 0) {
+			pr_err("failed to write monotonic_soc rc=%d\n", rc);
+			chip->soc_scale_mode = false;
+		}
+	}
+}
+
+static void fg_gen4_exit_soc_scale(struct fg_gen4_chip *chip)
+{
+	if (chip->soc_scale_mode) {
+		alarm_cancel(&chip->soc_scale_alarm_timer);
+		cancel_work(&chip->soc_scale_work);
+		/* While exiting soc_scale_mode, Update MSOC register */
+		fg_gen4_write_scale_msoc(chip);
+	}
+
+	chip->soc_scale_mode = false;
+	pr_debug("FVSS: Exit FVSS mode\n");
+}
+
+static int fg_gen4_validate_soc_scale_mode(struct fg_gen4_chip *chip)
+{
+	struct fg_dev *fg = &chip->fg;
+	int rc, msoc_actual;
+
+	if (!chip->dt.soc_scale_mode)
+		return 0;
+
+	rc = fg_gen4_get_prop_soc_scale(chip);
+	if (rc < 0) {
+		pr_err("Failed to get soc scale props\n");
+		goto fail_soc_scale;
+	}
+
+	rc = fg_get_msoc(fg, &msoc_actual);
+	if (rc < 0) {
+		pr_err("Failed to get msoc rc=%d\n", rc);
+		goto fail_soc_scale;
+	}
+
+	if (!chip->soc_scale_mode && fg->charge_status ==
+		POWER_SUPPLY_STATUS_DISCHARGING &&
+		chip->vbatt_avg < chip->dt.vbatt_scale_thr_mv) {
+		rc = fg_gen4_enter_soc_scale(chip);
+		if (rc < 0) {
+			pr_err("Failed to enter SOC scale mode\n");
+			goto fail_soc_scale;
+		}
+	} else if (chip->soc_scale_mode && chip->current_now < 0) {
+		/*
+		 * Stay in SOC scale mode till H/W SOC catch scaled SOC
+		 * while charging.
+		 */
+		if (msoc_actual >= chip->soc_scale_msoc)
+			fg_gen4_exit_soc_scale(chip);
+	}
+
+	return 0;
+fail_soc_scale:
+	fg_gen4_exit_soc_scale(chip);
+	return rc;
+}
+
+static int fg_gen4_set_vbatt_low(struct fg_gen4_chip *chip)
+{
+	struct fg_dev *fg = &chip->fg;
+	int rc, vbatt_flt;
+
+	if (chip->soc_scale_mode) {
+		rc = fg_get_sram_prop(fg, FG_SRAM_VBAT_FLT,
+					&vbatt_flt);
+		if (rc < 0) {
+			pr_err("failed to get filtered battery voltage, rc=%d\n",
+				rc);
+			/*
+			 * If we fail here, exit FVSS mode
+			 * and set Vbatt low flag true to report
+			 * 0 SOC
+			 */
+			fg_gen4_exit_soc_scale(chip);
+			chip->vbatt_low = true;
+			return 0;
+		}
+
+		vbatt_flt /= 1000;
+		if (vbatt_flt < chip->dt.empty_volt_mv ||
+		    vbatt_flt > (fg->bp.float_volt_uv/1000)) {
+			pr_err("Filtered Vbatt is not in range %d\n",
+			       vbatt_flt);
+			/*
+			 * If we fail here, exit FVSS mode
+			 * and set Vbatt low flag true to report
+			 * 0 SOC
+			 */
+			fg_gen4_exit_soc_scale(chip);
+			chip->vbatt_low = true;
+			return 0;
+		}
+
+		if (vbatt_flt <= chip->dt.cutoff_volt_mv)
+			chip->vbatt_low = true;
+	} else {
+		/* Set the flag to show 0% */
+		chip->vbatt_low = true;
+	}
+
+	return 0;
+}
+
 /* All irq handlers below this */
 
 static irqreturn_t fg_mem_attn_irq_handler(int irq, void *data)
@@ -2731,8 +3169,7 @@ static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
 				pr_err("Error in configuring for rapid SOC reduction rc:%d\n",
 					rc);
 		} else {
-			/* Set the flag to show 0% */
-			chip->vbatt_low = true;
+			fg_gen4_set_vbatt_low(chip);
 		}
 	}
 
@@ -2936,6 +3373,10 @@ static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data)
 			chip->esr_fast_calib_retry = true;
 	}
 
+	rc = fg_gen4_validate_soc_scale_mode(chip);
+	if (rc < 0)
+		pr_err("Failed to validate SOC scale mode, rc=%d\n", rc);
+
 	if (batt_psy_initialized(fg))
 		power_supply_changed(fg->batt_psy);
 
@@ -3163,9 +3604,15 @@ static void esr_calib_work(struct work_struct *work)
 	fg_dbg(fg, FG_STATUS, "esr_raw: 0x%x esr_char_raw: 0x%x esr_meas_diff: 0x%x esr_delta: 0x%x\n",
 		esr_raw, esr_char_raw, esr_meas_diff, esr_delta);
 
-	fg_esr_meas_diff = esr_delta - esr_meas_diff;
-	esr_filtered = fg_esr_meas_diff >> chip->dt.esr_filter_factor;
-	esr_delta = esr_delta - esr_filtered;
+	fg_esr_meas_diff = esr_meas_diff - (esr_delta / 32);
+
+	/* Don't filter for the first attempt so that ESR can converge faster */
+	if (!chip->delta_esr_count)
+		esr_filtered = fg_esr_meas_diff;
+	else
+		esr_filtered = fg_esr_meas_diff >> chip->dt.esr_filter_factor;
+
+	esr_delta = esr_delta + (esr_filtered * 32);
 
 	/* Bound the limits */
 	if (esr_delta > SHRT_MAX)
@@ -3198,35 +3645,93 @@ static void esr_calib_work(struct work_struct *work)
 	vote(fg->awake_votable, ESR_CALIB, false, 0);
 }
 
+static enum alarmtimer_restart fg_soc_scale_timer(struct alarm *alarm,
+							ktime_t time)
+{
+	struct fg_gen4_chip *chip = container_of(alarm, struct fg_gen4_chip,
+							soc_scale_alarm_timer);
+
+	schedule_work(&chip->soc_scale_work);
+	return ALARMTIMER_NORESTART;
+}
+
+static void soc_scale_work(struct work_struct *work)
+{
+	struct fg_gen4_chip *chip = container_of(work, struct fg_gen4_chip,
+						soc_scale_work);
+	struct fg_dev *fg = &chip->fg;
+	int soc, soc_thr_percent, rc;
+
+	if (!chip->soc_scale_mode)
+		return;
+
+	soc_thr_percent = chip->dt.delta_soc_thr / 10;
+	if (soc_thr_percent == 0) {
+		/* Set minimum SOC change that can be reported = 1% */
+		soc_thr_percent = 1;
+	}
+
+	rc = fg_gen4_validate_soc_scale_mode(chip);
+	if (rc < 0)
+		pr_err("Failed to validate SOC scale mode, rc=%d\n", rc);
+
+	if (chip->vbatt_res <= 0)
+		chip->vbatt_res = 0;
+
+	mutex_lock(&chip->soc_scale_lock);
+	soc = DIV_ROUND_CLOSEST(chip->vbatt_res,
+				chip->soc_scale_slope);
+	/* If calculated SOC is higher than current SOC, report current SOC */
+	if (soc > chip->prev_soc_scale_msoc) {
+		chip->soc_scale_msoc = chip->prev_soc_scale_msoc;
+		chip->scale_timer = chip->dt.scale_timer_ms;
+	} else if ((chip->prev_soc_scale_msoc - soc) > soc_thr_percent) {
+		/*
+		 * If difference b/w current SOC and calculated SOC
+		 * is higher than SOC threshold then handle this by
+		 * showing current SOC - SOC threshold and decrease
+		 * timer resolution to catch up the rate of decrement
+		 * of SOC.
+		 */
+		chip->soc_scale_msoc = chip->prev_soc_scale_msoc -
+					soc_thr_percent;
+		chip->scale_timer = chip->dt.scale_timer_ms /
+				(chip->prev_soc_scale_msoc - soc);
+	} else {
+		chip->soc_scale_msoc = soc;
+		chip->scale_timer = chip->dt.scale_timer_ms;
+	}
+
+	if (chip->soc_scale_msoc < 0)
+		chip->soc_scale_msoc = 0;
+
+	mutex_unlock(&chip->soc_scale_lock);
+	if (chip->prev_soc_scale_msoc != chip->soc_scale_msoc) {
+		if (batt_psy_initialized(fg))
+			power_supply_changed(fg->batt_psy);
+	}
+
+	chip->prev_soc_scale_msoc = chip->soc_scale_msoc;
+	pr_debug("FVSS: Calculated SOC=%d SOC reported=%d timer resolution=%d\n",
+		soc, chip->soc_scale_msoc, chip->scale_timer);
+	alarm_start_relative(&chip->soc_scale_alarm_timer,
+				ms_to_ktime(chip->scale_timer));
+}
+
 static void pl_current_en_work(struct work_struct *work)
 {
 	struct fg_gen4_chip *chip = container_of(work,
 				struct fg_gen4_chip,
-				pl_current_en_work.work);
+				pl_current_en_work);
 	struct fg_dev *fg = &chip->fg;
 	bool input_present = is_input_present(fg), en;
 
 	en = fg->charge_done ? false : input_present;
 
-	/*
-	 * If mem_attn_irq is disabled and parallel summing current
-	 * configuration needs to be modified, then enable mem_attn_irq and
-	 * wait for 1 second before doing it.
-	 */
-	if (get_effective_result(chip->parallel_current_en_votable) != en &&
-		!get_effective_result(chip->mem_attn_irq_en_votable)) {
-		vote(chip->mem_attn_irq_en_votable, MEM_ATTN_IRQ_VOTER,
-			true, 0);
-		schedule_delayed_work(&chip->pl_current_en_work,
-			msecs_to_jiffies(1000));
-		return;
-	}
-
-	if (!get_effective_result(chip->mem_attn_irq_en_votable))
+	if (get_effective_result(chip->parallel_current_en_votable) == en)
 		return;
 
 	vote(chip->parallel_current_en_votable, FG_PARALLEL_EN_VOTER, en, 0);
-	vote(chip->mem_attn_irq_en_votable, MEM_ATTN_IRQ_VOTER, false, 0);
 }
 
 static void pl_enable_work(struct work_struct *work)
@@ -3320,9 +3825,14 @@ static void status_change_work(struct work_struct *work)
 	if (rc < 0)
 		pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc);
 
-	if (is_parallel_charger_available(fg) &&
-		!delayed_work_pending(&chip->pl_current_en_work))
-		schedule_delayed_work(&chip->pl_current_en_work, 0);
+	if (is_parallel_charger_available(fg)) {
+		cancel_work_sync(&chip->pl_current_en_work);
+		schedule_work(&chip->pl_current_en_work);
+	}
+
+	rc = fg_gen4_validate_soc_scale_mode(chip);
+	if (rc < 0)
+		pr_err("Failed to validate SOC scale mode, rc=%d\n", rc);
 
 	ttf_update(chip->ttf, input_present);
 	fg->prev_charge_status = fg->charge_status;
@@ -3549,6 +4059,9 @@ static int fg_psy_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_VOLTAGE_OCV:
 		rc = fg_get_sram_prop(fg, FG_SRAM_OCV, &pval->intval);
 		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+		rc = fg_get_sram_prop(fg, FG_SRAM_VBAT_FLT, &pval->intval);
+		break;
 	case POWER_SUPPLY_PROP_RESISTANCE_ID:
 		pval->intval = fg->batt_id_ohms;
 		break;
@@ -3626,6 +4139,15 @@ static int fg_psy_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_BATT_AGE_LEVEL:
 		pval->intval = chip->batt_age_level;
 		break;
+	case POWER_SUPPLY_PROP_SCALE_MODE_EN:
+		pval->intval = chip->soc_scale_mode;
+		break;
+	case POWER_SUPPLY_PROP_POWER_NOW:
+		rc = fg_gen4_get_power(chip, &pval->intval, false);
+		break;
+	case POWER_SUPPLY_PROP_POWER_AVG:
+		rc = fg_gen4_get_power(chip, &pval->intval, true);
+		break;
 	default:
 		pr_err("unsupported property %d\n", psp);
 		rc = -EINVAL;
@@ -3749,6 +4271,7 @@ static enum power_supply_property fg_psy_props[] = {
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_VOLTAGE_OCV,
+	POWER_SUPPLY_PROP_VOLTAGE_AVG,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_RESISTANCE_ID,
 	POWER_SUPPLY_PROP_RESISTANCE,
@@ -3773,6 +4296,9 @@ static enum power_supply_property fg_psy_props[] = {
 	POWER_SUPPLY_PROP_CC_STEP,
 	POWER_SUPPLY_PROP_CC_STEP_SEL,
 	POWER_SUPPLY_PROP_BATT_AGE_LEVEL,
+	POWER_SUPPLY_PROP_POWER_NOW,
+	POWER_SUPPLY_PROP_POWER_AVG,
+	POWER_SUPPLY_PROP_SCALE_MODE_EN,
 };
 
 static const struct power_supply_desc fg_psy_desc = {
@@ -3881,6 +4407,8 @@ static int fg_parallel_current_en_cb(struct votable *votable, void *data,
 	int rc;
 	u8 val, mask;
 
+	vote(chip->mem_attn_irq_en_votable, MEM_ATTN_IRQ_VOTER, true, 0);
+
 	/* Wait for MEM_ATTN interrupt */
 	rc = fg_wait_for_mem_attn(chip);
 	if (rc < 0)
@@ -3893,6 +4421,7 @@ static int fg_parallel_current_en_cb(struct votable *votable, void *data,
 		pr_err("Error in writing to 0x%04x, rc=%d\n",
 			BATT_INFO_FG_CNV_CHAR_CFG(fg), rc);
 
+	vote(chip->mem_attn_irq_en_votable, MEM_ATTN_IRQ_VOTER, false, 0);
 	fg_dbg(fg, FG_STATUS, "Parallel current summing: %d\n", enable);
 
 	return rc;
@@ -4136,6 +4665,7 @@ static int fg_gen4_esr_calib_config(struct fg_gen4_chip *chip)
 #define BATT_TEMP_HYST_MASK	GENMASK(3, 0)
 #define BATT_TEMP_DELTA_MASK	GENMASK(7, 4)
 #define BATT_TEMP_DELTA_SHIFT	4
+#define VBATT_TAU_DEFAULT	3
 static int fg_gen4_hw_init(struct fg_gen4_chip *chip)
 {
 	struct fg_dev *fg = &chip->fg;
@@ -4191,30 +4721,28 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip)
 		}
 	}
 
-	if (chip->dt.delta_soc_thr > 0 && chip->dt.delta_soc_thr < 125) {
-		fg_encode(fg->sp, FG_SRAM_DELTA_MSOC_THR,
-			chip->dt.delta_soc_thr, buf);
-		rc = fg_sram_write(fg,
-				fg->sp[FG_SRAM_DELTA_MSOC_THR].addr_word,
-				fg->sp[FG_SRAM_DELTA_MSOC_THR].addr_byte,
-				buf, fg->sp[FG_SRAM_DELTA_MSOC_THR].len,
-				FG_IMA_DEFAULT);
-		if (rc < 0) {
-			pr_err("Error in writing delta_msoc_thr, rc=%d\n", rc);
-			return rc;
-		}
+	fg_encode(fg->sp, FG_SRAM_DELTA_MSOC_THR,
+		chip->dt.delta_soc_thr, buf);
+	rc = fg_sram_write(fg,
+			fg->sp[FG_SRAM_DELTA_MSOC_THR].addr_word,
+			fg->sp[FG_SRAM_DELTA_MSOC_THR].addr_byte,
+			buf, fg->sp[FG_SRAM_DELTA_MSOC_THR].len,
+			FG_IMA_DEFAULT);
+	if (rc < 0) {
+		pr_err("Error in writing delta_msoc_thr, rc=%d\n", rc);
+		return rc;
+	}
 
-		fg_encode(fg->sp, FG_SRAM_DELTA_BSOC_THR,
-			chip->dt.delta_soc_thr, buf);
-		rc = fg_sram_write(fg,
-				fg->sp[FG_SRAM_DELTA_BSOC_THR].addr_word,
-				fg->sp[FG_SRAM_DELTA_BSOC_THR].addr_byte,
-				buf, fg->sp[FG_SRAM_DELTA_BSOC_THR].len,
-				FG_IMA_DEFAULT);
-		if (rc < 0) {
-			pr_err("Error in writing delta_bsoc_thr, rc=%d\n", rc);
-			return rc;
-		}
+	fg_encode(fg->sp, FG_SRAM_DELTA_BSOC_THR,
+		chip->dt.delta_soc_thr, buf);
+	rc = fg_sram_write(fg,
+			fg->sp[FG_SRAM_DELTA_BSOC_THR].addr_word,
+			fg->sp[FG_SRAM_DELTA_BSOC_THR].addr_byte,
+			buf, fg->sp[FG_SRAM_DELTA_BSOC_THR].len,
+			FG_IMA_DEFAULT);
+	if (rc < 0) {
+		pr_err("Error in writing delta_bsoc_thr, rc=%d\n", rc);
+		return rc;
 	}
 
 	if (chip->dt.batt_temp_cold_thresh != -EINVAL) {
@@ -4382,12 +4910,6 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip)
 	if (rc < 0)
 		return rc;
 
-	rc = restore_cycle_count(chip->counter);
-	if (rc < 0) {
-		pr_err("Error in restoring cycle_count, rc=%d\n", rc);
-		return rc;
-	}
-
 	chip->batt_age_level = chip->last_batt_age_level = -EINVAL;
 	if (chip->dt.multi_profile_load) {
 		rc = fg_sram_read(fg, BATT_AGE_LEVEL_WORD,
@@ -4395,6 +4917,15 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip)
 		if (!rc)
 			chip->batt_age_level = chip->last_batt_age_level = val;
 	}
+
+	if (chip->dt.soc_scale_mode) {
+		rc = fg_gen4_set_vbatt_tau(chip, VBATT_TAU_DEFAULT);
+		if (rc < 0) {
+			fg_gen4_exit_soc_scale(chip);
+			return rc;
+		}
+	}
+
 	return 0;
 }
 
@@ -4591,8 +5122,31 @@ static int fg_parse_esr_cal_params(struct fg_dev *fg)
 	return 0;
 }
 
+static int fg_gen4_parse_nvmem_dt(struct fg_gen4_chip *chip)
+{
+	struct fg_dev *fg = &chip->fg;
+	int rc;
+
+	if (of_find_property(fg->dev->of_node, "nvmem", NULL)) {
+		chip->fg_nvmem = devm_nvmem_device_get(fg->dev, "fg_sdam");
+		if (IS_ERR_OR_NULL(chip->fg_nvmem)) {
+			rc = PTR_ERR(chip->fg_nvmem);
+			if (rc != -EPROBE_DEFER) {
+				dev_err(fg->dev, "Couldn't get nvmem device, rc=%d\n",
+					rc);
+				return -ENODEV;
+			}
+			chip->fg_nvmem = NULL;
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
 #define DEFAULT_CUTOFF_VOLT_MV		3100
 #define DEFAULT_EMPTY_VOLT_MV		2812
+#define DEFAULT_SYS_MIN_VOLT_MV		2800
 #define DEFAULT_SYS_TERM_CURR_MA	-125
 #define DEFAULT_CUTOFF_CURR_MA		200
 #define DEFAULT_DELTA_SOC_THR		5	/* 0.5 % */
@@ -4608,6 +5162,8 @@ static int fg_parse_esr_cal_params(struct fg_dev *fg)
 #define BTEMP_DELTA_HIGH		3
 #define DEFAULT_ESR_PULSE_THRESH_MA	47
 #define DEFAULT_ESR_MEAS_CURR_MA	120
+#define DEFAULT_SCALE_VBATT_THR_MV	3400
+#define DEFAULT_SCALE_ALARM_TIMER_MS	10000
 static int fg_gen4_parse_dt(struct fg_gen4_chip *chip)
 {
 	struct fg_dev *fg = &chip->fg;
@@ -4660,6 +5216,10 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip)
 		return -EINVAL;
 	}
 
+	rc = fg_gen4_parse_nvmem_dt(chip);
+	if (rc < 0)
+		return rc;
+
 	if (of_get_available_child_count(node) == 0) {
 		dev_err(fg->dev, "No child nodes specified!\n");
 		return -ENXIO;
@@ -4731,6 +5291,12 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip)
 	else
 		chip->dt.delta_soc_thr = temp;
 
+	if (chip->dt.delta_soc_thr < 0 || chip->dt.delta_soc_thr >= 125) {
+		pr_err("Invalid delta SOC threshold=%d\n",
+		       chip->dt.delta_soc_thr);
+		return -EINVAL;
+	}
+
 	chip->dt.esr_timer_chg_fast[TIMER_RETRY] = -EINVAL;
 	chip->dt.esr_timer_chg_fast[TIMER_MAX] = -EINVAL;
 	rc = fg_parse_dt_property_u32_array(node, "qcom,fg-esr-timer-chg-fast",
@@ -4851,6 +5417,17 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip)
 	chip->dt.linearize_soc = of_property_read_bool(node,
 					"qcom,linearize-soc");
 
+	chip->dt.soc_scale_mode = of_property_read_bool(node,
+						"qcom,soc-scale-mode-en");
+	if (chip->dt.soc_scale_mode) {
+		chip->dt.vbatt_scale_thr_mv = DEFAULT_SCALE_VBATT_THR_MV;
+		of_property_read_u32(node, "qcom,soc-scale-vbatt-mv",
+					&chip->dt.vbatt_scale_thr_mv);
+		chip->dt.scale_timer_ms = DEFAULT_SCALE_ALARM_TIMER_MS;
+		of_property_read_u32(node, "qcom,soc-scale-time-ms",
+					&chip->dt.scale_timer_ms);
+	}
+
 	rc = fg_parse_ki_coefficients(fg);
 	if (rc < 0)
 		pr_err("Error in parsing Ki coefficients, rc=%d\n", rc);
@@ -4890,6 +5467,10 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip)
 	chip->dt.multi_profile_load = of_property_read_bool(node,
 					"qcom,multi-profile-load");
 	chip->dt.soc_hi_res = of_property_read_bool(node, "qcom,soc-hi-res");
+
+	chip->dt.sys_min_volt_mv = DEFAULT_SYS_MIN_VOLT_MV;
+	of_property_read_u32(node, "qcom,fg-sys-min-voltage",
+				&chip->dt.sys_min_volt_mv);
 	return 0;
 }
 
@@ -4900,9 +5481,12 @@ static void fg_gen4_cleanup(struct fg_gen4_chip *chip)
 	fg_unregister_interrupts(fg, chip, FG_GEN4_IRQ_MAX);
 
 	cancel_work(&fg->status_change_work);
+	if (chip->soc_scale_mode)
+		fg_gen4_exit_soc_scale(chip);
+
 	cancel_delayed_work_sync(&fg->profile_load_work);
 	cancel_delayed_work_sync(&fg->sram_dump_work);
-	cancel_delayed_work_sync(&chip->pl_current_en_work);
+	cancel_work_sync(&chip->pl_current_en_work);
 
 	power_supply_unreg_notifier(&fg->nb);
 	debugfs_remove_recursive(fg->dfs_root);
@@ -4956,15 +5540,17 @@ static int fg_gen4_probe(struct platform_device *pdev)
 	mutex_init(&fg->bus_lock);
 	mutex_init(&fg->sram_rw_lock);
 	mutex_init(&fg->charge_full_lock);
+	mutex_init(&chip->soc_scale_lock);
 	init_completion(&fg->soc_update);
 	init_completion(&fg->soc_ready);
 	init_completion(&chip->mem_attn);
 	INIT_WORK(&fg->status_change_work, status_change_work);
 	INIT_WORK(&chip->esr_calib_work, esr_calib_work);
+	INIT_WORK(&chip->soc_scale_work, soc_scale_work);
 	INIT_DELAYED_WORK(&fg->profile_load_work, profile_load_work);
 	INIT_DELAYED_WORK(&fg->sram_dump_work, sram_dump_work);
 	INIT_DELAYED_WORK(&chip->pl_enable_work, pl_enable_work);
-	INIT_DELAYED_WORK(&chip->pl_current_en_work, pl_current_en_work);
+	INIT_WORK(&chip->pl_current_en_work, pl_current_en_work);
 
 	fg->awake_votable = create_votable("FG_WS", VOTE_SET_ANY,
 					fg_awake_cb, fg);
@@ -5036,6 +5622,17 @@ static int fg_gen4_probe(struct platform_device *pdev)
 		}
 	}
 
+	if (chip->dt.soc_scale_mode) {
+		if (alarmtimer_get_rtcdev()) {
+			alarm_init(&chip->soc_scale_alarm_timer,
+				ALARM_BOOTTIME, fg_soc_scale_timer);
+		} else {
+			dev_err(fg->dev, "Failed to initialize SOC scale timer\n");
+			rc = -EPROBE_DEFER;
+			goto exit;
+		}
+	}
+
 	rc = fg_memif_init(fg);
 	if (rc < 0) {
 		dev_err(fg->dev, "Error in initializing FG_MEMIF, rc:%d\n",
@@ -5078,6 +5675,10 @@ static int fg_gen4_probe(struct platform_device *pdev)
 		goto exit;
 	}
 
+	if (fg->irqs[MEM_ATTN_IRQ].irq)
+		irq_set_status_flags(fg->irqs[MEM_ATTN_IRQ].irq,
+					IRQ_DISABLE_UNLAZY);
+
 	/* Keep SOC_UPDATE irq disabled until we require it */
 	if (fg->irqs[SOC_UPDATE_IRQ].irq)
 		disable_irq_nosync(fg->irqs[SOC_UPDATE_IRQ].irq);
@@ -5147,6 +5748,9 @@ static void fg_gen4_shutdown(struct platform_device *pdev)
 
 	fg_unregister_interrupts(fg, chip, FG_GEN4_IRQ_MAX);
 
+	if (chip->soc_scale_mode)
+		fg_gen4_exit_soc_scale(chip);
+
 	if (chip->rapid_soc_dec_en) {
 		rc = fg_gen4_rapid_soc_config(chip, false);
 		if (rc < 0)
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index 08c3c36..7336409 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -1064,10 +1064,6 @@ static void process_udata_work(struct work_struct *work)
 			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;
 
@@ -1227,6 +1223,7 @@ static irqreturn_t qg_good_ocv_handler(int irq, void *data)
 	u8 status = 0;
 	u32 ocv_uv = 0, ocv_raw = 0;
 	struct qpnp_qg *chip = data;
+	unsigned long rtc_sec = 0;
 
 	qg_dbg(chip, QG_DEBUG_IRQ, "IRQ triggered\n");
 
@@ -1247,6 +1244,8 @@ static irqreturn_t qg_good_ocv_handler(int irq, void *data)
 		goto done;
 	}
 
+	get_rtc_time(&rtc_sec);
+	chip->kdata.fifo_time = (u32)rtc_sec;
 	chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
 	chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
 
@@ -1548,6 +1547,26 @@ static int qg_get_battery_capacity(struct qpnp_qg *chip, int *soc)
 	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, };
@@ -1829,7 +1848,7 @@ static int qg_psy_get_property(struct power_supply *psy,
 		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)
@@ -1963,8 +1982,9 @@ static int qg_charge_full_update(struct qpnp_qg *chip)
 	if (rc < 0 || prop.intval < 0) {
 		pr_debug("Failed to get recharge-soc\n");
 		recharge_soc = DEFAULT_RECHARGE_SOC;
+	} else {
+		recharge_soc = prop.intval;
 	}
-	recharge_soc = prop.intval;
 	chip->recharge_soc = recharge_soc;
 
 	qg_dbg(chip, QG_DEBUG_STATUS, "msoc=%d health=%d charge_full=%d charge_done=%d\n",
@@ -2695,7 +2715,7 @@ static struct ocv_all ocv[] = {
 #define S7_ERROR_MARGIN_UV		20000
 static int qg_determine_pon_soc(struct qpnp_qg *chip)
 {
-	int rc = 0, batt_temp = 0, i;
+	int rc = 0, batt_temp = 0, i, shutdown_temp = 0;
 	bool use_pon_ocv = true;
 	unsigned long rtc_sec = 0;
 	u32 ocv_uv = 0, soc = 0, pon_soc = 0, full_soc = 0, cutoff_soc = 0;
@@ -2736,6 +2756,7 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip)
 		pr_err("Failed to read shutdown params rc=%d\n", rc);
 		goto use_pon_ocv;
 	}
+	shutdown_temp = sign_extend32(shutdown[SDAM_TEMP], 15);
 
 	rc = lookup_soc_ocv(&pon_soc, ocv[S7_PON_OCV].ocv_uv, batt_temp, false);
 	if (rc < 0) {
@@ -2748,7 +2769,7 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip)
 			shutdown[SDAM_SOC],
 			shutdown[SDAM_OCV_UV],
 			shutdown[SDAM_TIME_SEC],
-			shutdown[SDAM_TEMP],
+			shutdown_temp,
 			rtc_sec, batt_temp,
 			pon_soc);
 	/*
@@ -2765,8 +2786,8 @@ static int qg_determine_pon_soc(struct qpnp_qg *chip)
 		goto use_pon_ocv;
 
 	if (!is_between(0, chip->dt.shutdown_temp_diff,
-			abs(shutdown[SDAM_TEMP] -  batt_temp)) &&
-			(shutdown[SDAM_TEMP] < 0 || batt_temp < 0))
+			abs(shutdown_temp -  batt_temp)) &&
+			(shutdown_temp < 0 || batt_temp < 0))
 		goto use_pon_ocv;
 
 	if ((chip->dt.shutdown_soc_threshold != -EINVAL) &&
@@ -2886,7 +2907,9 @@ static int qg_set_wa_flags(struct qpnp_qg *chip)
 {
 	switch (chip->pmic_rev_id->pmic_subtype) {
 	case PMI632_SUBTYPE:
-		chip->wa_flags |= QG_RECHARGE_SOC_WA | QG_PON_OCV_WA;
+		chip->wa_flags |= QG_RECHARGE_SOC_WA;
+		if (!chip->dt.use_s7_ocv)
+			chip->wa_flags |= QG_PON_OCV_WA;
 		if (chip->pmic_rev_id->rev4 == PMI632_V1P0_REV4)
 			chip->wa_flags |= QG_VBAT_LOW_WA;
 		break;
@@ -3557,6 +3580,8 @@ static int qg_parse_dt(struct qpnp_qg *chip)
 
 	chip->dt.qg_ext_sense = of_property_read_bool(node, "qcom,qg-ext-sns");
 
+	chip->dt.use_s7_ocv = of_property_read_bool(node, "qcom,qg-use-s7-ocv");
+
 	/* Capacity learning params*/
 	if (!chip->dt.cl_disable) {
 		chip->dt.cl_feedback_on = of_property_read_bool(node,
@@ -3709,6 +3734,7 @@ static int process_resume(struct qpnp_qg *chip)
 	u8 status2 = 0, rt_status = 0;
 	u32 ocv_uv = 0, ocv_raw = 0;
 	int rc;
+	unsigned long rtc_sec = 0;
 
 	/* skip if profile is not loaded */
 	if (!chip->profile_loaded)
@@ -3729,6 +3755,8 @@ static int process_resume(struct qpnp_qg *chip)
 
 		 /* Clear suspend data as there has been a GOOD OCV */
 		memset(&chip->kdata, 0, sizeof(chip->kdata));
+		get_rtc_time(&rtc_sec);
+		chip->kdata.fifo_time = (u32)rtc_sec;
 		chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
 		chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
 		chip->suspend_data = false;
diff --git a/drivers/power/supply/qcom/qpnp-qnovo5.c b/drivers/power/supply/qcom/qpnp-qnovo5.c
index d4d3b8d..9ded656 100644
--- a/drivers/power/supply/qcom/qpnp-qnovo5.c
+++ b/drivers/power/supply/qcom/qpnp-qnovo5.c
@@ -10,6 +10,8 @@
  * GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt)	"Qnovo: %s: " fmt, __func__
+
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -79,6 +81,7 @@
 #define USER_VOTER		"user_voter"
 #define SHUTDOWN_VOTER		"user_voter"
 #define OK_TO_QNOVO_VOTER	"ok_to_qnovo_voter"
+#define HW_OK_TO_QNOVO_VOTER	"HW_OK_TO_QNOVO_VOTER"
 
 #define QNOVO_VOTER		"qnovo_voter"
 #define QNOVO_OVERALL_VOTER	"QNOVO_OVERALL_VOTER"
@@ -1132,8 +1135,8 @@ static void status_change_work(struct work_struct *work)
 	struct qnovo *chip = container_of(work,
 			struct qnovo, status_change_work);
 	union power_supply_propval pval;
-	bool usb_present = false;
-	int rc;
+	bool usb_present = false, hw_ok_to_qnovo = false;
+	int rc, battery_health, charge_status;
 
 	if (is_usb_available(chip)) {
 		rc = power_supply_get_property(chip->usb_psy,
@@ -1165,6 +1168,36 @@ static void status_change_work(struct work_struct *work)
 		schedule_delayed_work(&chip->usb_debounce_work,
 				msecs_to_jiffies(DEBOUNCE_MS));
 	}
+
+	if (!is_batt_available(chip))
+		return;
+
+	rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
+					&pval);
+	if (rc < 0) {
+		pr_err("Error in getting battery health, rc=%d\n", rc);
+		return;
+	}
+	battery_health = pval.intval;
+
+	rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_STATUS,
+					&pval);
+	if (rc < 0) {
+		pr_err("Error in getting charging status, rc=%d\n", rc);
+		return;
+	}
+	charge_status = pval.intval;
+
+	pr_debug("USB present: %d health:%d charge_status: %d\n",
+		chip->usb_present, battery_health, charge_status);
+
+	if (chip->usb_present) {
+		hw_ok_to_qnovo =
+			(battery_health == POWER_SUPPLY_HEALTH_GOOD) &&
+			(charge_status == POWER_SUPPLY_STATUS_CHARGING);
+		vote(chip->not_ok_to_qnovo_votable, HW_OK_TO_QNOVO_VOTER,
+					!hw_ok_to_qnovo, 0);
+	}
 }
 
 static int qnovo_notifier_call(struct notifier_block *nb,
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 84e802c..ab6b55a 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -564,17 +564,10 @@ static int smb5_parse_dt(struct smb5 *chip)
 	if (rc < 0)
 		return rc;
 
-	if (!chg->iio.mid_chan) {
-		rc = smblib_get_iio_channel(chg, "usb_in_voltage",
-				&chg->iio.usbin_v_chan);
-		if (rc < 0)
-			return rc;
-
-		if (!chg->iio.usbin_v_chan) {
-			dev_err(chg->dev, "No voltage channel defined");
-			return -EINVAL;
-		}
-	}
+	rc = smblib_get_iio_channel(chg, "usb_in_voltage",
+					&chg->iio.usbin_v_chan);
+	if (rc < 0)
+		return rc;
 
 	rc = smblib_get_iio_channel(chg, "chg_temp", &chg->iio.temp_chan);
 	if (rc < 0)
@@ -649,6 +642,7 @@ static enum power_supply_property smb5_usb_props[] = {
 	POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
 	POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
 	POWER_SUPPLY_PROP_VOLTAGE_VPH,
+	POWER_SUPPLY_PROP_THERM_ICL_LIMIT,
 };
 
 static int smb5_usb_get_prop(struct power_supply *psy,
@@ -807,6 +801,10 @@ static int smb5_usb_get_prop(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_VOLTAGE_VPH:
 		rc = smblib_get_prop_vph_voltage_now(chg, val);
 		break;
+	case POWER_SUPPLY_PROP_THERM_ICL_LIMIT:
+		val->intval = get_client_vote(chg->usb_icl_votable,
+					THERMAL_THROTTLE_VOTER);
+		break;
 	default:
 		pr_err("get prop %d is not supported in usb\n", psp);
 		rc = -EINVAL;
@@ -827,7 +825,7 @@ static int smb5_usb_set_prop(struct power_supply *psy,
 {
 	struct smb5 *chip = power_supply_get_drvdata(psy);
 	struct smb_charger *chg = &chip->chg;
-	int rc = 0;
+	int icl, rc = 0;
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
@@ -871,6 +869,14 @@ static int smb5_usb_set_prop(struct power_supply *psy,
 		chg->connector_health = val->intval;
 		power_supply_changed(chg->usb_psy);
 		break;
+	case POWER_SUPPLY_PROP_THERM_ICL_LIMIT:
+		icl = get_effective_result(chg->usb_icl_votable);
+		if ((icl + val->intval) > 0)
+			rc = vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER,
+					true, icl + val->intval);
+		else
+			rc = -EINVAL;
+		break;
 	default:
 		pr_err("set prop %d is not supported\n", psp);
 		rc = -EINVAL;
@@ -886,6 +892,7 @@ static int smb5_usb_prop_is_writeable(struct power_supply *psy,
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
 	case POWER_SUPPLY_PROP_CONNECTOR_HEALTH:
+	case POWER_SUPPLY_PROP_THERM_ICL_LIMIT:
 		return 1;
 	default:
 		break;
@@ -1219,6 +1226,7 @@ static enum power_supply_property smb5_dc_props[] = {
 	POWER_SUPPLY_PROP_VOLTAGE_MAX,
 	POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
 	POWER_SUPPLY_PROP_REAL_TYPE,
+	POWER_SUPPLY_PROP_DC_RESET,
 };
 
 static int smb5_dc_get_prop(struct power_supply *psy,
@@ -1251,6 +1259,9 @@ static int smb5_dc_get_prop(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_REAL_TYPE:
 		val->intval = POWER_SUPPLY_TYPE_WIPOWER;
 		break;
+	case POWER_SUPPLY_PROP_DC_RESET:
+		val->intval = 0;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1280,6 +1291,9 @@ static int smb5_dc_set_prop(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
 		rc = smblib_set_prop_voltage_wls_output(chg, val);
 		break;
+	case POWER_SUPPLY_PROP_DC_RESET:
+		rc = smblib_set_prop_dc_reset(chg);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1657,6 +1671,209 @@ static int smb5_init_batt_psy(struct smb5 *chip)
 	return rc;
 }
 
+/********************************
+ * DUAL-ROLE CLASS REGISTRATION *
+ ********************************/
+static enum dual_role_property smb5_dr_properties[] = {
+	DUAL_ROLE_PROP_SUPPORTED_MODES,
+	DUAL_ROLE_PROP_MODE,
+	DUAL_ROLE_PROP_PR,
+	DUAL_ROLE_PROP_DR,
+};
+
+static int smb5_dr_get_property(struct dual_role_phy_instance *dual_role,
+			enum dual_role_property prop, unsigned int *val)
+{
+	struct smb_charger *chg = dual_role_get_drvdata(dual_role);
+	union power_supply_propval pval = {0, };
+	/* Initializing pr, dr and mode to value 2 corresponding to NONE case */
+	int mode = 2, pr = 2, dr = 2, rc = 0;
+
+	if (!chg)
+		return -ENODEV;
+
+	rc = smblib_get_prop_usb_present(chg, &pval);
+	if (rc < 0) {
+		pr_err("Couldn't get usb present status, rc=%d\n", rc);
+		return rc;
+	}
+
+	if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC) {
+		if (chg->typec_mode == POWER_SUPPLY_TYPEC_NONE) {
+			mode = DUAL_ROLE_PROP_MODE_NONE;
+			pr = DUAL_ROLE_PROP_PR_NONE;
+			dr = DUAL_ROLE_PROP_DR_NONE;
+		} else if (chg->typec_mode <
+				POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
+			mode = DUAL_ROLE_PROP_MODE_DFP;
+			pr = DUAL_ROLE_PROP_PR_SRC;
+			dr = DUAL_ROLE_PROP_DR_HOST;
+		} else if (chg->typec_mode >=
+				POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
+			mode = DUAL_ROLE_PROP_MODE_UFP;
+			pr = DUAL_ROLE_PROP_PR_SNK;
+			dr = DUAL_ROLE_PROP_DR_DEVICE;
+		}
+	} else if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB) {
+		pr = DUAL_ROLE_PROP_PR_NONE;
+
+		if (chg->otg_present) {
+			mode = DUAL_ROLE_PROP_MODE_DFP;
+			dr = DUAL_ROLE_PROP_DR_HOST;
+		} else if (pval.intval) {
+			mode = DUAL_ROLE_PROP_MODE_UFP;
+			dr = DUAL_ROLE_PROP_DR_DEVICE;
+		} else {
+			mode = DUAL_ROLE_PROP_MODE_NONE;
+			dr = DUAL_ROLE_PROP_DR_NONE;
+		}
+	}
+
+	switch (prop) {
+	case DUAL_ROLE_PROP_MODE:
+		*val = mode;
+		break;
+	case DUAL_ROLE_PROP_PR:
+		*val = pr;
+		break;
+	case DUAL_ROLE_PROP_DR:
+		*val = dr;
+		break;
+	default:
+		pr_err("dual role class get property %d not supported\n", prop);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int smb5_dr_set_property(struct dual_role_phy_instance *dual_role,
+			enum dual_role_property prop, const unsigned int *val)
+{
+	struct smb_charger *chg = dual_role_get_drvdata(dual_role);
+	int rc = 0;
+
+	if (!chg)
+		return -ENODEV;
+
+	mutex_lock(&chg->dr_lock);
+	switch (prop) {
+	case DUAL_ROLE_PROP_MODE:
+		if (chg->pr_swap_in_progress) {
+			pr_debug("Already in mode transition. Skipping request\n");
+			mutex_unlock(&chg->dr_lock);
+			return 0;
+		}
+
+		switch (*val) {
+		case DUAL_ROLE_PROP_MODE_UFP:
+			if (chg->typec_mode >=
+					POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
+				chg->dr_mode = DUAL_ROLE_PROP_MODE_UFP;
+			} else {
+				chg->pr_swap_in_progress = true;
+				rc = smblib_force_dr_mode(chg,
+						DUAL_ROLE_PROP_MODE_UFP);
+				if (rc < 0) {
+					chg->pr_swap_in_progress = false;
+					pr_err("Failed to force UFP mode, rc=%d\n",
+						rc);
+				}
+			}
+			break;
+		case DUAL_ROLE_PROP_MODE_DFP:
+			if (chg->typec_mode < POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
+				&& chg->typec_mode != POWER_SUPPLY_TYPEC_NONE) {
+				chg->dr_mode = DUAL_ROLE_PROP_MODE_DFP;
+			} else {
+				chg->pr_swap_in_progress = true;
+				rc = smblib_force_dr_mode(chg,
+						DUAL_ROLE_PROP_MODE_DFP);
+				if (rc < 0) {
+					chg->pr_swap_in_progress = false;
+					pr_err("Failed to force DFP mode, rc=%d\n",
+						rc);
+				}
+			}
+			break;
+		default:
+			pr_err("Invalid role (not DFP/UFP): %d\n", *val);
+			rc = -EINVAL;
+		}
+
+		/*
+		 * Schedule delayed work to check if the device latched to
+		 * the requested mode.
+		 */
+		if (chg->pr_swap_in_progress && !rc) {
+			cancel_delayed_work_sync(&chg->role_reversal_check);
+			vote(chg->awake_votable, DR_SWAP_VOTER, true, 0);
+			schedule_delayed_work(&chg->role_reversal_check,
+				msecs_to_jiffies(ROLE_REVERSAL_DELAY_MS));
+		}
+		break;
+	default:
+		pr_err("dual role class set property %d not supported\n", prop);
+		rc = -EINVAL;
+	}
+
+	mutex_unlock(&chg->dr_lock);
+	return rc;
+}
+
+static int smb5_dr_prop_writeable(struct dual_role_phy_instance *dual_role,
+			enum dual_role_property prop)
+{
+	struct smb_charger *chg = dual_role_get_drvdata(dual_role);
+
+	if (!chg)
+		return -ENODEV;
+
+	/* uUSB connector does not support role switch */
+	if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
+		return 0;
+
+	switch (prop) {
+	case DUAL_ROLE_PROP_MODE:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static const struct dual_role_phy_desc dr_desc = {
+	.name = "otg_default",
+	.supported_modes = DUAL_ROLE_SUPPORTED_MODES_DFP_AND_UFP,
+	.properties = smb5_dr_properties,
+	.num_properties = ARRAY_SIZE(smb5_dr_properties),
+	.get_property = smb5_dr_get_property,
+	.set_property = smb5_dr_set_property,
+	.property_is_writeable = smb5_dr_prop_writeable,
+};
+
+static int smb5_init_dual_role_class(struct smb5 *chip)
+{
+	struct smb_charger *chg = &chip->chg;
+	int rc = 0;
+
+	/* Register dual role class for only non-PD TypeC and uUSB designs */
+	if (!chg->pd_not_supported)
+		return rc;
+
+	mutex_init(&chg->dr_lock);
+	chg->dual_role = devm_dual_role_instance_register(chg->dev, &dr_desc);
+	if (IS_ERR(chg->dual_role)) {
+		pr_err("Couldn't register dual role class\n");
+		rc = PTR_ERR(chg->dual_role);
+	} else {
+		chg->dual_role->drv_data = chg;
+	}
+
+	return rc;
+}
+
 /******************************
  * VBUS REGULATOR REGISTRATION *
  ******************************/
@@ -1856,9 +2073,18 @@ static int smb5_configure_typec(struct smb_charger *chg)
 	rc = smblib_masked_write(chg, USBIN_LOAD_CFG_REG,
 		USBIN_IN_COLLAPSE_GF_SEL_MASK | USBIN_AICL_STEP_TIMING_SEL_MASK,
 		0);
-	if (rc < 0)
+	if (rc < 0) {
 		dev_err(chg->dev,
 			"Couldn't set USBIN_LOAD_CFG_REG rc=%d\n", rc);
+		return rc;
+	}
+
+	/* Set CC threshold to 1.6 V in source mode */
+	rc = smblib_masked_write(chg, TYPE_C_EXIT_STATE_CFG_REG,
+				SEL_SRC_UPPER_REF_BIT, SEL_SRC_UPPER_REF_BIT);
+	if (rc < 0)
+		dev_err(chg->dev,
+			"Couldn't configure CC threshold voltage rc=%d\n", rc);
 
 	return rc;
 }
@@ -2113,7 +2339,8 @@ static int smb5_init_hw(struct smb5 *chip)
 	 */
 	if (chg->wa_flags & SW_THERM_REGULATION_WA) {
 		rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG,
-					THERMREG_DIE_CMP_SRC_EN_BIT);
+					THERMREG_SW_ICL_ADJUST_BIT
+					| THERMREG_DIE_CMP_SRC_EN_BIT);
 		if (rc < 0) {
 			dev_err(chg->dev, "Couldn't disable HW thermal regulation rc=%d\n",
 				rc);
@@ -2325,36 +2552,27 @@ static int smb5_init_hw(struct smb5 *chip)
 
 	/* configure float charger options */
 	switch (chip->dt.float_option) {
-	case FLOAT_DCP:
-		rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
-				FLOAT_OPTIONS_MASK, 0);
-		break;
 	case FLOAT_SDP:
-		rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
-				FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT);
+		val = FORCE_FLOAT_SDP_CFG_BIT;
 		break;
 	case DISABLE_CHARGING:
-		rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
-				FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT);
+		val = FLOAT_DIS_CHGING_CFG_BIT;
 		break;
 	case SUSPEND_INPUT:
-		rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
-				FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT);
+		val = SUSPEND_FLOAT_CFG_BIT;
 		break;
+	case FLOAT_DCP:
 	default:
-		rc = 0;
+		val = 0;
 		break;
 	}
 
+	chg->float_cfg = val;
+	/* Update float charger setting and set DCD timeout 300ms */
+	rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+				FLOAT_OPTIONS_MASK | DCD_TIMEOUT_SEL_BIT, val);
 	if (rc < 0) {
-		dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n",
-			rc);
-		return rc;
-	}
-
-	rc = smblib_read(chg, USBIN_OPTIONS_2_CFG_REG, &chg->float_cfg);
-	if (rc < 0) {
-		dev_err(chg->dev, "Couldn't read float charger options rc=%d\n",
+		dev_err(chg->dev, "Couldn't change float charger setting rc=%d\n",
 			rc);
 		return rc;
 	}
@@ -3193,6 +3411,14 @@ static int smb5_probe(struct platform_device *pdev)
 		goto cleanup;
 	}
 
+	/* Register android dual-role class */
+	rc = smb5_init_dual_role_class(chip);
+	if (rc < 0) {
+		pr_err("Couldn't initialize dual role class, rc=%d\n",
+			rc);
+		goto cleanup;
+	}
+
 	rc = smb5_determine_initial_status(chip);
 	if (rc < 0) {
 		pr_err("Couldn't determine initial status rc=%d\n",
@@ -3263,14 +3489,9 @@ static void smb5_shutdown(struct platform_device *pdev)
 		smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
 				TYPEC_POWER_ROLE_CMD_MASK, EN_SNK_ONLY_BIT);
 
-	/* force HVDCP to 5V */
-	smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
-				HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
-	smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
-
 	/* force enable and rerun APSD */
 	smblib_apsd_enable(chg, true);
-	smblib_masked_write(chg, CMD_APSD_REG, APSD_RERUN_BIT, APSD_RERUN_BIT);
+	smblib_hvdcp_exit_config(chg);
 }
 
 static const struct of_device_id match_table[] = {
diff --git a/drivers/power/supply/qcom/smb1351-charger.c b/drivers/power/supply/qcom/smb1351-charger.c
index 6ab70c4..be624f1 100644
--- a/drivers/power/supply/qcom/smb1351-charger.c
+++ b/drivers/power/supply/qcom/smb1351-charger.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
@@ -2700,12 +2700,6 @@ static int smb1351_determine_initial_state(struct smb1351_charger *chip)
 	if (reg & IRQ_COLD_SOFT_BIT)
 		chip->batt_cool = true;
 
-	rc = smb1351_read_reg(chip, IRQ_E_REG, &reg);
-	if (rc) {
-		pr_err("Couldn't read IRQ_E rc = %d\n", rc);
-		goto fail_init_status;
-	}
-
 	/* check initial state of OTG */
 	rc = smb1351_read_reg(chip, IRQ_F_REG, &reg);
 	if (rc) {
@@ -2714,6 +2708,12 @@ static int smb1351_determine_initial_state(struct smb1351_charger *chip)
 	}
 	smb1351_rid_handler(chip, reg & IRQ_RID_BIT);
 
+	rc = smb1351_read_reg(chip, IRQ_E_REG, &reg);
+	if (rc) {
+		pr_err("Couldn't read IRQ_E rc = %d\n", rc);
+		goto fail_init_status;
+	}
+
 	if (reg & IRQ_USBIN_UV_BIT) {
 		smb1351_usbin_uv_handler(chip, 1);
 	} else {
diff --git a/drivers/power/supply/qcom/smb1355-charger.c b/drivers/power/supply/qcom/smb1355-charger.c
index 84a3cdc..6b2cef4 100644
--- a/drivers/power/supply/qcom/smb1355-charger.c
+++ b/drivers/power/supply/qcom/smb1355-charger.c
@@ -250,6 +250,7 @@ struct smb1355 {
 	int			c_health;
 	int			c_charger_temp_max;
 	int			die_temp_deciDegC;
+	int			suspended_usb_icl;
 	bool			exit_die_temp;
 	struct delayed_work	die_temp_work;
 	bool			disabled;
@@ -596,6 +597,7 @@ static int smb1355_get_prop_health(struct smb1355 *chip, int type)
 }
 
 #define MIN_PARALLEL_ICL_UA		250000
+#define SUSPEND_CURRENT_UA		2000
 static int smb1355_parallel_get_prop(struct power_supply *psy,
 				     enum power_supply_property prop,
 				     union power_supply_propval *val)
@@ -672,11 +674,16 @@ static int smb1355_parallel_get_prop(struct power_supply *psy,
 			val->intval = 0;
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		if (IS_USBIN(chip->dt.pl_mode))
-			rc = smb1355_get_charge_param(chip,
+		if (IS_USBIN(chip->dt.pl_mode)) {
+			/* Report cached ICL until its configured correctly */
+			if (chip->suspended_usb_icl)
+				val->intval = chip->suspended_usb_icl;
+			else
+				rc = smb1355_get_charge_param(chip,
 					&chip->param.usb_icl, &val->intval);
-		else
+		} else {
 			val->intval = 0;
+		}
 		break;
 	case POWER_SUPPLY_PROP_MIN_ICL:
 		val->intval = MIN_PARALLEL_ICL_UA;
@@ -709,6 +716,18 @@ static int smb1355_set_parallel_charging(struct smb1355 *chip, bool disable)
 	if (chip->disabled == disable)
 		return 0;
 
+	if (IS_USBIN(chip->dt.pl_mode)) {
+		/*
+		 * Initialize ICL configuration to minimum value while
+		 * depending upon the set icl configuration method to properly
+		 * configure the ICL value. At the same time, cache the value
+		 * of ICL to be reported as 2mA.
+		 */
+		chip->suspended_usb_icl = SUSPEND_CURRENT_UA;
+		smb1355_set_charge_param(chip,
+				&chip->param.usb_icl, MIN_PARALLEL_ICL_UA);
+	}
+
 	rc = smb1355_masked_write(chip, WD_CFG_REG, WDOG_TIMER_EN_BIT,
 				 disable ? 0 : WDOG_TIMER_EN_BIT);
 	if (rc < 0) {
@@ -777,6 +796,7 @@ static int smb1355_set_current_max(struct smb1355 *chip, int curr)
 
 		rc = smb1355_set_charge_param(chip,
 				&chip->param.usb_icl, curr);
+		chip->suspended_usb_icl = 0;
 	}
 
 	return rc;
diff --git a/drivers/power/supply/qcom/smb1390-charger-psy.c b/drivers/power/supply/qcom/smb1390-charger-psy.c
index 3f65739..e4d1cdfe6 100644
--- a/drivers/power/supply/qcom/smb1390-charger-psy.c
+++ b/drivers/power/supply/qcom/smb1390-charger-psy.c
@@ -97,6 +97,8 @@
 #define SRC_VOTER		"SRC_VOTER"
 #define SWITCHER_TOGGLE_VOTER	"SWITCHER_TOGGLE_VOTER"
 
+#define THERMAL_SUSPEND_DECIDEGC	1400
+
 #define smb1390_dbg(chip, reason, fmt, ...)				\
 	do {								\
 		if (chip->debug_mask & (reason))			\
@@ -747,9 +749,24 @@ static int smb1390_get_prop(struct power_supply *psy,
 			else
 				rc = -ENODATA;
 		} else {
+			/*
+			 * Add a filter to the die temp value read:
+			 * If temp > THERMAL_SUSPEND_DECIDEGC then
+			 *	- treat it as an error and report last valid
+			 *	  cached temperature.
+			 *	- return -ENODATA if the cached value is
+			 *	  invalid.
+			 */
+
 			rc = smb1390_get_die_temp(chip, val);
-			if (rc >= 0)
-				chip->die_temp = val->intval;
+			if (rc >= 0) {
+				if (val->intval <= THERMAL_SUSPEND_DECIDEGC)
+					chip->die_temp = val->intval;
+				else if (chip->die_temp == -ENODATA)
+					rc = -ENODATA;
+				else
+					val->intval = chip->die_temp;
+			}
 		}
 		break;
 	case POWER_SUPPLY_PROP_CP_ISNS:
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index 08820be..295722f 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -329,11 +329,14 @@ static void smblib_notify_extcon_props(struct smb_charger *chg, int id)
 		val.intval = ((prop_val.intval == 2) ? 1 : 0);
 		extcon_set_property(chg->extcon, id,
 				EXTCON_PROP_USB_TYPEC_POLARITY, val);
-	}
-
-	val.intval = true;
-	extcon_set_property(chg->extcon, id,
+		val.intval = true;
+		extcon_set_property(chg->extcon, id,
 				EXTCON_PROP_USB_SS, val);
+	} else if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB) {
+		val.intval = false;
+		extcon_set_property(chg->extcon, id,
+				EXTCON_PROP_USB_SS, val);
+	}
 }
 
 static void smblib_notify_device_mode(struct smb_charger *chg, bool enable)
@@ -924,6 +927,27 @@ void smblib_hvdcp_detect_enable(struct smb_charger *chg, bool enable)
 	return;
 }
 
+void smblib_hvdcp_exit_config(struct smb_charger *chg)
+{
+	u8 stat;
+	int rc;
+
+	rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat);
+	if (rc < 0)
+		return;
+
+	if (stat & (QC_3P0_BIT | QC_2P0_BIT)) {
+		/* force HVDCP to 5V */
+		smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+				HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
+		smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
+
+		/* rerun APSD */
+		smblib_masked_write(chg, CMD_APSD_REG, APSD_RERUN_BIT,
+				APSD_RERUN_BIT);
+	}
+}
+
 static int smblib_request_dpdm(struct smb_charger *chg, bool enable)
 {
 	int rc = 0;
@@ -1110,6 +1134,7 @@ static void smblib_uusb_removal(struct smb_charger *chg)
 	vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
 	vote(chg->usb_icl_votable, HVDCP2_ICL_VOTER, false, 0);
 	vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0);
+	vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER, false, 0);
 
 	/* Remove SW thermal regulation WA votes */
 	vote(chg->usb_icl_votable, SW_THERM_REGULATION_VOTER, false, 0);
@@ -2860,6 +2885,57 @@ int smblib_set_prop_voltage_wls_output(struct smb_charger *chg,
 	return rc;
 }
 
+int smblib_set_prop_dc_reset(struct smb_charger *chg)
+{
+	int rc;
+
+	rc = vote(chg->dc_suspend_votable, VOUT_VOTER, true, 0);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't suspend DC rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = smblib_masked_write(chg, DCIN_CMD_IL_REG, DCIN_EN_MASK,
+				DCIN_EN_OVERRIDE_BIT);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't set DCIN_EN_OVERRIDE_BIT rc=%d\n",
+			rc);
+		return rc;
+	}
+
+	rc = smblib_write(chg, DCIN_CMD_PON_REG, DCIN_PON_BIT | MID_CHG_BIT);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't write %d to DCIN_CMD_PON_REG rc=%d\n",
+			DCIN_PON_BIT | MID_CHG_BIT, rc);
+		return rc;
+	}
+
+	/* Wait for 10ms to allow the charge to get drained */
+	usleep_range(10000, 10010);
+
+	rc = smblib_write(chg, DCIN_CMD_PON_REG, 0);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't clear DCIN_CMD_PON_REG rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = smblib_masked_write(chg, DCIN_CMD_IL_REG, DCIN_EN_MASK, 0);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't clear DCIN_EN_OVERRIDE_BIT rc=%d\n",
+			rc);
+		return rc;
+	}
+
+	rc = vote(chg->dc_suspend_votable, VOUT_VOTER, false, 0);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't unsuspend  DC rc=%d\n", rc);
+		return rc;
+	}
+
+	smblib_dbg(chg, PR_MISC, "Wireless charger removal detection successful\n");
+	return rc;
+}
+
 /*******************
  * USB PSY GETTERS *
  *******************/
@@ -3017,18 +3093,12 @@ int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
 		return -ENODATA;
 	}
 
-	/* usb not present */
-	if (!pval.intval) {
-		val->intval = 0;
-		return 0;
-	}
-
 	/*
 	 * For PM8150B, use MID_CHG ADC channel because overvoltage is observed
 	 * to occur randomly in the USBIN channel, particularly at high
 	 * voltages.
 	 */
-	if (chg->smb_version == PM8150B_SUBTYPE)
+	if (chg->smb_version == PM8150B_SUBTYPE && pval.intval)
 		return smblib_read_mid_voltage_chan(chg, val);
 	else
 		return smblib_read_usbin_voltage_chan(chg, val);
@@ -3512,7 +3582,7 @@ int smblib_get_prop_die_health(struct smb_charger *chg)
 	return POWER_SUPPLY_HEALTH_COOL;
 }
 
-int smblib_get_prop_connector_health(struct smb_charger *chg)
+static int smblib_get_typec_connector_temp_status(struct smb_charger *chg)
 {
 	int rc;
 	u8 stat;
@@ -3552,6 +3622,56 @@ int smblib_get_prop_connector_health(struct smb_charger *chg)
 	return POWER_SUPPLY_HEALTH_COOL;
 }
 
+static int smblib_get_skin_temp_status(struct smb_charger *chg)
+{
+	int rc;
+	u8 stat;
+
+	rc = smblib_read(chg, SKIN_TEMP_STATUS_REG, &stat);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read SKIN_TEMP_STATUS_REG, rc=%d\n",
+				rc);
+		return POWER_SUPPLY_HEALTH_UNKNOWN;
+	}
+
+	if (stat & SKIN_TEMP_RST_BIT)
+		return POWER_SUPPLY_HEALTH_OVERHEAT;
+
+	if (stat & SKIN_TEMP_UB_BIT)
+		return POWER_SUPPLY_HEALTH_HOT;
+
+	if (stat & SKIN_TEMP_LB_BIT)
+		return POWER_SUPPLY_HEALTH_WARM;
+
+	return POWER_SUPPLY_HEALTH_COOL;
+}
+
+int smblib_get_prop_connector_health(struct smb_charger *chg)
+{
+	bool dc_present, usb_present;
+	int input_present;
+	int rc;
+
+	rc = smblib_is_input_present(chg, &input_present);
+	if (rc < 0)
+		return POWER_SUPPLY_HEALTH_UNKNOWN;
+
+	dc_present = input_present & INPUT_PRESENT_DC;
+	usb_present = input_present & INPUT_PRESENT_USB;
+
+	if (usb_present)
+		return smblib_get_typec_connector_temp_status(chg);
+
+	/*
+	 * In PM8150B, SKIN channel measures Wireless charger receiver
+	 * temp, used to regulate DC ICL.
+	 */
+	if (chg->smb_version == PM8150B_SUBTYPE && dc_present)
+		return smblib_get_skin_temp_status(chg);
+
+	return POWER_SUPPLY_HEALTH_COOL;
+}
+
 static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode)
 {
 	int rp_ua;
@@ -3601,12 +3721,12 @@ static int smblib_handle_usb_current(struct smb_charger *chg,
 				 * Confiugure USB500 mode if Float charger is
 				 * configured for SDP mode.
 				 */
-				rc = set_sdp_current(chg, USBIN_500MA);
+				rc = vote(chg->usb_icl_votable,
+					SW_ICL_MAX_VOTER, true, USBIN_500MA);
 				if (rc < 0)
 					smblib_err(chg,
 						"Couldn't set SDP ICL rc=%d\n",
 						rc);
-
 				return rc;
 			}
 
@@ -4622,6 +4742,8 @@ void smblib_usb_plugin_locked(struct smb_charger *chg)
 		smblib_micro_usb_plugin(chg, vbus_rising);
 
 	power_supply_changed(chg->usb_psy);
+	if (chg->dual_role)
+		dual_role_instance_changed(chg->dual_role);
 	smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
 					vbus_rising ? "attached" : "detached");
 }
@@ -4720,6 +4842,11 @@ static void update_sw_icl_max(struct smb_charger *chg, int pst)
 	if (chg->pd_active)
 		return;
 
+	if (chg->typec_mode == POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER) {
+		vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, 500000);
+		return;
+	}
+
 	/*
 	 * HVDCP 2/3, handled separately
 	 */
@@ -4856,6 +4983,8 @@ irqreturn_t usb_source_change_irq_handler(int irq, void *data)
 	smblib_hvdcp_adaptive_voltage_change(chg);
 
 	power_supply_changed(chg->usb_psy);
+	if (chg->dual_role)
+		dual_role_instance_changed(chg->dual_role);
 
 	rc = smblib_read(chg, APSD_STATUS_REG, &stat);
 	if (rc < 0) {
@@ -4948,11 +5077,23 @@ static bool smblib_src_lpd(struct smb_charger *chg)
 	return lpd_flag;
 }
 
+static void typec_src_fault_condition_cfg(struct smb_charger *chg, bool src)
+{
+	int rc;
+	u8 mask = USBIN_MID_COMP_FAULT_EN_BIT | USBIN_COLLAPSE_FAULT_EN_BIT;
+
+	rc = smblib_masked_write(chg, OTG_FAULT_CONDITION_CFG_REG, mask,
+					src ? 0 : mask);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't write OTG_FAULT_CONDITION_CFG_REG rc=%d\n",
+			rc);
+}
+
 static void typec_sink_insertion(struct smb_charger *chg)
 {
 	int rc;
 
-	vote(chg->usb_icl_votable, OTG_VOTER, true, 0);
+	typec_src_fault_condition_cfg(chg, true);
 	rc = smblib_set_charge_param(chg, &chg->param.freq_switcher,
 					chg->chg_freq.freq_above_otg_threshold);
 	if (rc < 0)
@@ -4992,11 +5133,19 @@ static void typec_src_insertion(struct smb_charger *chg)
 		smblib_hvdcp_detect_enable(chg, true);
 }
 
+static void typec_ra_ra_insertion(struct smb_charger *chg)
+{
+	vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, 500000);
+	vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
+	chg->ok_to_pd = false;
+	smblib_hvdcp_detect_enable(chg, true);
+}
+
 static void typec_sink_removal(struct smb_charger *chg)
 {
 	int rc;
 
-	vote(chg->usb_icl_votable, OTG_VOTER, false, 0);
+	typec_src_fault_condition_cfg(chg, false);
 	rc = smblib_set_charge_param(chg, &chg->param.freq_switcher,
 					chg->chg_freq.freq_removal);
 	if (rc < 0)
@@ -5025,6 +5174,7 @@ static void typec_src_removal(struct smb_charger *chg)
 		dev_err(chg->dev,
 			"Couldn't disable secondary charger rc=%d\n", rc);
 
+	typec_src_fault_condition_cfg(chg, false);
 	smblib_hvdcp_detect_enable(chg, false);
 	smblib_update_usb_type(chg);
 
@@ -5051,10 +5201,10 @@ static void typec_src_removal(struct smb_charger *chg)
 	vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
 	vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
 	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, HVDCP2_ICL_VOTER, false, 0);
 	vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0);
+	vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER, false, 0);
 
 	/* reset usb irq voters */
 	vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0);
@@ -5248,6 +5398,8 @@ irqreturn_t typec_state_change_irq_handler(int irq, void *data)
 				smblib_typec_mode_name[chg->typec_mode]);
 
 	power_supply_changed(chg->usb_psy);
+	if (chg->dual_role)
+		dual_role_instance_changed(chg->dual_role);
 
 	return IRQ_HANDLED;
 }
@@ -5290,7 +5442,11 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data)
 			return IRQ_HANDLED;
 		}
 
-		if (stat & SNK_SRC_MODE_BIT) {
+		if (smblib_get_prop_dfp_mode(chg) ==
+				POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER) {
+			chg->sink_src_mode = AUDIO_ACCESS_MODE;
+			typec_ra_ra_insertion(chg);
+		} else if (stat & SNK_SRC_MODE_BIT) {
 			if (smblib_src_lpd(chg))
 				return IRQ_HANDLED;
 			chg->sink_src_mode = SRC_MODE;
@@ -5306,6 +5462,7 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data)
 			typec_sink_removal(chg);
 			break;
 		case SINK_MODE:
+		case AUDIO_ACCESS_MODE:
 			typec_src_removal(chg);
 			break;
 		case UNATTACHED_MODE:
@@ -5319,6 +5476,15 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data)
 			chg->sink_src_mode = UNATTACHED_MODE;
 			chg->early_usb_attach = false;
 			smblib_apsd_enable(chg, true);
+
+			/*
+			 * Restore DRP mode on type-C cable disconnect if role
+			 * swap is not in progress, to ensure forced sink or src
+			 * mode configuration is reset properly.
+			 */
+			if (chg->dual_role)
+				smblib_force_dr_mode(chg,
+						DUAL_ROLE_PROP_MODE_NONE);
 		}
 
 		if (chg->lpd_stage == LPD_STAGE_FLOAT_CANCEL)
@@ -5327,6 +5493,8 @@ irqreturn_t typec_attach_detach_irq_handler(int irq, void *data)
 	}
 
 	power_supply_changed(chg->usb_psy);
+	if (chg->dual_role)
+		dual_role_instance_changed(chg->dual_role);
 
 	return IRQ_HANDLED;
 }
@@ -6216,6 +6384,97 @@ static void smblib_lpd_detach_work(struct work_struct *work)
 		chg->lpd_stage = LPD_STAGE_NONE;
 }
 
+static char *dr_mode_text[] = {
+	"ufp", "dfp", "none"
+};
+
+int smblib_force_dr_mode(struct smb_charger *chg, int mode)
+{
+	int rc = 0;
+
+	switch (mode) {
+	case DUAL_ROLE_PROP_MODE_UFP:
+		rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
+				TYPEC_POWER_ROLE_CMD_MASK | EN_TRY_SNK_BIT,
+				EN_SNK_ONLY_BIT);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't enable snk, rc=%d\n", rc);
+			return rc;
+		}
+		break;
+	case DUAL_ROLE_PROP_MODE_DFP:
+		rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
+				TYPEC_POWER_ROLE_CMD_MASK | EN_TRY_SNK_BIT,
+				EN_SRC_ONLY_BIT);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't enable src, rc=%d\n", rc);
+			return rc;
+		}
+		break;
+	case DUAL_ROLE_PROP_MODE_NONE:
+		rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
+				TYPEC_POWER_ROLE_CMD_MASK | EN_TRY_SNK_BIT,
+				EN_TRY_SNK_BIT);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't enable try.snk, rc=%d\n", rc);
+			return rc;
+		}
+		break;
+	default:
+		smblib_err(chg, "Power role %d not supported\n", mode);
+		return -EINVAL;
+	}
+
+	if (chg->dr_mode != mode) {
+		chg->dr_mode = mode;
+		smblib_dbg(chg, PR_MISC, "Forced mode: %s\n",
+					dr_mode_text[chg->dr_mode]);
+	}
+
+	return rc;
+}
+
+static void smblib_dual_role_check_work(struct work_struct *work)
+{
+	struct smb_charger *chg = container_of(work, struct smb_charger,
+					role_reversal_check.work);
+	int rc = 0;
+
+	mutex_lock(&chg->dr_lock);
+
+	switch (chg->dr_mode) {
+	case DUAL_ROLE_PROP_MODE_UFP:
+		if (chg->typec_mode < POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
+			smblib_dbg(chg, PR_MISC, "Role reversal not latched to UFP in %d msecs. Resetting to DRP mode\n",
+				ROLE_REVERSAL_DELAY_MS);
+			rc = smblib_force_dr_mode(chg,
+						DUAL_ROLE_PROP_MODE_NONE);
+			if (rc < 0)
+				pr_err("Failed to set DRP mode, rc=%d\n", rc);
+		}
+		chg->pr_swap_in_progress = false;
+		break;
+	case DUAL_ROLE_PROP_MODE_DFP:
+		if (chg->typec_mode >= POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
+				chg->typec_mode == POWER_SUPPLY_TYPEC_NONE) {
+			smblib_dbg(chg, PR_MISC, "Role reversal not latched to DFP in %d msecs. Resetting to DRP mode\n",
+				ROLE_REVERSAL_DELAY_MS);
+			rc = smblib_force_dr_mode(chg,
+						DUAL_ROLE_PROP_MODE_NONE);
+			if (rc < 0)
+				pr_err("Failed to set DRP mode, rc=%d\n", rc);
+		}
+		chg->pr_swap_in_progress = false;
+		break;
+	default:
+		pr_debug("Already in DRP mode\n");
+		break;
+	}
+
+	mutex_unlock(&chg->dr_lock);
+	vote(chg->awake_votable, DR_SWAP_VOTER, false, 0);
+}
+
 static int smblib_create_votables(struct smb_charger *chg)
 {
 	int rc = 0;
@@ -6361,6 +6620,8 @@ int smblib_init(struct smb_charger *chg)
 	INIT_DELAYED_WORK(&chg->thermal_regulation_work,
 					smblib_thermal_regulation_work);
 	INIT_DELAYED_WORK(&chg->usbov_dbc_work, smblib_usbov_dbc_work);
+	INIT_DELAYED_WORK(&chg->role_reversal_check,
+					smblib_dual_role_check_work);
 
 	if (chg->wa_flags & CHG_TERMINATION_WA) {
 		INIT_WORK(&chg->chg_termination_work,
@@ -6396,6 +6657,7 @@ int smblib_init(struct smb_charger *chg)
 	chg->sec_chg_selected = POWER_SUPPLY_CHARGER_SEC_NONE;
 	chg->cp_reason = POWER_SUPPLY_CP_NONE;
 	chg->thermal_status = TEMP_BELOW_RANGE;
+	chg->dr_mode = DUAL_ROLE_PROP_MODE_NONE;
 
 	switch (chg->mode) {
 	case PARALLEL_MASTER:
@@ -6500,6 +6762,7 @@ int smblib_deinit(struct smb_charger *chg)
 		cancel_delayed_work_sync(&chg->lpd_detach_work);
 		cancel_delayed_work_sync(&chg->thermal_regulation_work);
 		cancel_delayed_work_sync(&chg->usbov_dbc_work);
+		cancel_delayed_work_sync(&chg->role_reversal_check);
 		power_supply_unreg_notifier(&chg->nb);
 		smblib_destroy_votables(chg);
 		qcom_step_chg_deinit();
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 386aca3..cb807b3 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -20,6 +20,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/consumer.h>
 #include <linux/extcon.h>
+#include <linux/usb/class-dual-role.h>
 #include "storm-watch.h"
 
 enum print_reason {
@@ -58,7 +59,6 @@ enum print_reason {
 #define OTG_DELAY_VOTER			"OTG_DELAY_VOTER"
 #define USBIN_I_VOTER			"USBIN_I_VOTER"
 #define WEAK_CHARGER_VOTER		"WEAK_CHARGER_VOTER"
-#define OTG_VOTER			"OTG_VOTER"
 #define PL_FCC_LOW_VOTER		"PL_FCC_LOW_VOTER"
 #define WBC_VOTER			"WBC_VOTER"
 #define HW_LIMIT_VOTER			"HW_LIMIT_VOTER"
@@ -73,6 +73,9 @@ enum print_reason {
 #define AICL_THRESHOLD_VOTER		"AICL_THRESHOLD_VOTER"
 #define USBOV_DBC_VOTER			"USBOV_DBC_VOTER"
 #define CHG_TERMINATION_VOTER		"CHG_TERMINATION_VOTER"
+#define THERMAL_THROTTLE_VOTER		"THERMAL_THROTTLE_VOTER"
+#define VOUT_VOTER			"VOUT_VOTER"
+#define DR_SWAP_VOTER			"DR_SWAP_VOTER"
 
 #define BOOST_BACK_STORM_COUNT	3
 #define WEAK_CHG_STORM_COUNT	8
@@ -92,6 +95,8 @@ enum print_reason {
 #define TYPEC_MEDIUM_CURRENT_UA		1500000
 #define TYPEC_HIGH_CURRENT_UA		3000000
 
+#define ROLE_REVERSAL_DELAY_MS		2000
+
 enum smb_mode {
 	PARALLEL_MASTER = 0,
 	PARALLEL_SLAVE,
@@ -101,6 +106,7 @@ enum smb_mode {
 enum sink_src_mode {
 	SINK_MODE,
 	SRC_MODE,
+	AUDIO_ACCESS_MODE,
 	UNATTACHED_MODE,
 };
 
@@ -363,6 +369,7 @@ struct smb_charger {
 	/* locks */
 	struct mutex		smb_lock;
 	struct mutex		ps_change_lock;
+	struct mutex		dr_lock;
 
 	/* power supplies */
 	struct power_supply		*batt_psy;
@@ -375,6 +382,9 @@ struct smb_charger {
 	struct power_supply		*cp_psy;
 	enum power_supply_type		real_charger_type;
 
+	/* dual role class */
+	struct dual_role_phy_instance	*dual_role;
+
 	/* notifiers */
 	struct notifier_block	nb;
 
@@ -415,6 +425,7 @@ struct smb_charger {
 	struct delayed_work	lpd_detach_work;
 	struct delayed_work	thermal_regulation_work;
 	struct delayed_work	usbov_dbc_work;
+	struct delayed_work	role_reversal_check;
 
 	struct alarm		lpd_recheck_timer;
 	struct alarm		moisture_protection_alarm;
@@ -500,6 +511,7 @@ struct smb_charger {
 	bool			aicl_max_reached;
 	int			charge_full_cc;
 	int			cc_soc_ref;
+	int			dr_mode;
 
 	/* workaround flag */
 	u32			wa_flags;
@@ -634,6 +646,7 @@ int smblib_get_prop_dc_voltage_max(struct smb_charger *chg,
 				union power_supply_propval *val);
 int smblib_set_prop_voltage_wls_output(struct smb_charger *chg,
 				const union power_supply_propval *val);
+int smblib_set_prop_dc_reset(struct smb_charger *chg);
 int smblib_get_prop_usb_present(struct smb_charger *chg,
 				union power_supply_propval *val);
 int smblib_get_prop_usb_online(struct smb_charger *chg,
@@ -703,6 +716,7 @@ int smblib_get_prop_pr_swap_in_progress(struct smb_charger *chg,
 				union power_supply_propval *val);
 int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg,
 				const union power_supply_propval *val);
+int smblib_force_dr_mode(struct smb_charger *chg, int mode);
 int smblib_get_prop_from_bms(struct smb_charger *chg,
 				enum power_supply_property psp,
 				union power_supply_propval *val);
@@ -716,6 +730,7 @@ enum alarmtimer_restart smblib_lpd_recheck_timer(struct alarm *alarm,
 				ktime_t time);
 int smblib_toggle_smb_en(struct smb_charger *chg, int toggle);
 void smblib_hvdcp_detect_enable(struct smb_charger *chg, bool enable);
+void smblib_hvdcp_exit_config(struct smb_charger *chg);
 void smblib_apsd_enable(struct smb_charger *chg, bool enable);
 int smblib_force_vbus_voltage(struct smb_charger *chg, u8 val);
 
diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h
index 8ae7ef4..2182bd4 100644
--- a/drivers/power/supply/qcom/smb5-reg.h
+++ b/drivers/power/supply/qcom/smb5-reg.h
@@ -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
@@ -150,6 +150,10 @@ enum {
 #define DCDC_OTG_CFG_REG			(DCDC_BASE + 0x53)
 #define OTG_EN_SRC_CFG_BIT			BIT(1)
 
+#define OTG_FAULT_CONDITION_CFG_REG		(DCDC_BASE + 0x56)
+#define USBIN_MID_COMP_FAULT_EN_BIT		BIT(5)
+#define USBIN_COLLAPSE_FAULT_EN_BIT		BIT(4)
+
 #define DCDC_CFG_REF_MAX_PSNS_REG		(DCDC_BASE + 0x8C)
 
 #define DCDC_ENG_SDCDC_CFG5_REG			(DCDC_BASE + 0xC4)
@@ -283,6 +287,7 @@ enum {
 #define HVDCP_EN_BIT				BIT(2)
 
 #define USBIN_OPTIONS_2_CFG_REG			(USBIN_BASE + 0x63)
+#define DCD_TIMEOUT_SEL_BIT			BIT(5)
 #define FLOAT_OPTIONS_MASK			GENMASK(2, 0)
 #define FLOAT_DIS_CHGING_CFG_BIT		BIT(2)
 #define SUSPEND_FLOAT_CFG_BIT			BIT(1)
@@ -320,6 +325,12 @@ enum {
 
 #define DCIN_CMD_IL_REG				(DCIN_BASE + 0x40)
 #define DCIN_SUSPEND_BIT			BIT(0)
+#define DCIN_EN_OVERRIDE_BIT			BIT(1)
+#define DCIN_EN_MASK				GENMASK(2, 1)
+
+#define DCIN_CMD_PON_REG			(DCIN_BASE + 0x45)
+#define DCIN_PON_BIT				BIT(0)
+#define MID_CHG_BIT					BIT(1)
 
 #define DCIN_LOAD_CFG_REG			(DCIN_BASE + 0x65)
 #define INPUT_MISS_POLL_EN_BIT			BIT(5)
@@ -394,6 +405,7 @@ enum {
 
 #define TYPE_C_EXIT_STATE_CFG_REG		(TYPEC_BASE + 0x50)
 #define BYPASS_VSAFE0V_DURING_ROLE_SWAP_BIT	BIT(3)
+#define SEL_SRC_UPPER_REF_BIT			BIT(2)
 #define EXIT_SNK_BASED_ON_CC_BIT		BIT(0)
 
 #define TYPE_C_CURRSRC_CFG_REG			(TYPEC_BASE + 0x52)
@@ -463,6 +475,12 @@ enum {
 #define DIE_TEMP_UB_BIT				BIT(1)
 #define DIE_TEMP_LB_BIT				BIT(0)
 
+#define SKIN_TEMP_STATUS_REG			(MISC_BASE + 0x08)
+#define SKIN_TEMP_SHDN_BIT			BIT(3)
+#define SKIN_TEMP_RST_BIT			BIT(2)
+#define SKIN_TEMP_UB_BIT			BIT(1)
+#define SKIN_TEMP_LB_BIT			BIT(0)
+
 #define CONNECTOR_TEMP_STATUS_REG		(MISC_BASE + 0x09)
 #define CONNECTOR_TEMP_SHDN_BIT			BIT(3)
 #define CONNECTOR_TEMP_RST_BIT			BIT(2)
diff --git a/drivers/power/supply/qcom/step-chg-jeita.c b/drivers/power/supply/qcom/step-chg-jeita.c
index 73b4d19..fd9f85b 100644
--- a/drivers/power/supply/qcom/step-chg-jeita.c
+++ b/drivers/power/supply/qcom/step-chg-jeita.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
@@ -597,10 +597,12 @@ static int handle_step_chg_config(struct step_chg_info *chip)
 	if (!chip->fcc_votable)
 		return -EINVAL;
 
-	if (chip->taper_fcc)
+	if (chip->taper_fcc) {
 		taper_fcc_step_chg(chip, chip->step_index, pval.intval);
-	else
+	} else {
+		fcc_ua = chip->step_chg_config->fcc_cfg[chip->step_index].value;
 		vote(chip->fcc_votable, STEP_CHG_VOTER, true, fcc_ua);
+	}
 
 	pr_debug("%s = %d Step-FCC = %duA taper-fcc: %d\n",
 		chip->step_chg_config->param.prop_name, pval.intval,
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index a421d6c..ecb41ea 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -228,7 +228,9 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 			pct->sec = ts.tv_sec;
 			pct->nsec = ts.tv_nsec;
 			pct++;
-			ptp->info->gettime64(ptp->info, &ts);
+			err = ptp->info->gettime64(ptp->info, &ts);
+			if (err)
+				goto out;
 			pct->sec = ts.tv_sec;
 			pct->nsec = ts.tv_nsec;
 			pct++;
@@ -281,6 +283,7 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 		break;
 	}
 
+out:
 	kfree(sysoff);
 	return err;
 }
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 7eacc1c..c64903a 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -253,8 +253,10 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 	ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid,
 					     ptp, ptp->pin_attr_groups,
 					     "ptp%d", ptp->index);
-	if (IS_ERR(ptp->dev))
+	if (IS_ERR(ptp->dev)) {
+		err = PTR_ERR(ptp->dev);
 		goto no_device;
+	}
 
 	/* Register a new PPS source. */
 	if (info->pps) {
@@ -265,6 +267,7 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
 		pps.owner = info->owner;
 		ptp->pps_source = pps_register_source(&pps, PTP_PPS_DEFAULTS);
 		if (!ptp->pps_source) {
+			err = -EINVAL;
 			pr_err("failed to register pps source\n");
 			goto no_pps;
 		}
diff --git a/drivers/ptp/ptp_kvm.c b/drivers/ptp/ptp_kvm.c
index 2b1b212..c67dd11 100644
--- a/drivers/ptp/ptp_kvm.c
+++ b/drivers/ptp/ptp_kvm.c
@@ -178,8 +178,11 @@ static int __init ptp_kvm_init(void)
 {
 	long ret;
 
+	if (!kvm_para_available())
+		return -ENODEV;
+
 	clock_pair_gpa = slow_virt_to_phys(&clock_pair);
-	hv_clock = pvclock_pvti_cpu0_va();
+	hv_clock = pvclock_get_pvti_cpu0_va();
 
 	if (!hv_clock)
 		return -ENODEV;
diff --git a/drivers/regulator/qpnp-amoled-regulator.c b/drivers/regulator/qpnp-amoled-regulator.c
index 69ffeff..c9c6b2d 100644
--- a/drivers/regulator/qpnp-amoled-regulator.c
+++ b/drivers/regulator/qpnp-amoled-regulator.c
@@ -35,16 +35,24 @@
 /* AB */
 #define AB_STATUS1(chip)		(chip->ab_base + 0x08)
 #define AB_LDO_SW_DBG_CTL(chip)		(chip->ab_base + 0x72)
-
-/* IBB */
-#define IBB_PS_CTL(chip)		(chip->ibb_base + 0x50)
-#define IBB_NLIMIT_DAC(chip)		(chip->ibb_base + 0x61)
-#define IBB_SMART_PS_CTL(chip)		(chip->ibb_base + 0x65)
+#define AB_LDO_PD_CTL(chip)		(chip->ab_base + 0x78)
 
 /* AB_STATUS1 */
 #define VREG_OK_BIT			BIT(6)
 #define VREG_OK_SHIFT			6
 
+/* AB_LDO_PD_CTL */
+#define PULLDN_EN_BIT			BIT(7)
+
+/* IBB */
+#define IBB_PD_CTL(chip)		(chip->ibb_base + 0x47)
+#define IBB_PS_CTL(chip)		(chip->ibb_base + 0x50)
+#define IBB_NLIMIT_DAC(chip)		(chip->ibb_base + 0x61)
+#define IBB_SMART_PS_CTL(chip)		(chip->ibb_base + 0x65)
+
+/* IBB_PD_CTL */
+#define ENABLE_PD_BIT			BIT(7)
+
 struct amoled_regulator {
 	struct regulator_desc	rdesc;
 	struct regulator_dev	*rdev;
@@ -65,6 +73,7 @@ struct ab_regulator {
 
 	/* DT params */
 	bool			swire_control;
+	bool			pd_control;
 };
 
 struct ibb_regulator {
@@ -72,6 +81,7 @@ struct ibb_regulator {
 
 	/* DT params */
 	bool			swire_control;
+	bool			pd_control;
 };
 
 struct qpnp_amoled {
@@ -120,7 +130,7 @@ static int qpnp_amoled_write(struct qpnp_amoled *chip,
 	return rc;
 }
 
-int qpnp_amoled_masked_write(struct qpnp_amoled *chip,
+static int qpnp_amoled_masked_write(struct qpnp_amoled *chip,
 				u16 addr, u8 mask, u8 value)
 {
 	int rc = 0;
@@ -208,13 +218,28 @@ static int qpnp_ab_ibb_regulator_get_voltage(struct regulator_dev *rdev)
 	return 0;
 }
 
+static int qpnp_ab_pd_control(struct qpnp_amoled *chip, bool en)
+{
+	u8 val = en ? PULLDN_EN_BIT : 0;
+
+	return qpnp_amoled_write(chip, AB_LDO_PD_CTL(chip), &val, 1);
+}
+
 #define AB_VREG_OK_POLL_TRIES		50
+#define AB_VREG_OK_POLL_TIME_US		2000
+#define AB_VREG_OK_POLL_HIGH_TRIES	8
+#define AB_VREG_OK_POLL_HIGH_TIME_US	10000
+#define AB_VREG_OK_POLL_AGAIN_TRIES	10
+
 static int qpnp_ab_poll_vreg_ok(struct qpnp_amoled *chip, bool status)
 {
-	u32 i = AB_VREG_OK_POLL_TRIES, poll_us = 2000;
+	u32 i = AB_VREG_OK_POLL_TRIES, poll_us = AB_VREG_OK_POLL_TIME_US;
+	bool swire_high = false, poll_again = false, monitor = false;
+	u32 wait_time_us = 0;
 	int rc;
 	u8 val;
 
+loop:
 	while (i--) {
 		/* Write a dummy value before reading AB_STATUS1 */
 		rc = qpnp_amoled_write(chip, AB_STATUS1(chip), &val, 1);
@@ -225,19 +250,82 @@ static int qpnp_ab_poll_vreg_ok(struct qpnp_amoled *chip, bool status)
 		if (rc < 0)
 			return rc;
 
+		wait_time_us += poll_us;
 		if (((val & VREG_OK_BIT) >> VREG_OK_SHIFT) == status) {
-			pr_debug("Waited for %d us\n",
-				(AB_VREG_OK_POLL_TRIES - i) * poll_us);
-			return 0;
+			pr_debug("Waited for %d us\n", wait_time_us);
+
+			/*
+			 * Return if we're polling for VREG_OK low. Else, poll
+			 * for VREG_OK high for at least 80 ms. IF VREG_OK stays
+			 * high, then consider it as a valid SWIRE pulse.
+			 */
+
+			if (status) {
+				swire_high = true;
+				if (!poll_again && !monitor) {
+					pr_debug("SWIRE is high, start monitoring\n");
+					i = AB_VREG_OK_POLL_HIGH_TRIES;
+					poll_us = AB_VREG_OK_POLL_HIGH_TIME_US;
+					wait_time_us = 0;
+					monitor = true;
+				}
+
+				if (poll_again)
+					poll_again = false;
+			} else {
+				return 0;
+			}
+		} else {
+			/*
+			 * If we're here when polling for VREG_OK high, then it
+			 * is possibly because of an intermittent SWIRE pulse.
+			 * Ignore it and poll for valid SWIRE pulse again.
+			 */
+			if (status && swire_high && monitor) {
+				pr_debug("SWIRE is low\n");
+				poll_again = true;
+				swire_high = false;
+				break;
+			}
+
+			if (poll_again)
+				poll_again = false;
 		}
 
 		usleep_range(poll_us, poll_us + 1);
 	}
 
+	/*
+	 * If poll_again is set, then VREG_OK should be polled for another
+	 * 100 ms for valid SWIRE signal.
+	 */
+
+	if (poll_again) {
+		pr_debug("polling again for SWIRE\n");
+		i = AB_VREG_OK_POLL_AGAIN_TRIES;
+		poll_us = AB_VREG_OK_POLL_HIGH_TIME_US;
+		wait_time_us = 0;
+		goto loop;
+	}
+
+	/* If swire_high is set, then it's a valid SWIRE signal, return 0. */
+	if (swire_high) {
+		pr_debug("SWIRE is high\n");
+		return 0;
+	}
+
 	pr_err("AB_STATUS1: %x poll for VREG_OK %d timed out\n", val, status);
 	return -ETIMEDOUT;
 }
 
+static int qpnp_ibb_pd_control(struct qpnp_amoled *chip, bool en)
+{
+	u8 val = en ? ENABLE_PD_BIT : 0;
+
+	return qpnp_amoled_masked_write(chip, IBB_PD_CTL(chip), ENABLE_PD_BIT,
+					val);
+}
+
 static int qpnp_ibb_aod_config(struct qpnp_amoled *chip, bool aod)
 {
 	int rc;
@@ -300,18 +388,54 @@ static void qpnp_amoled_aod_work(struct work_struct *work)
 		rc = qpnp_ibb_aod_config(chip, false);
 		if (rc < 0)
 			goto error;
+
+		if (chip->ibb.pd_control) {
+			rc = qpnp_ibb_pd_control(chip, true);
+			if (rc < 0)
+				goto error;
+		}
+
+		if (chip->ab.pd_control) {
+			rc = qpnp_ab_pd_control(chip, true);
+			if (rc < 0)
+				goto error;
+		}
 	} else if (mode == REGULATOR_MODE_IDLE) {
 		/* poll for VREG_OK low */
 		rc = qpnp_ab_poll_vreg_ok(chip, false);
 		if (rc < 0)
 			goto error;
 
+		if (chip->ibb.pd_control) {
+			rc = qpnp_ibb_pd_control(chip, false);
+			if (rc < 0)
+				goto error;
+		}
+
+		if (chip->ab.pd_control) {
+			rc = qpnp_ab_pd_control(chip, false);
+			if (rc < 0)
+				goto error;
+		}
+
 		val = 0xF1;
 	} else if (mode == REGULATOR_MODE_STANDBY) {
 		/* Restore the normal configuration without any delay */
 		rc = qpnp_ibb_aod_config(chip, false);
 		if (rc < 0)
 			goto error;
+
+		if (chip->ibb.pd_control) {
+			rc = qpnp_ibb_pd_control(chip, true);
+			if (rc < 0)
+				goto error;
+		}
+
+		if (chip->ab.pd_control) {
+			rc = qpnp_ab_pd_control(chip, true);
+			if (rc < 0)
+				goto error;
+		}
 	}
 
 	rc = qpnp_amoled_write(chip, AB_LDO_SW_DBG_CTL(chip), &val, 1);
@@ -557,7 +681,6 @@ static int qpnp_amoled_parse_dt(struct qpnp_amoled *chip)
 {
 	struct device_node *temp, *node = chip->dev->of_node;
 	const __be32 *prop_addr;
-	bool swire_control;
 	int rc = 0;
 	u32 base, val;
 
@@ -579,23 +702,24 @@ static int qpnp_amoled_parse_dt(struct qpnp_amoled *chip)
 		case OLEDB_PERIPH_TYPE:
 			chip->oledb_base = base;
 			chip->oledb.vreg.node = temp;
-			swire_control = of_property_read_bool(temp,
-						"qcom,swire-control");
-			chip->oledb.swire_control = swire_control;
+			chip->oledb.swire_control = of_property_read_bool(temp,
+							"qcom,swire-control");
 			break;
 		case AB_PERIPH_TYPE:
 			chip->ab_base = base;
 			chip->ab.vreg.node = temp;
-			swire_control = of_property_read_bool(temp,
-						"qcom,swire-control");
-			chip->ab.swire_control = swire_control;
+			chip->ab.swire_control = of_property_read_bool(temp,
+							"qcom,swire-control");
+			chip->ab.pd_control = of_property_read_bool(temp,
+							"qcom,aod-pd-control");
 			break;
 		case IBB_PERIPH_TYPE:
 			chip->ibb_base = base;
 			chip->ibb.vreg.node = temp;
-			swire_control = of_property_read_bool(temp,
-						"qcom,swire-control");
-			chip->ibb.swire_control = swire_control;
+			chip->ibb.swire_control = of_property_read_bool(temp,
+							"qcom,swire-control");
+			chip->ibb.pd_control = of_property_read_bool(temp,
+							"qcom,aod-pd-control");
 			break;
 		default:
 			pr_err("Unknown peripheral type 0x%x\n", val);
@@ -687,7 +811,19 @@ static struct platform_driver qpnp_amoled_regulator_driver = {
 	.probe		= qpnp_amoled_regulator_probe,
 	.remove		= qpnp_amoled_regulator_remove,
 };
-module_platform_driver(qpnp_amoled_regulator_driver);
+
+static int __init qpnp_amoled_regulator_init(void)
+{
+	return platform_driver_register(&qpnp_amoled_regulator_driver);
+}
+
+static void __exit qpnp_amoled_regulator_exit(void)
+{
+	platform_driver_unregister(&qpnp_amoled_regulator_driver);
+}
 
 MODULE_DESCRIPTION("QPNP AMOLED regulator driver");
 MODULE_LICENSE("GPL v2");
+
+arch_initcall(qpnp_amoled_regulator_init);
+module_exit(qpnp_amoled_regulator_exit);
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index b85a5d6..4d4080d 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -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)
@@ -220,7 +228,9 @@ struct qpnp_lcdb {
 	struct regmap			*regmap;
 	struct pmic_revid_data		*pmic_rev_id;
 	u32				base;
+	u32				wa_flags;
 	int				sc_irq;
+	int				pwrdn_delay_ms;
 
 	/* TTW params */
 	bool				ttw_enable;
@@ -292,6 +302,11 @@ enum lcdb_settings_index {
 	LCDB_SETTING_MAX,
 };
 
+enum lcdb_wa_flags {
+	NCP_SCP_DISABLE_WA = BIT(0),
+	FORCE_PD_ENABLE_WA = BIT(1),
+};
+
 static u32 soft_start_us[] = {
 	0,
 	500,
@@ -313,6 +328,13 @@ static u32 ncp_ilim_ma[] = {
 	810,
 };
 
+static const u32 pwrup_pwrdn_ms[] = {
+	0,
+	1,
+	4,
+	8,
+};
+
 #define SETTING(_id, _sec_access, _valid)	\
 	[_id] = {				\
 		.address = _id##_REG,		\
@@ -915,6 +937,18 @@ static int qpnp_lcdb_disable(struct qpnp_lcdb *lcdb)
 		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);
@@ -923,6 +957,17 @@ static int qpnp_lcdb_disable(struct qpnp_lcdb *lcdb)
 	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;
 }
 
@@ -2020,11 +2065,40 @@ static int qpnp_lcdb_init_bst(struct qpnp_lcdb *lcdb)
 	return 0;
 }
 
+static void qpnp_lcdb_pmic_config(struct qpnp_lcdb *lcdb)
+{
+	switch (lcdb->pmic_rev_id->pmic_subtype) {
+	case PM660L_SUBTYPE:
+		if (lcdb->pmic_rev_id->rev4 < PM660L_V2P0_REV4)
+			lcdb->wa_flags |= NCP_SCP_DISABLE_WA;
+		break;
+	case PMI632_SUBTYPE:
+	case PM6150L_SUBTYPE:
+		lcdb->wa_flags |= FORCE_PD_ENABLE_WA;
+		break;
+	default:
+		break;
+	}
+
+	pr_debug("LCDB wa_flags = 0x%2x\n", lcdb->wa_flags);
+}
+
 static int qpnp_lcdb_hw_init(struct qpnp_lcdb *lcdb)
 {
 	int rc = 0;
 	u8 val = 0;
 
+	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);
@@ -2082,7 +2156,8 @@ static int qpnp_lcdb_hw_init(struct qpnp_lcdb *lcdb)
 
 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;
 
@@ -2146,7 +2221,24 @@ static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
 	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 int qpnp_lcdb_regulator_probe(struct platform_device *pdev)
diff --git a/drivers/regulator/rpm-smd-regulator.c b/drivers/regulator/rpm-smd-regulator.c
index 68fb34f..2785d90 100644
--- a/drivers/regulator/rpm-smd-regulator.c
+++ b/drivers/regulator/rpm-smd-regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -54,6 +54,14 @@ enum rpm_regulator_type {
 	RPM_REGULATOR_TYPE_MAX,
 };
 
+/* Supported PMIC regulator LDO types */
+enum rpm_regulator_hw_type {
+	RPM_REGULATOR_HW_TYPE_UNKNOWN,
+	RPM_REGULATOR_HW_TYPE_PMIC4_LDO,
+	RPM_REGULATOR_HW_TYPE_PMIC5_LDO,
+	RPM_REGULATOR_HW_TYPE_MAX,
+};
+
 /* RPM resource parameters */
 enum rpm_regulator_param_index {
 	RPM_REGULATOR_PARAM_ENABLE,
@@ -129,20 +137,20 @@ static struct rpm_regulator_param params[RPM_REGULATOR_PARAM_MAX] = {
 	/*    ID               LDO SMPS VS  NCP BOB  name  min max          property-name */
 	PARAM(ENABLE,            1,  1,  1,  1,  1, "swen", 0, 1,          "qcom,init-enable"),
 	PARAM(VOLTAGE,           1,  1,  0,  1,  1, "uv",   0, 0x7FFFFFF,  "qcom,init-voltage"),
-	PARAM(CURRENT,           1,  1,  0,  0,  0, "ma",   0, 0x1FFF,     "qcom,init-current"),
+	PARAM(CURRENT,           0,  1,  0,  0,  0, "ma",   0, 0x1FFF,     "qcom,init-current"),
 	PARAM(MODE_LDO,          1,  0,  0,  0,  0, "lsmd", 0, 1,          "qcom,init-ldo-mode"),
 	PARAM(MODE_SMPS,         0,  1,  0,  0,  0, "ssmd", 0, 2,          "qcom,init-smps-mode"),
 	PARAM(PIN_CTRL_ENABLE,   1,  1,  1,  0,  0, "pcen", 0, 0xF,        "qcom,init-pin-ctrl-enable"),
-	PARAM(PIN_CTRL_MODE,     1,  1,  1,  0,  0, "pcmd", 0, 0x1F,       "qcom,init-pin-ctrl-mode"),
+	PARAM(PIN_CTRL_MODE,     0,  1,  1,  0,  0, "pcmd", 0, 0x1F,       "qcom,init-pin-ctrl-mode"),
 	PARAM(FREQUENCY,         0,  1,  0,  1,  0, "freq", 0, 31,         "qcom,init-frequency"),
-	PARAM(HEAD_ROOM,         1,  0,  0,  1,  0, "hr",   0, 0x7FFFFFFF, "qcom,init-head-room"),
+	PARAM(HEAD_ROOM,         0,  0,  0,  1,  0, "hr",   0, 0x7FFFFFFF, "qcom,init-head-room"),
 	PARAM(QUIET_MODE,        0,  1,  0,  0,  0, "qm",   0, 2,          "qcom,init-quiet-mode"),
 	PARAM(FREQ_REASON,       0,  1,  0,  1,  0, "resn", 0, 8,          "qcom,init-freq-reason"),
-	PARAM(CORNER,            1,  1,  0,  0,  0, "corn", 0, 6,          "qcom,init-voltage-corner"),
-	PARAM(BYPASS,            1,  0,  0,  0,  0, "bypa", 0, 1,          "qcom,init-disallow-bypass"),
-	PARAM(FLOOR_CORNER,      1,  1,  0,  0,  0, "vfc",  0, 6,          "qcom,init-voltage-floor-corner"),
-	PARAM(LEVEL,             1,  1,  0,  0,  0, "vlvl", 0, 0xFFFF,     "qcom,init-voltage-level"),
-	PARAM(FLOOR_LEVEL,       1,  1,  0,  0,  0, "vfl",  0, 0xFFFF,     "qcom,init-voltage-floor-level"),
+	PARAM(CORNER,            0,  1,  0,  0,  0, "corn", 0, 6,          "qcom,init-voltage-corner"),
+	PARAM(BYPASS,            0,  0,  0,  0,  0, "bypa", 0, 1,          "qcom,init-disallow-bypass"),
+	PARAM(FLOOR_CORNER,      0,  1,  0,  0,  0, "vfc",  0, 6,          "qcom,init-voltage-floor-corner"),
+	PARAM(LEVEL,             0,  1,  0,  0,  0, "vlvl", 0, 0xFFFF,     "qcom,init-voltage-level"),
+	PARAM(FLOOR_LEVEL,       0,  1,  0,  0,  0, "vfl",  0, 0xFFFF,     "qcom,init-voltage-floor-level"),
 	PARAM(MODE_BOB,          0,  0,  0,  0,  1, "bobm", 0, 3,          "qcom,init-bob-mode"),
 	PARAM(PIN_CTRL_VOLTAGE1, 0,  0,  0,  0,  1, "pcv1", 0, 0x7FFFFFF,  "qcom,init-pin-ctrl-voltage1"),
 	PARAM(PIN_CTRL_VOLTAGE2, 0,  0,  0,  0,  1, "pcv2", 0, 0x7FFFFFF,  "qcom,init-pin-ctrl-voltage2"),
@@ -194,6 +202,7 @@ struct rpm_vreg {
 	bool			apps_only;
 	struct msm_rpm_request	*handle_active;
 	struct msm_rpm_request	*handle_sleep;
+	enum rpm_regulator_hw_type	regulator_hw_type;
 };
 
 struct rpm_regulator {
@@ -864,6 +873,113 @@ static int rpm_vreg_get_voltage(struct regulator_dev *rdev)
 	return uV;
 }
 
+#define REGULATOR_MODE_PMIC4_LDO_LPM	5
+#define REGULATOR_MODE_PMIC4_LDO_HPM	7
+#define REGULATOR_MODE_PMIC5_LDO_LPM	4
+#define REGULATOR_MODE_PMIC5_LDO_HPM	7
+
+static int _rpm_vreg_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+	u32 hw_mode;
+	int rc = 0;
+
+	if (mode == REGULATOR_MODE_NORMAL) {
+		switch (reg->rpm_vreg->regulator_hw_type) {
+		case RPM_REGULATOR_HW_TYPE_PMIC4_LDO:
+			hw_mode = REGULATOR_MODE_PMIC4_LDO_HPM;
+			break;
+
+		case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
+			hw_mode = REGULATOR_MODE_PMIC5_LDO_HPM;
+			break;
+
+		default:
+			vreg_err(reg, "unsupported ldo hw type: %d\n",
+					reg->rpm_vreg->regulator_hw_type);
+			return -EINVAL;
+		}
+	} else if (mode == REGULATOR_MODE_IDLE) {
+		switch (reg->rpm_vreg->regulator_hw_type) {
+		case RPM_REGULATOR_HW_TYPE_PMIC4_LDO:
+			hw_mode = REGULATOR_MODE_PMIC4_LDO_LPM;
+			break;
+
+		case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
+			hw_mode = REGULATOR_MODE_PMIC5_LDO_LPM;
+			break;
+
+		default:
+			vreg_err(reg, "unsupported ldo hw type: %d\n",
+					reg->rpm_vreg->regulator_hw_type);
+			return -EINVAL;
+		}
+	} else {
+		vreg_err(reg, "invalid mode: %u\n", mode);
+		return -EINVAL;
+	}
+
+	RPM_VREG_SET_PARAM(reg, MODE_LDO, hw_mode);
+
+	/*
+	 * Only send the mode if the regulator is currently enabled or if the
+	 * regulator has been configured to always send current updates.
+	 */
+	if (reg->always_send_current
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg)
+	    || rpm_vreg_shared_active_or_sleep_enabled_valid(reg->rpm_vreg))
+		rc = rpm_vreg_aggregate_requests(reg);
+
+	if (rc)
+		vreg_err(reg, "set mode failed, rc=%d\n", rc);
+
+	return rc;
+}
+
+static int rpm_vreg_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+	int rc = 0;
+
+	rpm_vreg_lock(reg->rpm_vreg);
+
+	rc = _rpm_vreg_ldo_set_mode(rdev, mode);
+
+	rpm_vreg_unlock(reg->rpm_vreg);
+
+	return rc;
+}
+
+static unsigned int rpm_vreg_ldo_get_mode(struct regulator_dev *rdev)
+{
+	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+	u32 hw_mode;
+
+	hw_mode = reg->req.param[RPM_REGULATOR_PARAM_MODE_LDO];
+	if (hw_mode == REGULATOR_MODE_PMIC4_LDO_HPM ||
+			hw_mode == REGULATOR_MODE_PMIC5_LDO_HPM)
+		return REGULATOR_MODE_NORMAL;
+
+	return REGULATOR_MODE_IDLE;
+}
+
+static int rpm_vreg_ldo_set_load(struct regulator_dev *rdev, int load_uA)
+{
+	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+	unsigned int mode;
+	int rc = 0;
+
+	rpm_vreg_lock(reg->rpm_vreg);
+
+	mode = (load_uA + reg->system_load >= reg->rpm_vreg->hpm_min_load)
+		? REGULATOR_MODE_NORMAL : REGULATOR_MODE_IDLE;
+	rc = _rpm_vreg_ldo_set_mode(rdev, mode);
+
+	rpm_vreg_unlock(reg->rpm_vreg);
+
+	return rc;
+}
+
 static int rpm_vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
 	struct rpm_regulator *reg = rdev_get_drvdata(rdev);
@@ -1355,9 +1471,9 @@ static struct regulator_ops ldo_ops = {
 	.is_enabled		= rpm_vreg_is_enabled,
 	.set_voltage		= rpm_vreg_set_voltage,
 	.get_voltage		= rpm_vreg_get_voltage,
-	.set_mode		= rpm_vreg_set_mode,
-	.get_mode		= rpm_vreg_get_mode,
-	.get_optimum_mode	= rpm_vreg_get_optimum_mode,
+	.set_load		= rpm_vreg_ldo_set_load,
+	.set_mode		= rpm_vreg_ldo_set_mode,
+	.get_mode		= rpm_vreg_ldo_get_mode,
 	.enable_time		= rpm_vreg_enable_time,
 };
 
@@ -1749,6 +1865,8 @@ static int rpm_vreg_resource_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
 	struct rpm_vreg *rpm_vreg;
+	const char *type = "";
+	const char *prop;
 	int val = 0;
 	u32 resource_type;
 	int rc;
@@ -1797,6 +1915,29 @@ static int rpm_vreg_resource_probe(struct platform_device *pdev)
 		goto fail_free_vreg;
 	}
 
+	if (rpm_vreg->regulator_type == RPM_REGULATOR_TYPE_LDO) {
+		prop = "qcom,regulator-hw-type";
+		rpm_vreg->regulator_hw_type = RPM_REGULATOR_HW_TYPE_UNKNOWN;
+		rc = of_property_read_string(node, prop, &type);
+		if (rc) {
+			dev_err(dev, "%s is missing in DT node rc=%d\n",
+				prop, rc);
+			goto fail_free_vreg;
+		}
+
+		if (!strcmp(type, "pmic4-ldo")) {
+			rpm_vreg->regulator_hw_type
+				= RPM_REGULATOR_HW_TYPE_PMIC4_LDO;
+		} else if (!strcmp(type, "pmic5-ldo")) {
+			rpm_vreg->regulator_hw_type
+				= RPM_REGULATOR_HW_TYPE_PMIC5_LDO;
+		} else {
+			dev_err(dev, "unknown %s = %s\n",
+				prop, type);
+			goto fail_free_vreg;
+		}
+	}
+
 	/* Optional device tree properties: */
 	of_property_read_u32(node, "qcom,allow-atomic", &val);
 	rpm_vreg->allow_atomic = !!val;
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
index 471df45..76a41f3 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1480,6 +1480,9 @@ static int __qcom_glink_send(struct glink_channel *channel,
 			if (intent)
 				break;
 
+			if (atomic_read(&glink->in_reset))
+				return -ECONNRESET;
+
 			if (!wait)
 				return -EBUSY;
 
diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c
index 69b25d1..6bd0723 100644
--- a/drivers/rpmsg/qcom_glink_rpm.c
+++ b/drivers/rpmsg/qcom_glink_rpm.c
@@ -346,7 +346,7 @@ static int __init glink_rpm_init(void)
 {
 	return platform_driver_register(&glink_rpm_driver);
 }
-subsys_initcall(glink_rpm_init);
+postcore_initcall(glink_rpm_init);
 
 static void __exit glink_rpm_exit(void)
 {
diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
index a914914..8b279dc 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016, Linaro Ltd
- * 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
@@ -80,9 +80,14 @@ static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np)
 	tail = le32_to_cpu(*pipe->tail);
 
 	if (head < tail)
-		return pipe->native.length - tail + head;
+		len = pipe->native.length - tail + head;
 	else
-		return head - tail;
+		len = head - tail;
+
+	if (WARN_ON_ONCE(len > pipe->native.length))
+		len = 0;
+
+	return len;
 }
 
 static void glink_smem_rx_peak(struct qcom_glink_pipe *np,
@@ -93,6 +98,10 @@ static void glink_smem_rx_peak(struct qcom_glink_pipe *np,
 	u32 tail;
 
 	tail = le32_to_cpu(*pipe->tail);
+
+	if (WARN_ON_ONCE(tail > pipe->native.length))
+		return;
+
 	tail += offset;
 	if (tail >= pipe->native.length)
 		tail -= pipe->native.length;
@@ -117,7 +126,7 @@ static void glink_smem_rx_advance(struct qcom_glink_pipe *np,
 
 	tail += count;
 	if (tail >= pipe->native.length)
-		tail -= pipe->native.length;
+		tail %= pipe->native.length;
 
 	*pipe->tail = cpu_to_le32(tail);
 }
@@ -142,6 +151,9 @@ static size_t glink_smem_tx_avail(struct qcom_glink_pipe *np)
 	else
 		avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE;
 
+	if (WARN_ON_ONCE(avail > pipe->native.length))
+		avail = 0;
+
 	return avail;
 }
 
@@ -151,6 +163,9 @@ static unsigned int glink_smem_tx_write_one(struct glink_smem_pipe *pipe,
 {
 	size_t len;
 
+	if (WARN_ON_ONCE(head > pipe->native.length))
+		return head;
+
 	len = min_t(size_t, count, pipe->native.length - head);
 	if (len)
 		memcpy(pipe->fifo + head, data, len);
diff --git a/drivers/rpmsg/qcom_glink_spi.c b/drivers/rpmsg/qcom_glink_spi.c
index 1510176..96f1007 100644
--- a/drivers/rpmsg/qcom_glink_spi.c
+++ b/drivers/rpmsg/qcom_glink_spi.c
@@ -884,6 +884,7 @@ static int glink_spi_request_intent(struct glink_spi *glink,
 	struct glink_spi_msg req = { 0 };
 	int ret;
 
+	kref_get(&channel->refcount);
 	mutex_lock(&channel->intent_req_lock);
 
 	reinit_completion(&channel->intent_req_comp);
@@ -908,6 +909,7 @@ static int glink_spi_request_intent(struct glink_spi *glink,
 
 unlock:
 	mutex_unlock(&channel->intent_req_lock);
+	kref_put(&channel->refcount, glink_spi_channel_release);
 	return ret;
 }
 
@@ -2405,6 +2407,8 @@ static void glink_spi_remove(struct glink_spi *glink)
 	mutex_lock(&glink->idr_lock);
 	/* Release any defunct local channels, waiting for close-ack */
 	idr_for_each_entry(&glink->lcids, channel, cid) {
+		/* Wakeup threads waiting for intent*/
+		complete(&channel->intent_req_comp);
 		kref_put(&channel->refcount, glink_spi_channel_release);
 		idr_remove(&glink->lcids, cid);
 	}
diff --git a/drivers/rpmsg/rpm-smd.c b/drivers/rpmsg/rpm-smd.c
index be2e69d..8bfae98 100644
--- a/drivers/rpmsg/rpm-smd.c
+++ b/drivers/rpmsg/rpm-smd.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
@@ -1647,4 +1647,4 @@ int __init msm_rpm_driver_init(void)
 
 	return ret;
 }
-postcore_initcall(msm_rpm_driver_init);
+postcore_initcall_sync(msm_rpm_driver_init);
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index 194ffd5..039b207 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -60,7 +60,9 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
 
 static void __ref sclp_cpu_change_notify(struct work_struct *work)
 {
+	lock_device_hotplug();
 	smp_rescan_cpus();
+	unlock_device_hotplug();
 }
 
 static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h
index 13df602..9499cd3 100644
--- a/drivers/s390/crypto/zcrypt_error.h
+++ b/drivers/s390/crypto/zcrypt_error.h
@@ -65,6 +65,7 @@ struct error_hdr {
 #define REP82_ERROR_FORMAT_FIELD	    0x29
 #define REP82_ERROR_INVALID_COMMAND	    0x30
 #define REP82_ERROR_MALFORMED_MSG	    0x40
+#define REP82_ERROR_INVALID_SPECIAL_CMD	    0x41
 #define REP82_ERROR_INVALID_DOMAIN_PRECHECK 0x42
 #define REP82_ERROR_RESERVED_FIELDO	    0x50 /* old value	*/
 #define REP82_ERROR_WORD_ALIGNMENT	    0x60
@@ -103,6 +104,7 @@ static inline int convert_error(struct zcrypt_queue *zq,
 	case REP88_ERROR_MESSAGE_MALFORMD:
 	case REP82_ERROR_INVALID_DOMAIN_PRECHECK:
 	case REP82_ERROR_INVALID_DOMAIN_PENDING:
+	case REP82_ERROR_INVALID_SPECIAL_CMD:
 	//   REP88_ERROR_INVALID_KEY		// '82' CEX2A
 	//   REP88_ERROR_OPERAND		// '84' CEX2A
 	//   REP88_ERROR_OPERAND_EVEN_MOD	// '85' CEX2A
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 8475215..fab02bd 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -274,16 +274,16 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
  */
 int zfcp_status_read_refill(struct zfcp_adapter *adapter)
 {
-	while (atomic_read(&adapter->stat_miss) > 0)
+	while (atomic_add_unless(&adapter->stat_miss, -1, 0))
 		if (zfcp_fsf_status_read(adapter->qdio)) {
+			atomic_inc(&adapter->stat_miss); /* undo add -1 */
 			if (atomic_read(&adapter->stat_miss) >=
 			    adapter->stat_read_buf_num) {
 				zfcp_erp_adapter_reopen(adapter, 0, "axsref1");
 				return 1;
 			}
 			break;
-		} else
-			atomic_dec(&adapter->stat_miss);
+		}
 	return 0;
 }
 
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 4a4746c..eb5ee0e 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -281,7 +281,7 @@ static ssize_t asd_show_dev_rev(struct device *dev,
 	return snprintf(buf, PAGE_SIZE, "%s\n",
 			asd_dev_rev[asd_ha->revision_id]);
 }
-static DEVICE_ATTR(revision, S_IRUGO, asd_show_dev_rev, NULL);
+static DEVICE_ATTR(aic_revision, S_IRUGO, asd_show_dev_rev, NULL);
 
 static ssize_t asd_show_dev_bios_build(struct device *dev,
 				       struct device_attribute *attr,char *buf)
@@ -478,7 +478,7 @@ static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
 {
 	int err;
 
-	err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+	err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
 	if (err)
 		return err;
 
@@ -500,13 +500,13 @@ static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
 err_biosb:
 	device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
 err_rev:
-	device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+	device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
 	return err;
 }
 
 static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha)
 {
-	device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+	device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
 	device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
 	device_remove_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn);
 	device_remove_file(&asd_ha->pcidev->dev, &dev_attr_update_bios);
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 6844ba3..89f09b1 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -2372,7 +2372,7 @@ static int _bnx2fc_create(struct net_device *netdev,
 	if (!interface) {
 		printk(KERN_ERR PFX "bnx2fc_interface_create failed\n");
 		rc = -ENOMEM;
-		goto ifput_err;
+		goto netdev_err;
 	}
 
 	if (is_vlan_dev(netdev)) {
diff --git a/drivers/scsi/csiostor/csio_attr.c b/drivers/scsi/csiostor/csio_attr.c
index 2d1c4eb..6587f20 100644
--- a/drivers/scsi/csiostor/csio_attr.c
+++ b/drivers/scsi/csiostor/csio_attr.c
@@ -582,12 +582,12 @@ csio_vport_create(struct fc_vport *fc_vport, bool disable)
 	}
 
 	fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
+	ln->fc_vport = fc_vport;
 
 	if (csio_fcoe_alloc_vnp(hw, ln))
 		goto error;
 
 	*(struct csio_lnode **)fc_vport->dd_data = ln;
-	ln->fc_vport = fc_vport;
 	if (!fc_vport->node_name)
 		fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
 	if (!fc_vport->port_name)
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 737314ca..b37149e 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -3659,6 +3659,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
 	host->max_cmd_len = CXLFLASH_MAX_CDB_LEN;
 
 	cfg = shost_priv(host);
+	cfg->state = STATE_PROBING;
 	cfg->host = host;
 	rc = alloc_mem(cfg);
 	if (rc) {
@@ -3741,6 +3742,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
 	return rc;
 
 out_remove:
+	cfg->state = STATE_PROBED;
 	cxlflash_remove(pdev);
 	goto out;
 }
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 922e3e5..c71e0f3 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -591,6 +591,13 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
 	shost->max_lun = ~0;
 	shost->max_cmd_len = MAX_COMMAND_SIZE;
 
+	/* turn on DIF support */
+	scsi_host_set_prot(shost,
+			   SHOST_DIF_TYPE1_PROTECTION |
+			   SHOST_DIF_TYPE2_PROTECTION |
+			   SHOST_DIF_TYPE3_PROTECTION);
+	scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
+
 	err = scsi_add_host(shost, &pdev->dev);
 	if (err)
 		goto err_shost;
@@ -678,13 +685,6 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 			goto err_host_alloc;
 		}
 		pci_info->hosts[i] = h;
-
-		/* turn on DIF support */
-		scsi_host_set_prot(to_shost(h),
-				   SHOST_DIF_TYPE1_PROTECTION |
-				   SHOST_DIF_TYPE2_PROTECTION |
-				   SHOST_DIF_TYPE3_PROTECTION);
-		scsi_host_set_guard(to_shost(h), SHOST_DIX_GUARD_CRC);
 	}
 
 	err = isci_setup_interrupts(pdev);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index e2ea389..56dec66 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -829,6 +829,7 @@ static struct domain_device *sas_ex_discover_end_dev(
 		rphy = sas_end_device_alloc(phy->port);
 		if (!rphy)
 			goto out_free;
+		rphy->identify.phy_identifier = phy_id;
 
 		child->rphy = rphy;
 		get_device(&rphy->dev);
@@ -856,6 +857,7 @@ static struct domain_device *sas_ex_discover_end_dev(
 
 		child->rphy = rphy;
 		get_device(&rphy->dev);
+		rphy->identify.phy_identifier = phy_id;
 		sas_fill_in_rphy(child, rphy);
 
 		list_add_tail(&child->disco_list_node, &parent->port->disco_list);
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 91783db..57cddbc 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -242,6 +242,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
 		icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
 		if (elscmd == ELS_CMD_FLOGI)
 			icmd->ulpTimeout = FF_DEF_RATOV * 2;
+		else if (elscmd == ELS_CMD_LOGO)
+			icmd->ulpTimeout = phba->fc_ratov;
 		else
 			icmd->ulpTimeout = phba->fc_ratov * 2;
 	} else {
@@ -2674,16 +2676,15 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 		goto out;
 	}
 
+	/* The LOGO will not be retried on failure.  A LOGO was
+	 * issued to the remote rport and a ACC or RJT or no Answer are
+	 * all acceptable.  Note the failure and move forward with
+	 * discovery.  The PLOGI will retry.
+	 */
 	if (irsp->ulpStatus) {
-		/* Check for retry */
-		if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
-			/* ELS command is being retried */
-			skip_recovery = 1;
-			goto out;
-		}
 		/* LOGO failed */
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
-				 "2756 LOGO failure DID:%06X Status:x%x/x%x\n",
+				 "2756 LOGO failure, No Retry DID:%06X Status:x%x/x%x\n",
 				 ndlp->nlp_DID, irsp->ulpStatus,
 				 irsp->un.ulpWord[4]);
 		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
@@ -2729,7 +2730,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 	 * For any other port type, the rpi is unregistered as an implicit
 	 * LOGO.
 	 */
-	if ((ndlp->nlp_type & NLP_FCP_TARGET) && (skip_recovery == 0)) {
+	if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET) &&
+	    skip_recovery == 0) {
 		lpfc_cancel_retry_delay_tmo(vport, ndlp);
 		spin_lock_irqsave(shost->host_lock, flags);
 		ndlp->nlp_flag |= NLP_NPR_2B_DISC;
@@ -2762,6 +2764,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
  * will be stored into the context1 field of the IOCB for the completion
  * callback function to the LOGO ELS command.
  *
+ * Callers of this routine are expected to unregister the RPI first
+ *
  * Return code
  *   0 - successfully issued logo
  *   1 - failed to issue logo
@@ -2803,22 +2807,6 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 		"Issue LOGO:      did:x%x",
 		ndlp->nlp_DID, 0, 0);
 
-	/*
-	 * If we are issuing a LOGO, we may try to recover the remote NPort
-	 * by issuing a PLOGI later. Even though we issue ELS cmds by the
-	 * VPI, if we have a valid RPI, and that RPI gets unreg'ed while
-	 * that ELS command is in-flight, the HBA returns a IOERR_INVALID_RPI
-	 * for that ELS cmd. To avoid this situation, lets get rid of the
-	 * RPI right now, before any ELS cmds are sent.
-	 */
-	spin_lock_irq(shost->host_lock);
-	ndlp->nlp_flag |= NLP_ISSUE_LOGO;
-	spin_unlock_irq(shost->host_lock);
-	if (lpfc_unreg_rpi(vport, ndlp)) {
-		lpfc_els_free_iocb(phba, elsiocb);
-		return 0;
-	}
-
 	phba->fc_stat.elsXmitLOGO++;
 	elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
 	spin_lock_irq(shost->host_lock);
@@ -2826,7 +2814,6 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 	ndlp->nlp_flag &= ~NLP_ISSUE_LOGO;
 	spin_unlock_irq(shost->host_lock);
 	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
-
 	if (rc == IOCB_ERROR) {
 		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_LOGO_SND;
@@ -2834,6 +2821,11 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 		lpfc_els_free_iocb(phba, elsiocb);
 		return 1;
 	}
+
+	spin_lock_irq(shost->host_lock);
+	ndlp->nlp_prev_state = ndlp->nlp_state;
+	spin_unlock_irq(shost->host_lock);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE);
 	return 0;
 }
 
@@ -5696,6 +5688,9 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 	stat = (struct ls_rjt *)(pcmd + sizeof(uint32_t));
 	stat->un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 
+	if (shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE)
+		stat->un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
+
 	elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
 	phba->fc_stat.elsXmitLSRJT++;
 	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
@@ -9480,7 +9475,8 @@ lpfc_sli_abts_recover_port(struct lpfc_vport *vport,
 				"rport in state 0x%x\n", ndlp->nlp_state);
 		return;
 	}
-	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+	lpfc_printf_log(phba, KERN_ERR,
+			LOG_ELS | LOG_FCP_ERROR | LOG_NVME_IOERR,
 			"3094 Start rport recovery on shost id 0x%x "
 			"fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x "
 			"flags 0x%x\n",
@@ -9493,8 +9489,8 @@ lpfc_sli_abts_recover_port(struct lpfc_vport *vport,
 	 */
 	spin_lock_irqsave(shost->host_lock, flags);
 	ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
+	ndlp->nlp_flag |= NLP_ISSUE_LOGO;
 	spin_unlock_irqrestore(shost->host_lock, flags);
-	lpfc_issue_els_logo(vport, ndlp, 0);
-	lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE);
+	lpfc_unreg_rpi(vport, ndlp);
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index d489f68..36fb549 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -801,7 +801,9 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 
 	if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
+		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+		spin_unlock_irq(shost->host_lock);
 		return 0;
 	}
 
@@ -816,7 +818,10 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 			return 1;
 		}
 	}
+
+	spin_lock_irq(shost->host_lock);
 	ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+	spin_unlock_irq(shost->host_lock);
 	lpfc_unreg_rpi(vport, ndlp);
 	return 0;
 }
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 24b6e56..6c2b098 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -13941,7 +13941,8 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size,
 			hw_page_size))/hw_page_size;
 
 	/* If needed, Adjust page count to match the max the adapter supports */
-	if (queue->page_count > phba->sli4_hba.pc_sli4_params.wqpcnt)
+	if (phba->sli4_hba.pc_sli4_params.wqpcnt &&
+	    (queue->page_count > phba->sli4_hba.pc_sli4_params.wqpcnt))
 		queue->page_count = phba->sli4_hba.pc_sli4_params.wqpcnt;
 
 	INIT_LIST_HEAD(&queue->list);
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index f2ffde4..9a2a62e3 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -1266,7 +1266,7 @@ void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *drv_map,
 
 	for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) {
 		ld = MR_TargetIdToLdGet(ldCount, drv_map);
-		if (ld >= MAX_LOGICAL_DRIVES_EXT) {
+		if (ld >= MAX_LOGICAL_DRIVES_EXT - 1) {
 			lbInfo[ldCount].loadBalanceFlag = 0;
 			continue;
 		}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 06a2e3d..7be2b9e 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -2529,7 +2529,7 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance,
 		device_id < instance->fw_supported_vd_count)) {
 
 		ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
-		if (ld >= instance->fw_supported_vd_count)
+		if (ld >= instance->fw_supported_vd_count - 1)
 			fp_possible = 0;
 		else {
 			raid = MR_LdRaidGet(ld, local_map_ptr);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index decf9d5..83640d9 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -8260,6 +8260,7 @@ static void scsih_remove(struct pci_dev *pdev)
 
 	/* release all the volumes */
 	_scsih_ir_shutdown(ioc);
+	sas_remove_host(shost);
 	list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
 	    list) {
 		if (raid_device->starget) {
@@ -8296,7 +8297,6 @@ static void scsih_remove(struct pci_dev *pdev)
 		ioc->sas_hba.num_phys = 0;
 	}
 
-	sas_remove_host(shost);
 	mpt3sas_base_detach(ioc);
 	spin_lock(&gioc_lock);
 	list_del(&ioc->list);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index 63dd9bc..66d9f04 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -846,10 +846,13 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
 			    mpt3sas_port->remote_identify.sas_address,
 			    mpt3sas_phy->phy_id);
 		mpt3sas_phy->phy_belongs_to_port = 0;
-		sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
+		if (!ioc->remove_host)
+			sas_port_delete_phy(mpt3sas_port->port,
+						mpt3sas_phy->phy);
 		list_del(&mpt3sas_phy->port_siblings);
 	}
-	sas_port_delete(mpt3sas_port->port);
+	if (!ioc->remove_host)
+		sas_port_delete(mpt3sas_port->port);
 	kfree(mpt3sas_port);
 }
 
diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c
index a02b34e..45f044f 100644
--- a/drivers/scsi/qedi/qedi_iscsi.c
+++ b/drivers/scsi/qedi/qedi_iscsi.c
@@ -961,6 +961,7 @@ static int qedi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
 
 	qedi_ep = ep->dd_data;
 	if (qedi_ep->state == EP_STATE_IDLE ||
+	    qedi_ep->state == EP_STATE_OFLDCONN_NONE ||
 	    qedi_ep->state == EP_STATE_OFLDCONN_FAILED)
 		return -1;
 
@@ -1043,6 +1044,7 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
 
 	switch (qedi_ep->state) {
 	case EP_STATE_OFLDCONN_START:
+	case EP_STATE_OFLDCONN_NONE:
 		goto ep_release_conn;
 	case EP_STATE_OFLDCONN_FAILED:
 			break;
@@ -1233,6 +1235,7 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
 
 	if (!is_valid_ether_addr(&path_data->mac_addr[0])) {
 		QEDI_NOTICE(&qedi->dbg_ctx, "dst mac NOT VALID\n");
+		qedi_ep->state = EP_STATE_OFLDCONN_NONE;
 		ret = -EIO;
 		goto set_path_exit;
 	}
diff --git a/drivers/scsi/qedi/qedi_iscsi.h b/drivers/scsi/qedi/qedi_iscsi.h
index 3247287..812b4b6 100644
--- a/drivers/scsi/qedi/qedi_iscsi.h
+++ b/drivers/scsi/qedi/qedi_iscsi.h
@@ -59,6 +59,7 @@ enum {
 	EP_STATE_OFLDCONN_FAILED        = 0x2000,
 	EP_STATE_CONNECT_FAILED         = 0x4000,
 	EP_STATE_DISCONN_TIMEDOUT       = 0x8000,
+	EP_STATE_OFLDCONN_NONE          = 0x10000,
 };
 
 struct qedi_conn;
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index a6aa08d..22dc70a 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -7241,6 +7241,8 @@ static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha,
 
 	rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn,
 					   fw_ddb_entry);
+	if (rc)
+		goto free_sess;
 
 	ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n",
 		   __func__, fnode_sess->dev.kobj.name);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 99e3b25..a4bd6f9 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -206,6 +206,12 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
 	sp = buffer_data[0] & 0x80 ? 1 : 0;
 	buffer_data[0] &= ~0x80;
 
+	/*
+	 * Ensure WP, DPOFUA, and RESERVED fields are cleared in
+	 * received mode parameter buffer before doing MODE SELECT.
+	 */
+	data.device_specific = 0;
+
 	if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
 			     SD_MAX_RETRIES, &data, &sshdr)) {
 		if (scsi_sense_valid(&sshdr))
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index 83bdbd84..5ec2898 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -653,6 +653,7 @@ struct bmic_host_wellness_driver_version {
 	u8	driver_version_tag[2];
 	__le16	driver_version_length;
 	char	driver_version[32];
+	u8	dont_write_tag[2];
 	u8	end_tag[2];
 };
 
@@ -682,6 +683,8 @@ static int pqi_write_driver_version_to_host_wellness(
 	strncpy(buffer->driver_version, "Linux " DRIVER_VERSION,
 		sizeof(buffer->driver_version) - 1);
 	buffer->driver_version[sizeof(buffer->driver_version) - 1] = '\0';
+	buffer->dont_write_tag[0] = 'D';
+	buffer->dont_write_tag[1] = 'W';
 	buffer->end_tag[0] = 'Z';
 	buffer->end_tag[1] = 'Z';
 
@@ -1181,6 +1184,9 @@ static void pqi_get_volume_status(struct pqi_ctrl_info *ctrl_info,
 	if (rc)
 		goto out;
 
+	if (vpd->page_code != CISS_VPD_LV_STATUS)
+		goto out;
+
 	page_length = offsetof(struct ciss_vpd_logical_volume_status,
 		volume_status) + vpd->page_length;
 	if (page_length < sizeof(*vpd))
@@ -2709,6 +2715,9 @@ static unsigned int pqi_process_io_intr(struct pqi_ctrl_info *ctrl_info,
 		switch (response->header.iu_type) {
 		case PQI_RESPONSE_IU_RAID_PATH_IO_SUCCESS:
 		case PQI_RESPONSE_IU_AIO_PATH_IO_SUCCESS:
+			if (io_request->scmd)
+				io_request->scmd->result = 0;
+			/* fall through */
 		case PQI_RESPONSE_IU_GENERAL_MANAGEMENT:
 			break;
 		case PQI_RESPONSE_IU_TASK_MANAGEMENT:
@@ -6700,6 +6709,7 @@ static void pqi_shutdown(struct pci_dev *pci_dev)
 	 * storage.
 	 */
 	rc = pqi_flush_cache(ctrl_info, SHUTDOWN);
+	pqi_free_interrupts(ctrl_info);
 	pqi_reset(ctrl_info);
 	if (rc == 0)
 		return;
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c
index 5141bd4..ca7dfb3 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
+++ b/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -59,7 +59,7 @@
 
 #define SIS_CTRL_KERNEL_UP			0x80
 #define SIS_CTRL_KERNEL_PANIC			0x100
-#define SIS_CTRL_READY_TIMEOUT_SECS		30
+#define SIS_CTRL_READY_TIMEOUT_SECS		180
 #define SIS_CTRL_READY_RESUME_TIMEOUT_SECS	90
 #define SIS_CTRL_READY_POLL_INTERVAL_MSECS	10
 
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index 656e3be..1ec66a6 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.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
@@ -389,6 +389,7 @@ static const struct file_operations ufsdbg_err_inj_scenario_ops = {
 	.open		= ufsdbg_err_inj_scenario_open,
 	.read		= seq_read,
 	.write		= ufsdbg_err_inj_scenario_write,
+	.release	= single_release,
 };
 
 static int ufsdbg_err_inj_stats_read(struct seq_file *file, void *data)
@@ -430,6 +431,7 @@ static const struct file_operations ufsdbg_err_inj_stats_ops = {
 	.open		= ufsdbg_err_inj_stats_open,
 	.read		= seq_read,
 	.write		= ufsdbg_err_inj_stats_write,
+	.release	= single_release,
 };
 
 static void ufsdbg_setup_fault_injection(struct ufs_hba *hba)
@@ -614,6 +616,7 @@ static const struct file_operations ufsdbg_tag_stats_fops = {
 	.open		= ufsdbg_tag_stats_open,
 	.read		= seq_read,
 	.write		= ufsdbg_tag_stats_write,
+	.release	= single_release,
 };
 
 static int ufsdbg_query_stats_show(struct seq_file *file, void *data)
@@ -685,6 +688,7 @@ static const struct file_operations ufsdbg_query_stats_fops = {
 	.open		= ufsdbg_query_stats_open,
 	.read		= seq_read,
 	.write		= ufsdbg_query_stats_write,
+	.release	= single_release,
 };
 
 static int ufsdbg_err_stats_show(struct seq_file *file, void *data)
@@ -789,6 +793,7 @@ static const struct file_operations ufsdbg_err_stats_fops = {
 	.open		= ufsdbg_err_stats_open,
 	.read		= seq_read,
 	.write		= ufsdbg_err_stats_write,
+	.release	= single_release,
 };
 
 static int ufshcd_init_statistics(struct ufs_hba *hba)
@@ -868,6 +873,7 @@ static int ufsdbg_host_regs_open(struct inode *inode, struct file *file)
 static const struct file_operations ufsdbg_host_regs_fops = {
 	.open		= ufsdbg_host_regs_open,
 	.read		= seq_read,
+	.release	= single_release,
 };
 
 static int ufsdbg_dump_device_desc_show(struct seq_file *file, void *data)
@@ -1032,6 +1038,7 @@ static int ufsdbg_show_hba_open(struct inode *inode, struct file *file)
 static const struct file_operations ufsdbg_show_hba_fops = {
 	.open		= ufsdbg_show_hba_open,
 	.read		= seq_read,
+	.release	= single_release,
 };
 
 static int ufsdbg_dump_device_desc_open(struct inode *inode, struct file *file)
@@ -1043,6 +1050,7 @@ static int ufsdbg_dump_device_desc_open(struct inode *inode, struct file *file)
 static const struct file_operations ufsdbg_dump_device_desc = {
 	.open		= ufsdbg_dump_device_desc_open,
 	.read		= seq_read,
+	.release	= single_release,
 };
 
 static int ufsdbg_power_mode_show(struct seq_file *file, void *data)
@@ -1204,8 +1212,8 @@ static int ufsdbg_config_pwr_mode(struct ufs_hba *hba,
 	/* let's not get into low power until clock scaling is completed */
 	hba->ufs_stats.clk_hold.ctx = DBGFS_CFG_PWR_MODE;
 	ufshcd_hold(hba, false);
-	ufshcd_scsi_block_requests(hba);
 	down_write(&hba->lock);
+	ufshcd_scsi_block_requests(hba);
 	if (ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) {
 		ret = -EBUSY;
 		goto out;
@@ -1330,6 +1338,7 @@ static const struct file_operations ufsdbg_power_mode_desc = {
 	.open		= ufsdbg_power_mode_open,
 	.read		= seq_read,
 	.write		= ufsdbg_power_mode_write,
+	.release	= single_release,
 };
 
 static int ufsdbg_dme_read(void *data, u64 *attr_val, bool peer)
@@ -1509,6 +1518,7 @@ static const struct file_operations ufsdbg_req_stats_desc = {
 	.open		= ufsdbg_req_stats_open,
 	.read		= seq_read,
 	.write		= ufsdbg_req_stats_write,
+	.release	= single_release,
 };
 
 
@@ -1557,6 +1567,7 @@ static const struct file_operations ufsdbg_reset_controller = {
 	.open		= ufsdbg_reset_controller_open,
 	.read		= seq_read,
 	.write		= ufsdbg_reset_controller_write,
+	.release	= single_release,
 };
 
 static int ufsdbg_clear_err_state(void *data, u64 val)
diff --git a/drivers/scsi/ufs/ufs-qcom-debugfs.c b/drivers/scsi/ufs/ufs-qcom-debugfs.c
index bc5b6b1..8e84530 100644
--- a/drivers/scsi/ufs/ufs-qcom-debugfs.c
+++ b/drivers/scsi/ufs/ufs-qcom-debugfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015,2017, Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019 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
@@ -186,6 +186,7 @@ static const struct file_operations ufs_qcom_dbg_testbus_cfg_desc = {
 	.open		= ufs_qcom_dbg_testbus_cfg_open,
 	.read		= seq_read,
 	.write		= ufs_qcom_dbg_testbus_cfg_write,
+	.release	= single_release,
 };
 
 static int ufs_qcom_dbg_testbus_bus_read(void *data, u64 *attr_val)
@@ -240,6 +241,7 @@ static int ufs_qcom_dbg_dbg_regs_open(struct inode *inode,
 static const struct file_operations ufs_qcom_dbg_dbg_regs_desc = {
 	.open		= ufs_qcom_dbg_dbg_regs_open,
 	.read		= seq_read,
+	.release	= single_release,
 };
 
 static int ufs_qcom_dbg_pm_qos_show(struct seq_file *file, void *data)
@@ -273,6 +275,7 @@ static int ufs_qcom_dbg_pm_qos_open(struct inode *inode,
 static const struct file_operations ufs_qcom_dbg_pm_qos_desc = {
 	.open		= ufs_qcom_dbg_pm_qos_open,
 	.read		= seq_read,
+	.release	= single_release,
 };
 
 void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root)
diff --git a/drivers/scsi/ufs/ufs_test.c b/drivers/scsi/ufs/ufs_test.c
index 1bcc55f..92b3485 100644
--- a/drivers/scsi/ufs/ufs_test.c
+++ b/drivers/scsi/ufs/ufs_test.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, 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
@@ -74,6 +74,7 @@ const struct file_operations ufs_test_ ## test_name ## _ops = {		\
 	.open = ufs_test_ ## test_name ## _open,			\
 	.read = seq_read,						\
 	.write = ufs_test_ ## test_name ## _write,			\
+	.release = single_release,					\
 };
 
 #define add_test(utd, test_name, upper_case_name)			\
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c2a2ff2..de19b9f 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1746,8 +1746,8 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)
 	 * make sure that there are no outstanding requests when
 	 * clock scaling is in progress
 	 */
-	ufshcd_scsi_block_requests(hba);
 	down_write(&hba->lock);
+	ufshcd_scsi_block_requests(hba);
 	if (ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) {
 		ret = -EBUSY;
 		up_write(&hba->lock);
@@ -2766,8 +2766,8 @@ static void __ufshcd_set_auto_hibern8_timer(struct ufs_hba *hba,
 {
 	pm_runtime_get_sync(hba->dev);
 	ufshcd_hold_all(hba);
-	ufshcd_scsi_block_requests(hba);
 	down_write(&hba->lock);
+	ufshcd_scsi_block_requests(hba);
 	/* wait for all the outstanding requests to finish */
 	ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
 	ufshcd_set_auto_hibern8_timer(hba, delay_ms);
@@ -4068,6 +4068,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
 	int tag;
 	struct completion wait;
 	unsigned long flags;
+	bool has_read_lock = false;
 
 	/*
 	 * May get invoked from shutdown and IOCTL contexts.
@@ -4075,8 +4076,10 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
 	 * In error recovery context, it may come with lock acquired.
 	 */
 
-	if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba))
+	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.
@@ -4110,7 +4113,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
 out_put_tag:
 	ufshcd_put_dev_cmd_tag(hba, tag);
 	wake_up(&hba->dev_cmd.tag_wq);
-	if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba))
+	if (has_read_lock)
 		up_read(&hba->lock);
 	return err;
 }
@@ -7154,8 +7157,10 @@ static void ufshcd_rls_handler(struct work_struct *work)
 
 	hba = container_of(work, struct ufs_hba, rls_work);
 	pm_runtime_get_sync(hba->dev);
-	ufshcd_scsi_block_requests(hba);
 	down_write(&hba->lock);
+	ufshcd_scsi_block_requests(hba);
+	if (ufshcd_is_shutdown_ongoing(hba))
+		goto out;
 	ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
 	if (ret) {
 		dev_err(hba->dev,
@@ -7693,7 +7698,10 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
 	 * To avoid these unnecessary/illegal step we skip to the last error
 	 * handling stage: reset and restore.
 	 */
-	if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN)
+	if ((lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) ||
+	    (lrbp->lun == UFS_UPIU_REPORT_LUNS_WLUN) ||
+	    (lrbp->lun == UFS_UPIU_BOOT_WLUN) ||
+	    (lrbp->lun == UFS_UPIU_RPMB_WLUN))
 		return ufshcd_eh_host_reset_handler(cmd);
 
 	ufshcd_hold_all(hba);
@@ -7912,6 +7920,8 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba)
 	unsigned long flags;
 	int retries = MAX_HOST_RESET_RETRIES;
 
+	ufshcd_enable_irq(hba);
+
 	do {
 		err = ufshcd_detect_device(hba);
 	} while (err && --retries);
@@ -9199,7 +9209,7 @@ static int ufshcd_query_ioctl(struct ufs_hba *hba, u8 lun, void __user *buffer)
 		switch (ioctl_data->idn) {
 		case QUERY_ATTR_IDN_BOOT_LU_EN:
 			index = 0;
-			if (att > QUERY_ATTR_IDN_BOOT_LU_EN_MAX) {
+			if (!att || att > QUERY_ATTR_IDN_BOOT_LU_EN_MAX) {
 				dev_err(hba->dev,
 					"%s: Illegal ufs query ioctl data, opcode 0x%x, idn 0x%x, att 0x%x\n",
 					__func__, ioctl_data->opcode,
@@ -10440,6 +10450,8 @@ int ufshcd_system_resume(struct ufs_hba *hba)
 	trace_ufshcd_system_resume(dev_name(hba->dev), ret,
 		ktime_to_us(ktime_sub(ktime_get(), start)),
 		hba->curr_dev_pwr_mode, hba->uic_link_state);
+	if (!ret)
+		hba->is_sys_suspended = false;
 	return ret;
 }
 EXPORT_SYMBOL(ufshcd_system_resume);
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 8607889..0596f95 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.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
@@ -2098,7 +2098,18 @@ static int ngd_slim_runtime_suspend(struct device *device)
 	int ret = 0;
 
 	mutex_lock(&dev->tx_lock);
-	ret = ngd_slim_power_down(dev);
+	if (dev->qmi.handle != NULL) {
+		ret = ngd_slim_power_down(dev);
+	} else {
+		if (dev->state == MSM_CTRL_DOWN)
+			SLIM_INFO(dev, "SB rt suspend in SSR: %d\n",
+								dev->state);
+		else
+			SLIM_INFO(dev, "SB rt suspend bad state: %d\n",
+								dev->state);
+		mutex_unlock(&dev->tx_lock);
+		return ret;
+	}
 	if (ret && ret != -EBUSY)
 		SLIM_INFO(dev, "slim resource not idle:%d\n", ret);
 	if (!ret || ret == -ETIMEDOUT)
diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c
index 22e98a9..2f5ec42 100644
--- a/drivers/soc/bcm/brcmstb/common.c
+++ b/drivers/soc/bcm/brcmstb/common.c
@@ -31,13 +31,17 @@ static const struct of_device_id brcmstb_machine_match[] = {
 
 bool soc_is_brcmstb(void)
 {
+	const struct of_device_id *match;
 	struct device_node *root;
 
 	root = of_find_node_by_path("/");
 	if (!root)
 		return false;
 
-	return of_match_node(brcmstb_machine_match, root) != NULL;
+	match = of_match_node(brcmstb_machine_match, root);
+	of_node_put(root);
+
+	return match != NULL;
 }
 
 static const struct of_device_id sun_top_ctrl_match[] = {
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 5baf1a1..2289d1c 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -102,6 +102,14 @@
 	  data required to configure LLCC so that clients can start using the
 	  LLCC slices.
 
+config QCOM_ATOLL_LLCC
+	tristate "Qualcomm Technologies, Inc. ATOLL LLCC driver"
+	depends on QCOM_LLCC
+	help
+	  Say yes here to enable the LLCC driver for ATOLL. This provides
+	  data required to configure LLCC so that clients can start using the
+	  LLCC slices.
+
 config QCOM_SDXPRAIRIE_LLCC
 	tristate "Qualcomm Technologies, Inc. SDXPRAIRIE LLCC driver"
 	depends on QCOM_LLCC
@@ -152,7 +160,7 @@
 
 config QCOM_QMI_HELPERS
 	bool "Qualcomm QMI Helpers"
-	depends on QRTR
+	depends on QRTR || QTI_QRTR
 	help
 	  Helper library for handling QMI encoded messages.  QMI encoded
 	  messages are used in communication between the majority of QRTR
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 5b618bd..e5b6e43 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_QCOM_SDMSHRIKE_LLCC) += llcc-sdmshrike.o
 obj-$(CONFIG_QCOM_SDXPRAIRIE_LLCC) += llcc-sdxprairie.o
 obj-$(CONFIG_QCOM_SM6150_LLCC) += llcc-sm6150.o
+obj-$(CONFIG_QCOM_ATOLL_LLCC) += llcc-atoll.o
 obj-$(CONFIG_QCOM_LLCC_PERFMON) += llcc_perfmon.o
 obj-$(CONFIG_QCOM_SDMMAGPIE_LLCC) += llcc-sdmmagpie.o
 obj-$(CONFIG_QCOM_LLCC_AMON) += llcc-amon.o
diff --git a/drivers/soc/qcom/cdsprm.c b/drivers/soc/qcom/cdsprm.c
index c021c37..90c8ff63 100644
--- a/drivers/soc/qcom/cdsprm.c
+++ b/drivers/soc/qcom/cdsprm.c
@@ -1,7 +1,7 @@
 /*
  * CDSP Request Manager
  *
- * 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
@@ -398,21 +398,22 @@ static int cdsprm_thermal_cdsp_clk_limit(unsigned int level)
 	struct sysmon_msg_tx rpmsg_msg_tx;
 
 	mutex_lock(&gcdsprm.thermal_lock);
-	gcdsprm.thermal_cdsp_level = level;
 
 	if (gcdsprm.rpmsgdev && gcdsprm.cdsp_version) {
 		rpmsg_msg_tx.feature_id =
 			SYSMON_CDSP_FEATURE_THERMAL_LIMIT_TX;
 		rpmsg_msg_tx.fs.thermal.hvx_level =
 			gcdsprm.thermal_hvx_level;
-		rpmsg_msg_tx.fs.thermal.cdsp_level =
-			gcdsprm.thermal_cdsp_level;
+		rpmsg_msg_tx.fs.thermal.cdsp_level = level;
 		rpmsg_msg_tx.size = sizeof(rpmsg_msg_tx);
 		result = rpmsg_send(gcdsprm.rpmsgdev->ept,
 					&rpmsg_msg_tx,
 					sizeof(rpmsg_msg_tx));
 	}
 
+	if (result == 0)
+		gcdsprm.thermal_cdsp_level = level;
+
 	mutex_unlock(&gcdsprm.thermal_lock);
 
 	return result;
@@ -424,21 +425,22 @@ static int cdsprm_thermal_hvx_instruction_limit(unsigned int level)
 	struct sysmon_msg_tx rpmsg_msg_tx;
 
 	mutex_lock(&gcdsprm.thermal_lock);
-	gcdsprm.thermal_hvx_level = level;
 
 	if (gcdsprm.rpmsgdev && gcdsprm.cdsp_version) {
 		rpmsg_msg_tx.feature_id =
 			SYSMON_CDSP_FEATURE_THERMAL_LIMIT_TX;
-		rpmsg_msg_tx.fs.thermal.hvx_level =
-			gcdsprm.thermal_hvx_level;
+		rpmsg_msg_tx.fs.thermal.hvx_level = level;
 		rpmsg_msg_tx.fs.thermal.cdsp_level =
-			gcdsprm.thermal_cdsp_level;
+				gcdsprm.thermal_cdsp_level;
 		rpmsg_msg_tx.size = sizeof(rpmsg_msg_tx);
 		result = rpmsg_send(gcdsprm.rpmsgdev->ept,
 				&rpmsg_msg_tx,
 				sizeof(rpmsg_msg_tx));
 	}
 
+	if (result == 0)
+		gcdsprm.thermal_hvx_level = level;
+
 	mutex_unlock(&gcdsprm.thermal_lock);
 
 	return result;
@@ -857,6 +859,9 @@ static int cdsp_get_cur_state(struct thermal_cooling_device *cdev,
 static int cdsp_set_cur_state(struct thermal_cooling_device *cdev,
 				unsigned long state)
 {
+	if (gcdsprm.thermal_cdsp_level == state)
+		return 0;
+
 	cdsprm_thermal_cdsp_clk_limit(state);
 
 	return 0;
@@ -887,6 +892,9 @@ static int hvx_get_cur_state(struct thermal_cooling_device *cdev,
 static int hvx_set_cur_state(struct thermal_cooling_device *cdev,
 				unsigned long state)
 {
+	if (gcdsprm.thermal_hvx_level == state)
+		return 0;
+
 	cdsprm_thermal_hvx_instruction_limit(state);
 
 	return 0;
diff --git a/drivers/soc/qcom/cx_ipeak.c b/drivers/soc/qcom/cx_ipeak.c
index 1abe3a0..cfc834a 100644
--- a/drivers/soc/qcom/cx_ipeak.c
+++ b/drivers/soc/qcom/cx_ipeak.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
@@ -124,8 +124,9 @@ static struct cx_ipeak_client *cx_ipeak_register_v2(int client_id)
 	struct cx_ipeak_client *client;
 	unsigned int client_offset = 0;
 	void __iomem *vptr = device_ipeak.tcsr_vptr;
+	int i;
 
-	for (int i = 0; i <= client_id; i++)
+	for (i = 0; i <= client_id; i++)
 		client_offset += CXIP_CLIENT_OFFSET;
 
 	reg_enable = readl_relaxed(device_ipeak.tcsr_vptr +
diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c
index a9cb6f5..cf3aaa6 100644
--- a/drivers/soc/qcom/dcc_v2.c
+++ b/drivers/soc/qcom/dcc_v2.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
@@ -149,6 +149,7 @@ struct dcc_drvdata {
 	uint32_t		nr_config[DCC_MAX_LINK_LIST];
 	uint8_t			curr_list;
 	uint8_t			cti_trig;
+	uint8_t			loopoff;
 };
 
 static int dcc_sram_writel(struct dcc_drvdata *drvdata,
@@ -271,7 +272,6 @@ static int __dcc_ll_cfg(struct dcc_drvdata *drvdata, int curr_list)
 				/* write new offset = 1 to continue
 				 * processing the list
 				 */
-				link |= ((0x1 << 8) & BM(8, 14));
 				ret = dcc_sram_writel(drvdata,
 							link, sram_offset);
 				if (ret)
@@ -318,7 +318,8 @@ static int __dcc_ll_cfg(struct dcc_drvdata *drvdata, int curr_list)
 
 			if (loop_start) {
 				loop = (sram_offset - loop_off) / 4;
-				loop |= (loop_cnt << 13) & BM(13, 27);
+				loop |= (loop_cnt << drvdata->loopoff) &
+					BM(drvdata->loopoff, 27);
 				loop |= DCC_LOOP_DESCRIPTOR;
 				total_len += (total_len - loop_len) * loop_cnt;
 
@@ -353,7 +354,6 @@ static int __dcc_ll_cfg(struct dcc_drvdata *drvdata, int curr_list)
 				/* write new offset = 1 to continue
 				 * processing the list
 				 */
-				link |= ((0x1 << 8) & BM(8, 14));
 				ret = dcc_sram_writel(drvdata,
 						link, sram_offset);
 				if (ret)
@@ -1694,6 +1694,8 @@ static int dcc_probe(struct platform_device *pdev)
 	if (ret)
 		return -EINVAL;
 
+	drvdata->loopoff = get_bitmask_order((drvdata->ram_size +
+				drvdata->ram_offset) / 4 - 1);
 	mutex_init(&drvdata->mutex);
 
 	for (i = 0; i < DCC_MAX_LINK_LIST; i++) {
diff --git a/drivers/soc/qcom/dfc_qmi.c b/drivers/soc/qcom/dfc_qmi.c
index acb5ac4..4a9ad70 100644
--- a/drivers/soc/qcom/dfc_qmi.c
+++ b/drivers/soc/qcom/dfc_qmi.c
@@ -15,11 +15,17 @@
 #include <net/pkt_sched.h>
 #include <linux/soc/qcom/qmi.h>
 #include <soc/qcom/rmnet_qmi.h>
+#include <soc/qcom/qmi_rmnet.h>
 
 #include "qmi_rmnet_i.h"
 #define CREATE_TRACE_POINTS
 #include <trace/events/dfc.h>
 
+#define DFC_MASK_TCP_BIDIR 0x1
+#define DFC_MASK_RAT_SWITCH 0x2
+#define DFC_IS_TCP_BIDIR(r) (bool)((r) & DFC_MASK_TCP_BIDIR)
+#define DFC_IS_RAT_SWITCH(r) (bool)((r) & DFC_MASK_RAT_SWITCH)
+
 #define DFC_IS_ANCILLARY(type) ((type) != AF_INET && (type) != AF_INET6)
 
 #define DFC_MAX_QOS_ID_V01 2
@@ -79,11 +85,13 @@ static void dfc_svc_init(struct work_struct *work);
 
 #define QMI_DFC_INDICATION_REGISTER_REQ_V01 0x0001
 #define QMI_DFC_INDICATION_REGISTER_RESP_V01 0x0001
-#define QMI_DFC_INDICATION_REGISTER_REQ_V01_MAX_MSG_LEN 4
+#define QMI_DFC_INDICATION_REGISTER_REQ_V01_MAX_MSG_LEN 8
 #define QMI_DFC_INDICATION_REGISTER_RESP_V01_MAX_MSG_LEN 7
 
 #define QMI_DFC_FLOW_STATUS_IND_V01 0x0022
 #define QMI_DFC_FLOW_STATUS_IND_V01_MAX_MSG_LEN 540
+#define QMI_DFC_TX_LINK_STATUS_IND_V01 0x0024
+#define QMI_DFC_TX_LINK_STATUS_IND_V01_MAX_MSG_LEN 120
 
 #define QMI_DFC_GET_FLOW_STATUS_REQ_V01 0x0023
 #define QMI_DFC_GET_FLOW_STATUS_RESP_V01 0x0023
@@ -102,6 +110,8 @@ struct dfc_bind_client_resp_msg_v01 {
 struct dfc_indication_register_req_msg_v01 {
 	u8 report_flow_status_valid;
 	u8 report_flow_status;
+	u8 report_tx_link_status_valid;
+	u8 report_tx_link_status;
 };
 
 struct dfc_indication_register_resp_msg_v01 {
@@ -313,6 +323,20 @@ struct dfc_flow_status_ind_msg_v01 {
 	struct dfc_ancillary_info_type_v01 ancillary_info[DFC_MAX_BEARERS_V01];
 };
 
+struct dfc_bearer_info_type_v01 {
+	u8 subs_id;
+	u8 mux_id;
+	u8 bearer_id;
+	enum dfc_ip_type_enum_v01 ip_type;
+};
+
+struct dfc_tx_link_status_ind_msg_v01 {
+	u8 tx_status;
+	u8 bearer_info_valid;
+	u8 bearer_info_len;
+	struct dfc_bearer_info_type_v01 bearer_info[DFC_MAX_BEARERS_V01];
+};
+
 struct dfc_get_flow_status_req_msg_v01 {
 	u8 bearer_id_list_valid;
 	u8 bearer_id_list_len;
@@ -328,7 +352,11 @@ struct dfc_get_flow_status_resp_msg_v01 {
 
 struct dfc_svc_ind {
 	struct list_head list;
-	struct dfc_flow_status_ind_msg_v01 dfc_info;
+	u16 msg_id;
+	union {
+		struct dfc_flow_status_ind_msg_v01 dfc_info;
+		struct dfc_tx_link_status_ind_msg_v01 tx_status;
+	} d;
 };
 
 static struct qmi_elem_info dfc_bind_client_req_msg_v01_ei[] = {
@@ -401,6 +429,28 @@ static struct qmi_elem_info dfc_indication_register_req_msg_v01_ei[] = {
 		.ei_array	= NULL,
 	},
 	{
+		.data_type	= QMI_OPT_FLAG,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= 0x11,
+		.offset		= offsetof(struct
+					   dfc_indication_register_req_msg_v01,
+					   report_tx_link_status_valid),
+		.ei_array	= NULL,
+	},
+	{
+		.data_type	= QMI_UNSIGNED_1_BYTE,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= 0x11,
+		.offset		= offsetof(struct
+					   dfc_indication_register_req_msg_v01,
+					   report_tx_link_status),
+		.ei_array	= NULL,
+	},
+	{
 		.data_type	= QMI_EOTI,
 		.is_array	= NO_ARRAY,
 		.tlv_type	= QMI_COMMON_TLV_TYPE,
@@ -618,6 +668,111 @@ static struct qmi_elem_info dfc_get_flow_status_resp_msg_v01_ei[] = {
 	},
 };
 
+static struct qmi_elem_info dfc_bearer_info_type_v01_ei[] = {
+	{
+		.data_type	= QMI_UNSIGNED_1_BYTE,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+		.offset		= offsetof(struct
+					   dfc_bearer_info_type_v01,
+					   subs_id),
+		.ei_array	= NULL,
+	},
+	{
+		.data_type	= QMI_UNSIGNED_1_BYTE,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+		.offset		= offsetof(struct
+					   dfc_bearer_info_type_v01,
+					   mux_id),
+		.ei_array	= NULL,
+	},
+	{
+		.data_type	= QMI_UNSIGNED_1_BYTE,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+		.offset		= offsetof(struct
+					   dfc_bearer_info_type_v01,
+					   bearer_id),
+		.ei_array	= NULL,
+	},
+	{
+		.data_type	= QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len	= 1,
+		.elem_size	= sizeof(enum dfc_ip_type_enum_v01),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+		.offset		= offsetof(struct
+					   dfc_bearer_info_type_v01,
+					   ip_type),
+		.ei_array	= NULL,
+	},
+	{
+		.data_type	= QMI_EOTI,
+		.is_array	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+	},
+};
+
+static struct qmi_elem_info dfc_tx_link_status_ind_v01_ei[] = {
+	{
+		.data_type	= QMI_UNSIGNED_1_BYTE,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= 0x01,
+		.offset		= offsetof(struct
+					   dfc_tx_link_status_ind_msg_v01,
+					   tx_status),
+		.ei_array	= NULL,
+	},
+	{
+		.data_type	= QMI_OPT_FLAG,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= 0x10,
+		.offset		= offsetof(struct
+					   dfc_tx_link_status_ind_msg_v01,
+					   bearer_info_valid),
+		.ei_array	= NULL,
+	},
+	{
+		.data_type	= QMI_DATA_LEN,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= 0x10,
+		.offset		= offsetof(struct
+					   dfc_tx_link_status_ind_msg_v01,
+					   bearer_info_len),
+		.ei_array	= NULL,
+	},
+	{
+		.data_type	= QMI_STRUCT,
+		.elem_len	= DFC_MAX_BEARERS_V01,
+		.elem_size	= sizeof(struct
+					 dfc_bearer_info_type_v01),
+		.is_array	= VAR_LEN_ARRAY,
+		.tlv_type	= 0x10,
+		.offset		= offsetof(struct
+					   dfc_tx_link_status_ind_msg_v01,
+					   bearer_info),
+		.ei_array	= dfc_bearer_info_type_v01_ei,
+	},
+	{
+		.data_type	= QMI_EOTI,
+		.is_array	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+	},
+};
+
 static int
 dfc_bind_client_req(struct qmi_handle *dfc_handle,
 		    struct sockaddr_qrtr *ssctl, struct svc_info *svc)
@@ -704,6 +859,9 @@ dfc_indication_register_req(struct qmi_handle *dfc_handle,
 
 	req->report_flow_status_valid = 1;
 	req->report_flow_status = reg;
+	req->report_tx_link_status_valid = 1;
+	req->report_tx_link_status = reg;
+
 	ret = qmi_send_request(dfc_handle, ssctl, &txn,
 			       QMI_DFC_INDICATION_REGISTER_REQ_V01,
 			       QMI_DFC_INDICATION_REGISTER_REQ_V01_MAX_MSG_LEN,
@@ -836,9 +994,9 @@ dfc_send_ack(struct net_device *dev, u8 bearer_id, u16 seq, u8 mux_id, u8 type)
 	rmnet_map_tx_qmap_cmd(skb);
 }
 
-static int dfc_bearer_flow_ctl(struct net_device *dev,
-			       struct rmnet_bearer_map *bearer,
-			       struct qos_info *qos)
+int dfc_bearer_flow_ctl(struct net_device *dev,
+			struct rmnet_bearer_map *bearer,
+			struct qos_info *qos)
 {
 	struct rmnet_flow_map *itm;
 	int rc = 0, qlen;
@@ -851,7 +1009,7 @@ static int dfc_bearer_flow_ctl(struct net_device *dev,
 			/*
 			 * Do not flow disable ancillary q if ancillary is true
 			 */
-			if (bearer->ancillary && enable == 0 &&
+			if (bearer->tcp_bidir && enable == 0 &&
 					DFC_IS_ANCILLARY(itm->ip_type))
 				continue;
 
@@ -889,7 +1047,9 @@ static int dfc_all_bearer_flow_ctl(struct net_device *dev,
 			qmi_rmnet_grant_per(bearer_itm->grant_size);
 		bearer_itm->seq = fc_info->seq_num;
 		bearer_itm->ack_req = ack_req;
-		bearer_itm->ancillary = ancillary;
+		bearer_itm->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary);
+		bearer_itm->last_grant = fc_info->num_bytes;
+		bearer_itm->last_seq = fc_info->seq_num;
 	}
 
 	list_for_each_entry(flow_itm, &qos->flow_head, list) {
@@ -915,22 +1075,36 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
 {
 	struct rmnet_bearer_map *itm = NULL;
 	int rc = 0;
-	int action = -1;
+	bool action = false;
 
 	itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id);
 	if (itm) {
-		if (itm->grant_size == 0 && fc_info->num_bytes > 0)
-			action = 1;
-		else if (itm->grant_size > 0 && fc_info->num_bytes == 0)
-			action = 0;
+		/* The RAT switch flag indicates the start and end of
+		 * the switch. Ignore indications in between.
+		 */
+		if (DFC_IS_RAT_SWITCH(ancillary))
+			itm->rat_switch = !fc_info->num_bytes;
+		else
+			if (itm->rat_switch)
+				return 0;
+
+		/* If TX is OFF but we received grant, ignore it */
+		if (itm->tx_off  && fc_info->num_bytes > 0)
+			return 0;
+
+		if ((itm->grant_size == 0 && fc_info->num_bytes > 0) ||
+		    (itm->grant_size > 0 && fc_info->num_bytes == 0))
+			action = true;
 
 		itm->grant_size = fc_info->num_bytes;
 		itm->grant_thresh = qmi_rmnet_grant_per(itm->grant_size);
 		itm->seq = fc_info->seq_num;
 		itm->ack_req = ack_req;
-		itm->ancillary = ancillary;
+		itm->tcp_bidir = DFC_IS_TCP_BIDIR(ancillary);
+		itm->last_grant = fc_info->num_bytes;
+		itm->last_seq = fc_info->seq_num;
 
-		if (action != -1)
+		if (action)
 			rc = dfc_bearer_flow_ctl(dev, itm, qos);
 	} else {
 		pr_debug("grant %u before flow activate", fc_info->num_bytes);
@@ -942,7 +1116,7 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos,
 static void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc,
 				      struct dfc_svc_ind *svc_ind)
 {
-	struct dfc_flow_status_ind_msg_v01 *ind = &svc_ind->dfc_info;
+	struct dfc_flow_status_ind_msg_v01 *ind = &svc_ind->d.dfc_info;
 	struct net_device *dev;
 	struct qos_info *qos;
 	struct dfc_flow_status_info_type_v01 *flow_status;
@@ -1001,6 +1175,71 @@ static void dfc_do_burst_flow_control(struct dfc_qmi_data *dfc,
 	rcu_read_unlock();
 }
 
+static void dfc_update_tx_link_status(struct net_device *dev,
+				      struct qos_info *qos, u8 tx_status,
+				      struct dfc_bearer_info_type_v01 *binfo)
+{
+	struct rmnet_bearer_map *itm = NULL;
+
+	itm = qmi_rmnet_get_bearer_map(qos, binfo->bearer_id);
+	if (!itm)
+		return;
+
+	if (itm->grant_size && !tx_status) {
+		itm->grant_size = 0;
+		itm->tcp_bidir = false;
+		dfc_bearer_flow_ctl(dev, itm, qos);
+	} else if (itm->grant_size == 0 && tx_status && !itm->rat_switch) {
+		itm->grant_size = DEFAULT_GRANT;
+		itm->grant_thresh = DEFAULT_GRANT;
+		itm->seq = 0;
+		itm->ack_req = 0;
+		dfc_bearer_flow_ctl(dev, itm, qos);
+	}
+
+	itm->tx_off = !tx_status;
+}
+
+static void dfc_handle_tx_link_status_ind(struct dfc_qmi_data *dfc,
+					  struct dfc_svc_ind *svc_ind)
+{
+	struct dfc_tx_link_status_ind_msg_v01 *ind = &svc_ind->d.tx_status;
+	struct net_device *dev;
+	struct qos_info *qos;
+	struct dfc_bearer_info_type_v01 *bearer_info;
+	int i;
+
+	rcu_read_lock();
+
+	for (i = 0; i < ind->bearer_info_len; i++) {
+		bearer_info = &ind->bearer_info[i];
+
+		trace_dfc_tx_link_status_ind(dfc->index, i,
+					     ind->tx_status,
+					     bearer_info->mux_id,
+					     bearer_info->bearer_id);
+
+		dev = rmnet_get_rmnet_dev(dfc->rmnet_port,
+					  bearer_info->mux_id);
+		if (!dev)
+			goto clean_out;
+
+		qos = (struct qos_info *)rmnet_get_qos_pt(dev);
+		if (!qos)
+			continue;
+
+		spin_lock_bh(&qos->qos_lock);
+
+		dfc_update_tx_link_status(
+			dev, qos, ind->tx_status, bearer_info);
+
+		spin_unlock_bh(&qos->qos_lock);
+	}
+
+clean_out:
+	rcu_read_unlock();
+}
+
 static void dfc_qmi_ind_work(struct work_struct *work)
 {
 	struct dfc_qmi_data *dfc = container_of(work, struct dfc_qmi_data,
@@ -1021,14 +1260,22 @@ static void dfc_qmi_ind_work(struct work_struct *work)
 			list_del(&svc_ind->list);
 		spin_unlock_irqrestore(&dfc->qmi_ind_lock, flags);
 
-		if (svc_ind) {
-			if (!dfc->restart_state)
+		if (!svc_ind)
+			break;
+
+		if (!dfc->restart_state) {
+			if (svc_ind->msg_id == QMI_DFC_FLOW_STATUS_IND_V01)
 				dfc_do_burst_flow_control(dfc, svc_ind);
-			kfree(svc_ind);
+			else if (svc_ind->msg_id ==
+					QMI_DFC_TX_LINK_STATUS_IND_V01)
+				dfc_handle_tx_link_status_ind(dfc, svc_ind);
 		}
-	} while (svc_ind != NULL);
+		kfree(svc_ind);
+	} while (1);
 
 	local_bh_enable();
+
+	qmi_rmnet_set_dl_msg_active(dfc->rmnet_port);
 }
 
 static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
@@ -1055,7 +1302,44 @@ static void dfc_clnt_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
 		if (!svc_ind)
 			return;
 
-		memcpy(&svc_ind->dfc_info, ind_msg, sizeof(*ind_msg));
+		svc_ind->msg_id = QMI_DFC_FLOW_STATUS_IND_V01;
+		memcpy(&svc_ind->d.dfc_info, ind_msg, sizeof(*ind_msg));
+
+		spin_lock_irqsave(&dfc->qmi_ind_lock, flags);
+		list_add_tail(&svc_ind->list, &dfc->qmi_ind_q);
+		spin_unlock_irqrestore(&dfc->qmi_ind_lock, flags);
+
+		queue_work(dfc->dfc_wq, &dfc->qmi_ind_work);
+	}
+}
+
+static void dfc_tx_link_status_ind_cb(struct qmi_handle *qmi,
+				      struct sockaddr_qrtr *sq,
+				      struct qmi_txn *txn, const void *data)
+{
+	struct dfc_qmi_data *dfc = container_of(qmi, struct dfc_qmi_data,
+						handle);
+	struct dfc_tx_link_status_ind_msg_v01 *ind_msg;
+	struct dfc_svc_ind *svc_ind;
+	unsigned long flags;
+
+	if (qmi != &dfc->handle)
+		return;
+
+	ind_msg = (struct dfc_tx_link_status_ind_msg_v01 *)data;
+	if (ind_msg->bearer_info_valid) {
+		if (ind_msg->bearer_info_len > DFC_MAX_BEARERS_V01) {
+			pr_err("%s() Invalid bearer info len: %d\n",
+			       __func__, ind_msg->bearer_info_len);
+			return;
+		}
+
+		svc_ind = kzalloc(sizeof(struct dfc_svc_ind), GFP_ATOMIC);
+		if (!svc_ind)
+			return;
+
+		svc_ind->msg_id = QMI_DFC_TX_LINK_STATUS_IND_V01;
+		memcpy(&svc_ind->d.tx_status, ind_msg, sizeof(*ind_msg));
 
 		spin_lock_irqsave(&dfc->qmi_ind_lock, flags);
 		list_add_tail(&svc_ind->list, &dfc->qmi_ind_q);
@@ -1136,6 +1420,13 @@ static struct qmi_msg_handler qmi_indication_handler[] = {
 		.decoded_size = QMI_DFC_FLOW_STATUS_IND_V01_MAX_MSG_LEN,
 		.fn = dfc_clnt_ind_cb,
 	},
+	{
+		.type = QMI_INDICATION,
+		.msg_id = QMI_DFC_TX_LINK_STATUS_IND_V01,
+		.ei = dfc_tx_link_status_ind_v01_ei,
+		.decoded_size = QMI_DFC_TX_LINK_STATUS_IND_V01_MAX_MSG_LEN,
+		.fn = dfc_tx_link_status_ind_cb,
+	},
 	{},
 };
 
@@ -1296,9 +1587,9 @@ void dfc_qmi_query_flow(void *dfc_data)
 	    resp->flow_status_len > DFC_MAX_BEARERS_V01)
 		goto done;
 
-	svc_ind->dfc_info.flow_status_valid = resp->flow_status_valid;
-	svc_ind->dfc_info.flow_status_len = resp->flow_status_len;
-	memcpy(&svc_ind->dfc_info.flow_status, resp->flow_status,
+	svc_ind->d.dfc_info.flow_status_valid = resp->flow_status_valid;
+	svc_ind->d.dfc_info.flow_status_len = resp->flow_status_len;
+	memcpy(&svc_ind->d.dfc_info.flow_status, resp->flow_status,
 		sizeof(resp->flow_status[0]) * resp->flow_status_len);
 	dfc_do_burst_flow_control(data, svc_ind);
 
diff --git a/drivers/soc/qcom/fsa4480-i2c.c b/drivers/soc/qcom/fsa4480-i2c.c
index 0ae1fb2..fa95fb5 100644
--- a/drivers/soc/qcom/fsa4480-i2c.c
+++ b/drivers/soc/qcom/fsa4480-i2c.c
@@ -158,20 +158,27 @@ static int fsa4480_usbc_analog_setup_switches(struct fsa4480_priv *fsa_priv)
 	dev_dbg(dev, "%s: setting GPIOs active = %d\n",
 		__func__, mode.intval != POWER_SUPPLY_TYPEC_NONE);
 
-	if (mode.intval != POWER_SUPPLY_TYPEC_NONE) {
+	switch (mode.intval) {
+	/* add all modes FSA should notify for in here */
+	case POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER:
 		/* activate switches */
 		fsa4480_usbc_update_settings(fsa_priv, 0x00, 0x9F);
 
 		/* notify call chain on event */
 		blocking_notifier_call_chain(&fsa_priv->fsa4480_notifier,
-		POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER, NULL);
-	} else {
+		mode.intval, NULL);
+		break;
+	case POWER_SUPPLY_TYPEC_NONE:
 		/* notify call chain on event */
 		blocking_notifier_call_chain(&fsa_priv->fsa4480_notifier,
 				POWER_SUPPLY_TYPEC_NONE, NULL);
 
 		/* deactivate switches */
 		fsa4480_usbc_update_settings(fsa_priv, 0x18, 0x98);
+		break;
+	default:
+		/* ignore other usb connection modes */
+		break;
 	}
 
 done:
diff --git a/drivers/soc/qcom/glink_probe.c b/drivers/soc/qcom/glink_probe.c
index 22b2e25..3b7b78d 100644
--- a/drivers/soc/qcom/glink_probe.c
+++ b/drivers/soc/qcom/glink_probe.c
@@ -216,6 +216,7 @@ static void glink_ssr_init_notify(struct glink_ssr *ssr)
 
 		nb->nb.notifier_call = glink_ssr_ssr_cb;
 		nb->nb.priority = GLINK_SSR_PRIORITY;
+		nb->ssr = ssr;
 
 		handle = subsys_notif_register_notifier(nb->ssr_label, &nb->nb);
 		if (IS_ERR_OR_NULL(handle)) {
@@ -225,7 +226,6 @@ static void glink_ssr_init_notify(struct glink_ssr *ssr)
 			continue;
 		}
 
-		nb->ssr = ssr;
 		nb->ssr_register_handle = handle;
 		list_add_tail(&nb->list, &ssr->notify_list);
 	}
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 50afa5c..c332a47 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -35,6 +35,9 @@
 #include <linux/ipc_logging.h>
 #include <linux/thread_info.h>
 #include <linux/uaccess.h>
+#include <linux/adc-tm-clients.h>
+#include <linux/iio/consumer.h>
+#include <dt-bindings/iio/qcom,spmi-vadc.h>
 #include <linux/etherdevice.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -677,14 +680,15 @@ static irqreturn_t fw_crash_indication_handler(int irq, void *ctx)
 	icnss_pr_err("Received early crash indication from FW\n");
 
 	if (priv) {
+		set_bit(ICNSS_FW_DOWN, &priv->state);
+		icnss_ignore_fw_timeout(true);
+
 		if (test_bit(ICNSS_FW_READY, &priv->state) &&
 		    !test_bit(ICNSS_DRIVER_UNLOADING, &priv->state)) {
 			fw_down_data.crashed = true;
 			icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_DOWN,
 						 &fw_down_data);
 		}
-		set_bit(ICNSS_FW_DOWN, &priv->state);
-		icnss_ignore_fw_timeout(true);
 	}
 
 	icnss_driver_event_post(ICNSS_DRIVER_EVENT_FW_EARLY_CRASH_IND,
@@ -790,6 +794,136 @@ int icnss_call_driver_uevent(struct icnss_priv *priv,
 	return priv->ops->uevent(&priv->pdev->dev, &uevent_data);
 }
 
+
+static int icnss_get_phone_power(struct icnss_priv *priv, uint64_t *result_uv)
+{
+	int ret = 0;
+	int result;
+
+	if (!priv->channel) {
+		icnss_pr_err("Channel doesn't exists\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = iio_read_channel_processed(penv->channel, &result);
+	if (ret < 0) {
+		icnss_pr_err("Error reading channel, ret = %d\n", ret);
+		goto out;
+	}
+
+	*result_uv = (uint64_t) result;
+out:
+	return ret;
+}
+
+static void icnss_vph_notify(enum adc_tm_state state, void *ctx)
+{
+	struct icnss_priv *priv = ctx;
+	uint64_t vph_pwr = 0;
+	uint64_t vph_pwr_prev;
+	int ret = 0;
+	bool update = true;
+
+	if (!priv) {
+		icnss_pr_err("Priv pointer is NULL\n");
+		return;
+	}
+
+	vph_pwr_prev = priv->vph_pwr;
+
+	ret = icnss_get_phone_power(priv, &vph_pwr);
+	if (ret < 0)
+		return;
+
+	if (vph_pwr < ICNSS_THRESHOLD_LOW) {
+		if (vph_pwr_prev < ICNSS_THRESHOLD_LOW)
+			update = false;
+		priv->vph_monitor_params.state_request =
+			ADC_TM_HIGH_THR_ENABLE;
+		priv->vph_monitor_params.high_thr = ICNSS_THRESHOLD_LOW +
+			ICNSS_THRESHOLD_GUARD;
+		priv->vph_monitor_params.low_thr = 0;
+	} else if (vph_pwr > ICNSS_THRESHOLD_HIGH) {
+		if (vph_pwr_prev > ICNSS_THRESHOLD_HIGH)
+			update = false;
+		priv->vph_monitor_params.state_request =
+			ADC_TM_LOW_THR_ENABLE;
+		priv->vph_monitor_params.low_thr = ICNSS_THRESHOLD_HIGH -
+			ICNSS_THRESHOLD_GUARD;
+		priv->vph_monitor_params.high_thr = 0;
+	} else {
+		if (vph_pwr_prev > ICNSS_THRESHOLD_LOW &&
+		    vph_pwr_prev < ICNSS_THRESHOLD_HIGH)
+			update = false;
+		priv->vph_monitor_params.state_request =
+			ADC_TM_HIGH_LOW_THR_ENABLE;
+		priv->vph_monitor_params.low_thr = ICNSS_THRESHOLD_LOW;
+		priv->vph_monitor_params.high_thr = ICNSS_THRESHOLD_HIGH;
+	}
+
+	priv->vph_pwr = vph_pwr;
+
+	if (update) {
+		icnss_send_vbatt_update(priv, vph_pwr);
+		icnss_pr_dbg("set low threshold to %d, high threshold to %d Phone power=%llu\n",
+			     priv->vph_monitor_params.low_thr,
+			     priv->vph_monitor_params.high_thr, vph_pwr);
+	}
+
+	ret = adc_tm5_channel_measure(priv->adc_tm_dev,
+				      &priv->vph_monitor_params);
+	if (ret)
+		icnss_pr_err("TM channel setup failed %d\n", ret);
+}
+
+static int icnss_setup_vph_monitor(struct icnss_priv *priv)
+{
+	int ret = 0;
+
+	if (!priv->adc_tm_dev) {
+		icnss_pr_err("ADC TM handler is NULL\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	priv->vph_monitor_params.low_thr = ICNSS_THRESHOLD_LOW;
+	priv->vph_monitor_params.high_thr = ICNSS_THRESHOLD_HIGH;
+	priv->vph_monitor_params.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
+	priv->vph_monitor_params.channel = ADC_VBAT_SNS;
+	priv->vph_monitor_params.btm_ctx = priv;
+	priv->vph_monitor_params.threshold_notification = &icnss_vph_notify;
+	icnss_pr_dbg("Set low threshold to %d, high threshold to %d\n",
+		     priv->vph_monitor_params.low_thr,
+		     priv->vph_monitor_params.high_thr);
+
+	ret = adc_tm5_channel_measure(priv->adc_tm_dev,
+				      &priv->vph_monitor_params);
+	if (ret)
+		icnss_pr_err("TM channel setup failed %d\n", ret);
+out:
+	return ret;
+}
+
+static int icnss_init_vph_monitor(struct icnss_priv *priv)
+{
+	int ret = 0;
+
+	ret = icnss_get_phone_power(priv, &priv->vph_pwr);
+	if (ret < 0)
+		goto out;
+
+	icnss_pr_dbg("Phone power=%llu\n", priv->vph_pwr);
+
+	icnss_send_vbatt_update(priv, priv->vph_pwr);
+
+	ret = icnss_setup_vph_monitor(priv);
+	if (ret)
+		goto out;
+out:
+	return ret;
+}
+
 static int icnss_driver_event_server_arrive(void *data)
 {
 	int ret = 0;
@@ -859,6 +993,9 @@ static int icnss_driver_event_server_arrive(void *data)
 	if (!penv->fw_early_crash_irq)
 		register_early_crash_notifications(&penv->pdev->dev);
 
+	if (penv->vbatt_supported)
+		icnss_init_vph_monitor(penv);
+
 	return ret;
 
 err_setup_msa:
@@ -882,6 +1019,10 @@ static int icnss_driver_event_server_exit(void *data)
 
 	icnss_clear_server(penv);
 
+	if (penv->adc_tm_dev && penv->vbatt_supported)
+		adc_tm5_disable_chan_meas(penv->adc_tm_dev,
+					  &penv->vph_monitor_params);
+
 	return 0;
 }
 
@@ -1090,9 +1231,14 @@ static int icnss_driver_event_unregister_driver(void *data)
 	}
 
 	set_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
+
+	icnss_block_shutdown(true);
+
 	if (penv->ops)
 		penv->ops->remove(&penv->pdev->dev);
 
+	icnss_block_shutdown(false);
+
 	clear_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
 	clear_bit(ICNSS_DRIVER_PROBED, &penv->state);
 
@@ -1151,7 +1297,8 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv,
 		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);
@@ -3045,6 +3192,45 @@ static void icnss_debugfs_destroy(struct icnss_priv *priv)
 	debugfs_remove_recursive(priv->root_dentry);
 }
 
+
+static int icnss_get_vbatt_info(struct icnss_priv *priv)
+{
+	struct adc_tm_chip *adc_tm_dev = NULL;
+	struct iio_channel *channel = NULL;
+	int ret = 0;
+
+	adc_tm_dev = get_adc_tm(&priv->pdev->dev, "icnss");
+	if (PTR_ERR(adc_tm_dev) == -EPROBE_DEFER) {
+		icnss_pr_err("adc_tm_dev probe defer\n");
+		return -EPROBE_DEFER;
+	}
+
+	if (IS_ERR(adc_tm_dev)) {
+		ret = PTR_ERR(adc_tm_dev);
+		icnss_pr_err("Not able to get ADC dev, VBATT monitoring is disabled: %d\n",
+			     ret);
+		return ret;
+	}
+
+	channel = iio_channel_get(&priv->pdev->dev, "icnss");
+	if (PTR_ERR(channel) == -EPROBE_DEFER) {
+		icnss_pr_err("channel probe defer\n");
+		return -EPROBE_DEFER;
+	}
+
+	if (IS_ERR(channel)) {
+		ret = PTR_ERR(channel);
+		icnss_pr_err("Not able to get VADC dev, VBATT monitoring is disabled: %d\n",
+			     ret);
+		return ret;
+	}
+
+	priv->adc_tm_dev = adc_tm_dev;
+	priv->channel = channel;
+
+	return 0;
+}
+
 static int icnss_probe(struct platform_device *pdev)
 {
 	int ret = 0;
@@ -3074,6 +3260,13 @@ static int icnss_probe(struct platform_device *pdev)
 
 	priv->vreg_info = icnss_vreg_info;
 
+	if (of_property_read_bool(pdev->dev.of_node, "qcom,icnss-adc_tm")) {
+		ret = icnss_get_vbatt_info(priv);
+		if (ret == -EPROBE_DEFER)
+			goto out;
+		priv->vbatt_supported = true;
+	}
+
 	for (i = 0; i < ICNSS_VREG_INFO_SIZE; i++) {
 		ret = icnss_get_vreg_info(dev, &priv->vreg_info[i]);
 
diff --git a/drivers/soc/qcom/icnss_private.h b/drivers/soc/qcom/icnss_private.h
index 4068122ac..40ca688 100644
--- a/drivers/soc/qcom/icnss_private.h
+++ b/drivers/soc/qcom/icnss_private.h
@@ -13,6 +13,9 @@
 #ifndef __ICNSS_PRIVATE_H__
 #define __ICNSS_PRIVATE_H__
 
+#include <linux/adc-tm-clients.h>
+#include <linux/iio/consumer.h>
+
 #define icnss_ipc_log_string(_x...) do {				\
 	if (icnss_ipc_log_context)					\
 		ipc_log_string(icnss_ipc_log_context, _x);		\
@@ -239,6 +242,9 @@ struct icnss_stats {
 	uint32_t rejuvenate_ack_req;
 	uint32_t rejuvenate_ack_resp;
 	uint32_t rejuvenate_ack_err;
+	uint32_t vbatt_req;
+	uint32_t vbatt_resp;
+	uint32_t vbatt_req_err;
 };
 
 #define WLFW_MAX_TIMESTAMP_LEN 32
@@ -356,6 +362,11 @@ struct icnss_priv {
 	uint32_t fw_error_fatal_irq;
 	uint32_t fw_early_crash_irq;
 	struct completion unblock_shutdown;
+	struct adc_tm_param vph_monitor_params;
+	struct adc_tm_chip *adc_tm_dev;
+	struct iio_channel *channel;
+	uint64_t vph_pwr;
+	bool vbatt_supported;
 	char function_name[WLFW_FUNCTION_NAME_LEN + 1];
 };
 
diff --git a/drivers/soc/qcom/icnss_qmi.c b/drivers/soc/qcom/icnss_qmi.c
index 6da3be7..1836352 100644
--- a/drivers/soc/qcom/icnss_qmi.c
+++ b/drivers/soc/qcom/icnss_qmi.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
@@ -31,6 +31,7 @@
 #include <soc/qcom/service-notifier.h>
 #include "wlan_firmware_service_v01.h"
 #include "icnss_private.h"
+#include "icnss_qmi.h"
 
 #ifdef CONFIG_ICNSS_DEBUG
 unsigned long qmi_timeout = 3000;
@@ -750,6 +751,8 @@ int wlfw_athdiag_read_send_sync_msg(struct icnss_priv *priv,
 			resp->resp.result, resp->resp.error);
 		ret = -resp->resp.result;
 		goto out;
+	} else {
+		ret = 0;
 	}
 
 	if (!resp->data_valid || resp->data_len < data_len) {
@@ -1322,4 +1325,73 @@ int icnss_send_wlan_disable_to_fw(struct icnss_priv *priv)
 	return wlfw_wlan_mode_send_sync_msg(priv, mode);
 }
 
+int icnss_send_vbatt_update(struct icnss_priv *priv, uint64_t voltage_uv)
+{
+	int ret;
+	struct wlfw_vbatt_req_msg_v01 *req;
+	struct wlfw_vbatt_resp_msg_v01 *resp;
+	struct qmi_txn txn;
 
+	if (!priv)
+		return -ENODEV;
+
+	if (test_bit(ICNSS_FW_DOWN, &priv->state))
+		return -EINVAL;
+
+	icnss_pr_dbg("Sending Vbatt message, state: 0x%lx\n", priv->state);
+
+	req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		kfree(req);
+		return -ENOMEM;
+	}
+
+	priv->stats.vbatt_req++;
+
+	req->voltage_uv = voltage_uv;
+
+	ret = qmi_txn_init(&priv->qmi, &txn, wlfw_vbatt_resp_msg_v01_ei, resp);
+	if (ret < 0) {
+		icnss_pr_err("Fail to init txn for Vbatt message resp %d\n",
+			     ret);
+		goto out;
+	}
+
+	ret = qmi_send_request(&priv->qmi, NULL, &txn,
+			       QMI_WLFW_VBATT_REQ_V01,
+			       WLFW_VBATT_REQ_MSG_V01_MAX_MSG_LEN,
+			       wlfw_vbatt_req_msg_v01_ei, req);
+	if (ret < 0) {
+		qmi_txn_cancel(&txn);
+		icnss_pr_err("Fail to send Vbatt message req %d\n", ret);
+		goto out;
+	}
+
+	ret = qmi_txn_wait(&txn, WLFW_TIMEOUT);
+	if (ret < 0) {
+		icnss_pr_err("VBATT message resp wait failed with ret %d\n",
+				    ret);
+		goto out;
+	} else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
+		icnss_pr_err("QMI Vbatt message request rejected, result:%d error:%d\n",
+				    resp->resp.result, resp->resp.error);
+		ret = -resp->resp.result;
+		goto out;
+	}
+
+	priv->stats.vbatt_resp++;
+
+	kfree(resp);
+	kfree(req);
+	return 0;
+
+out:
+	kfree(resp);
+	kfree(req);
+	priv->stats.vbatt_req_err++;
+	return ret;
+}
diff --git a/drivers/soc/qcom/icnss_qmi.h b/drivers/soc/qcom/icnss_qmi.h
index a94c35d..983f430 100644
--- a/drivers/soc/qcom/icnss_qmi.h
+++ b/drivers/soc/qcom/icnss_qmi.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
@@ -92,6 +92,11 @@ static inline int icnss_register_fw_service(struct icnss_priv *priv)
 	return 0;
 }
 static inline void icnss_unregister_fw_service(struct icnss_priv *priv) {}
+static inline int icnss_send_vbatt_update(struct icnss_priv *priv,
+					  uint64_t voltage_uv)
+{
+	return 0;
+}
 
 #else
 int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv);
@@ -121,6 +126,7 @@ int icnss_send_wlan_enable_to_fw(struct icnss_priv *priv,
 int icnss_send_wlan_disable_to_fw(struct icnss_priv *priv);
 int icnss_register_fw_service(struct icnss_priv *priv);
 void icnss_unregister_fw_service(struct icnss_priv *priv);
+int icnss_send_vbatt_update(struct icnss_priv *priv, uint64_t voltage_uv);
 #endif
 
 #endif /* __ICNSS_QMI_H__*/
diff --git a/drivers/soc/qcom/llcc-atoll.c b/drivers/soc/qcom/llcc-atoll.c
new file mode 100644
index 0000000..b4be758
--- /dev/null
+++ b/drivers/soc/qcom/llcc-atoll.c
@@ -0,0 +1,100 @@
+/* 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/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
+/*
+ * SCT entry contains of the following parameters
+ * name: Name of the client's use case for which the llcc slice is used
+ * uid: Unique id for the client's use case
+ * slice_id: llcc slice id for each client
+ * max_cap: The maximum capacity of the cache slice provided in KB
+ * priority: Priority of the client used to select victim line for replacement
+ * fixed_size: Determine of the slice has a fixed capacity
+ * bonus_ways: Bonus ways to be used by any slice, bonus way is used only if
+ *             it't not a reserved way.
+ * res_ways: Reserved ways for the cache slice, the reserved ways cannot be used
+ *           by any other client than the one its assigned to.
+ * cache_mode: Each slice operates as a cache, this controls the mode of the
+ *             slice normal or TCM
+ * probe_target_ways: Determines what ways to probe for access hit. When
+ *                    configured to 1 only bonus and reseved ways are probed.
+ *                    when configured to 0 all ways in llcc are probed.
+ * dis_cap_alloc: Disable capacity based allocation for a client
+ * retain_on_pc: If this bit is set and client has maitained active vote
+ *               then the ways assigned to this client are not flushed on power
+ *               collapse.
+ * activate_on_init: Activate the slice immidiately after the SCT is programmed
+ */
+#define SCT_ENTRY(n, uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \
+	{					\
+		.name = n,			\
+		.usecase_id = uid,		\
+		.slice_id = sid,		\
+		.max_cap = mc,			\
+		.priority = p,			\
+		.fixed_size = fs,		\
+		.bonus_ways = bway,		\
+		.res_ways = rway,		\
+		.cache_mode = cmod,		\
+		.probe_target_ways = ptw,	\
+		.dis_cap_alloc = dca,		\
+		.retain_on_pc = rp,		\
+		.activate_on_init = a,		\
+	}
+
+static struct llcc_slice_config atoll_data[] =  {
+	SCT_ENTRY("cpuss",       1, 1, 256, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 1),
+	SCT_ENTRY("modem",       8, 8, 256, 0, 0, 0xF, 0x0, 0, 0, 0, 1, 0),
+	SCT_ENTRY("gpuhtw",      11, 11, 128, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 0),
+	SCT_ENTRY("gpu",         12, 12, 128, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 0),
+};
+
+static int atoll_qcom_llcc_probe(struct platform_device *pdev)
+{
+	return qcom_llcc_probe(pdev, atoll_data,
+				 ARRAY_SIZE(atoll_data));
+}
+
+static const struct of_device_id atoll_qcom_llcc_of_match[] = {
+	{ .compatible = "qcom,atoll-llcc", },
+	{ },
+};
+
+static struct platform_driver atoll_qcom_llcc_driver = {
+	.driver = {
+		.name = "atoll-llcc",
+		.owner = THIS_MODULE,
+		.of_match_table = atoll_qcom_llcc_of_match,
+	},
+	.probe = atoll_qcom_llcc_probe,
+	.remove = qcom_llcc_remove,
+};
+
+static int __init atoll_init_qcom_llcc_init(void)
+{
+	return platform_driver_register(&atoll_qcom_llcc_driver);
+}
+module_init(atoll_init_qcom_llcc_init);
+
+static void __exit atoll_exit_qcom_llcc_exit(void)
+{
+	platform_driver_unregister(&atoll_qcom_llcc_driver);
+}
+module_exit(atoll_exit_qcom_llcc_exit);
+
+MODULE_DESCRIPTION("Qualcomm Technologies Inc atoll LLCC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/llcc-core.c b/drivers/soc/qcom/llcc-core.c
index ded05248..919ac77 100644
--- a/drivers/soc/qcom/llcc-core.c
+++ b/drivers/soc/qcom/llcc-core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-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
@@ -19,47 +19,6 @@
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 
-/* Config registers offsets*/
-#define DRP_ECC_ERROR_CFG	0x00040000
-
-/* TRP, DRP interrupt register offsets */
-#define CMN_INTERRUPT_0_ENABLE		0x0003001C
-#define CMN_INTERRUPT_2_ENABLE		0x0003003C
-#define TRP_INTERRUPT_0_ENABLE		0x00020488
-#define DRP_INTERRUPT_ENABLE		0x0004100C
-
-#define SB_ERROR_THRESHOLD	0x1
-#define SB_ERROR_THRESHOLD_SHIFT	24
-#define SB_DB_TRP_INTERRUPT_ENABLE	0x3
-#define TRP0_INTERRUPT_ENABLE	0x1
-#define DRP0_INTERRUPT_ENABLE	BIT(6)
-#define SB_DB_DRP_INTERRUPT_ENABLE	0x3
-
-static void qcom_llcc_core_setup(struct regmap *llcc_regmap, uint32_t b_off)
-{
-	u32 sb_err_threshold;
-
-	/* Enable TRP in instance 2 of common interrupt enable register */
-	regmap_update_bits(llcc_regmap, b_off + CMN_INTERRUPT_2_ENABLE,
-			   TRP0_INTERRUPT_ENABLE, TRP0_INTERRUPT_ENABLE);
-
-	/* Enable ECC interrupts on Tag Ram */
-	regmap_update_bits(llcc_regmap, b_off + TRP_INTERRUPT_0_ENABLE,
-		SB_DB_TRP_INTERRUPT_ENABLE, SB_DB_TRP_INTERRUPT_ENABLE);
-
-	/* Enable SB error for Data RAM */
-	sb_err_threshold = (SB_ERROR_THRESHOLD << SB_ERROR_THRESHOLD_SHIFT);
-	regmap_write(llcc_regmap, b_off + DRP_ECC_ERROR_CFG, sb_err_threshold);
-
-	/* Enable DRP in instance 2 of common interrupt enable register */
-	regmap_update_bits(llcc_regmap, b_off + CMN_INTERRUPT_2_ENABLE,
-			   DRP0_INTERRUPT_ENABLE, DRP0_INTERRUPT_ENABLE);
-
-	/* Enable ECC interrupts on Data Ram */
-	regmap_write(llcc_regmap, b_off + DRP_INTERRUPT_ENABLE,
-		     SB_DB_DRP_INTERRUPT_ENABLE);
-}
-
 static int qcom_llcc_core_probe(struct platform_device *pdev)
 {
 	struct regmap *llcc_regmap;
@@ -81,8 +40,6 @@ static int qcom_llcc_core_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	qcom_llcc_core_setup(llcc_regmap, b_off);
-
 	return 0;
 }
 
diff --git a/drivers/soc/qcom/llcc-sdmmagpie.c b/drivers/soc/qcom/llcc-sdmmagpie.c
index 04a6783..20e4dbb4 100644
--- a/drivers/soc/qcom/llcc-sdmmagpie.c
+++ b/drivers/soc/qcom/llcc-sdmmagpie.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* 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
@@ -58,8 +58,7 @@
 
 static struct llcc_slice_config sdmmagpie_data[] =  {
 	SCT_ENTRY("cpuss",       1,  1, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 1),
-	SCT_ENTRY("modem",       8,  8, 512, 0, 0, 0xF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("modemhw",     9,  9, 512, 0, 0, 0xF, 0x0, 0, 0, 0, 1, 0),
+	SCT_ENTRY("modem",       8,  8, 128, 2, 0, 0xF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("gpuhtw",     11, 11, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("gpu",        12, 12, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("npu",        23, 23, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 0),
diff --git a/drivers/soc/qcom/mem-offline.c b/drivers/soc/qcom/mem-offline.c
index 3396d87..9144607 100644
--- a/drivers/soc/qcom/mem-offline.c
+++ b/drivers/soc/qcom/mem-offline.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
@@ -24,7 +24,9 @@
 #include <linux/of.h>
 #include <linux/mailbox_client.h>
 #include <linux/mailbox/qmp.h>
+#include <soc/qcom/rpm-smd.h>
 
+#define RPM_DDR_REQ 0x726464
 #define AOP_MSG_ADDR_MASK		0xffffffff
 #define AOP_MSG_ADDR_HIGH_SHIFT		32
 #define MAX_LEN				96
@@ -32,6 +34,7 @@
 static unsigned long start_section_nr, end_section_nr;
 static struct kobject *kobj;
 static unsigned int offline_granule, sections_per_block;
+static bool is_rpm_controller;
 #define MODULE_CLASS_NAME	"mem-offline"
 #define BUF_LEN			100
 
@@ -56,6 +59,15 @@ static struct mem_offline_mailbox {
 	struct mbox_chan *mbox;
 } mailbox;
 
+struct memory_refresh_request {
+	u64 start;	/* Lower bit signifies action
+			 * 0 - disable self-refresh
+			 * 1 - enable self-refresh
+			 * upper bits are for base address
+			 */
+	u32 size;	/* size of memory region */
+};
+
 static struct section_stat *mem_info;
 
 void record_stat(unsigned long sec, ktime_t delay, int mode)
@@ -85,6 +97,25 @@ void record_stat(unsigned long sec, ktime_t delay, int mode)
 	mem_info[blk_nr].last_recorded_time = delay;
 }
 
+static int mem_region_refresh_control(unsigned long pfn,
+				      unsigned long nr_pages,
+				      bool enable)
+{
+	struct memory_refresh_request mem_req;
+	struct msm_rpm_kvp rpm_kvp;
+
+	mem_req.start = enable;
+	mem_req.start |= pfn << PAGE_SHIFT;
+	mem_req.size = nr_pages * PAGE_SIZE;
+
+	rpm_kvp.key = RPM_DDR_REQ;
+	rpm_kvp.data = (void *)&mem_req;
+	rpm_kvp.length = sizeof(mem_req);
+
+	return msm_rpm_send_message(MSM_RPM_CTX_ACTIVE_SET, RPM_DDR_REQ, 0,
+				    &rpm_kvp, 1);
+}
+
 static int aop_send_msg(unsigned long addr, bool online)
 {
 	struct qmp_pkt pkt;
@@ -103,6 +134,17 @@ static int aop_send_msg(unsigned long addr, bool online)
 	return mbox_send_message(mailbox.mbox, &pkt);
 }
 
+static int send_msg(struct memory_notify *mn, bool online)
+{
+	int start = SECTION_ALIGN_DOWN(mn->start_pfn);
+
+	if (is_rpm_controller)
+		return mem_region_refresh_control(start, mn->nr_pages,
+						  online);
+	else
+		return aop_send_msg(__pfn_to_phys(start), online);
+}
+
 static int mem_event_callback(struct notifier_block *self,
 				unsigned long action, void *arg)
 {
@@ -142,16 +184,18 @@ static int mem_event_callback(struct notifier_block *self,
 			   idx) / sections_per_block].fail_count;
 		cur = ktime_get();
 
-		if (aop_send_msg(__pfn_to_phys(start), true))
-			pr_err("PASR: AOP online request addr:0x%llx failed\n",
+		if (send_msg(mn, true))
+			pr_err("PASR: %s online request addr:0x%llx failed\n",
+			       is_rpm_controller ? "RPM" : "AOP",
 			       __pfn_to_phys(start));
 
 		break;
 	case MEM_ONLINE:
-		pr_info("mem-offline: Onlined memory block mem%lu\n", sec_nr);
 		delay = ktime_ms_delta(ktime_get(), cur);
 		record_stat(sec_nr, delay, MEMORY_ONLINE);
 		cur = 0;
+		pr_info("mem-offline: Onlined memory block mem%pK\n",
+			(void *)sec_nr);
 		break;
 	case MEM_GOING_OFFLINE:
 		pr_debug("mem-offline: MEM_GOING_OFFLINE : start = 0x%lx end = 0x%lx",
@@ -161,19 +205,24 @@ static int mem_event_callback(struct notifier_block *self,
 		cur = ktime_get();
 		break;
 	case MEM_OFFLINE:
-		pr_info("mem-offline: Offlined memory block mem%lu\n", sec_nr);
-
-		if (aop_send_msg(__pfn_to_phys(start), false))
-			pr_err("PASR: AOP offline request addr:0x%llx failed\n",
+		if (send_msg(mn, false))
+			pr_err("PASR: %s offline request addr:0x%llx failed\n",
+			       is_rpm_controller ? "RPM" : "AOP",
 			       __pfn_to_phys(start));
 
 		delay = ktime_ms_delta(ktime_get(), cur);
 		record_stat(sec_nr, delay, MEMORY_OFFLINE);
 		cur = 0;
+		pr_info("mem-offline: Offlined memory block mem%pK\n",
+			(void *)sec_nr);
 		break;
 	case MEM_CANCEL_ONLINE:
 		pr_info("mem-offline: MEM_CANCEL_ONLINE: start = 0x%lx end = 0x%lx",
 				start_addr, end_addr);
+		if (send_msg(mn, false))
+			pr_err("PASR: %s online request addr:0x%llx failed\n",
+			       is_rpm_controller ? "RPM" : "AOP",
+			       __pfn_to_phys(start));
 		break;
 	default:
 		break;
@@ -347,6 +396,11 @@ static int mem_parse_dt(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
+	if (!of_find_property(node, "mboxes", NULL)) {
+		is_rpm_controller = true;
+		return 0;
+	}
+
 	mailbox.cl.dev = &pdev->dev;
 	mailbox.cl.tx_block = true;
 	mailbox.cl.tx_tout = 1000;
diff --git a/drivers/soc/qcom/msm_bus/Makefile b/drivers/soc/qcom/msm_bus/Makefile
index c2ef70c..29204fd 100644
--- a/drivers/soc/qcom/msm_bus/Makefile
+++ b/drivers/soc/qcom/msm_bus/Makefile
@@ -11,7 +11,7 @@
 	obj-$(CONFIG_OF) += msm_bus_of_rpmh.o
 else
 	obj-y += msm_bus_fabric_adhoc.o msm_bus_arb_adhoc.o msm_bus_rules.o \
-		msm_bus_bimc_adhoc.o msm_bus_noc_adhoc.o
+		msm_bus_bimc_adhoc.o msm_bus_noc_adhoc.o msm_bus_qnoc_adhoc.o
 	obj-$(CONFIG_OF) += msm_bus_of_adhoc.o
 endif
 
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_adhoc.h b/drivers/soc/qcom/msm_bus/msm_bus_adhoc.h
index 90bc467..d9ef0a9 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_adhoc.h
+++ b/drivers/soc/qcom/msm_bus/msm_bus_adhoc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 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
@@ -67,6 +67,23 @@ struct msm_bus_fab_device_type {
 	bool bypass_qos_prg;
 };
 
+struct msm_bus_noc_limiter {
+	uint32_t bw;
+	uint32_t sat;
+};
+
+struct msm_bus_noc_regulator {
+	uint32_t low_prio;
+	uint32_t hi_prio;
+	uint32_t bw;
+	uint32_t sat;
+};
+
+struct msm_bus_noc_regulator_mode {
+	uint32_t read;
+	uint32_t write;
+};
+
 struct qos_params_type {
 	int mode;
 	unsigned int prio_lvl;
@@ -79,6 +96,12 @@ struct qos_params_type {
 	unsigned int gp;
 	unsigned int thmp;
 	unsigned int ws;
+	unsigned int prio_dflt;
+	struct msm_bus_noc_limiter limiter;
+	bool limiter_en;
+	struct msm_bus_noc_regulator reg;
+	struct msm_bus_noc_regulator_mode reg_mode;
+	bool urg_fwd_en;
 	u64 bw_buffer;
 };
 
@@ -158,6 +181,7 @@ extern struct msm_bus_device_node_registration
 extern void msm_bus_arb_setops_adhoc(struct msm_bus_arb_ops *arb_ops);
 extern int msm_bus_bimc_set_ops(struct msm_bus_node_device_type *bus_dev);
 extern int msm_bus_noc_set_ops(struct msm_bus_node_device_type *bus_dev);
+extern int msm_bus_qnoc_set_ops(struct msm_bus_node_device_type *bus_dev);
 extern int msm_bus_of_get_static_rules(struct platform_device *pdev,
 					struct bus_rule_type **static_rule);
 extern int msm_rules_update_path(struct list_head *input_list,
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
index 5f40edc..f553e17 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.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
@@ -17,6 +17,7 @@
 #include <linux/rtmutex.h>
 #include <linux/clk.h>
 #include <linux/msm-bus.h>
+#include <dt-bindings/msm/msm-bus-ids.h>
 #include "msm_bus_core.h"
 #include "msm_bus_rpmh.h"
 
@@ -1393,6 +1394,16 @@ static int update_client_paths(struct msm_bus_client *client, bool log_trns,
 			goto exit_update_client_paths;
 		}
 
+		if (dest == MSM_BUS_SLAVE_IPA_CORE && cur_idx <= 0 && idx > 0) {
+			struct device *dev;
+
+			dev = bus_find_device(&msm_bus_type, NULL,
+				(void *) &dest, msm_bus_device_match_adhoc);
+
+			if (dev)
+				msm_bus_commit_single(dev);
+		}
+
 		if (log_trns)
 			getpath_debug(src, lnode, pdata->active_only);
 	}
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_bimc_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_bimc_adhoc.c
index 4e81163..49e4717 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_bimc_adhoc.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_bimc_adhoc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 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
@@ -179,46 +179,46 @@ enum bimc_m_bke_thresh_low {
 #define M_BKE_HEALTH_0_CONFIG_ADDR(b, n) \
 	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000340)
 enum bimc_m_bke_health_0 {
-	M_BKE_HEALTH_0_CONFIG_RMSK			= 0x80000303,
+	M_BKE_HEALTH_0_CONFIG_RMSK			= 0x80000707,
 	M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_BMSK		= 0x80000000,
 	M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_SHFT		= 0x1f,
-	M_BKE_HEALTH_0_CONFIG_AREQPRIO_BMSK		= 0x300,
+	M_BKE_HEALTH_0_CONFIG_AREQPRIO_BMSK		= 0x700,
 	M_BKE_HEALTH_0_CONFIG_AREQPRIO_SHFT		= 0x8,
-	M_BKE_HEALTH_0_CONFIG_PRIOLVL_BMSK		= 0x3,
+	M_BKE_HEALTH_0_CONFIG_PRIOLVL_BMSK		= 0x7,
 	M_BKE_HEALTH_0_CONFIG_PRIOLVL_SHFT		= 0x0,
 };
 
 #define M_BKE_HEALTH_1_CONFIG_ADDR(b, n) \
 	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000344)
 enum bimc_m_bke_health_1 {
-	M_BKE_HEALTH_1_CONFIG_RMSK			= 0x80000303,
+	M_BKE_HEALTH_1_CONFIG_RMSK			= 0x80000707,
 	M_BKE_HEALTH_1_CONFIG_LIMIT_CMDS_BMSK		= 0x80000000,
 	M_BKE_HEALTH_1_CONFIG_LIMIT_CMDS_SHFT		= 0x1f,
-	M_BKE_HEALTH_1_CONFIG_AREQPRIO_BMSK		= 0x300,
+	M_BKE_HEALTH_1_CONFIG_AREQPRIO_BMSK		= 0x700,
 	M_BKE_HEALTH_1_CONFIG_AREQPRIO_SHFT		= 0x8,
-	M_BKE_HEALTH_1_CONFIG_PRIOLVL_BMSK		= 0x3,
+	M_BKE_HEALTH_1_CONFIG_PRIOLVL_BMSK		= 0x7,
 	M_BKE_HEALTH_1_CONFIG_PRIOLVL_SHFT		= 0x0,
 };
 
 #define M_BKE_HEALTH_2_CONFIG_ADDR(b, n) \
 	(M_REG_BASE(b) + (0x4000 * (n)) + 0x00000348)
 enum bimc_m_bke_health_2 {
-	M_BKE_HEALTH_2_CONFIG_RMSK			= 0x80000303,
+	M_BKE_HEALTH_2_CONFIG_RMSK			= 0x80000707,
 	M_BKE_HEALTH_2_CONFIG_LIMIT_CMDS_BMSK		= 0x80000000,
 	M_BKE_HEALTH_2_CONFIG_LIMIT_CMDS_SHFT		= 0x1f,
-	M_BKE_HEALTH_2_CONFIG_AREQPRIO_BMSK		= 0x300,
+	M_BKE_HEALTH_2_CONFIG_AREQPRIO_BMSK		= 0x700,
 	M_BKE_HEALTH_2_CONFIG_AREQPRIO_SHFT		= 0x8,
-	M_BKE_HEALTH_2_CONFIG_PRIOLVL_BMSK		= 0x3,
+	M_BKE_HEALTH_2_CONFIG_PRIOLVL_BMSK		= 0x7,
 	M_BKE_HEALTH_2_CONFIG_PRIOLVL_SHFT		= 0x0,
 };
 
 #define M_BKE_HEALTH_3_CONFIG_ADDR(b, n) \
 	(M_REG_BASE(b) + (0x4000 * (n)) + 0x0000034c)
 enum bimc_m_bke_health_3 {
-	M_BKE_HEALTH_3_CONFIG_RMSK			= 0x303,
-	M_BKE_HEALTH_3_CONFIG_AREQPRIO_BMSK	= 0x300,
+	M_BKE_HEALTH_3_CONFIG_RMSK			= 0x707,
+	M_BKE_HEALTH_3_CONFIG_AREQPRIO_BMSK	= 0x700,
 	M_BKE_HEALTH_3_CONFIG_AREQPRIO_SHFT	= 0x8,
-	M_BKE_HEALTH_3_CONFIG_PRIOLVL_BMSK		= 0x3,
+	M_BKE_HEALTH_3_CONFIG_PRIOLVL_BMSK		= 0x7,
 	M_BKE_HEALTH_3_CONFIG_PRIOLVL_SHFT		= 0x0,
 };
 
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_core.h b/drivers/soc/qcom/msm_bus/msm_bus_core.h
index ee67ac0..1abfa964 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_core.h
+++ b/drivers/soc/qcom/msm_bus/msm_bus_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -54,6 +54,7 @@ enum msm_bus_hw_sel {
 	MSM_BUS_RPM = 0,
 	MSM_BUS_NOC,
 	MSM_BUS_BIMC,
+	MSM_BUS_QNOC,
 };
 
 struct msm_bus_arb_ops {
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
index fcfde73..e0c10c8 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, 2018, Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2019, 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
@@ -477,6 +477,9 @@ static void msm_bus_fab_init_noc_ops(struct msm_bus_node_device_type *bus_dev)
 	case MSM_BUS_BIMC:
 		msm_bus_bimc_set_ops(bus_dev);
 		break;
+	case MSM_BUS_QNOC:
+		msm_bus_qnoc_set_ops(bus_dev);
+		break;
 	default:
 		MSM_BUS_ERR("%s: Invalid Bus type", __func__);
 	}
@@ -829,6 +832,9 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata,
 	node_info->qos_params.mode = pdata_node_info->qos_params.mode;
 	node_info->qos_params.prio1 = pdata_node_info->qos_params.prio1;
 	node_info->qos_params.prio0 = pdata_node_info->qos_params.prio0;
+	node_info->qos_params.prio_dflt = pdata_node_info->qos_params.prio_dflt;
+	node_info->qos_params.urg_fwd_en =
+				pdata_node_info->qos_params.urg_fwd_en;
 	node_info->qos_params.reg_prio1 = pdata_node_info->qos_params.reg_prio1;
 	node_info->qos_params.reg_prio0 = pdata_node_info->qos_params.reg_prio0;
 	node_info->qos_params.prio_lvl = pdata_node_info->qos_params.prio_lvl;
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index 772f0a73..c78bfa60 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.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
@@ -735,6 +735,26 @@ static void bcm_commit_single_req(struct msm_bus_node_device_type *cur_bcm,
 	kfree(cmd_active);
 }
 
+void msm_bus_commit_single(struct device *dev)
+{
+	struct msm_bus_node_device_type *bus_dev;
+	struct msm_bus_node_device_type *bcm_dev;
+
+	if (!dev)
+		return;
+
+	bus_dev = to_msm_bus_node(dev);
+	if (!bus_dev)
+		return;
+
+	bcm_dev = to_msm_bus_node(bus_dev->node_info->bcm_devs[0]);
+	if (!bcm_dev)
+		return;
+
+	bcm_commit_single_req(bcm_dev, bcm_dev->node_vec[DUAL_CTX].vec_a,
+				bcm_dev->node_vec[DUAL_CTX].vec_b);
+}
+
 void *msm_bus_realloc_devmem(struct device *dev, void *p, size_t old_size,
 					size_t new_size, gfp_t flags)
 {
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c
index 1426685..34a0c5c 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c
@@ -190,6 +190,12 @@ static void get_qos_params(
 	of_property_read_u32(dev_node, "qcom,prio-wr",
 						&node_info->qos_params.prio_wr);
 
+	of_property_read_u32(dev_node, "qcom,prio",
+					&node_info->qos_params.prio_dflt);
+
+	node_info->qos_params.urg_fwd_en = of_property_read_bool(dev_node,
+						"qcom,forwarding");
+
 	of_property_read_u32(dev_node, "qcom,gp",
 						&node_info->qos_params.gp);
 
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_qnoc_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_qnoc_adhoc.c
new file mode 100644
index 0000000..370bcd0
--- /dev/null
+++ b/drivers/soc/qcom/msm_bus/msm_bus_qnoc_adhoc.c
@@ -0,0 +1,259 @@
+/* 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/io.h>
+#include "msm_bus_adhoc.h"
+#include "msm_bus_core.h"
+#include "msm_bus_noc.h"
+
+/* NOC_QOS generic */
+#define NOC_QOS_REG_BASE(b, o)		((b) + (o))
+
+#define NOC_QOS_MAINCTL_LOWn_ADDR(b, o, n, d)	\
+	(NOC_QOS_REG_BASE(b, o) + 0x8 + (d) * (n))
+enum noc_qos_id_mainctl_lown {
+	NOC_QOS_MCTL_DFLT_PRIOn_BMSK	= 0x00000070,
+	NOC_QOS_MCTL_DFLT_PRIOn_SHFT	= 0x4,
+	NOC_QOS_MCTL_URGFWD_ENn_BMSK	= 0x00000008,
+	NOC_QOS_MCTL_URGFWD_ENn_SHFT	= 0x3,
+	NOC_QOS_MCTL_LIMIT_ENn_BMSK	= 0x00000001,
+	NOC_QOS_MCTL_LIMIT_ENn_SHFT	= 0x0,
+};
+
+#define NOC_QOS_LIMITBWn_ADDR(b, o, n, d)	\
+	(NOC_QOS_REG_BASE(b, o) + 0x18 + (d) * (n))
+enum noc_qos_id_limitbwn {
+	NOC_QOS_LIMITBW_BWn_BMSK	= 0x000007FF,
+	NOC_QOS_LIMITBW_BWn_SHFT	= 0x0,
+	NOC_QOS_LIMITBW_SATn_BMSK	= 0x03FF0000,
+	NOC_QOS_LIMITBW_SATn_SHFT	= 0x11,
+};
+
+#define NOC_QOS_REGUL0CTLn_ADDR(b, o, n, d)	\
+	(NOC_QOS_REG_BASE(b, o) + 0x40 + (d) * (n))
+enum noc_qos_id_regul0ctln {
+	NOC_QOS_REGUL0CTL_HI_PRIOn_BMSK	= 0x00007000,
+	NOC_QOS_REGUL0CTL_HI_PRIOn_SHFT	= 0x8,
+	NOC_QOS_REGUL0CTL_LW_PRIOn_BMSK	= 0x00000700,
+	NOC_QOS_REGUL0CTL_LW_PRIOn_SHFT	= 0xC,
+	NOC_QOS_REGUL0CTL_WRENn_BMSK	= 0x00000002,
+	NOC_QOS_REGUL0CTL_WRENn_SHFT	= 0x1,
+	NOC_QOS_REGUL0CTL_RDENn_BMSK	= 0x00000001,
+	NOC_QOS_REGUL0CTL_RDENn_SHFT	= 0x0,
+};
+
+#define NOC_QOS_REGUL0BWn_ADDR(b, o, n, d)	\
+	(NOC_QOS_REG_BASE(b, o) + 0x48 + (d) * (n))
+enum noc_qos_id_regul0bwbwn {
+	NOC_QOS_REGUL0BW_BWn_BMSK	= 0x000007FF,
+	NOC_QOS_REGUL0BW_BWn_SHFT	= 0x0,
+	NOC_QOS_REGUL0BW_SATn_BMSK	= 0x03FF0000,
+	NOC_QOS_REGUL0BW_SATn_SHFT	= 0x11,
+};
+
+static void noc_set_qos_dflt_prio(void __iomem *base, uint32_t qos_off,
+		uint32_t mport, uint32_t qos_delta,
+		uint32_t prio)
+{
+	uint32_t reg_val, val;
+
+	reg_val = readl_relaxed(NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport,
+		qos_delta));
+	val = prio << NOC_QOS_MCTL_DFLT_PRIOn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_MCTL_DFLT_PRIOn_BMSK))) |
+		(val & NOC_QOS_MCTL_DFLT_PRIOn_BMSK)),
+		NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta));
+
+	/* Ensure qos priority is set before exiting */
+	wmb();
+}
+
+static void noc_set_qos_limiter(void __iomem *base, uint32_t qos_off,
+		uint32_t mport, uint32_t qos_delta,
+		struct msm_bus_noc_limiter *lim, uint32_t lim_en)
+{
+	uint32_t reg_val, val;
+
+	reg_val = readl_relaxed(NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport,
+		qos_delta));
+
+	writel_relaxed((reg_val & (~(NOC_QOS_MCTL_LIMIT_ENn_BMSK))),
+		NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta));
+
+	/* Ensure we disable limiter before config*/
+	wmb();
+
+	reg_val = readl_relaxed(NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport,
+		qos_delta));
+	val = lim->bw << NOC_QOS_LIMITBW_BWn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_LIMITBW_BWn_BMSK))) |
+		(val & NOC_QOS_LIMITBW_BWn_BMSK)),
+		NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport, qos_delta));
+
+	reg_val = readl_relaxed(NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport,
+		qos_delta));
+	val = lim->sat << NOC_QOS_LIMITBW_SATn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_LIMITBW_SATn_BMSK))) |
+		(val & NOC_QOS_LIMITBW_SATn_BMSK)),
+		NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport, qos_delta));
+
+	/* Ensure qos limiter settings in place before possibly enabling */
+	wmb();
+
+	reg_val = readl_relaxed(NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport,
+		qos_delta));
+	val = lim_en << NOC_QOS_MCTL_LIMIT_ENn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_MCTL_LIMIT_ENn_BMSK))) |
+		(val & NOC_QOS_MCTL_LIMIT_ENn_BMSK)),
+		NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta));
+
+	/* Ensure qos limiter writes take place before exiting*/
+	wmb();
+}
+
+static void noc_set_qos_regulator(void __iomem *base, uint32_t qos_off,
+		uint32_t mport, uint32_t qos_delta,
+		struct msm_bus_noc_regulator *reg,
+		struct msm_bus_noc_regulator_mode *reg_mode)
+{
+	uint32_t reg_val, val;
+
+	reg_val = readl_relaxed(NOC_QOS_REGUL0CTLn_ADDR(base, qos_off, mport,
+		qos_delta)) & (NOC_QOS_REGUL0CTL_WRENn_BMSK |
+						NOC_QOS_REGUL0CTL_RDENn_BMSK);
+
+	writel_relaxed((reg_val & (~(NOC_QOS_REGUL0CTL_WRENn_BMSK |
+						NOC_QOS_REGUL0CTL_RDENn_BMSK))),
+		NOC_QOS_REGUL0CTLn_ADDR(base, qos_off, mport, qos_delta));
+
+	/* Ensure qos regulator is disabled before configuring */
+	wmb();
+
+	reg_val = readl_relaxed(NOC_QOS_REGUL0CTLn_ADDR(base, qos_off, mport,
+		qos_delta)) & NOC_QOS_REGUL0CTL_HI_PRIOn_BMSK;
+	val = reg->hi_prio << NOC_QOS_REGUL0CTL_HI_PRIOn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_REGUL0CTL_HI_PRIOn_BMSK))) |
+		(val & NOC_QOS_REGUL0CTL_HI_PRIOn_BMSK)),
+		NOC_QOS_REGUL0CTLn_ADDR(base, qos_off, mport, qos_delta));
+
+	reg_val = readl_relaxed(NOC_QOS_REGUL0CTLn_ADDR(base, qos_off, mport,
+		qos_delta)) & NOC_QOS_REGUL0CTL_LW_PRIOn_BMSK;
+	val = reg->low_prio << NOC_QOS_REGUL0CTL_LW_PRIOn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_REGUL0CTL_LW_PRIOn_BMSK))) |
+		(val & NOC_QOS_REGUL0CTL_LW_PRIOn_BMSK)),
+		NOC_QOS_REGUL0CTLn_ADDR(base, qos_off, mport, qos_delta));
+
+	reg_val = readl_relaxed(NOC_QOS_REGUL0BWn_ADDR(base, qos_off, mport,
+		qos_delta)) & NOC_QOS_REGUL0BW_BWn_BMSK;
+	val = reg->bw << NOC_QOS_REGUL0BW_BWn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_REGUL0BW_BWn_BMSK))) |
+		(val & NOC_QOS_REGUL0BW_BWn_BMSK)),
+		NOC_QOS_REGUL0BWn_ADDR(base, qos_off, mport, qos_delta));
+
+	reg_val = readl_relaxed(NOC_QOS_REGUL0BWn_ADDR(base, qos_off, mport,
+		qos_delta)) & NOC_QOS_REGUL0BW_SATn_BMSK;
+	val = reg->sat << NOC_QOS_REGUL0BW_SATn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_REGUL0BW_SATn_BMSK))) |
+		(val & NOC_QOS_REGUL0BW_SATn_BMSK)),
+		NOC_QOS_REGUL0BWn_ADDR(base, qos_off, mport, qos_delta));
+
+	/* Ensure regulator is configured before possibly enabling */
+	wmb();
+
+	reg_val = readl_relaxed(NOC_QOS_REGUL0CTLn_ADDR(base, qos_off, mport,
+		qos_delta));
+	val = reg_mode->write << NOC_QOS_REGUL0CTL_WRENn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_REGUL0CTL_WRENn_BMSK))) |
+		(val & NOC_QOS_REGUL0CTL_WRENn_BMSK)),
+		NOC_QOS_REGUL0CTLn_ADDR(base, qos_off, mport, qos_delta));
+
+	reg_val = readl_relaxed(NOC_QOS_REGUL0CTLn_ADDR(base, qos_off, mport,
+		qos_delta));
+	val = reg_mode->read << NOC_QOS_REGUL0CTL_RDENn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_REGUL0CTL_RDENn_BMSK))) |
+		(val & NOC_QOS_REGUL0CTL_RDENn_BMSK)),
+		NOC_QOS_REGUL0CTLn_ADDR(base, qos_off, mport, qos_delta));
+
+	/* Ensure regulator is ready before exiting */
+	wmb();
+}
+
+static void noc_set_qos_forwarding(void __iomem *base, uint32_t qos_off,
+		uint32_t mport, uint32_t qos_delta,
+		bool urg_fwd_en)
+{
+	uint32_t reg_val, val;
+
+	reg_val = readl_relaxed(NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport,
+		qos_delta));
+	val = (urg_fwd_en ? 1:0) << NOC_QOS_MCTL_URGFWD_ENn_SHFT;
+	writel_relaxed(((reg_val & (~(NOC_QOS_MCTL_URGFWD_ENn_BMSK))) |
+		(val & NOC_QOS_MCTL_URGFWD_ENn_BMSK)),
+		NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta));
+
+	/* Ensure qos priority is set before exiting */
+	wmb();
+}
+
+static int msm_bus_noc_qos_init(struct msm_bus_node_device_type *info,
+				void __iomem *qos_base,
+				uint32_t qos_off, uint32_t qos_delta,
+				uint32_t qos_freq)
+{
+	struct qos_params_type *qos_params;
+	int ret = 0;
+	int i;
+
+	qos_params = &info->node_info->qos_params;
+
+	if (!info->node_info->qport) {
+		MSM_BUS_DBG("No QoS Ports to init\n");
+		ret = 0;
+		goto err_qos_init;
+	}
+
+	for (i = 0; i < info->node_info->num_qports; i++) {
+		noc_set_qos_dflt_prio(qos_base, qos_off,
+					info->node_info->qport[i],
+					qos_delta,
+					qos_params->prio_dflt);
+
+		noc_set_qos_limiter(qos_base, qos_off,
+					info->node_info->qport[i],
+					qos_delta,
+					&qos_params->limiter,
+					qos_params->limiter_en);
+
+		noc_set_qos_regulator(qos_base, qos_off,
+					info->node_info->qport[i],
+					qos_delta,
+					&qos_params->reg,
+					&qos_params->reg_mode);
+
+		noc_set_qos_forwarding(qos_base, qos_off,
+					info->node_info->qport[i],
+					qos_delta,
+					qos_params->urg_fwd_en);
+	}
+err_qos_init:
+	return ret;
+}
+
+int msm_bus_qnoc_set_ops(struct msm_bus_node_device_type *bus_dev)
+{
+	if (!bus_dev)
+		return -ENODEV;
+
+	bus_dev->fabdev->noc_ops.qos_init = msm_bus_noc_qos_init;
+
+	return 0;
+}
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h b/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
index ffa6f92..ba752c6 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
+++ b/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
@@ -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
@@ -242,6 +242,7 @@ static inline struct msm_bus_node_device_type *to_msm_bus_node(struct device *d)
 int msm_bus_enable_limiter(struct msm_bus_node_device_type *nodedev,
 				int throttle_en, uint64_t lim_bw);
 int msm_bus_commit_data(struct list_head *clist);
+void msm_bus_commit_single(struct device *dev);
 int bcm_remove_handoff_req(struct device *dev, void *data);
 int commit_late_init_data(bool lock);
 int msm_bus_query_gen(struct list_head *qlist,
diff --git a/drivers/soc/qcom/qmi_encdec.c b/drivers/soc/qcom/qmi_encdec.c
index f14847a..4f18327 100644
--- a/drivers/soc/qcom/qmi_encdec.c
+++ b/drivers/soc/qcom/qmi_encdec.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, 2017, 2019 The Linux Foundation. All rights reserved.
  * Copyright (C) 2017 Linaro Ltd.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -543,8 +543,8 @@ static int qmi_decode_string_elem(struct qmi_elem_info *ei_array,
 		decoded_bytes += rc;
 	}
 
-	if (string_len > temp_ei->elem_len) {
-		pr_err("%s: String len %d > Max Len %d\n",
+	if (string_len >= temp_ei->elem_len) {
+		pr_err("%s: String len %d >= Max Len %d\n",
 		       __func__, string_len, temp_ei->elem_len);
 		return -ETOOSMALL;
 	} else if (string_len > tlv_len) {
diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
index c6800eb..381f224 100644
--- a/drivers/soc/qcom/qmi_interface.c
+++ b/drivers/soc/qcom/qmi_interface.c
@@ -454,6 +454,7 @@ static void qmi_handle_net_reset(struct qmi_handle *qmi)
 	struct sockaddr_qrtr sq;
 	struct qmi_service *svc;
 	struct socket *sock;
+	long timeo = qmi->sock->sk->sk_sndtimeo;
 
 	sock = qmi_sock_create(qmi, &sq);
 	if (IS_ERR(sock))
@@ -473,6 +474,7 @@ static void qmi_handle_net_reset(struct qmi_handle *qmi)
 	sock_release(qmi->sock);
 	qmi->sock = sock;
 	qmi->sq = sq;
+	qmi->sock->sk->sk_sndtimeo = timeo;
 	mutex_unlock(&qmi->sock_lock);
 
 	list_for_each_entry(svc, &qmi->lookups, list_node)
@@ -624,6 +626,21 @@ static struct socket *qmi_sock_create(struct qmi_handle *qmi,
 }
 
 /**
+ * qmi_set_sndtimeo() - set the sk_sndtimeo of the qmi handle
+ * @qmi:	QMI client handle
+ * @timeo:	timeout in jiffies.
+ *
+ * This sets the timeout for the blocking socket send in qmi send.
+ */
+void qmi_set_sndtimeo(struct qmi_handle *qmi, long timeo)
+{
+	mutex_lock(&qmi->sock_lock);
+	qmi->sock->sk->sk_sndtimeo = timeo;
+	mutex_unlock(&qmi->sock_lock);
+}
+EXPORT_SYMBOL(qmi_set_sndtimeo);
+
+/**
  * qmi_handle_init() - initialize a QMI client handle
  * @qmi:	QMI handle to initialize
  * @max_msg_len: maximum size of incoming message
@@ -789,7 +806,7 @@ static ssize_t qmi_send_message(struct qmi_handle *qmi,
 	if (qmi->sock) {
 		ret = kernel_sendmsg(qmi->sock, &msghdr, &iv, 1, len);
 		if (ret < 0)
-			pr_err("failed to send QMI message\n");
+			pr_info("failed to send QMI message %d\n", ret);
 	} else {
 		ret = -EPIPE;
 	}
diff --git a/drivers/soc/qcom/qmi_rmnet.c b/drivers/soc/qcom/qmi_rmnet.c
index b04796e..8a45bb3 100644
--- a/drivers/soc/qcom/qmi_rmnet.c
+++ b/drivers/soc/qcom/qmi_rmnet.c
@@ -453,7 +453,7 @@ __qmi_rmnet_delete_client(void *port, struct qmi_info *qmi, int idx)
 		qmi->dfc_pending[idx] = NULL;
 	}
 
-	if (!qmi_rmnet_has_client(qmi)) {
+	if (!qmi_rmnet_has_client(qmi) && !qmi_rmnet_has_pending(qmi)) {
 		rmnet_reset_qmi_pt(port);
 		kfree(qmi);
 		return 0;
@@ -481,6 +481,8 @@ qmi_rmnet_delete_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm)
 		wda_qmi_client_exit(data);
 		qmi->wda_client = NULL;
 		qmi->wda_pending = NULL;
+	} else {
+		qmi_rmnet_flush_ps_wq();
 	}
 
 	__qmi_rmnet_delete_client(port, qmi, idx);
@@ -575,7 +577,7 @@ void qmi_rmnet_enable_all_flows(struct net_device *dev)
 {
 	struct qos_info *qos;
 	struct rmnet_bearer_map *bearer;
-	int do_wake = 0;
+	bool do_wake;
 
 	qos = (struct qos_info *)rmnet_get_qos_pt(dev);
 	if (!qos)
@@ -584,25 +586,49 @@ void qmi_rmnet_enable_all_flows(struct net_device *dev)
 	spin_lock_bh(&qos->qos_lock);
 
 	list_for_each_entry(bearer, &qos->bearer_head, list) {
-		bearer->grant_before_ps = bearer->grant_size;
-		bearer->seq_before_ps = bearer->seq;
+		if (bearer->tx_off)
+			continue;
+		do_wake = !bearer->grant_size;
 		bearer->grant_size = DEFAULT_GRANT;
 		bearer->grant_thresh = DEFAULT_GRANT;
 		bearer->seq = 0;
 		bearer->ack_req = 0;
-		bearer->ancillary = 0;
-		do_wake = 1;
-	}
+		bearer->tcp_bidir = false;
+		bearer->rat_switch = false;
 
-	if (do_wake) {
-		netif_tx_wake_all_queues(dev);
-		trace_dfc_qmi_tc(dev->name, 0xFF, 0, DEFAULT_GRANT, 0, 0, 1);
+		if (do_wake)
+			dfc_bearer_flow_ctl(dev, bearer, qos);
 	}
 
 	spin_unlock_bh(&qos->qos_lock);
 }
 EXPORT_SYMBOL(qmi_rmnet_enable_all_flows);
 
+bool qmi_rmnet_all_flows_enabled(struct net_device *dev)
+{
+	struct qos_info *qos;
+	struct rmnet_bearer_map *bearer;
+	bool ret = true;
+
+	qos = (struct qos_info *)rmnet_get_qos_pt(dev);
+	if (!qos)
+		return true;
+
+	spin_lock_bh(&qos->qos_lock);
+
+	list_for_each_entry(bearer, &qos->bearer_head, list) {
+		if (!bearer->grant_size) {
+			ret = false;
+			break;
+		}
+	}
+
+	spin_unlock_bh(&qos->qos_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(qmi_rmnet_all_flows_enabled);
+
 #ifdef CONFIG_QCOM_QMI_DFC
 void qmi_rmnet_burst_fc_check(struct net_device *dev,
 			      int ip_type, u32 mark, unsigned int len)
@@ -713,7 +739,7 @@ EXPORT_SYMBOL(qmi_rmnet_qos_exit);
 #ifdef CONFIG_QCOM_QMI_POWER_COLLAPSE
 static struct workqueue_struct  *rmnet_ps_wq;
 static struct rmnet_powersave_work *rmnet_work;
-static struct list_head ps_list;
+static LIST_HEAD(ps_list);
 
 struct rmnet_powersave_work {
 	struct delayed_work work;
@@ -798,13 +824,12 @@ int qmi_rmnet_set_powersave_mode(void *port, uint8_t enable)
 }
 EXPORT_SYMBOL(qmi_rmnet_set_powersave_mode);
 
-void qmi_rmnet_work_restart(void *port)
+static void qmi_rmnet_work_restart(void *port)
 {
 	if (!rmnet_ps_wq || !rmnet_work)
 		return;
 	queue_delayed_work(rmnet_ps_wq, &rmnet_work->work, NO_DELAY);
 }
-EXPORT_SYMBOL(qmi_rmnet_work_restart);
 
 static void qmi_rmnet_check_stats(struct work_struct *work)
 {
@@ -812,6 +837,7 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
 	struct qmi_info *qmi;
 	u64 rxd, txd;
 	u64 rx, tx;
+	bool dl_msg_active;
 
 	real_work = container_of(to_delayed_work(work),
 				 struct rmnet_powersave_work, work);
@@ -824,17 +850,15 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
 		return;
 
 	if (qmi->ps_enabled) {
-		/* Retry after small delay if qmi error
-		 * This resumes UL grants by disabling
-		 * powersave mode if successful.
-		 */
+		/* Register to get QMI DFC and DL marker */
 		if (qmi_rmnet_set_powersave_mode(real_work->port, 0) < 0) {
+			/* If this failed need to retry quickly */
 			queue_delayed_work(rmnet_ps_wq,
 					   &real_work->work, HZ / 50);
 			return;
 
 		}
-		qmi->ps_enabled = 0;
+		qmi->ps_enabled = false;
 
 		if (rmnet_get_powersave_notif(real_work->port))
 			qmi_rmnet_ps_off_notify(real_work->port);
@@ -849,18 +873,29 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
 	real_work->old_rx_pkts = rx;
 	real_work->old_tx_pkts = tx;
 
+	dl_msg_active = qmi->dl_msg_active;
+	qmi->dl_msg_active = false;
+
 	if (!rxd && !txd) {
+		/* If no DL msg received and there is a flow disabled,
+		 * (likely in RLF), no need to enter powersave
+		 */
+		if (!dl_msg_active &&
+		    !rmnet_all_flows_enabled(real_work->port))
+			goto end;
+
+		/* Deregister to suppress QMI DFC and DL marker */
 		if (qmi_rmnet_set_powersave_mode(real_work->port, 1) < 0) {
 			queue_delayed_work(rmnet_ps_wq,
 					   &real_work->work, PS_INTERVAL);
 			return;
 		}
-		qmi->ps_enabled = 1;
-		clear_bit(PS_WORK_ACTIVE_BIT, &qmi->ps_work_active);
+		qmi->ps_enabled = true;
 
-		/* Enable flow after clear the bit so a new
-		 * work can be triggered.
+		/* Clear the bit before enabling flow so pending packets
+		 * can trigger the work again
 		 */
+		clear_bit(PS_WORK_ACTIVE_BIT, &qmi->ps_work_active);
 		rmnet_enable_all_flows(real_work->port);
 
 		if (rmnet_get_powersave_notif(real_work->port))
@@ -900,7 +935,6 @@ void qmi_rmnet_work_init(void *port)
 		rmnet_ps_wq = NULL;
 		return;
 	}
-	INIT_LIST_HEAD(&ps_list);
 	INIT_DEFERRABLE_WORK(&rmnet_work->work, qmi_rmnet_check_stats);
 	rmnet_work->port = port;
 	rmnet_get_packets(rmnet_work->port, &rmnet_work->old_rx_pkts,
@@ -936,4 +970,22 @@ void qmi_rmnet_work_exit(void *port)
 	rmnet_work = NULL;
 }
 EXPORT_SYMBOL(qmi_rmnet_work_exit);
+
+void qmi_rmnet_set_dl_msg_active(void *port)
+{
+	struct qmi_info *qmi;
+
+	qmi = (struct qmi_info *)rmnet_get_qmi_pt(port);
+	if (unlikely(!qmi))
+		return;
+
+	qmi->dl_msg_active = true;
+}
+EXPORT_SYMBOL(qmi_rmnet_set_dl_msg_active);
+
+void qmi_rmnet_flush_ps_wq(void)
+{
+	if (rmnet_ps_wq)
+		flush_workqueue(rmnet_ps_wq);
+}
 #endif
diff --git a/drivers/soc/qcom/qmi_rmnet_i.h b/drivers/soc/qcom/qmi_rmnet_i.h
index 0e10429..bfea572 100644
--- a/drivers/soc/qcom/qmi_rmnet_i.h
+++ b/drivers/soc/qcom/qmi_rmnet_i.h
@@ -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
@@ -41,9 +41,11 @@ struct rmnet_bearer_map {
 	u32 grant_thresh;
 	u16 seq;
 	u8  ack_req;
-	u32 grant_before_ps;
-	u16 seq_before_ps;
-	u32 ancillary;
+	u32 last_grant;
+	u16 last_seq;
+	bool tcp_bidir;
+	bool rat_switch;
+	bool tx_off;
 };
 
 struct svc_info {
@@ -74,7 +76,8 @@ struct qmi_info {
 	void *dfc_clients[MAX_CLIENT_NUM];
 	void *dfc_pending[MAX_CLIENT_NUM];
 	unsigned long ps_work_active;
-	int ps_enabled;
+	bool ps_enabled;
+	bool dl_msg_active;
 };
 
 enum data_ep_type_enum_v01 {
@@ -120,6 +123,10 @@ int qmi_rmnet_flow_control(struct net_device *dev, u32 tcm_handle, int enable);
 void dfc_qmi_wq_flush(struct qmi_info *qmi);
 
 void dfc_qmi_query_flow(void *dfc_data);
+
+int dfc_bearer_flow_ctl(struct net_device *dev,
+			struct rmnet_bearer_map *bearer,
+			struct qos_info *qos);
 #else
 static inline struct rmnet_flow_map *
 qmi_rmnet_get_flow_map(struct qos_info *qos_info,
@@ -160,6 +167,14 @@ static inline void
 dfc_qmi_query_flow(void *dfc_data)
 {
 }
+
+static inline int
+dfc_bearer_flow_ctl(struct net_device *dev,
+		    struct rmnet_bearer_map *bearer,
+		    struct qos_info *qos)
+{
+	return 0;
+}
 #endif
 
 #ifdef CONFIG_QCOM_QMI_POWER_COLLAPSE
@@ -167,6 +182,7 @@ int
 wda_qmi_client_init(void *port, struct svc_info *psvc, struct qmi_info *qmi);
 void wda_qmi_client_exit(void *wda_data);
 int wda_set_powersave_mode(void *wda_data, u8 enable);
+void qmi_rmnet_flush_ps_wq(void);
 #else
 static inline int
 wda_qmi_client_init(void *port, struct svc_info *psvc, struct qmi_info *qmi)
@@ -182,5 +198,8 @@ static inline int wda_set_powersave_mode(void *wda_data, u8 enable)
 {
 	return -EINVAL;
 }
+static inline void qmi_rmnet_flush_ps_wq(void)
+{
+}
 #endif
 #endif /*_RMNET_QMI_I_H*/
diff --git a/drivers/soc/qcom/ramdump.c b/drivers/soc/qcom/ramdump.c
index 62b0204..fc2ef00 100644
--- a/drivers/soc/qcom/ramdump.c
+++ b/drivers/soc/qcom/ramdump.c
@@ -514,19 +514,19 @@ static int _do_ramdump(void *handle, struct ramdump_segment *segments,
 }
 
 static inline unsigned int set_section_name(const char *name,
-					    struct elfhdr *ehdr)
+					    struct elfhdr *ehdr,
+					    int *strtable_idx)
 {
 	char *strtab = elf_str_table(ehdr);
-	static int strtable_idx = 1;
 	int idx, ret = 0;
 
-	idx = strtable_idx;
+	idx = *strtable_idx;
 	if ((strtab == NULL) || (name == NULL))
 		return 0;
 
 	ret = idx;
 	idx += strlcpy((strtab + idx), name, MAX_NAME_LENGTH);
-	strtable_idx = idx + 1;
+	*strtable_idx = idx + 1;
 
 	return ret;
 }
@@ -540,6 +540,7 @@ static int _do_minidump(void *handle, struct ramdump_segment *segments,
 	struct elfhdr *ehdr;
 	struct elf_shdr *shdr;
 	unsigned long offset, strtbl_off;
+	int strtable_idx = 1;
 
 	/*
 	 * Acquire the consumer lock here, and hold the lock until we are done
@@ -595,13 +596,14 @@ static int _do_minidump(void *handle, struct ramdump_segment *segments,
 	shdr->sh_size = MAX_STRTBL_SIZE;
 	shdr->sh_entsize = 0;
 	shdr->sh_flags = 0;
-	shdr->sh_name = set_section_name("STR_TBL", ehdr);
+	shdr->sh_name = set_section_name("STR_TBL", ehdr, &strtable_idx);
 	shdr++;
 
 	for (i = 0; i < nsegments; i++, shdr++) {
 		/* Update elf header */
 		shdr->sh_type = SHT_PROGBITS;
-		shdr->sh_name = set_section_name(segments[i].name, ehdr);
+		shdr->sh_name = set_section_name(segments[i].name, ehdr,
+							&strtable_idx);
 		shdr->sh_addr = (elf_addr_t)segments[i].address;
 		shdr->sh_size = segments[i].size;
 		shdr->sh_flags = SHF_WRITE;
diff --git a/drivers/soc/qcom/rpmh_master_stat.c b/drivers/soc/qcom/rpmh_master_stat.c
index 22704b8..98ca413 100644
--- a/drivers/soc/qcom/rpmh_master_stat.c
+++ b/drivers/soc/qcom/rpmh_master_stat.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
@@ -41,6 +41,7 @@ enum master_smem_id {
 	SLPI,
 	GPU,
 	DISPLAY,
+	SLPI_ISLAND = 613,
 };
 
 enum master_pid {
@@ -70,8 +71,10 @@ struct msm_rpmh_master_data {
 static const struct msm_rpmh_master_data rpmh_masters[] = {
 	{"MPSS", MPSS, PID_MPSS},
 	{"ADSP", ADSP, PID_ADSP},
+	{"ADSP_ISLAND", SLPI_ISLAND, PID_ADSP},
 	{"CDSP", CDSP, PID_CDSP},
 	{"SLPI", SLPI, PID_SLPI},
+	{"SLPI_ISLAND", SLPI_ISLAND, PID_SLPI},
 	{"GPU", GPU, PID_GPU},
 	{"DISPLAY", DISPLAY, PID_DISPLAY},
 };
diff --git a/drivers/soc/qcom/smcinvoke.c b/drivers/soc/qcom/smcinvoke.c
index 46304b2..7f95bb2 100644
--- a/drivers/soc/qcom/smcinvoke.c
+++ b/drivers/soc/qcom/smcinvoke.c
@@ -1,7 +1,7 @@
 /*
  * SMC Invoke driver
  *
- * 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
@@ -134,6 +134,10 @@
 #define FILE_IS_REMOTE_OBJ(f) ((f)->f_op && (f)->f_op == &g_smcinvoke_fops)
 
 static DEFINE_MUTEX(g_smcinvoke_lock);
+#define NO_LOCK 0
+#define TAKE_LOCK 1
+#define MUTEX_LOCK(x) { if (x) mutex_lock(&g_smcinvoke_lock); }
+#define MUTEX_UNLOCK(x) { if (x) mutex_unlock(&g_smcinvoke_lock); }
 static DEFINE_HASHTABLE(g_cb_servers, 8);
 static LIST_HEAD(g_mem_objs);
 static uint16_t g_last_cb_server_id = CBOBJ_SERVER_ID_START;
@@ -143,6 +147,7 @@ static size_t g_max_cb_buf_size = SMCINVOKE_TZ_MIN_BUF_SIZE;
 static long smcinvoke_ioctl(struct file *, unsigned int, unsigned long);
 static int smcinvoke_open(struct inode *, struct file *);
 static int smcinvoke_release(struct inode *, struct file *);
+static int destroy_cb_server(uint16_t);
 
 static const struct file_operations g_smcinvoke_fops = {
 	.owner		= THIS_MODULE,
@@ -280,10 +285,8 @@ static  struct smcinvoke_mem_obj *find_mem_obj_locked(uint16_t mem_obj_id,
 {
 	struct smcinvoke_mem_obj *mem_obj = NULL;
 
-	if (list_empty(&g_mem_objs)) {
-		pr_err("%s: mem obj %d not found\n", __func__, mem_obj_id);
+	if (list_empty(&g_mem_objs))
 		return NULL;
-	}
 
 	list_for_each_entry(mem_obj, &g_mem_objs, list) {
 		if ((is_mem_rgn_obj &&
@@ -379,8 +382,10 @@ static void free_pending_cbobj_locked(struct kref *kref)
 	server = obj->server;
 	kfree(obj);
 	if ((server->state == SMCINVOKE_SERVER_STATE_DEFUNCT) &&
-				list_empty(&server->pending_cbobjs))
+				list_empty(&server->pending_cbobjs)) {
+		hash_del(&server->hash);
 		kfree(server);
+	}
 }
 
 static int get_pending_cbobj_locked(uint16_t srvr_id, int16_t obj_id)
@@ -618,10 +623,6 @@ static int get_tzhandle_from_uhandle(int32_t uhandle, int32_t server_fd,
 		}
 	}
 out:
-	if (ret && *filp) {
-		fput(*filp);
-		*filp = NULL;
-	}
 	return ret;
 }
 
@@ -669,7 +670,7 @@ static int get_fd_for_obj(uint32_t obj_type, uint32_t obj, int64_t *fd)
 }
 
 static int get_uhandle_from_tzhandle(int32_t tzhandle, int32_t srvr_id,
-						int64_t *uhandle)
+				int64_t *uhandle, bool lock)
 {
 	int ret = -1;
 
@@ -680,14 +681,14 @@ static int get_uhandle_from_tzhandle(int32_t tzhandle, int32_t srvr_id,
 		if (srvr_id != TZHANDLE_GET_SERVER(tzhandle))
 			goto out;
 		*uhandle = UHANDLE_MAKE_CB_OBJ(TZHANDLE_GET_OBJID(tzhandle));
-		mutex_lock(&g_smcinvoke_lock);
-		ret = get_pending_cbobj_locked(srvr_id,
+		MUTEX_LOCK(lock)
+		ret = get_pending_cbobj_locked(TZHANDLE_GET_SERVER(tzhandle),
 						TZHANDLE_GET_OBJID(tzhandle));
-		mutex_unlock(&g_smcinvoke_lock);
+		MUTEX_UNLOCK(lock)
 	} else if (TZHANDLE_IS_MEM_RGN_OBJ(tzhandle)) {
 		struct smcinvoke_mem_obj *mem_obj =  NULL;
 
-		mutex_lock(&g_smcinvoke_lock);
+		MUTEX_LOCK(lock)
 		mem_obj = find_mem_obj_locked(TZHANDLE_GET_OBJID(tzhandle),
 						SMCINVOKE_MEM_RGN_OBJ);
 
@@ -705,7 +706,7 @@ static int get_uhandle_from_tzhandle(int32_t tzhandle, int32_t srvr_id,
 			ret = 0;
 		}
 exit_lock:
-		mutex_unlock(&g_smcinvoke_lock);
+		MUTEX_UNLOCK(lock)
 	} else if (TZHANDLE_IS_REMOTE(tzhandle)) {
 		/* if execution comes here => tzhandle is an unsigned int */
 		ret = get_fd_for_obj(SMCINVOKE_OBJ_TYPE_TZ_OBJ,
@@ -882,9 +883,7 @@ static void process_tzcb_req(void *buf, size_t buf_len, struct file **arr_filp)
 		    srvr_info->state == SMCINVOKE_SERVER_STATE_DEFUNCT &&
 		    OBJECT_OP_METHODID(cb_req->hdr.op) == OBJECT_OP_RELEASE) {
 			mutex_lock(&g_smcinvoke_lock);
-			put_pending_cbobj_locked(
-				TZHANDLE_GET_SERVER(cb_req->hdr.tzhandle),
-				TZHANDLE_GET_OBJID(cb_req->hdr.tzhandle));
+			release_tzhandle_locked(cb_req->hdr.tzhandle);
 			mutex_unlock(&g_smcinvoke_lock);
 		}
 	}
@@ -937,7 +936,8 @@ static int marshal_out_invoke_req(const uint8_t *buf, uint32_t buf_size,
 		 * to server who serves it and that info comes from USpace.
 		 */
 		ret = get_uhandle_from_tzhandle(tz_args->handle,
-			args_buf[i].o.cb_server_fd, &(args_buf[i].o.fd));
+					TZHANDLE_GET_SERVER(tz_args->handle),
+					&(args_buf[i].o.fd), NO_LOCK);
 		if (ret)
 			goto out;
 		tz_args++;
@@ -1152,7 +1152,7 @@ static int marshal_in_tzcb_req(const struct smcinvoke_cb_txn *cb_txn,
 
 	user_req->txn_id = cb_txn->txn_id;
 	if (get_uhandle_from_tzhandle(tzcb_req->hdr.tzhandle, srvr_id,
-					(int64_t *)&user_req->cbobj_id)) {
+				(int64_t *)&user_req->cbobj_id, TAKE_LOCK)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -1214,7 +1214,7 @@ static int marshal_in_tzcb_req(const struct smcinvoke_cb_txn *cb_txn,
 		 * context
 		 */
 		ret = get_uhandle_from_tzhandle(tz_args[i].handle, srvr_id,
-							&(tmp_arg.o.fd));
+						&(tmp_arg.o.fd), TAKE_LOCK);
 		if (ret) {
 			ret = -EINVAL;
 			goto out;
@@ -1238,10 +1238,8 @@ static int marshal_out_tzcb_req(const struct smcinvoke_accept *user_req,
 	int32_t tzhandles_to_release[OBJECT_COUNTS_MAX_OO] = {0};
 	struct smcinvoke_tzcb_req *tzcb_req = cb_txn->cb_req;
 	union smcinvoke_tz_args *tz_args = tzcb_req->args;
-	put_pending_cbobj_locked(
-			TZHANDLE_GET_SERVER(cb_txn->cb_req->hdr.tzhandle),
-			TZHANDLE_GET_OBJID(cb_txn->cb_req->hdr.tzhandle));
 
+	release_tzhandles(&cb_txn->cb_req->hdr.tzhandle, 1);
 	tzcb_req->result = user_req->result;
 	FOR_ARGS(i, tzcb_req->hdr.counts, BO) {
 		union smcinvoke_arg tmp_arg;
@@ -1271,18 +1269,16 @@ static int marshal_out_tzcb_req(const struct smcinvoke_accept *user_req,
 			ret = -EFAULT;
 			goto out;
 		}
-		ret = get_tzhandle_from_uhandle(tmp_arg.o.fd, 0, &arr_filp[i],
-							&(tz_args[i].handle));
+		ret = get_tzhandle_from_uhandle(tmp_arg.o.fd,
+				tmp_arg.o.cb_server_fd, &arr_filp[i],
+						&(tz_args[i].handle));
 		if (ret)
 			goto out;
 		tzhandles_to_release[i] = tz_args[i].handle;
 	}
 	FOR_ARGS(i, tzcb_req->hdr.counts, OI) {
-		if (TZHANDLE_IS_CB_OBJ(tz_args[i].handle)) {
-			put_pending_cbobj_locked(
-				TZHANDLE_GET_SERVER(tz_args[i].handle),
-				TZHANDLE_GET_OBJID(tz_args[i].handle));
-		}
+		if (TZHANDLE_IS_CB_OBJ(tz_args[i].handle))
+			release_tzhandles(&tz_args[i].handle, 1);
 	}
 	ret = 0;
 out:
@@ -1375,12 +1371,9 @@ static long process_server_req(struct file *filp, unsigned int cmd,
 	ret = get_fd_for_obj(SMCINVOKE_OBJ_TYPE_SERVER,
 				server_info->server_id, &server_fd);
 
-	if (ret) {
-		mutex_lock(&g_smcinvoke_lock);
-		hash_del(&server_info->hash);
-		mutex_unlock(&g_smcinvoke_lock);
-		kfree(server_info);
-	}
+	if (ret)
+		destroy_cb_server(server_info->server_id);
+
 	return server_fd;
 }
 
@@ -1435,9 +1428,7 @@ static long process_accept_req(struct file *filp, unsigned int cmd,
 			cb_txn->cb_req->result = OBJECT_ERROR_UNAVAIL;
 
 		if (OBJECT_OP_METHODID(user_args.op) == OBJECT_OP_RELEASE)
-			put_pending_cbobj_locked(
-			    TZHANDLE_GET_SERVER(cb_txn->cb_req->hdr.tzhandle),
-			    TZHANDLE_GET_OBJID(cb_txn->cb_req->hdr.tzhandle));
+			release_tzhandles(&cb_txn->cb_req->hdr.tzhandle, 1);
 
 		cb_txn->state = SMCINVOKE_REQ_PROCESSED;
 		wake_up(&server_info->rsp_wait_q);
@@ -1455,8 +1446,10 @@ static long process_accept_req(struct file *filp, unsigned int cmd,
 	do {
 		ret = wait_event_interruptible(server_info->req_wait_q,
 				!hash_empty(server_info->reqs_table));
-		if (ret)
+		if (ret) {
+			destroy_cb_server(server_obj->server_id);
 			goto out;
+		}
 
 		mutex_lock(&g_smcinvoke_lock);
 		cb_txn = find_cbtxn_locked(server_info,
@@ -1703,6 +1696,8 @@ static int smcinvoke_release(struct inode *nodp, struct file *filp)
 		goto out;
 	}
 
+	memset(in_buf, 0, PAGE_SIZE);
+	memset(out_buf, 0, PAGE_SIZE);
 	hdr.tzhandle = tzhandle;
 	hdr.op = OBJECT_OP_RELEASE;
 	hdr.counts = 0;
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index e4b1702..004c421 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -344,6 +344,9 @@ static struct msm_soc_info cpu_of_id[] = {
 	/* sm6150 ID */
 	[355] = {MSM_CPU_SM6150, "SM6150"},
 
+	/* sm6150p ID */
+	[369] = {MSM_CPU_SM6150P, "SM6150P"},
+
 	/* qcs405 ID */
 	[352] = {MSM_CPU_QCS405, "QCS405"},
 
@@ -360,6 +363,9 @@ static struct msm_soc_info cpu_of_id[] = {
 	/* sdmmagpie ID */
 	[365] = {MSM_CPU_SDMMAGPIE, "SDMMAGPIE"},
 
+	/* sdmmagpiep ID */
+	[366] = {MSM_CPU_SDMMAGPIEP, "SDMMAGPIEP"},
+
 	/* sa6155P ID */
 	[377] = {MSM_CPU_SA6155P, "SA6155P"},
 
@@ -372,6 +378,15 @@ static struct msm_soc_info cpu_of_id[] = {
 	/* trinket ID */
 	[394] = {MSM_CPU_TRINKET, "TRINKET"},
 
+	/* qcs610 ID */
+	[401] = {MSM_CPU_QCS610, "QCS610"},
+
+	/* qcs410 ID */
+	[406] = {MSM_CPU_QCS410, "QCS410"},
+
+	/* atoll ID */
+	[407] = {MSM_CPU_ATOLL, "ATOLL"},
+
 	/* Uninitialized IDs are not known to run Linux.
 	 * MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
 	 * considered as unknown CPU.
@@ -1256,6 +1271,10 @@ static void * __init setup_dummy_socinfo(void)
 		dummy_socinfo.id = 355;
 		strlcpy(dummy_socinfo.build_id, "sm6150 - ",
 		sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_sm6150p()) {
+		dummy_socinfo.id = 369;
+		strlcpy(dummy_socinfo.build_id, "sm6150p - ",
+		sizeof(dummy_socinfo.build_id));
 	} else if (early_machine_is_qcs405()) {
 		dummy_socinfo.id = 352;
 		strlcpy(dummy_socinfo.build_id, "qcs405 - ",
@@ -1276,6 +1295,10 @@ static void * __init setup_dummy_socinfo(void)
 		dummy_socinfo.id = 365;
 		strlcpy(dummy_socinfo.build_id, "sdmmagpie - ",
 		sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_sdmmagpiep()) {
+		dummy_socinfo.id = 366;
+		strlcpy(dummy_socinfo.build_id, "sdmmagpiep - ",
+		sizeof(dummy_socinfo.build_id));
 	} else if (early_machine_is_sa6155p()) {
 		dummy_socinfo.id = 377;
 		strlcpy(dummy_socinfo.build_id, "sa6155p - ",
@@ -1292,6 +1315,18 @@ static void * __init setup_dummy_socinfo(void)
 		dummy_socinfo.id = 394;
 		strlcpy(dummy_socinfo.build_id, "trinket - ",
 		sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_qcs610()) {
+		dummy_socinfo.id = 401;
+		strlcpy(dummy_socinfo.build_id, "qcs610 - ",
+		sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_qcs410()) {
+		dummy_socinfo.id = 406;
+		strlcpy(dummy_socinfo.build_id, "qcs410 - ",
+		sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_atoll()) {
+		dummy_socinfo.id = 407;
+		strlcpy(dummy_socinfo.build_id, "atoll - ",
+		sizeof(dummy_socinfo.build_id));
 	} else
 		strlcat(dummy_socinfo.build_id, "Dummy socinfo",
 			sizeof(dummy_socinfo.build_id));
diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c
index 1b3e54c..48f71ab 100644
--- a/drivers/soc/qcom/subsystem_restart.c
+++ b/drivers/soc/qcom/subsystem_restart.c
@@ -620,6 +620,22 @@ static int for_each_subsys_device(struct subsys_device **list,
 	return 0;
 }
 
+static void subsys_notif_uevent(struct subsys_desc *desc,
+				enum subsys_notif_type notif)
+{
+	char *envp[3];
+
+	if (notif == SUBSYS_AFTER_POWERUP) {
+		envp[0] = kasprintf(GFP_KERNEL, "SUBSYSTEM=%s", desc->name);
+		envp[1] = kasprintf(GFP_KERNEL, "NOTIFICATION=%d", notif);
+		envp[2] = NULL;
+		kobject_uevent_env(&desc->dev->kobj, KOBJ_CHANGE, envp);
+		pr_debug("%s %s sent\n", envp[0], envp[1]);
+		kfree(envp[1]);
+		kfree(envp[0]);
+	}
+}
+
 static void notify_each_subsys_device(struct subsys_device **list,
 		unsigned int count,
 		enum subsys_notif_type notif, void *data)
@@ -666,6 +682,7 @@ static void notify_each_subsys_device(struct subsys_device **list,
 								&notif_data);
 		cancel_timeout(dev->desc);
 		trace_pil_notif("after_send_notif", notif, dev->desc->fw_name);
+		subsys_notif_uevent(dev->desc, notif);
 	}
 }
 
diff --git a/drivers/soc/qcom/sysmon-qmi.c b/drivers/soc/qcom/sysmon-qmi.c
index e5aad12..9bb278f 100644
--- a/drivers/soc/qcom/sysmon-qmi.c
+++ b/drivers/soc/qcom/sysmon-qmi.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
@@ -655,6 +655,7 @@ int sysmon_notifier_register(struct subsys_desc *desc)
 		kfree(data);
 		return rc;
 	}
+	qmi_set_sndtimeo(&data->clnt_handle, HZ);
 
 	qmi_add_lookup(&data->clnt_handle, SSCTL_SERVICE_ID,
 			SSCTL_VER_2, data->instance_id);
diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
index cd8f413..7bfb154 100644
--- a/drivers/soc/tegra/common.c
+++ b/drivers/soc/tegra/common.c
@@ -22,11 +22,15 @@ static const struct of_device_id tegra_machine_match[] = {
 
 bool soc_is_tegra(void)
 {
+	const struct of_device_id *match;
 	struct device_node *root;
 
 	root = of_find_node_by_path("/");
 	if (!root)
 		return false;
 
-	return of_match_node(tegra_machine_match, root) != NULL;
+	match = of_match_node(tegra_machine_match, root);
+	of_node_put(root);
+
+	return match != NULL;
 }
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index b95b97d..9fcafcd 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -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
@@ -25,6 +25,7 @@
 #include <linux/msm_gpi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi-geni-qcom.h>
+#include <soc/qcom/boot_stats.h>
 
 #define SPI_NUM_CHIPSELECT	(4)
 #define SPI_XFER_TIMEOUT_MS	(250)
@@ -91,7 +92,7 @@
 #define TIMESTAMP_AFTER		BIT(3)
 #define POST_CMD_DELAY		BIT(4)
 
-#define SPI_CORE2X_VOTE		(7600)
+#define SPI_CORE2X_VOTE		(5000)
 /* GSI CONFIG0 TRE Params */
 /* Flags bit fields */
 #define GSI_LOOPBACK_EN		(BIT(0))
@@ -152,6 +153,7 @@ struct spi_geni_master {
 	struct completion tx_cb;
 	struct completion rx_cb;
 	bool qn_err;
+	bool disable_dma_mode;
 	int cur_xfer_mode;
 	int num_tx_eot;
 	int num_rx_eot;
@@ -1063,17 +1065,30 @@ static void setup_fifo_xfer(struct spi_transfer *xfer,
 		mas->rx_rem_bytes = xfer->len;
 	}
 
-	fifo_size =
-		(mas->tx_fifo_depth * mas->tx_fifo_width / mas->cur_word_len);
-	if (trans_len > fifo_size) {
-		if (mas->cur_xfer_mode != SE_DMA) {
-			mas->cur_xfer_mode = SE_DMA;
-			geni_se_select_mode(mas->base, mas->cur_xfer_mode);
-		}
+	/*
+	 * Controller has support to transfer data either in FIFO mode
+	 * or in SE_DMA mode. Either force the controller to choose FIFO
+	 * mode for transfers or select the mode dynamically based on
+	 * size of data.
+	 */
+	if (mas->disable_dma_mode) {
+		mas->cur_xfer_mode = FIFO_MODE;
+		geni_se_select_mode(mas->base, mas->cur_xfer_mode);
 	} else {
-		if (mas->cur_xfer_mode != FIFO_MODE) {
-			mas->cur_xfer_mode = FIFO_MODE;
-			geni_se_select_mode(mas->base, mas->cur_xfer_mode);
+		fifo_size = (mas->tx_fifo_depth *
+				mas->tx_fifo_width / mas->cur_word_len);
+		if (trans_len > fifo_size) {
+			if (mas->cur_xfer_mode != SE_DMA) {
+				mas->cur_xfer_mode = SE_DMA;
+				geni_se_select_mode(mas->base,
+						mas->cur_xfer_mode);
+			}
+		} else {
+			if (mas->cur_xfer_mode != FIFO_MODE) {
+				mas->cur_xfer_mode = FIFO_MODE;
+				geni_se_select_mode(mas->base,
+						mas->cur_xfer_mode);
+			}
 		}
 	}
 
@@ -1432,6 +1447,7 @@ static int spi_geni_probe(struct platform_device *pdev)
 	struct platform_device *wrapper_pdev;
 	struct device_node *wrapper_ph_node;
 	bool rt_pri, slave_en;
+	char boot_marker[40];
 
 	spi = spi_alloc_master(&pdev->dev, sizeof(struct spi_geni_master));
 	if (!spi) {
@@ -1440,6 +1456,10 @@ static int spi_geni_probe(struct platform_device *pdev)
 		goto spi_geni_probe_err;
 	}
 
+	snprintf(boot_marker, sizeof(boot_marker),
+			"M - DRIVER GENI_SPI Init");
+	place_marker(boot_marker);
+
 	platform_set_drvdata(pdev, spi);
 	geni_mas = spi_master_get_devdata(spi);
 	rsc = &geni_mas->spi_rsc;
@@ -1492,11 +1512,16 @@ static int spi_geni_probe(struct platform_device *pdev)
 		goto spi_geni_probe_err;
 	}
 
-	ret = pinctrl_select_state(rsc->geni_pinctrl,
+	geni_mas->disable_dma_mode = of_property_read_bool(pdev->dev.of_node,
+			"qcom,disable-dma");
+	if (!geni_mas->disable_dma_mode) {
+		ret = pinctrl_select_state(rsc->geni_pinctrl,
 					rsc->geni_gpio_sleep);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to set sleep configuration\n");
-		goto spi_geni_probe_err;
+		if (ret) {
+			dev_err(&pdev->dev,
+					"Failed to set sleep configuration\n");
+			goto spi_geni_probe_err;
+		}
 	}
 
 	rsc->se_clk = devm_clk_get(&pdev->dev, "se-clk");
@@ -1608,6 +1633,10 @@ static int spi_geni_probe(struct platform_device *pdev)
 	}
 	sysfs_create_file(&(geni_mas->dev->kobj),
 				&dev_attr_spi_slave_state.attr);
+	snprintf(boot_marker, sizeof(boot_marker),
+			"M - DRIVER GENI_SPI_%d Ready", spi->bus_num);
+	place_marker(boot_marker);
+
 	return ret;
 spi_geni_probe_unmap:
 	devm_iounmap(&pdev->dev, geni_mas->base);
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 9bf1b8f..73556da 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -321,9 +321,9 @@ static void ion_dma_buf_detatch(struct dma_buf *dmabuf,
 	struct ion_buffer *buffer = dmabuf->priv;
 
 	mutex_lock(&buffer->lock);
-	free_duped_table(a->table);
 	list_del(&a->list);
 	mutex_unlock(&buffer->lock);
+	free_duped_table(a->table);
 
 	kfree(a);
 }
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index a602be6..7782183 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -4,7 +4,7 @@
  * Copyright (C) Linaro 2012
  * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
  *
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -214,6 +214,9 @@ static int ion_secure_cma_allocate(
 {
 	int ret;
 
+	if (!(flags & ION_FLAGS_CP_MASK))
+		return -EINVAL;
+
 	ret = ion_cma_allocate(heap, buffer, len, flags);
 	if (ret) {
 		dev_err(heap->priv, "Unable to allocate cma buffer");
@@ -221,8 +224,14 @@ static int ion_secure_cma_allocate(
 	}
 
 	ret = ion_hyp_assign_sg_from_flags(buffer->sg_table, flags, true);
-	if (ret)
-		goto out_free_buf;
+	if (ret) {
+		if (ret == -EADDRNOTAVAIL) {
+			goto out_free_buf;
+		} else {
+			ion_cma_free(buffer);
+			goto out;
+		}
+	}
 
 	return ret;
 
diff --git a/drivers/staging/android/ion/ion_secure_util.c b/drivers/staging/android/ion/ion_secure_util.c
index efbc48b4..5904173 100644
--- a/drivers/staging/android/ion/ion_secure_util.c
+++ b/drivers/staging/android/ion/ion_secure_util.c
@@ -1,6 +1,6 @@
 /*
  *
- * 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
@@ -87,6 +87,9 @@ static int populate_vm_list(unsigned long flags, unsigned int *vm_list,
 	int vmid;
 
 	flags = flags & ION_FLAGS_CP_MASK;
+	if (!flags)
+		return -EINVAL;
+
 	for_each_set_bit(itr, &flags, BITS_PER_LONG) {
 		vmid = get_vmid(0x1UL << itr);
 		if (vmid < 0 || !nelems)
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index 562eba5..723d49b 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -116,8 +116,13 @@ void free_buffer_page(struct ion_system_heap *heap,
 			ion_page_pool_free_immediate(pool, page);
 		else
 			ion_page_pool_free(pool, page);
+
+		mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES,
+				    -(1 << pool->order));
 	} else {
 		__free_pages(page, order);
+		mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES,
+				    -(1 << order));
 	}
 }
 
@@ -164,6 +169,9 @@ static struct page_info *alloc_from_pool_preferred(
 	struct page_info *info;
 	int i;
 
+	if (buffer->flags & ION_FLAG_POOL_FORCE_ALLOC)
+		goto force_alloc;
+
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return ERR_PTR(-ENOMEM);
@@ -195,6 +203,7 @@ static struct page_info *alloc_from_pool_preferred(
 	}
 
 	kfree(info);
+force_alloc:
 	return alloc_largest_available(heap, buffer, size, max_order);
 }
 
@@ -313,6 +322,10 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
 
 		sz = (1 << info->order) * PAGE_SIZE;
 
+		mod_node_page_state(
+				page_pgdat(info->page), NR_UNRECLAIMABLE_PAGES,
+				(1 << (info->order)));
+
 		if (info->from_pool) {
 			list_add_tail(&info->list, &pages_from_pool);
 		} else {
diff --git a/drivers/staging/android/uapi/msm_ion.h b/drivers/staging/android/uapi/msm_ion.h
index 846b769..4a8f8db 100644
--- a/drivers/staging/android/uapi/msm_ion.h
+++ b/drivers/staging/android/uapi/msm_ion.h
@@ -69,7 +69,7 @@ enum ion_heap_ids {
 #define ION_FLAG_CP_CDSP		ION_BIT(29)
 #define ION_FLAG_CP_SPSS_HLOS_SHARED	ION_BIT(30)
 
-#define ION_FLAGS_CP_MASK	0x7FFF0000
+#define ION_FLAGS_CP_MASK	0x6FFE0000
 
 /**
  * Flag to allow non continguous allocation of memory from secure
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
index f85dde9..f17f700 100644
--- a/drivers/staging/iio/adc/ad7280a.c
+++ b/drivers/staging/iio/adc/ad7280a.c
@@ -256,7 +256,9 @@ static int ad7280_read(struct ad7280_state *st, unsigned int devaddr,
 	if (ret)
 		return ret;
 
-	__ad7280_read32(st, &tmp);
+	ret = __ad7280_read32(st, &tmp);
+	if (ret)
+		return ret;
 
 	if (ad7280_check_crc(st, tmp))
 		return -EIO;
@@ -294,7 +296,9 @@ static int ad7280_read_channel(struct ad7280_state *st, unsigned int devaddr,
 
 	ad7280_delay(st);
 
-	__ad7280_read32(st, &tmp);
+	ret = __ad7280_read32(st, &tmp);
+	if (ret)
+		return ret;
 
 	if (ad7280_check_crc(st, tmp))
 		return -EIO;
@@ -327,7 +331,9 @@ static int ad7280_read_all_channels(struct ad7280_state *st, unsigned int cnt,
 	ad7280_delay(st);
 
 	for (i = 0; i < cnt; i++) {
-		__ad7280_read32(st, &tmp);
+		ret = __ad7280_read32(st, &tmp);
+		if (ret)
+			return ret;
 
 		if (ad7280_check_crc(st, tmp))
 			return -EIO;
@@ -370,7 +376,10 @@ static int ad7280_chain_setup(struct ad7280_state *st)
 		return ret;
 
 	for (n = 0; n <= AD7280A_MAX_CHAIN; n++) {
-		__ad7280_read32(st, &val);
+		ret = __ad7280_read32(st, &val);
+		if (ret)
+			return ret;
+
 		if (val == 0)
 			return n - 1;
 
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index dec3ba6..52613f6 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -87,12 +87,16 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
 			   long m)
 {
 	struct ad7780_state *st = iio_priv(indio_dev);
+	int voltage_uv;
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
 		return ad_sigma_delta_single_conversion(indio_dev, chan, val);
 	case IIO_CHAN_INFO_SCALE:
-		*val = st->int_vref_mv * st->gain;
+		voltage_uv = regulator_get_voltage(st->reg);
+		if (voltage_uv < 0)
+			return voltage_uv;
+		*val = (voltage_uv / 1000) * st->gain;
 		*val2 = chan->scan_type.realbits - 1;
 		return IIO_VAL_FRACTIONAL_LOG2;
 	case IIO_CHAN_INFO_OFFSET:
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index b227090..cbee9ad 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -86,7 +86,12 @@ static int ad2s90_probe(struct spi_device *spi)
 	/* need 600ns between CS and the first falling edge of SCLK */
 	spi->max_speed_hz = 830000;
 	spi->mode = SPI_MODE_3;
-	spi_setup(spi);
+	ret = spi_setup(spi);
+
+	if (ret < 0) {
+		dev_err(&spi->dev, "spi_setup failed!\n");
+		return ret;
+	}
 
 	return 0;
 }
diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c
index 93c0168..5be40bd 100644
--- a/drivers/staging/pi433/pi433_if.c
+++ b/drivers/staging/pi433/pi433_if.c
@@ -1210,6 +1210,10 @@ static int pi433_probe(struct spi_device *spi)
 
 	/* create cdev */
 	device->cdev = cdev_alloc();
+	if (!device->cdev) {
+		dev_dbg(device->dev, "allocation of cdev failed");
+		goto cdev_failed;
+	}
 	device->cdev->owner = THIS_MODULE;
 	cdev_init(device->cdev, &pi433_fops);
 	retval = cdev_add(device->cdev, device->devt, 1);
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index 32c7225..2fc7056 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -43,6 +43,7 @@ static const struct usb_device_id rtw_usb_id_tbl[] = {
 	{USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
 	{USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
 	{USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
+	{USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
 	{USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
 	{USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
 	{USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
diff --git a/drivers/staging/rtl8723bs/include/ieee80211.h b/drivers/staging/rtl8723bs/include/ieee80211.h
index 73ce637..fa9c80f 100644
--- a/drivers/staging/rtl8723bs/include/ieee80211.h
+++ b/drivers/staging/rtl8723bs/include/ieee80211.h
@@ -1008,18 +1008,18 @@ enum ieee80211_state {
 #define IP_FMT "%pI4"
 #define IP_ARG(x) (x)
 
-extern __inline int is_multicast_mac_addr(const u8 *addr)
+static inline int is_multicast_mac_addr(const u8 *addr)
 {
         return ((addr[0] != 0xff) && (0x01 & addr[0]));
 }
 
-extern __inline int is_broadcast_mac_addr(const u8 *addr)
+static inline int is_broadcast_mac_addr(const u8 *addr)
 {
 	return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&   \
 		(addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
 }
 
-extern __inline int is_zero_mac_addr(const u8 *addr)
+static inline int is_zero_mac_addr(const u8 *addr)
 {
 	return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) &&   \
 		(addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00));
diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/staging/speakup/spk_ttyio.c
index 4d7d8f2..71edd3c 100644
--- a/drivers/staging/speakup/spk_ttyio.c
+++ b/drivers/staging/speakup/spk_ttyio.c
@@ -246,7 +246,8 @@ static void spk_ttyio_send_xchar(char ch)
 		return;
 	}
 
-	speakup_tty->ops->send_xchar(speakup_tty, ch);
+	if (speakup_tty->ops->send_xchar)
+		speakup_tty->ops->send_xchar(speakup_tty, ch);
 	mutex_unlock(&speakup_tty_mutex);
 }
 
@@ -258,7 +259,8 @@ static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
 		return;
 	}
 
-	speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+	if (speakup_tty->ops->tiocmset)
+		speakup_tty->ops->tiocmset(speakup_tty, set, clear);
 	mutex_unlock(&speakup_tty_mutex);
 }
 
diff --git a/drivers/target/iscsi/cxgbit/cxgbit_cm.c b/drivers/target/iscsi/cxgbit/cxgbit_cm.c
index d4fa41b..0c00bb2 100644
--- a/drivers/target/iscsi/cxgbit/cxgbit_cm.c
+++ b/drivers/target/iscsi/cxgbit/cxgbit_cm.c
@@ -631,8 +631,11 @@ static void cxgbit_send_halfclose(struct cxgbit_sock *csk)
 
 static void cxgbit_arp_failure_discard(void *handle, struct sk_buff *skb)
 {
+	struct cxgbit_sock *csk = handle;
+
 	pr_debug("%s cxgbit_device %p\n", __func__, handle);
 	kfree_skb(skb);
+	cxgbit_put_csk(csk);
 }
 
 static void cxgbit_abort_arp_failure(void *handle, struct sk_buff *skb)
@@ -1147,7 +1150,7 @@ cxgbit_pass_accept_rpl(struct cxgbit_sock *csk, struct cpl_pass_accept_req *req)
 	rpl5->opt0 = cpu_to_be64(opt0);
 	rpl5->opt2 = cpu_to_be32(opt2);
 	set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->ctrlq_idx);
-	t4_set_arp_err_handler(skb, NULL, cxgbit_arp_failure_discard);
+	t4_set_arp_err_handler(skb, csk, cxgbit_arp_failure_discard);
 	cxgbit_l2t_send(csk->com.cdev, skb, csk->l2t);
 }
 
diff --git a/drivers/target/iscsi/cxgbit/cxgbit_main.c b/drivers/target/iscsi/cxgbit/cxgbit_main.c
index 4fd775a..6340e2e 100644
--- a/drivers/target/iscsi/cxgbit/cxgbit_main.c
+++ b/drivers/target/iscsi/cxgbit/cxgbit_main.c
@@ -58,6 +58,7 @@ static void *cxgbit_uld_add(const struct cxgb4_lld_info *lldi)
 		return ERR_PTR(-ENOMEM);
 
 	kref_init(&cdev->kref);
+	spin_lock_init(&cdev->np_lock);
 
 	cdev->lldi = *lldi;
 
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index cb0461a1..93424db 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -108,12 +108,17 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf)
 
 	buf[7] = 0x2; /* CmdQue=1 */
 
-	memcpy(&buf[8], "LIO-ORG ", 8);
-	memset(&buf[16], 0x20, 16);
+	/*
+	 * ASCII data fields described as being left-aligned shall have any
+	 * unused bytes at the end of the field (i.e., highest offset) and the
+	 * unused bytes shall be filled with ASCII space characters (20h).
+	 */
+	memset(&buf[8], 0x20, 8 + 16 + 4);
+	memcpy(&buf[8], "LIO-ORG", sizeof("LIO-ORG") - 1);
 	memcpy(&buf[16], dev->t10_wwn.model,
-	       min_t(size_t, strlen(dev->t10_wwn.model), 16));
+	       strnlen(dev->t10_wwn.model, 16));
 	memcpy(&buf[32], dev->t10_wwn.revision,
-	       min_t(size_t, strlen(dev->t10_wwn.revision), 4));
+	       strnlen(dev->t10_wwn.revision, 4));
 	buf[4] = 31; /* Set additional length to 31 */
 
 	return 0;
@@ -251,7 +256,9 @@ spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
 	buf[off] = 0x2; /* ASCII */
 	buf[off+1] = 0x1; /* T10 Vendor ID */
 	buf[off+2] = 0x0;
-	memcpy(&buf[off+4], "LIO-ORG", 8);
+	/* left align Vendor ID and pad with spaces */
+	memset(&buf[off+4], 0x20, 8);
+	memcpy(&buf[off+4], "LIO-ORG", sizeof("LIO-ORG") - 1);
 	/* Extra Byte for NULL Terminator */
 	id_len++;
 	/* Identifier Length */
diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
index 23ad4f9..24b006a 100644
--- a/drivers/thermal/broadcom/bcm2835_thermal.c
+++ b/drivers/thermal/broadcom/bcm2835_thermal.c
@@ -27,6 +27,8 @@
 #include <linux/platform_device.h>
 #include <linux/thermal.h>
 
+#include "../thermal_hwmon.h"
+
 #define BCM2835_TS_TSENSCTL			0x00
 #define BCM2835_TS_TSENSSTAT			0x04
 
@@ -275,6 +277,15 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, tz);
 
+	/*
+	 * Thermal_zone doesn't enable hwmon as default,
+	 * enable it here
+	 */
+	tz->tzp->no_hwmon = false;
+	err = thermal_add_hwmon_sysfs(tz);
+	if (err)
+		goto err_tz;
+
 	bcm2835_thermal_debugfs(pdev);
 
 	return 0;
diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c
index f02341f..c344a37 100644
--- a/drivers/thermal/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c
@@ -77,7 +77,12 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \
 	struct pci_dev *pci_dev; \
 	struct platform_device *pdev; \
 	struct proc_thermal_device *proc_dev; \
-\
+	\
+	if (proc_thermal_emum_mode == PROC_THERMAL_NONE) { \
+		dev_warn(dev, "Attempted to get power limit before device was initialized!\n"); \
+		return 0; \
+	} \
+	\
 	if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { \
 		pdev = to_platform_device(dev); \
 		proc_dev = platform_get_drvdata(pdev); \
@@ -291,11 +296,6 @@ static int proc_thermal_add(struct device *dev,
 	*priv = proc_priv;
 
 	ret = proc_thermal_read_ppcc(proc_priv);
-	if (!ret) {
-		ret = sysfs_create_group(&dev->kobj,
-					 &power_limit_attribute_group);
-
-	}
 	if (ret)
 		return ret;
 
@@ -309,8 +309,7 @@ static int proc_thermal_add(struct device *dev,
 
 	proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops);
 	if (IS_ERR(proc_priv->int340x_zone)) {
-		ret = PTR_ERR(proc_priv->int340x_zone);
-		goto remove_group;
+		return PTR_ERR(proc_priv->int340x_zone);
 	} else
 		ret = 0;
 
@@ -324,9 +323,6 @@ static int proc_thermal_add(struct device *dev,
 
 remove_zone:
 	int340x_thermal_zone_remove(proc_priv->int340x_zone);
-remove_group:
-	sysfs_remove_group(&proc_priv->dev->kobj,
-			   &power_limit_attribute_group);
 
 	return ret;
 }
@@ -357,7 +353,10 @@ static int int3401_add(struct platform_device *pdev)
 	platform_set_drvdata(pdev, proc_priv);
 	proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV;
 
-	return 0;
+	dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n");
+
+	return sysfs_create_group(&pdev->dev.kobj,
+					 &power_limit_attribute_group);
 }
 
 static int int3401_remove(struct platform_device *pdev)
@@ -416,7 +415,7 @@ static int  proc_thermal_pci_probe(struct pci_dev *pdev,
 		proc_priv->soc_dts = intel_soc_dts_iosf_init(
 					INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0);
 
-		if (proc_priv->soc_dts && pdev->irq) {
+		if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) {
 			ret = pci_enable_msi(pdev);
 			if (!ret) {
 				ret = request_threaded_irq(pdev->irq, NULL,
@@ -434,7 +433,10 @@ static int  proc_thermal_pci_probe(struct pci_dev *pdev,
 			dev_err(&pdev->dev, "No auxiliary DTSs enabled\n");
 	}
 
-	return 0;
+	dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n");
+
+	return sysfs_create_group(&pdev->dev.kobj,
+					 &power_limit_attribute_group);
 }
 
 static void  proc_thermal_pci_remove(struct pci_dev *pdev)
diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c
index dfbb3be..336940e 100644
--- a/drivers/thermal/msm-tsens.c
+++ b/drivers/thermal/msm-tsens.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
@@ -165,6 +165,8 @@ static int get_device_tree_data(struct platform_device *pdev,
 		return PTR_ERR(tmdev->tsens_tm_addr);
 	}
 
+	tmdev->phys_addr_tm = res_tsens_mem->start;
+
 	/* TSENS eeprom register region */
 	res_tsens_mem = platform_get_resource_byname(pdev,
 				IORESOURCE_MEM, "tsens_eeprom_physical");
@@ -232,6 +234,7 @@ int tsens_tm_probe(struct platform_device *pdev)
 {
 	struct tsens_device *tmdev = NULL;
 	int rc;
+	char tsens_name[40];
 
 	if (!(pdev->dev.of_node))
 		return -ENODEV;
@@ -268,6 +271,33 @@ int tsens_tm_probe(struct platform_device *pdev)
 		return rc;
 	}
 
+	snprintf(tsens_name, sizeof(tsens_name), "tsens_%pa_0",
+					&tmdev->phys_addr_tm);
+
+	tmdev->ipc_log0 = ipc_log_context_create(IPC_LOGPAGES,
+							tsens_name, 0);
+	if (!tmdev->ipc_log0)
+		pr_err("%s : unable to create IPC Logging 0 for tsens %pa",
+					__func__, &tmdev->phys_addr_tm);
+
+	snprintf(tsens_name, sizeof(tsens_name), "tsens_%pa_1",
+					&tmdev->phys_addr_tm);
+
+	tmdev->ipc_log1 = ipc_log_context_create(IPC_LOGPAGES,
+							tsens_name, 0);
+	if (!tmdev->ipc_log1)
+		pr_err("%s : unable to create IPC Logging 1 for tsens %pa",
+					__func__, &tmdev->phys_addr_tm);
+
+	snprintf(tsens_name, sizeof(tsens_name), "tsens_%pa_2",
+					&tmdev->phys_addr_tm);
+
+	tmdev->ipc_log2 = ipc_log_context_create(IPC_LOGPAGES,
+							tsens_name, 0);
+	if (!tmdev->ipc_log2)
+		pr_err("%s : unable to create IPC Logging 2 for tsens %pa",
+					__func__, &tmdev->phys_addr_tm);
+
 	list_add_tail(&tmdev->list, &tsens_device_list);
 	platform_set_drvdata(pdev, tmdev);
 
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index 4856afc..8b29b71 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -81,6 +81,7 @@ struct __sensor_param {
  * @slope: slope of the temperature adjustment curve
  * @offset: offset of the temperature adjustment curve
  * @default_disable: Keep the thermal zone disabled by default
+ * @is_wakeable: Ignore post suspend thermal zone re-evaluation
  * @tzd: thermal zone device pointer for this sensor
  * @ntrips: number of trip points
  * @trips: an array of trip points (0..ntrips - 1)
@@ -98,6 +99,7 @@ struct __thermal_zone {
 	int offset;
 	struct thermal_zone_device *tzd;
 	bool default_disable;
+	bool is_wakeable;
 
 	/* trip data */
 	int ntrips;
@@ -512,6 +514,33 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
 	return -EINVAL;
 }
 
+static bool of_thermal_is_wakeable(struct thermal_zone_device *tz)
+{
+	struct __thermal_zone *data = tz->devdata;
+
+	return data->is_wakeable;
+}
+
+static int of_thermal_set_polling_delay(struct thermal_zone_device *tz,
+				    int delay)
+{
+	struct __thermal_zone *data = tz->devdata;
+
+	data->polling_delay = delay;
+
+	return 0;
+}
+
+static int of_thermal_set_passive_delay(struct thermal_zone_device *tz,
+				    int delay)
+{
+	struct __thermal_zone *data = tz->devdata;
+
+	data->passive_delay = delay;
+
+	return 0;
+}
+
 static int of_thermal_aggregate_trip_types(struct thermal_zone_device *tz,
 		unsigned int trip_type_mask, int *low, int *high)
 {
@@ -637,6 +666,10 @@ static struct thermal_zone_device_ops of_thermal_ops = {
 
 	.bind = of_thermal_bind,
 	.unbind = of_thermal_unbind,
+
+	.is_wakeable = of_thermal_is_wakeable,
+	.set_polling_delay = of_thermal_set_polling_delay,
+	.set_passive_delay = of_thermal_set_passive_delay,
 };
 
 static struct thermal_zone_of_device_ops of_virt_ops = {
@@ -1255,6 +1288,9 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
 
 	tz->default_disable = of_property_read_bool(np,
 					"disable-thermal-zone");
+
+	tz->is_wakeable = of_property_read_bool(np,
+					"wake-capable-sensor");
 	/*
 	 * REVIST: for now, the thermal framework supports only
 	 * one sensor per thermal zone. Thus, we are considering
diff --git a/drivers/thermal/qcom/adc-tm.h b/drivers/thermal/qcom/adc-tm.h
index f29c7b6..e586a60 100644
--- a/drivers/thermal/qcom/adc-tm.h
+++ b/drivers/thermal/qcom/adc-tm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -20,8 +20,7 @@
 #include <linux/delay.h>
 #include <linux/iio/consumer.h>
 #include <linux/qpnp/qpnp-revid.h>
-
-struct adc_tm_chip;
+#include <linux/adc-tm-clients.h>
 
 #define ADC_TM_DECIMATION_DEFAULT	840
 #define ADC_TM_DECIMATION_SAMPLES_MAX	3
@@ -56,56 +55,6 @@ enum adc_timer_select {
 };
 
 /**
- * enum adc_tm_state - This lets the client know whether the threshold
- *		that was crossed was high/low.
- * %ADC_TM_HIGH_STATE: Client is notified of crossing the requested high
- *			voltage threshold.
- * %ADC_TM_COOL_STATE: Client is notified of crossing the requested cool
- *			temperature threshold.
- * %ADC_TM_LOW_STATE: Client is notified of crossing the requested low
- *			voltage threshold.
- * %ADC_TM_WARM_STATE: Client is notified of crossing the requested high
- *			temperature threshold.
- */
-enum adc_tm_state {
-	ADC_TM_HIGH_STATE = 0,
-	ADC_TM_COOL_STATE = ADC_TM_HIGH_STATE,
-	ADC_TM_LOW_STATE,
-	ADC_TM_WARM_STATE = ADC_TM_LOW_STATE,
-	ADC_TM_STATE_NUM,
-};
-
-/**
- * enum adc_tm_state_request - Request to enable/disable the corresponding
- *			high/low voltage/temperature thresholds.
- * %ADC_TM_HIGH_THR_ENABLE: Enable high voltage threshold.
- * %ADC_TM_COOL_THR_ENABLE = Enables cool temperature threshold.
- * %ADC_TM_LOW_THR_ENABLE: Enable low voltage/temperature threshold.
- * %ADC_TM_WARM_THR_ENABLE = Enables warm temperature threshold.
- * %ADC_TM_HIGH_LOW_THR_ENABLE: Enable high and low voltage/temperature
- *				threshold.
- * %ADC_TM_HIGH_THR_DISABLE: Disable high voltage/temperature threshold.
- * %ADC_TM_COOL_THR_ENABLE = Disables cool temperature threshold.
- * %ADC_TM_LOW_THR_DISABLE: Disable low voltage/temperature threshold.
- * %ADC_TM_WARM_THR_ENABLE = Disables warm temperature threshold.
- * %ADC_TM_HIGH_THR_DISABLE: Disable high and low voltage/temperature
- *				threshold.
- */
-enum adc_tm_state_request {
-	ADC_TM_HIGH_THR_ENABLE = 0,
-	ADC_TM_COOL_THR_ENABLE = ADC_TM_HIGH_THR_ENABLE,
-	ADC_TM_LOW_THR_ENABLE,
-	ADC_TM_WARM_THR_ENABLE = ADC_TM_LOW_THR_ENABLE,
-	ADC_TM_HIGH_LOW_THR_ENABLE,
-	ADC_TM_HIGH_THR_DISABLE,
-	ADC_TM_COOL_THR_DISABLE = ADC_TM_HIGH_THR_DISABLE,
-	ADC_TM_LOW_THR_DISABLE,
-	ADC_TM_WARM_THR_DISABLE = ADC_TM_LOW_THR_DISABLE,
-	ADC_TM_HIGH_LOW_THR_DISABLE,
-	ADC_TM_THR_NUM,
-};
-
-/**
  * enum adc_tm_rscale_fn_type - Scaling function used to convert the
  *	channels input voltage/temperature to corresponding ADC code that is
  *	applied for thresholds. Check the corresponding channels scaling to
@@ -141,16 +90,6 @@ struct adc_tm_sensor {
 	struct work_struct		work;
 };
 
-struct adc_tm_param {
-	int			low_thr;
-	int			high_thr;
-	uint32_t				channel;
-	enum adc_tm_state_request	state_request;
-	void					*btm_ctx;
-	void	(*threshold_notification)(enum adc_tm_state state,
-						void *ctx);
-};
-
 struct adc_tm_client_info {
 	struct list_head			list;
 	struct adc_tm_param			*param;
@@ -331,12 +270,6 @@ int32_t adc_tm_absolute_rthr(const struct adc_tm_data *data,
 
 void notify_adc_tm_fn(struct work_struct *work);
 
-struct adc_tm_chip *get_adc_tm(struct device *dev, const char *name);
-int32_t adc_tm5_channel_measure(struct adc_tm_chip *chip,
-					struct adc_tm_param *param);
-int32_t adc_tm5_disable_chan_meas(struct adc_tm_chip *chip,
-					struct adc_tm_param *param);
-
 int adc_tm_is_valid(struct adc_tm_chip *chip);
 
 #endif /* __QCOM_ADC_TM_H__ */
diff --git a/drivers/thermal/qcom/msm_lmh_dcvs.c b/drivers/thermal/qcom/msm_lmh_dcvs.c
index 68d374b..ae0f900 100644
--- a/drivers/thermal/qcom/msm_lmh_dcvs.c
+++ b/drivers/thermal/qcom/msm_lmh_dcvs.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
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/timer.h>
 #include <linux/pm_opp.h>
+#include <linux/cpufreq.h>
 #include <linux/cpu_cooling.h>
 #include <linux/atomic.h>
 #include <linux/regulator/consumer.h>
@@ -96,6 +97,7 @@ struct limits_dcvs_hw {
 	struct device_attribute lmh_freq_attr;
 	struct list_head list;
 	bool is_irq_enabled;
+	bool is_plat_mit_disabled;
 	struct mutex access_lock;
 	struct __limits_cdev_data *cdev_data;
 	uint32_t cdev_registered;
@@ -408,6 +410,8 @@ static void register_cooling_device(struct work_struct *work)
 {
 	struct limits_dcvs_hw *hw;
 	unsigned int cpu = 0, idx = 0;
+	struct device_node *cpu_node;
+	struct cpufreq_policy *policy;
 
 	mutex_lock(&lmh_dcvs_list_access);
 	list_for_each_entry(hw, &lmh_dcvs_hw_list, list) {
@@ -424,12 +428,33 @@ static void register_cooling_device(struct work_struct *work)
 				idx++;
 				continue;
 			}
-			cpumask_set_cpu(cpu, &cpu_mask);
 			hw->cdev_data[idx].max_freq = U32_MAX;
 			hw->cdev_data[idx].min_freq = 0;
-			hw->cdev_data[idx].cdev =
+
+			if (!hw->is_plat_mit_disabled) {
+				cpumask_set_cpu(cpu, &cpu_mask);
+				hw->cdev_data[idx].cdev =
 					cpufreq_platform_cooling_register(
 							&cpu_mask, &cd_ops);
+			} else {
+				cpu_node = of_cpu_device_node_get(cpu);
+				if (WARN_ON(!cpu_node)) {
+					hw->cdev_data[idx].cdev = NULL;
+					continue;
+				}
+
+				policy = cpufreq_cpu_get(cpu);
+				if (!policy) {
+					pr_err("No policy for cpu%d\n", cpu);
+					hw->cdev_data[idx].cdev = NULL;
+					of_node_put(cpu_node);
+					continue;
+				}
+				hw->cdev_data[idx].cdev =
+					of_cpufreq_cooling_register(cpu_node,
+						policy);
+				of_node_put(cpu_node);
+			}
 			if (IS_ERR_OR_NULL(hw->cdev_data[idx].cdev)) {
 				pr_err("CPU:%u cdev register error:%ld\n",
 					cpu, PTR_ERR(hw->cdev_data[idx].cdev));
@@ -588,6 +613,10 @@ static int limits_dcvs_probe(struct platform_device *pdev)
 		return -EINVAL;
 	};
 
+	/* Check whether platform mitigation needs to enable or not */
+	hw->is_plat_mit_disabled = of_property_read_bool(dn,
+				"qcom,plat-mitigation-disable");
+
 	addr = of_get_address(dn, 0, NULL, NULL);
 	if (!addr) {
 		pr_err("Property llm-base-addr not found\n");
@@ -616,8 +645,14 @@ static int limits_dcvs_probe(struct platform_device *pdev)
 			affinity);
 	tzdev = thermal_zone_of_sensor_register(&pdev->dev, 0, hw,
 			&limits_sensor_ops);
-	if (IS_ERR_OR_NULL(tzdev))
-		return PTR_ERR(tzdev);
+	if (IS_ERR_OR_NULL(tzdev)) {
+		/*
+		 * Ignore error in case if thermal zone devicetree node is not
+		 * defined for this lmh hardware.
+		 */
+		if (!tzdev || PTR_ERR(tzdev) != -ENODEV)
+			return PTR_ERR(tzdev);
+	}
 
 	hw->min_freq_reg = devm_ioremap(&pdev->dev, min_reg, 0x4);
 	if (!hw->min_freq_reg) {
@@ -648,7 +683,7 @@ static int limits_dcvs_probe(struct platform_device *pdev)
 	hw->is_irq_enabled = true;
 	ret = devm_request_threaded_irq(&pdev->dev, hw->irq_num, NULL,
 		lmh_dcvs_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT
-		| IRQF_NO_SUSPEND, hw->sensor_name, hw);
+		| IRQF_NO_SUSPEND | IRQF_SHARED, hw->sensor_name, hw);
 	if (ret) {
 		pr_err("Error registering for irq. err:%d\n", ret);
 		ret = 0;
diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c
index 73f55d6..ad601e5 100644
--- a/drivers/thermal/thermal-generic-adc.c
+++ b/drivers/thermal/thermal-generic-adc.c
@@ -26,7 +26,7 @@ struct gadc_thermal_info {
 
 static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val)
 {
-	int temp, adc_hi, adc_lo;
+	int temp, temp_hi, temp_lo, adc_hi, adc_lo;
 	int i;
 
 	for (i = 0; i < gti->nlookup_table; i++) {
@@ -36,13 +36,17 @@ static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val)
 
 	if (i == 0) {
 		temp = gti->lookup_table[0];
-	} else if (i >= (gti->nlookup_table - 1)) {
+	} else if (i >= gti->nlookup_table) {
 		temp = gti->lookup_table[2 * (gti->nlookup_table - 1)];
 	} else {
 		adc_hi = gti->lookup_table[2 * i - 1];
 		adc_lo = gti->lookup_table[2 * i + 1];
-		temp = gti->lookup_table[2 * i];
-		temp -= ((val - adc_lo) * 1000) / (adc_hi - adc_lo);
+
+		temp_hi = gti->lookup_table[2 * i - 2];
+		temp_lo = gti->lookup_table[2 * i];
+
+		temp = temp_hi + mult_frac(temp_lo - temp_hi, val - adc_hi,
+					   adc_lo - adc_hi);
 	}
 
 	return temp;
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index af06ff0..891ed3b 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -473,22 +473,27 @@ static void update_temperature(struct thermal_zone_device *tz)
 	store_temperature(tz, temp);
 }
 
-static void thermal_zone_device_reset(struct thermal_zone_device *tz)
+static void thermal_zone_device_init(struct thermal_zone_device *tz)
 {
 	struct thermal_instance *pos;
-
 	tz->temperature = THERMAL_TEMP_INVALID;
-	tz->passive = 0;
 	list_for_each_entry(pos, &tz->thermal_instances, tz_node)
 		pos->initialized = false;
 }
 
+static void thermal_zone_device_reset(struct thermal_zone_device *tz)
+{
+	tz->passive = 0;
+	thermal_zone_device_init(tz);
+}
+
 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))
+	if (atomic_read(&in_suspend) && (!tz->ops->is_wakeable ||
+		!(tz->ops->is_wakeable(tz))))
 		return;
 
 	trace_thermal_device_update(tz, event);
@@ -508,7 +513,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz,
 {
 	int count;
 
-	if (atomic_read(&in_suspend))
+	if (atomic_read(&in_suspend) && (!tz->ops->is_wakeable ||
+		!(tz->ops->is_wakeable(tz))))
 		return;
 
 	if (!tz->ops->get_temp)
@@ -1597,7 +1603,10 @@ static int thermal_pm_notify(struct notifier_block *nb,
 	case PM_POST_SUSPEND:
 		atomic_set(&in_suspend, 0);
 		list_for_each_entry(tz, &thermal_tz_list, node) {
-			thermal_zone_device_reset(tz);
+			if (tz->ops->is_wakeable &&
+				tz->ops->is_wakeable(tz))
+				continue;
+			thermal_zone_device_init(tz);
 			thermal_zone_device_update(tz,
 						   THERMAL_EVENT_UNSPECIFIED);
 		}
diff --git a/drivers/thermal/thermal_hwmon.h b/drivers/thermal/thermal_hwmon.h
index c798fdb..f97f766 100644
--- a/drivers/thermal/thermal_hwmon.h
+++ b/drivers/thermal/thermal_hwmon.h
@@ -34,13 +34,13 @@
 int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz);
 void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz);
 #else
-static int
+static inline int
 thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
 {
 	return 0;
 }
 
-static void
+static inline void
 thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
 {
 }
diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
index 3fe10af..03d5010 100644
--- a/drivers/thermal/thermal_sysfs.c
+++ b/drivers/thermal/thermal_sysfs.c
@@ -393,6 +393,8 @@ polling_delay_store(struct device *dev, struct device_attribute *attr,
 
 	mutex_lock(&tz->lock);
 	tz->polling_delay = delay;
+	if (tz->ops->set_polling_delay)
+		tz->ops->set_polling_delay(tz, delay);
 	mutex_unlock(&tz->lock);
 	thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
 
@@ -420,6 +422,8 @@ passive_delay_store(struct device *dev, struct device_attribute *attr,
 
 	mutex_lock(&tz->lock);
 	tz->passive_delay = delay;
+	if (tz->ops->set_passive_delay)
+		tz->ops->set_passive_delay(tz, delay);
 	mutex_unlock(&tz->lock);
 	thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
 
diff --git a/drivers/thermal/tsens-dbg.c b/drivers/thermal/tsens-dbg.c
index 97aee8f8..b2ad37a 100644
--- a/drivers/thermal/tsens-dbg.c
+++ b/drivers/thermal/tsens-dbg.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
@@ -251,6 +251,8 @@ static int tsens_dbg_log_temp_reads(struct tsens_device *data, u32 id,
 	idx++;
 	tmdev->tsens_dbg.sensor_dbg_info[sensor->hw_id].idx = idx;
 
+	TSENS_DBG(tmdev, "Sensor_id: %d temp: %d\n", id, *temp);
+
 	return 0;
 }
 
@@ -298,7 +300,7 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data,
 	srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr);
 
 	cntrl_id = readl_relaxed(controller_id_addr);
-	pr_err("Controller_id: 0x%x\n", cntrl_id);
+	TSENS_DUMP(tmdev, "TSENS Controller_id: 0x%x\n", cntrl_id);
 
 	loop = 0;
 	i = 0;
@@ -311,8 +313,11 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data,
 		r2 = readl_relaxed(debug_data_addr);
 		r3 = readl_relaxed(debug_data_addr);
 		r4 = readl_relaxed(debug_data_addr);
-		pr_err("cntrl:%d, bus-id:%d value:0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
+
+		TSENS_DUMP(tmdev,
+			"ctl:%d, bus-id:%d val:0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
 			cntrl_id, i, debug_dump, r1, r2, r3, r4);
+
 		loop++;
 	}
 
@@ -324,8 +329,9 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data,
 				TSENS_DEBUG_CONTROL(tmdev->tsens_tm_addr));
 		while (loop < TSENS_DEBUG_LOOP_COUNT) {
 			debug_dump = readl_relaxed(debug_data_addr);
-			pr_err("cntrl:%d, bus-id:%d with value: 0x%x\n",
-				cntrl_id, i, debug_dump);
+			TSENS_DUMP(tmdev,
+				"cntrl:%d, bus-id:%d with value: 0x%x\n",
+				 cntrl_id, i, debug_dump);
 			if (i == TSENS_DBG_BUS_ID_2)
 				usleep_range(
 					TSENS_DEBUG_BUS_ID2_MIN_CYCLE,
@@ -334,7 +340,9 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data,
 		}
 	}
 
-	pr_err("Start of TSENS TM dump\n");
+	TSENS_DUMP(tmdev, "Start of TSENS TM dump for ctr 0x%x\n",
+			cntrl_id);
+
 	for (i = 0; i < TSENS_DEBUG_OFFSET_RANGE; i++) {
 		r1 = readl_relaxed(controller_id_addr + offset);
 		r2 = readl_relaxed(controller_id_addr + (offset +
@@ -344,13 +352,16 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data,
 		r4 = readl_relaxed(controller_id_addr + (offset +
 					TSENS_DEBUG_OFFSET_WORD3));
 
-		pr_err("ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
-			cntrl_id, offset, r1, r2, r3, r4);
+		TSENS_DUMP(tmdev,
+			"ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+				cntrl_id, offset, r1, r2, r3, r4);
+
 		offset += TSENS_DEBUG_OFFSET_ROW;
 	}
 
 	offset = 0;
-	pr_err("Start of TSENS SROT dump\n");
+	TSENS_DUMP(tmdev, "Start of TSENS SROT dump for ctr 0x%x\n",
+			cntrl_id);
 	for (i = 0; i < TSENS_DEBUG_OFFSET_RANGE; i++) {
 		r1 = readl_relaxed(srot_addr + offset);
 		r2 = readl_relaxed(srot_addr + (offset +
@@ -360,8 +371,9 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data,
 		r4 = readl_relaxed(srot_addr + (offset +
 					TSENS_DEBUG_OFFSET_WORD3));
 
-		pr_err("ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
-			cntrl_id, offset, r1, r2, r3, r4);
+		TSENS_DUMP(tmdev,
+			"ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+				cntrl_id, offset, r1, r2, r3, r4);
 		offset += TSENS_DEBUG_OFFSET_ROW;
 	}
 
@@ -369,7 +381,8 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data,
 	while (loop < TSENS_DEBUG_LOOP_COUNT) {
 		offset = TSENS_DEBUG_OFFSET_ROW *
 				TSENS_DEBUG_STATUS_REG_START;
-		pr_err("Start of TSENS TM dump %d\n", loop);
+		TSENS_DUMP(tmdev, "Start of TSENS TM dump %d\n",
+					loop);
 		/* Limited dump of the registers for the temperature */
 		for (i = 0; i < TSENS_DEBUG_LOOP_COUNT; i++) {
 			r1 = readl_relaxed(controller_id_addr + offset);
@@ -380,8 +393,9 @@ static int tsens_dbg_log_bus_id_data(struct tsens_device *data,
 			r4 = readl_relaxed(controller_id_addr +
 				(offset + TSENS_DEBUG_OFFSET_WORD3));
 
-		pr_err("ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
-			cntrl_id, offset, r1, r2, r3, r4);
+		TSENS_DUMP(tmdev,
+			"ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+				cntrl_id, offset, r1, r2, r3, r4);
 			offset += TSENS_DEBUG_OFFSET_ROW;
 		}
 		loop++;
diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h
index ada15f1..1529c2a 100644
--- a/drivers/thermal/tsens.h
+++ b/drivers/thermal/tsens.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
@@ -20,6 +20,7 @@
 #include <linux/workqueue.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/ipc_logging.h>
 
 #define DEBUG_SIZE					10
 #define TSENS_MAX_SENSORS			16
@@ -36,6 +37,8 @@
 #define SLOPE_FACTOR		1000
 #define SLOPE_DEFAULT		3200
 
+#define IPC_LOGPAGES 10
+
 enum tsens_dbg_type {
 	TSENS_DBG_POLL,
 	TSENS_DBG_LOG_TEMP_READS,
@@ -49,6 +52,54 @@ enum tsens_dbg_type {
 
 struct tsens_device;
 
+#ifdef CONFIG_DEBUG_FS
+#define TSENS_IPC(idx, dev, msg, args...) do { \
+		if (dev) { \
+			if ((idx == 0) && (dev)->ipc_log0) \
+				ipc_log_string((dev)->ipc_log0, \
+					"%s: " msg, __func__, args); \
+			else if ((idx == 1) && (dev)->ipc_log1) \
+				ipc_log_string((dev)->ipc_log1, \
+					"%s: " msg, __func__, args); \
+			else if ((idx == 2) && (dev)->ipc_log2) \
+				ipc_log_string((dev)->ipc_log2, \
+					"%s: " msg, __func__, args); \
+			else \
+				pr_debug("tsens: invalid logging index\n"); \
+		} \
+	} while (0)
+#define TSENS_DUMP(dev, msg, args...) do {				\
+		TSENS_IPC(2, dev, msg, args); \
+		pr_info(msg, ##args);	\
+	} while (0)
+#define TSENS_ERR(dev, msg, args...) do {				\
+		pr_err(msg, ##args);	\
+		TSENS_IPC(1, dev, msg, args); \
+	} while (0)
+#define TSENS_INFO(dev, msg, args...) do {				\
+		pr_info(msg, ##args);	\
+		TSENS_IPC(1, dev, msg, args); \
+	} while (0)
+#define TSENS_DBG(dev, msg, args...) do {				\
+		pr_debug(msg, ##args);	\
+		if (dev) { \
+			TSENS_IPC(0, dev, msg, args); \
+		}	\
+	} while (0)
+#define TSENS_DBG1(dev, msg, args...) do {				\
+		pr_debug(msg, ##args);	\
+		if (dev) { \
+			TSENS_IPC(1, dev, msg, args); \
+		}	\
+	} while (0)
+#else
+#define	TSENS_DBG1(x...)		pr_debug(x)
+#define	TSENS_DBG(x...)		pr_debug(x)
+#define	TSENS_INFO(x...)		pr_info(x)
+#define	TSENS_ERR(x...)		pr_err(x)
+#define	TSENS_DUMP(x...)		pr_info(x)
+#endif
+
 #if defined(CONFIG_THERMAL_TSENS)
 int tsens2xxx_dbg(struct tsens_device *data, u32 id, u32 dbg_type, int *temp);
 #else
@@ -153,11 +204,16 @@ struct tsens_device {
 	void __iomem			*tsens_tm_addr;
 	void __iomem			*tsens_calib_addr;
 	const struct tsens_ops		*ops;
+	void					*ipc_log0;
+	void					*ipc_log1;
+	void					*ipc_log2;
+	phys_addr_t				phys_addr_tm;
 	struct tsens_dbg_context	tsens_dbg;
 	spinlock_t			tsens_crit_lock;
 	spinlock_t			tsens_upp_low_lock;
 	const struct tsens_data		*ctrl_data;
 	struct tsens_mtc_sysfs  mtcsys;
+	int				trdy_fail_ctr;
 	struct tsens_sensor		sensor[0];
 };
 
diff --git a/drivers/thermal/tsens2xxx.c b/drivers/thermal/tsens2xxx.c
index 7b9bdb3b..b126cfe 100644
--- a/drivers/thermal/tsens2xxx.c
+++ b/drivers/thermal/tsens2xxx.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
@@ -96,10 +96,22 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
 	code = readl_relaxed_no_log(trdy);
 	if (!((code & TSENS_TM_TRDY_FIRST_ROUND_COMPLETE) >>
 			TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT)) {
-		pr_err("TSENS device first round not complete0x%x\n", code);
+		pr_err("tsens device first round not complete0x%x, ctr is %d\n",
+			code, tmdev->trdy_fail_ctr);
+		tmdev->trdy_fail_ctr++;
+
+		if (tmdev->trdy_fail_ctr >= 50) {
+			if (tmdev->ops->dbg)
+				tmdev->ops->dbg(tmdev, 0,
+					TSENS_DBG_LOG_BUS_ID_DATA, NULL);
+			BUG();
+		}
+
 		return -ENODATA;
 	}
 
+	tmdev->trdy_fail_ctr = 0;
+
 	code = readl_relaxed_no_log(sensor_addr +
 			(sensor->hw_id << TSENS_STATUS_ADDR_OFFSET));
 	last_temp = code & TSENS_TM_SN_LAST_TEMP_MASK;
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
index 7b2a466..08bd6b9 100644
--- a/drivers/tty/n_hdlc.c
+++ b/drivers/tty/n_hdlc.c
@@ -598,6 +598,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
 				/* too large for caller's buffer */
 				ret = -EOVERFLOW;
 			} else {
+				__set_current_state(TASK_RUNNING);
 				if (copy_to_user(buf, rbuf->buf, rbuf->count))
 					ret = -EFAULT;
 				else
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 4986b4a..790375b 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -3425,6 +3425,11 @@ static int
 serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
 {
 	int num_iomem, num_port, first_port = -1, i;
+	int rc;
+
+	rc = serial_pci_is_class_communication(dev);
+	if (rc)
+		return rc;
 
 	/*
 	 * Should we try to make guesses for multiport serial devices later?
@@ -3652,10 +3657,6 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 
 	board = &pci_boards[ent->driver_data];
 
-	rc = serial_pci_is_class_communication(dev);
-	if (rc)
-		return rc;
-
 	rc = serial_pci_is_blacklisted(dev);
 	if (rc)
 		return rc;
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index c9f701a..4a4a9f3 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2800,6 +2800,7 @@ static struct platform_driver arm_sbsa_uart_platform_driver = {
 		.name	= "sbsa-uart",
 		.of_match_table = of_match_ptr(sbsa_uart_of_match),
 		.acpi_match_table = ACPI_PTR(sbsa_uart_acpi_match),
+		.suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_AMBA_PL011),
 	},
 };
 
@@ -2828,6 +2829,7 @@ static struct amba_driver pl011_driver = {
 	.drv = {
 		.name	= "uart-pl011",
 		.pm	= &pl011_dev_pm_ops,
+		.suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_AMBA_PL011),
 	},
 	.id_table	= pl011_ids,
 	.probe		= pl011_probe,
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index fd64ac2..32a473f 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1482,6 +1482,8 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 			else
 				cr1 &= ~UARTCR1_PT;
 		}
+	} else {
+		cr1 &= ~UARTCR1_PE;
 	}
 
 	/* ask the core to calculate the divisor */
@@ -1694,10 +1696,12 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
 			else
 				ctrl &= ~UARTCTRL_PT;
 		}
+	} else {
+		ctrl &= ~UARTCTRL_PE;
 	}
 
 	/* ask the core to calculate the divisor */
-	baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
+	baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 4);
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 05beb1f..5f48ebc 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
+#include <soc/qcom/boot_stats.h>
 
 /* UART specific GENI registers */
 #define SE_UART_LOOPBACK_CFG		(0x22C)
@@ -111,7 +112,7 @@
 #define DEF_FIFO_DEPTH_WORDS	(16)
 #define DEF_TX_WM		(2)
 #define DEF_FIFO_WIDTH_BITS	(32)
-#define UART_CORE2X_VOTE	(10000)
+#define UART_CORE2X_VOTE	(5000)
 #define UART_CONSOLE_CORE2X_VOTE (960)
 
 #define WAKEBYTE_TIMEOUT_MSEC	(2000)
@@ -462,7 +463,7 @@ static struct msm_geni_serial_port *get_port_from_line(int line,
 
 	if (is_console) {
 		if ((line < 0) || (line >= GENI_UART_CONS_PORTS))
-			port = ERR_PTR(-ENXIO);
+			return ERR_PTR(-ENXIO);
 		port = &msm_geni_console_port;
 	} else {
 		if ((line < 0) || (line >= GENI_UART_NR_PORTS))
@@ -1565,10 +1566,7 @@ static void msm_geni_serial_shutdown(struct uart_port *uport)
 	struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
 	unsigned long flags;
 
-	/* Stop the console before stopping the current tx */
-	if (uart_console(uport)) {
-		console_stop(uport->cons);
-	} else {
+	if (!uart_console(uport)) {
 		msm_geni_serial_power_on(uport);
 		wait_for_transfers_inflight(uport);
 	}
@@ -1635,7 +1633,7 @@ static int msm_geni_serial_port_setup(struct uart_port *uport)
 		msm_port->rx_buf = devm_kzalloc(uport->dev, DMA_RX_BUF_SIZE,
 								GFP_KERNEL);
 		if (!msm_port->rx_buf) {
-			kfree(msm_port->rx_fifo);
+			devm_kfree(uport->dev, msm_port->rx_fifo);
 			msm_port->rx_fifo = NULL;
 			ret = -ENOMEM;
 			goto exit_portsetup;
@@ -2338,6 +2336,7 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
 	struct platform_device *wrapper_pdev;
 	struct device_node *wrapper_ph_node;
 	u32 wake_char = 0;
+	char boot_marker[40];
 
 	id = of_match_device(msm_geni_device_tbl, &pdev->dev);
 	if (id) {
@@ -2362,6 +2361,15 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
 
 	if ((line < 0) || (line >= GENI_UART_NR_PORTS))
 		return -ENXIO;
+
+	if (strcmp(id->compatible, "qcom,msm-geni-console") == 0)
+		snprintf(boot_marker, sizeof(boot_marker),
+				"M - DRIVER GENI_UART_%d Init", line);
+	else
+		snprintf(boot_marker, sizeof(boot_marker),
+				"M - DRIVER GENI_HS_UART_%d Init", line);
+	place_marker(boot_marker);
+
 	is_console = (drv->cons ? true : false);
 	dev_port = get_port_from_line(line, is_console);
 	if (IS_ERR_OR_NULL(dev_port)) {
@@ -2469,11 +2477,21 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
 	}
 	dev_port->serial_rsc.geni_gpio_active =
 		pinctrl_lookup_state(dev_port->serial_rsc.geni_pinctrl,
-							PINCTRL_DEFAULT);
+							PINCTRL_ACTIVE);
+
 	if (IS_ERR_OR_NULL(dev_port->serial_rsc.geni_gpio_active)) {
-		dev_err(&pdev->dev, "No default config specified!\n");
-		ret = PTR_ERR(dev_port->serial_rsc.geni_gpio_active);
-		goto exit_geni_serial_probe;
+		/*
+		 * Backward compatible : In case few chips doesn't have ACTIVE
+		 * state defined.
+		 */
+		dev_port->serial_rsc.geni_gpio_active =
+			pinctrl_lookup_state(dev_port->serial_rsc.geni_pinctrl,
+							PINCTRL_DEFAULT);
+		if (IS_ERR_OR_NULL(dev_port->serial_rsc.geni_gpio_active)) {
+			dev_err(&pdev->dev, "No default config specified!\n");
+			ret = PTR_ERR(dev_port->serial_rsc.geni_gpio_active);
+			goto exit_geni_serial_probe;
+		}
 	}
 
 	/*
@@ -2528,8 +2546,16 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
 	device_create_file(uport->dev, &dev_attr_xfer_mode);
 	msm_geni_serial_debug_init(uport, is_console);
 	dev_port->port_setup = false;
-	return uart_add_one_port(drv, uport);
-
+	ret = uart_add_one_port(drv, uport);
+	if (!ret) {
+		if (strcmp(id->compatible, "qcom,msm-geni-console") == 0)
+			snprintf(boot_marker, sizeof(boot_marker),
+				"M - DRIVER GENI_UART_%d Ready", line);
+		else
+			snprintf(boot_marker, sizeof(boot_marker),
+				"M - DRIVER GENI_HS_UART_%d Ready", line);
+		place_marker(boot_marker);
+	}
 exit_geni_serial_probe:
 	return ret;
 }
diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c
index 00a33eb..e3d7d9d 100644
--- a/drivers/tty/serial/pic32_uart.c
+++ b/drivers/tty/serial/pic32_uart.c
@@ -920,6 +920,7 @@ static struct platform_driver pic32_uart_platform_driver = {
 	.driver		= {
 		.name	= PIC32_DEV_NAME,
 		.of_match_table	= of_match_ptr(pic32_serial_dt_ids),
+		.suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_PIC32),
 	},
 };
 
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 57baa84..f4b8e4e 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1343,11 +1343,14 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
 	wr_regl(port, S3C2410_ULCON, ulcon);
 	wr_regl(port, S3C2410_UBRDIV, quot);
 
+	port->status &= ~UPSTAT_AUTOCTS;
+
 	umcon = rd_regl(port, S3C2410_UMCON);
 	if (termios->c_cflag & CRTSCTS) {
 		umcon |= S3C2410_UMCOM_AFC;
 		/* Disable RTS when RX FIFO contains 63 bytes */
 		umcon &= ~S3C2412_UMCON_AFC_8;
+		port->status = UPSTAT_AUTOCTS;
 	} else {
 		umcon &= ~S3C2410_UMCOM_AFC;
 	}
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 17fd89a..574ac2f 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -146,6 +146,9 @@ static void uart_start(struct tty_struct *tty)
 	struct uart_port *port;
 	unsigned long flags;
 
+	if (!state)
+		return;
+
 	port = uart_port_lock(state, flags);
 	__uart_start(tty);
 	uart_port_unlock(port, flags);
@@ -221,10 +224,15 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
 	if (!state->xmit.buf) {
 		state->xmit.buf = (unsigned char *) page;
 		uart_circ_clear(&state->xmit);
+		uart_port_unlock(uport, flags);
 	} else {
+		uart_port_unlock(uport, flags);
+		/*
+		 * Do not free() the page under the port lock, see
+		 * uart_shutdown().
+		 */
 		free_page(page);
 	}
-	uart_port_unlock(uport, flags);
 
 	retval = uport->ops->startup(uport);
 	if (retval == 0) {
@@ -284,6 +292,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
 	struct uart_port *uport = uart_port_check(state);
 	struct tty_port *port = &state->port;
 	unsigned long flags = 0;
+	char *xmit_buf = NULL;
 
 	/*
 	 * Set the TTY IO error marker
@@ -314,14 +323,18 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
 	tty_port_set_suspended(port, 0);
 
 	/*
-	 * Free the transmit buffer page.
+	 * Do not free() the transmit buffer page under the port lock since
+	 * this can create various circular locking scenarios. For instance,
+	 * console driver may need to allocate/free a debug object, which
+	 * can endup in printk() recursion.
 	 */
 	uart_port_lock(state, flags);
-	if (state->xmit.buf) {
-		free_page((unsigned long)state->xmit.buf);
-		state->xmit.buf = NULL;
-	}
+	xmit_buf = state->xmit.buf;
+	state->xmit.buf = NULL;
 	uart_port_unlock(uport, flags);
+
+	if (xmit_buf)
+		free_page((unsigned long)xmit_buf);
 }
 
 /**
@@ -556,10 +569,12 @@ static int uart_put_char(struct tty_struct *tty, unsigned char c)
 	int ret = 0;
 
 	circ = &state->xmit;
-	if (!circ->buf)
-		return 0;
-
 	port = uart_port_lock(state, flags);
+	if (!circ->buf) {
+		uart_port_unlock(port, flags);
+		return 0;
+	}
+
 	if (port && uart_circ_chars_free(circ) != 0) {
 		circ->buf[circ->head] = c;
 		circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
@@ -592,11 +607,13 @@ static int uart_write(struct tty_struct *tty,
 		return -EL3HLT;
 	}
 
-	circ = &state->xmit;
-	if (!circ->buf)
-		return 0;
-
 	port = uart_port_lock(state, flags);
+	circ = &state->xmit;
+	if (!circ->buf) {
+		uart_port_unlock(port, flags);
+		return 0;
+	}
+
 	while (port) {
 		c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
 		if (count < c)
@@ -2404,6 +2421,9 @@ static void uart_poll_put_char(struct tty_driver *driver, int line, char ch)
 	struct uart_state *state = drv->state + line;
 	struct uart_port *port;
 
+	if (!state)
+		return;
+
 	port = uart_port_ref(state);
 	if (!port)
 		return;
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 95d34d7..1cf78cec7 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -1393,22 +1393,43 @@ static inline struct console *SUNSU_CONSOLE(void)
 static enum su_type su_get_type(struct device_node *dp)
 {
 	struct device_node *ap = of_find_node_by_path("/aliases");
+	enum su_type rc = SU_PORT_PORT;
 
 	if (ap) {
 		const char *keyb = of_get_property(ap, "keyboard", NULL);
 		const char *ms = of_get_property(ap, "mouse", NULL);
+		struct device_node *match;
 
 		if (keyb) {
-			if (dp == of_find_node_by_path(keyb))
-				return SU_PORT_KBD;
+			match = of_find_node_by_path(keyb);
+
+			/*
+			 * The pointer is used as an identifier not
+			 * as a pointer, we can drop the refcount on
+			 * the of__node immediately after getting it.
+			 */
+			of_node_put(match);
+
+			if (dp == match) {
+				rc = SU_PORT_KBD;
+				goto out;
+			}
 		}
 		if (ms) {
-			if (dp == of_find_node_by_path(ms))
-				return SU_PORT_MS;
+			match = of_find_node_by_path(ms);
+
+			of_node_put(match);
+
+			if (dp == match) {
+				rc = SU_PORT_MS;
+				goto out;
+			}
 		}
 	}
 
-	return SU_PORT_PORT;
+out:
+	of_node_put(ap);
+	return rc;
 }
 
 static int su_probe(struct platform_device *op)
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 897b1c5..217686cb4 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -1644,6 +1644,7 @@ static struct platform_driver cdns_uart_platform_driver = {
 		.name = CDNS_UART_NAME,
 		.of_match_table = cdns_uart_of_match,
 		.pm = &cdns_uart_dev_pm_ops,
+		.suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_XILINX_PS_UART),
 		},
 };
 
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 83376ca..7e351d2 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1254,7 +1254,8 @@ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *
 static int tty_reopen(struct tty_struct *tty)
 {
 	struct tty_driver *driver = tty->driver;
-	int retval;
+	struct tty_ldisc *ld;
+	int retval = 0;
 
 	if (driver->type == TTY_DRIVER_TYPE_PTY &&
 	    driver->subtype == PTY_TYPE_MASTER)
@@ -1266,14 +1267,21 @@ static int tty_reopen(struct tty_struct *tty)
 	if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
 		return -EBUSY;
 
-	tty->count++;
+	ld = tty_ldisc_ref_wait(tty);
+	if (ld) {
+		tty_ldisc_deref(ld);
+	} else {
+		retval = tty_ldisc_lock(tty, 5 * HZ);
+		if (retval)
+			return retval;
 
-	if (tty->ldisc)
-		return 0;
+		if (!tty->ldisc)
+			retval = tty_ldisc_reinit(tty, tty->termios.c_line);
+		tty_ldisc_unlock(tty);
+	}
 
-	retval = tty_ldisc_reinit(tty, tty->termios.c_line);
-	if (retval)
-		tty->count--;
+	if (retval == 0)
+		tty->count++;
 
 	return retval;
 }
@@ -2172,7 +2180,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
 	ld = tty_ldisc_ref_wait(tty);
 	if (!ld)
 		return -EIO;
-	ld->ops->receive_buf(tty, &ch, &mbz, 1);
+	if (ld->ops->receive_buf)
+		ld->ops->receive_buf(tty, &ch, &mbz, 1);
 	tty_ldisc_deref(ld);
 	return 0;
 }
diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c
index 52b7bae..5c2cec2 100644
--- a/drivers/tty/tty_ldsem.c
+++ b/drivers/tty/tty_ldsem.c
@@ -307,6 +307,16 @@ down_write_failed(struct ld_semaphore *sem, long count, long timeout)
 	if (!locked)
 		ldsem_atomic_update(-LDSEM_WAIT_BIAS, sem);
 	list_del(&waiter.list);
+
+	/*
+	 * In case of timeout, wake up every reader who gave the right of way
+	 * to writer. Prevent separation readers into two groups:
+	 * one that helds semaphore and another that sleeps.
+	 * (in case of no contention with a writer)
+	 */
+	if (!locked && list_empty(&sem->write_wait))
+		__ldsem_wake_readers(sem);
+
 	raw_spin_unlock_irq(&sem->wait_lock);
 
 	__set_current_state(TASK_RUNNING);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index e77421e..1fb5e7f 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -953,6 +953,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
 	if (con_is_visible(vc))
 		update_screen(vc);
 	vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
+	notify_update(vc);
 	return err;
 }
 
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 654579b..fb5c970 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -215,7 +215,20 @@ static ssize_t name_show(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
-	return sprintf(buf, "%s\n", idev->info->name);
+	int ret;
+
+	mutex_lock(&idev->info_lock);
+	if (!idev->info) {
+		ret = -EINVAL;
+		dev_err(dev, "the device has been unregistered\n");
+		goto out;
+	}
+
+	ret = sprintf(buf, "%s\n", idev->info->name);
+
+out:
+	mutex_unlock(&idev->info_lock);
+	return ret;
 }
 static DEVICE_ATTR_RO(name);
 
@@ -223,7 +236,20 @@ static ssize_t version_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
-	return sprintf(buf, "%s\n", idev->info->version);
+	int ret;
+
+	mutex_lock(&idev->info_lock);
+	if (!idev->info) {
+		ret = -EINVAL;
+		dev_err(dev, "the device has been unregistered\n");
+		goto out;
+	}
+
+	ret = sprintf(buf, "%s\n", idev->info->version);
+
+out:
+	mutex_unlock(&idev->info_lock);
+	return ret;
 }
 static DEVICE_ATTR_RO(version);
 
@@ -272,7 +298,7 @@ static int uio_dev_add_attributes(struct uio_device *idev)
 		if (!map_found) {
 			map_found = 1;
 			idev->map_dir = kobject_create_and_add("maps",
-							&idev->dev->kobj);
+							&idev->dev.kobj);
 			if (!idev->map_dir) {
 				ret = -ENOMEM;
 				goto err_map;
@@ -301,7 +327,7 @@ static int uio_dev_add_attributes(struct uio_device *idev)
 		if (!portio_found) {
 			portio_found = 1;
 			idev->portio_dir = kobject_create_and_add("portio",
-							&idev->dev->kobj);
+							&idev->dev.kobj);
 			if (!idev->portio_dir) {
 				ret = -ENOMEM;
 				goto err_portio;
@@ -344,7 +370,7 @@ static int uio_dev_add_attributes(struct uio_device *idev)
 		kobject_put(&map->kobj);
 	}
 	kobject_put(idev->map_dir);
-	dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);
+	dev_err(&idev->dev, "error creating sysfs files (%d)\n", ret);
 	return ret;
 }
 
@@ -381,7 +407,7 @@ static int uio_get_minor(struct uio_device *idev)
 		idev->minor = retval;
 		retval = 0;
 	} else if (retval == -ENOSPC) {
-		dev_err(idev->dev, "too many uio devices\n");
+		dev_err(&idev->dev, "too many uio devices\n");
 		retval = -EINVAL;
 	}
 	mutex_unlock(&minor_lock);
@@ -417,8 +443,9 @@ EXPORT_SYMBOL_GPL(uio_event_notify);
 static irqreturn_t uio_interrupt(int irq, void *dev_id)
 {
 	struct uio_device *idev = (struct uio_device *)dev_id;
-	irqreturn_t ret = idev->info->handler(irq, idev->info);
+	irqreturn_t ret;
 
+	ret = idev->info->handler(irq, idev->info);
 	if (ret == IRQ_HANDLED)
 		uio_event_notify(idev->info);
 
@@ -444,9 +471,11 @@ static int uio_open(struct inode *inode, struct file *filep)
 		goto out;
 	}
 
+	get_device(&idev->dev);
+
 	if (!try_module_get(idev->owner)) {
 		ret = -ENODEV;
-		goto out;
+		goto err_module_get;
 	}
 
 	listener = kmalloc(sizeof(*listener), GFP_KERNEL);
@@ -459,11 +488,19 @@ static int uio_open(struct inode *inode, struct file *filep)
 	listener->event_count = atomic_read(&idev->event);
 	filep->private_data = listener;
 
-	if (idev->info->open) {
-		ret = idev->info->open(idev->info, inode);
-		if (ret)
-			goto err_infoopen;
+	mutex_lock(&idev->info_lock);
+	if (!idev->info) {
+		mutex_unlock(&idev->info_lock);
+		ret = -EINVAL;
+		goto err_alloc_listener;
 	}
+
+	if (idev->info && idev->info->open)
+		ret = idev->info->open(idev->info, inode);
+	mutex_unlock(&idev->info_lock);
+	if (ret)
+		goto err_infoopen;
+
 	return 0;
 
 err_infoopen:
@@ -472,6 +509,9 @@ static int uio_open(struct inode *inode, struct file *filep)
 err_alloc_listener:
 	module_put(idev->owner);
 
+err_module_get:
+	put_device(&idev->dev);
+
 out:
 	return ret;
 }
@@ -490,11 +530,14 @@ static int uio_release(struct inode *inode, struct file *filep)
 	struct uio_listener *listener = filep->private_data;
 	struct uio_device *idev = listener->dev;
 
-	if (idev->info->release)
+	mutex_lock(&idev->info_lock);
+	if (idev->info && idev->info->release)
 		ret = idev->info->release(idev->info, inode);
+	mutex_unlock(&idev->info_lock);
 
 	module_put(idev->owner);
 	kfree(listener);
+	put_device(&idev->dev);
 	return ret;
 }
 
@@ -502,9 +545,15 @@ static unsigned int uio_poll(struct file *filep, poll_table *wait)
 {
 	struct uio_listener *listener = filep->private_data;
 	struct uio_device *idev = listener->dev;
+	unsigned int ret = 0;
 
-	if (!idev->info->irq)
-		return -EIO;
+	mutex_lock(&idev->info_lock);
+	if (!idev->info || !idev->info->irq)
+		ret = -EIO;
+	mutex_unlock(&idev->info_lock);
+
+	if (ret)
+		return ret;
 
 	poll_wait(filep, &idev->wait, wait);
 	if (listener->event_count != atomic_read(&idev->event))
@@ -518,11 +567,16 @@ static ssize_t uio_read(struct file *filep, char __user *buf,
 	struct uio_listener *listener = filep->private_data;
 	struct uio_device *idev = listener->dev;
 	DECLARE_WAITQUEUE(wait, current);
-	ssize_t retval;
+	ssize_t retval = 0;
 	s32 event_count;
 
-	if (!idev->info->irq)
-		return -EIO;
+	mutex_lock(&idev->info_lock);
+	if (!idev->info || !idev->info->irq)
+		retval = -EIO;
+	mutex_unlock(&idev->info_lock);
+
+	if (retval)
+		return retval;
 
 	if (count != sizeof(s32))
 		return -EINVAL;
@@ -570,20 +624,32 @@ static ssize_t uio_write(struct file *filep, const char __user *buf,
 	ssize_t retval;
 	s32 irq_on;
 
-	if (!idev->info->irq)
-		return -EIO;
-
 	if (count != sizeof(s32))
 		return -EINVAL;
 
-	if (!idev->info->irqcontrol)
-		return -ENOSYS;
-
 	if (copy_from_user(&irq_on, buf, count))
 		return -EFAULT;
 
+	mutex_lock(&idev->info_lock);
+	if (!idev->info) {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	if (!idev->info || !idev->info->irq) {
+		retval = -EIO;
+		goto out;
+	}
+
+	if (!idev->info->irqcontrol) {
+		retval = -ENOSYS;
+		goto out;
+	}
+
 	retval = idev->info->irqcontrol(idev->info, irq_on);
 
+out:
+	mutex_unlock(&idev->info_lock);
 	return retval ? retval : sizeof(s32);
 }
 
@@ -605,10 +671,20 @@ static int uio_vma_fault(struct vm_fault *vmf)
 	struct page *page;
 	unsigned long offset;
 	void *addr;
+	int ret = 0;
+	int mi;
 
-	int mi = uio_find_mem_index(vmf->vma);
-	if (mi < 0)
-		return VM_FAULT_SIGBUS;
+	mutex_lock(&idev->info_lock);
+	if (!idev->info) {
+		ret = VM_FAULT_SIGBUS;
+		goto out;
+	}
+
+	mi = uio_find_mem_index(vmf->vma);
+	if (mi < 0) {
+		ret = VM_FAULT_SIGBUS;
+		goto out;
+	}
 
 	/*
 	 * We need to subtract mi because userspace uses offset = N*PAGE_SIZE
@@ -623,7 +699,11 @@ static int uio_vma_fault(struct vm_fault *vmf)
 		page = vmalloc_to_page(addr);
 	get_page(page);
 	vmf->page = page;
-	return 0;
+
+out:
+	mutex_unlock(&idev->info_lock);
+
+	return ret;
 }
 
 static const struct vm_operations_struct uio_logical_vm_ops = {
@@ -648,6 +728,7 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
 	struct uio_device *idev = vma->vm_private_data;
 	int mi = uio_find_mem_index(vma);
 	struct uio_mem *mem;
+
 	if (mi < 0)
 		return -EINVAL;
 	mem = idev->info->mem + mi;
@@ -689,30 +770,46 @@ static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
 
 	vma->vm_private_data = idev;
 
+	mutex_lock(&idev->info_lock);
+	if (!idev->info) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	mi = uio_find_mem_index(vma);
-	if (mi < 0)
-		return -EINVAL;
+	if (mi < 0) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	requested_pages = vma_pages(vma);
 	actual_pages = ((idev->info->mem[mi].addr & ~PAGE_MASK)
 			+ idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT;
-	if (requested_pages > actual_pages)
-		return -EINVAL;
+	if (requested_pages > actual_pages) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	if (idev->info->mmap) {
 		ret = idev->info->mmap(idev->info, vma);
-		return ret;
+		goto out;
 	}
 
 	switch (idev->info->mem[mi].memtype) {
 		case UIO_MEM_PHYS:
-			return uio_mmap_physical(vma);
+			ret = uio_mmap_physical(vma);
+			break;
 		case UIO_MEM_LOGICAL:
 		case UIO_MEM_VIRTUAL:
-			return uio_mmap_logical(vma);
+			ret = uio_mmap_logical(vma);
+			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
 	}
+
+out:
+	mutex_unlock(&idev->info_lock);
+	return ret;
 }
 
 static const struct file_operations uio_fops = {
@@ -800,6 +897,13 @@ static void release_uio_class(void)
 	uio_major_cleanup();
 }
 
+static void uio_device_release(struct device *dev)
+{
+	struct uio_device *idev = dev_get_drvdata(dev);
+
+	kfree(idev);
+}
+
 /**
  * uio_register_device - register a new userspace IO device
  * @owner:	module that creates the new device
@@ -823,13 +927,14 @@ int __uio_register_device(struct module *owner,
 
 	info->uio_dev = NULL;
 
-	idev = devm_kzalloc(parent, sizeof(*idev), GFP_KERNEL);
+	idev = kzalloc(sizeof(*idev), GFP_KERNEL);
 	if (!idev) {
 		return -ENOMEM;
 	}
 
 	idev->owner = owner;
 	idev->info = info;
+	mutex_init(&idev->info_lock);
 	init_waitqueue_head(&idev->wait);
 	atomic_set(&idev->event, 0);
 
@@ -837,14 +942,19 @@ int __uio_register_device(struct module *owner,
 	if (ret)
 		return ret;
 
-	idev->dev = device_create(&uio_class, parent,
-				  MKDEV(uio_major, idev->minor), idev,
-				  "uio%d", idev->minor);
-	if (IS_ERR(idev->dev)) {
-		printk(KERN_ERR "UIO: device register failed\n");
-		ret = PTR_ERR(idev->dev);
+	idev->dev.devt = MKDEV(uio_major, idev->minor);
+	idev->dev.class = &uio_class;
+	idev->dev.parent = parent;
+	idev->dev.release = uio_device_release;
+	dev_set_drvdata(&idev->dev, idev);
+
+	ret = dev_set_name(&idev->dev, "uio%d", idev->minor);
+	if (ret)
 		goto err_device_create;
-	}
+
+	ret = device_register(&idev->dev);
+	if (ret)
+		goto err_device_create;
 
 	ret = uio_dev_add_attributes(idev);
 	if (ret)
@@ -874,7 +984,7 @@ int __uio_register_device(struct module *owner,
 err_request_irq:
 	uio_dev_del_attributes(idev);
 err_uio_dev_add_attributes:
-	device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
+	device_unregister(&idev->dev);
 err_device_create:
 	uio_free_minor(idev);
 	return ret;
@@ -897,12 +1007,16 @@ void uio_unregister_device(struct uio_info *info)
 
 	uio_free_minor(idev);
 
+	mutex_lock(&idev->info_lock);
 	uio_dev_del_attributes(idev);
 
 	if (info->irq && info->irq != UIO_IRQ_CUSTOM)
 		free_irq(info->irq, idev);
 
-	device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
+	idev->info = NULL;
+	mutex_unlock(&idev->info_lock);
+
+	device_unregister(&idev->dev);
 
 	return;
 }
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 423a339..8ab0195 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1893,6 +1893,13 @@ static const struct usb_device_id acm_ids[] = {
 	.driver_info = IGNORE_DEVICE,
 	},
 
+	{ USB_DEVICE(0x1bc7, 0x0021), /* Telit 3G ACM only composition */
+	.driver_info = SEND_ZERO_PACKET,
+	},
+	{ USB_DEVICE(0x1bc7, 0x0023), /* Telit 3G ACM + ECM composition */
+	.driver_info = SEND_ZERO_PACKET,
+	},
+
 	/* control interfaces without any protocol set */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_PROTO_NONE) },
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 6a0a20e..cf85ca8 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1435,10 +1435,10 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
 	int	w;
 
 	/* Remote wakeup is needed only when we actually go to sleep.
-	 * For things like FREEZE and QUIESCE, if the device is already
+	 * For QUIESCE, if the device is already
 	 * autosuspended then its current wakeup setting is okay.
 	 */
-	if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_QUIESCE) {
+	if (msg.event == PM_EVENT_QUIESCE) {
 		if (udev->state != USB_STATE_SUSPENDED)
 			udev->do_remote_wakeup = 0;
 		return;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 0c116e0..8ce80fa 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1121,6 +1121,16 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 						   USB_PORT_FEAT_ENABLE);
 		}
 
+		/*
+		 * Add debounce if USB3 link is in polling/link training state.
+		 * Link will automatically transition to Enabled state after
+		 * link training completes.
+		 */
+		if (hub_is_superspeed(hdev) &&
+		    ((portstatus & USB_PORT_STAT_LINK_STATE) ==
+						USB_SS_PORT_LS_POLLING))
+			need_debounce_delay = true;
+
 		/* Clear status-change flags; we'll debounce later */
 		if (portchange & USB_PORT_STAT_C_CONNECTION) {
 			need_debounce_delay = true;
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index cf378b1..733479dd 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -240,7 +240,8 @@ static const struct usb_device_id usb_quirk_list[] = {
 			USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
 
 	/* Corsair K70 RGB */
-	{ USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT },
+	{ USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT |
+	  USB_QUIRK_DELAY_CTRL_MSG },
 
 	/* Corsair Strafe */
 	{ USB_DEVICE(0x1b1c, 0x1b15), .driver_info = USB_QUIRK_DELAY_INIT |
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 92e63778..da67caf 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -855,8 +855,9 @@ struct dwc3_scratchpad_array {
 #define DWC3_GSI_EVT_BUF_ALLOC			10
 #define DWC3_GSI_EVT_BUF_SETUP			11
 #define DWC3_GSI_EVT_BUF_CLEANUP		12
-#define DWC3_GSI_EVT_BUF_FREE			13
-#define DWC3_CONTROLLER_NOTIFY_CLEAR_DB		14
+#define DWC3_GSI_EVT_BUF_CLEAR			13
+#define DWC3_GSI_EVT_BUF_FREE			14
+#define DWC3_CONTROLLER_NOTIFY_CLEAR_DB		15
 
 #define MAX_INTR_STATS				10
 
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 730f9e9..59dc690 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -2002,6 +2002,15 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
 			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), 0);
 		}
 		break;
+	case DWC3_GSI_EVT_BUF_CLEAR:
+		dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_CLEAR\n");
+		for (i = 0; i < mdwc->num_gsi_event_buffers; i++) {
+			reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT((i+1)));
+			reg &= DWC3_GEVNTCOUNT_MASK;
+			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), reg);
+			dbg_log_string("remaining EVNTCOUNT(%d)=%d", i+1, reg);
+		}
+		break;
 	case DWC3_GSI_EVT_BUF_FREE:
 		dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_FREE\n");
 		if (!mdwc->gsi_ev_buff)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 5ef1377..879a0ef 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -306,6 +306,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
 
 	complete(&dwc->ep0_in_setup);
 
+	if (!dwc->softconnect)
+		return;
+
 	dep = dwc->eps[0];
 	dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 8,
 			DWC3_TRBCTL_CONTROL_SETUP, false);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index a0169a7..64b7f7c 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -204,7 +204,7 @@ void dwc3_ep_inc_deq(struct dwc3_ep *dep)
 int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc, struct dwc3_ep *dep)
 {
 	int		fifo_size, mdwidth, max_packet = 1024;
-	int		tmp, mult = 1, size;
+	int		tmp, mult = 1, fifo_0_start;
 
 	if (!dwc->needs_fifo_resize || !dwc->tx_fifo_size)
 		return 0;
@@ -239,13 +239,11 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc, struct dwc3_ep *dep)
 	fifo_size = DIV_ROUND_UP(tmp, mdwidth);
 	dep->fifo_depth = fifo_size;
 
-	size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
-	if (dwc3_is_usb31(dwc))
-		size = DWC31_GTXFIFOSIZ_TXFDEF(size);
-	else
-		size = DWC3_GTXFIFOSIZ_TXFDEF(size);
+	/* Check if TXFIFOs start at non-zero addr */
+	tmp = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
+	fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(tmp);
 
-	fifo_size |= (size + (dwc->last_fifo_depth << 16));
+	fifo_size |= (fifo_0_start + (dwc->last_fifo_depth << 16));
 	if (dwc3_is_usb31(dwc))
 		dwc->last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEF(fifo_size);
 	else
@@ -467,7 +465,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
 		ret = -ETIMEDOUT;
 		dev_err(dwc->dev, "%s command timeout for %s\n",
 			dwc3_gadget_ep_cmd_string(cmd), dep->name);
-		if (!(cmd & DWC3_DEPCMD_ENDTRANSFER)) {
+		if (DWC3_DEPCMD_CMD(cmd) != DWC3_DEPCMD_ENDTRANSFER) {
 			dwc->ep_cmd_timeout_cnt++;
 			dwc3_notify_event(dwc,
 				DWC3_CONTROLLER_RESTART_USB_SESSION, 0);
@@ -1035,8 +1033,6 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
 	struct usb_gadget	*gadget = &dwc->gadget;
 	enum usb_device_speed	speed = gadget->speed;
 
-	dwc3_ep_inc_enq(dep);
-
 	trb->size = DWC3_TRB_SIZE_LENGTH(length);
 	trb->bpl = lower_32_bits(dma);
 	trb->bph = upper_32_bits(dma);
@@ -1106,16 +1102,20 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
 				usb_endpoint_type(dep->endpoint.desc));
 	}
 
-	/* always enable Continue on Short Packet */
+	/*
+	 * Enable Continue on Short Packet
+	 * when endpoint is not a stream capable
+	 */
 	if (usb_endpoint_dir_out(dep->endpoint.desc)) {
-		trb->ctrl |= DWC3_TRB_CTRL_CSP;
+		if (!dep->stream_capable)
+			trb->ctrl |= DWC3_TRB_CTRL_CSP;
 
 		if (short_not_ok)
 			trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
 	}
 
 	if ((!no_interrupt && !chain) ||
-			(dwc3_calc_trbs_left(dep) == 0))
+			(dwc3_calc_trbs_left(dep) == 1))
 		trb->ctrl |= DWC3_TRB_CTRL_IOC;
 
 	if (chain)
@@ -1126,6 +1126,8 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
 
 	trb->ctrl |= DWC3_TRB_CTRL_HWO;
 
+	dwc3_ep_inc_enq(dep);
+
 	trace_dwc3_prepare_trb(dep, trb);
 }
 
@@ -1258,7 +1260,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
 	unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
 	unsigned int rem = length % maxp;
 
-	if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) {
+	if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) {
 		struct dwc3	*dwc = dep->dwc;
 		struct dwc3_trb	*trb;
 
@@ -1360,6 +1362,11 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param)
 	int				ret;
 	u32				cmd;
 
+	if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) {
+		dbg_event(dep->number, "ENDXFER Pending", dep->flags);
+		return -EBUSY;
+	}
+
 	starting = !(dep->flags & DWC3_EP_BUSY);
 
 	dwc3_prepare_trbs(dep);
@@ -2099,6 +2106,19 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 
+	/* Controller is not halted until the events are acknowledged */
+	if (!is_on) {
+		/*
+		 * Clear out any pending events (i.e. End Transfer Command
+		 * Complete).
+		 */
+		reg1 = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
+		reg1 &= DWC3_GEVNTCOUNT_MASK;
+		dbg_log_string("remaining EVNTCOUNT(0)=%d", reg1);
+		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg1);
+		dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEAR, 0);
+	}
+
 	do {
 		reg = dwc3_readl(dwc->regs, DWC3_DSTS);
 		reg &= DWC3_DSTS_DEVCTRLHLT;
@@ -2163,6 +2183,9 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 				msecs_to_jiffies(DWC3_PULL_UP_TIMEOUT));
 		if (ret == 0) {
 			dev_err(dwc->dev, "timed out waiting for SETUP phase\n");
+			pm_runtime_put_autosuspend(dwc->dev);
+			dbg_event(0xFF, "Pullup timeout put",
+				atomic_read(&dwc->dev->power.usage_count));
 			return -ETIMEDOUT;
 		}
 	}
@@ -2370,6 +2393,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
 
 	/* begin to receive SETUP packets */
 	dwc->ep0state = EP0_SETUP_PHASE;
+	dwc->link_state = DWC3_LINK_STATE_SS_DIS;
 	dwc3_ep0_out_start(dwc);
 
 	dwc3_gadget_enable_irq(dwc);
@@ -3728,6 +3752,12 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
 	if (dwc->err_evt_seen)
 		return IRQ_HANDLED;
 
+	/* Controller is being halted, ignore the interrupts */
+	if (!dwc->pullups_connected) {
+		dbg_event(0xFF, "NO_PULLUP", 0);
+		return IRQ_HANDLED;
+	}
+
 	/*
 	 * With PCIe legacy interrupt, test shows that top-half irq handler can
 	 * be called again after HW interrupt deassertion. Check if bottom-half
@@ -3742,6 +3772,19 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
 	if (!count)
 		return IRQ_NONE;
 
+	if (count > evt->length) {
+		dbg_event(0xFF, "HUGE_EVCNT", count);
+		/*
+		 * If writes from dwc3_interrupt and run_stop(0) races
+		 * with each other, the count can result in a very large
+		 * value.In that case setting the evt->lpos here
+		 * is a no-op. The value will be reset as part of run_stop(1).
+		 */
+		evt->lpos = (evt->lpos + count) % DWC3_EVENT_BUFFERS_SIZE;
+		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
+		return IRQ_HANDLED;
+	}
+
 	evt->count = count;
 	evt->flags |= DWC3_EVENT_PENDING;
 
@@ -3947,6 +3990,8 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
 	dwc3_disconnect_gadget(dwc);
 	__dwc3_gadget_stop(dwc);
 
+	synchronize_irq(dwc->irq_gadget);
+
 	return 0;
 }
 
diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h
index 960be7d..885653d6 100644
--- a/drivers/usb/dwc3/trace.h
+++ b/drivers/usb/dwc3/trace.h
@@ -262,9 +262,11 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
 				s = "2x ";
 				break;
 			case 3:
+			default:
 				s = "3x ";
 				break;
 			}
+			break;
 		default:
 			s = "";
 		} s; }),
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 81be8e6..35e37d5 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -533,8 +533,14 @@ int usb_func_ep_queue(struct usb_function *func, struct usb_ep *ep,
 		} else if (ret < 0 && ret != -ENOTSUPP) {
 			pr_err("Failed to wake function %s from suspend state. ret=%d.\n",
 				func->name ? func->name : "", ret);
+		} else {
+			/*
+			 * Return -EAGAIN to queue the request from
+			 * function driver wakeup function.
+			 */
+			ret = -EAGAIN;
+			goto done;
 		}
-		goto done;
 	}
 
 	if (!func->func_is_suspended)
@@ -652,18 +658,10 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
 	w_value &= 0xff;
 
 	pos = &cdev->configs;
-	c = cdev->os_desc_config;
-	if (c)
-		goto check_config;
 
 	while ((pos = pos->next) !=  &cdev->configs) {
 		c = list_entry(pos, typeof(*c), list);
 
-		/* skip OS Descriptors config which is handled separately */
-		if (c == cdev->os_desc_config)
-			continue;
-
-check_config:
 		/* ignore configs that won't work at this speed */
 		switch (speed) {
 		case USB_SPEED_SUPER_PLUS:
diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c
index ca97f6e..e596c4b 100644
--- a/drivers/usb/gadget/function/f_accessory.c
+++ b/drivers/usb/gadget/function/f_accessory.c
@@ -659,16 +659,16 @@ static ssize_t acc_write(struct file *fp, const char __user *buf,
 	}
 
 	while (count > 0) {
-		if (!dev->online) {
+		/* get an idle tx request to use */
+		req = 0;
+		ret = wait_event_interruptible(dev->write_wq,
+			((req = req_get(dev, &dev->tx_idle)) || !dev->online));
+		if (!dev->online || dev->disconnected) {
 			pr_debug("acc_write dev->error\n");
 			r = -EIO;
 			break;
 		}
 
-		/* get an idle tx request to use */
-		req = 0;
-		ret = wait_event_interruptible(dev->write_wq,
-			((req = req_get(dev, &dev->tx_idle)) || !dev->online));
 		if (!req) {
 			r = ret;
 			break;
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index db8e47d..8343b84 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, 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
@@ -103,6 +103,21 @@ static inline bool usb_gsi_remote_wakeup_allowed(struct usb_function *f)
 	return remote_wakeup_allowed;
 }
 
+static void usb_gsi_check_pending_wakeup(struct usb_function *f)
+{
+	struct f_gsi *gsi = func_to_gsi(f);
+
+	/*
+	 * If host suspended bus without receiving notification request then
+	 * initiate remote-wakeup. As driver won't be able to do it later since
+	 * notification request is already queued.
+	 */
+	if (gsi->c_port.notify_req_queued && usb_gsi_remote_wakeup_allowed(f)) {
+		mod_timer(&gsi->gsi_rw_timer, jiffies + msecs_to_jiffies(2000));
+		log_event_dbg("%s: pending response, arm rw_timer\n", __func__);
+	}
+}
+
 static void post_event(struct gsi_data_port *port, u8 event)
 {
 	unsigned long flags;
@@ -203,6 +218,8 @@ static int gsi_wakeup_host(struct f_gsi *gsi)
 		return -ENODEV;
 	}
 
+	gsi->rwake_inprogress = true;
+
 	/*
 	 * In Super-Speed mode, remote wakeup is not allowed for suspended
 	 * functions which have been disallowed by the host to issue Function
@@ -225,6 +242,9 @@ static int gsi_wakeup_host(struct f_gsi *gsi)
 	else if (ret)
 		log_event_err("wakeup failed. ret=%d.", ret);
 
+	if (ret)
+		gsi->rwake_inprogress = false;
+
 	return ret;
 }
 
@@ -502,7 +522,8 @@ int ipa_usb_notify_cb(enum ipa_usb_notify_event event,
 		break;
 
 	case IPA_USB_REMOTE_WAKEUP:
-		gsi_wakeup_host(gsi);
+		if (!gsi->rwake_inprogress)
+			gsi_wakeup_host(gsi);
 		break;
 
 	case IPA_USB_SUSPEND_COMPLETED:
@@ -931,8 +952,9 @@ static void ipa_work_handler(struct work_struct *w)
 			log_event_dbg("%s: ST_CON_IN_PROG_EVT_HOST_READY",
 					 __func__);
 		} else if (event == EVT_CONNECTED) {
-			if (peek_event(d_port) == EVT_SUSPEND) {
-				log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUSPEND",
+			if (peek_event(d_port) == EVT_SUSPEND ||
+				peek_event(d_port) == EVT_DISCONNECTED) {
+				log_event_dbg("%s: NO_OP CONN_SUS CONN_DIS",
 					 __func__);
 				break;
 			}
@@ -1394,7 +1416,7 @@ static long gsi_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
 						cdev);
 	struct f_gsi *gsi;
 	struct gsi_ctrl_pkt *cpkt;
-	struct ep_info info;
+	struct ep_info info = { {0}, {0} };
 	struct data_buf_info data_info = {0};
 	int val, ret = 0;
 	unsigned long flags;
@@ -1619,6 +1641,15 @@ static unsigned int gsi_xfer_bitrate(struct usb_gadget *g)
 		return 19 * 64 * 1 * 1000 * 8;
 }
 
+static void gsi_uevent_work(struct work_struct *w)
+{
+	struct gsi_ctrl_port *c_port =
+			container_of(w, struct gsi_ctrl_port, uevent_work);
+
+	if (c_port->dev)
+		kobject_uevent(&c_port->dev->kobj, KOBJ_CHANGE);
+}
+
 static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
 {
 	int ret;
@@ -1633,6 +1664,9 @@ static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
 	spin_lock_init(&gsi->c_port.lock);
 
 	init_waitqueue_head(&gsi->c_port.read_wq);
+	INIT_WORK(&gsi->c_port.uevent_work, gsi_uevent_work);
+	gsi->c_port.dev = NULL;
+	gsi->c_port.uevent_wq = NULL;
 
 	switch (gsi->prot_id) {
 	case USB_PROT_RMNET_IPA:
@@ -1662,6 +1696,10 @@ static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
 	else
 		strlcat(gsi->c_port.name, cdev_name, sz);
 
+	gsi->c_port.uevent_wq = alloc_workqueue(gsi->c_port.name,
+						WQ_UNBOUND | WQ_MEM_RECLAIM |
+						WQ_FREEZABLE, 1);
+
 	minor = ida_simple_get(&gsi_ida, 0, MAX_CDEV_INSTANCES, GFP_KERNEL);
 	if (minor < 0) {
 		pr_err("%s: No more minor numbers left! rc:%d\n", __func__,
@@ -1677,7 +1715,7 @@ static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
 		goto err_cdev_add;
 	}
 
-	dev = device_create(gsi_class, NULL, MKDEV(major, minor), NULL,
+	dev = device_create(gsi_class, NULL, MKDEV(major, minor), &gsi->c_port,
 			gsi->c_port.name);
 	if (IS_ERR(dev)) {
 		log_event_err("%s: device_create failed for (%s)\n", __func__,
@@ -1686,6 +1724,8 @@ static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
 		goto err_create_dev;
 	}
 
+	gsi->c_port.dev = dev;
+
 	return 0;
 
 err_create_dev:
@@ -1785,11 +1825,16 @@ static int gsi_ctrl_send_notification(struct f_gsi *gsi)
 	__le32 *data;
 	struct usb_cdc_notification *event;
 	struct usb_request *req = gsi->c_port.notify_req;
-	struct usb_composite_dev *cdev = gsi->function.config->cdev;
+	struct usb_composite_dev *cdev;
 	struct gsi_ctrl_pkt *cpkt;
 	unsigned long flags;
 	bool del_free_cpkt = false;
 
+	if (!gsi->function.config)
+		return -ENODEV;
+
+	cdev = gsi->function.config->cdev;
+
 	if (!atomic_read(&gsi->connected)) {
 		log_event_dbg("%s: cable disconnect", __func__);
 		return -ENODEV;
@@ -1903,6 +1948,9 @@ static void gsi_ctrl_notify_resp_complete(struct usb_ep *ep,
 	gsi->c_port.notify_req_queued = false;
 	spin_unlock_irqrestore(&gsi->c_port.lock, flags);
 
+	log_event_dbg("%s: status:%d req_queued:%d",
+		__func__, status, gsi->c_port.notify_req_queued);
+
 	switch (status) {
 	case -ECONNRESET:
 	case -ESHUTDOWN:
@@ -2127,6 +2175,10 @@ gsi_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 			gsi->rmnet_dtr_status = line_state;
 		log_event_dbg("%s: USB_CDC_REQ_SET_CONTROL_LINE_STATE DTR:%d\n",
 						__func__, line_state);
+		if (gsi->c_port.uevent_wq)
+			queue_work(gsi->c_port.uevent_wq,
+					&gsi->c_port.uevent_work);
+
 		gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
 		value = 0;
 		break;
@@ -2491,6 +2543,9 @@ static int gsi_set_alt(struct usb_function *f, unsigned int intf,
 				gsi->prot_id == USB_PROT_MBIM_IPA)
 		gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
 
+	if (gsi->c_port.uevent_wq)
+		queue_work(gsi->c_port.uevent_wq, &gsi->c_port.uevent_work);
+
 	return 0;
 
 notify_ep_disable:
@@ -2524,6 +2579,10 @@ static void gsi_disable(struct usb_function *f)
 	}
 
 	gsi_ctrl_clear_cpkt_queues(gsi, false);
+
+	if (gsi->c_port.uevent_wq)
+		queue_work(gsi->c_port.uevent_wq, &gsi->c_port.uevent_work);
+
 	/* send 0 len pkt to qti/qbi/gps to notify state change */
 	gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
 	gsi->c_port.notify_req_queued = false;
@@ -2570,6 +2629,7 @@ static void gsi_suspend(struct usb_function *f)
 	 */
 	if (!gsi->data_interface_up) {
 		log_event_dbg("%s: suspend done\n", __func__);
+		usb_gsi_check_pending_wakeup(f);
 		return;
 	}
 
@@ -2579,16 +2639,7 @@ static void gsi_suspend(struct usb_function *f)
 	post_event(&gsi->d_port, EVT_SUSPEND);
 	queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w);
 	log_event_dbg("gsi suspended");
-
-	/*
-	 * If host suspended bus without receiving notification request then
-	 * initiate remote-wakeup. As driver won't be able to do it later since
-	 * notification request is already queued.
-	 */
-	if (gsi->c_port.notify_req_queued && usb_gsi_remote_wakeup_allowed(f)) {
-		mod_timer(&gsi->gsi_rw_timer, jiffies + msecs_to_jiffies(2000));
-		log_event_dbg("%s: pending response, arm rw_timer\n", __func__);
-	}
+	usb_gsi_check_pending_wakeup(f);
 }
 
 static void gsi_resume(struct usb_function *f)
@@ -2632,6 +2683,8 @@ static void gsi_resume(struct usb_function *f)
 			gsi->host_supports_flow_control)
 		rndis_flow_control(gsi->params, false);
 
+	gsi->rwake_inprogress = false;
+
 	post_event(&gsi->d_port, EVT_RESUMED);
 	queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w);
 
@@ -2902,6 +2955,7 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
 	struct gsi_function_bind_info info = {0};
 	struct f_gsi *gsi = func_to_gsi(f);
 	struct rndis_params *params;
+	struct gsi_opts *opts;
 	struct net_device *net;
 	char *name = NULL;
 	int status;
@@ -3110,18 +3164,15 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
 		info.notify_buf_len = sizeof(struct usb_cdc_notification);
 		mbim_gsi_desc.wMaxSegmentSize = cpu_to_le16(0x800);
 
-		/*
-		 * If MBIM is bound in a config other than the first, tell
-		 * Windows about it by returning the num as a string in the
-		 * OS descriptor's subCompatibleID field. Windows only supports
-		 * up to config #4.
-		 */
-		if (c->bConfigurationValue >= 2 &&
-				c->bConfigurationValue <= 4) {
-			log_event_dbg("MBIM in configuration %d",
-					c->bConfigurationValue);
-			mbim_gsi_ext_config_desc.function.subCompatibleID[0] =
-				c->bConfigurationValue + '0';
+		if (cdev->use_os_string) {
+			f->os_desc_table = kzalloc(sizeof(*f->os_desc_table),
+						GFP_KERNEL);
+			if (!f->os_desc_table)
+				return -ENOMEM;
+			opts = container_of(f->fi, struct gsi_opts, func_inst);
+			f->os_desc_n = 1;
+			f->os_desc_table[0].os_desc = &opts->os_desc;
+			f->os_desc_table[0].if_id = gsi->data_id;
 		}
 		break;
 	case USB_PROT_RMNET_IPA:
@@ -3311,6 +3362,7 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
 
 dereg_rndis:
 	rndis_deregister(gsi->params);
+	kfree(f->os_desc_table);
 fail:
 	return status;
 }
@@ -3342,8 +3394,11 @@ static void gsi_unbind(struct usb_configuration *c, struct usb_function *f)
 		rndis_deregister(gsi->params);
 	}
 
-	if (gsi->prot_id == USB_PROT_MBIM_IPA)
-		mbim_gsi_ext_config_desc.function.subCompatibleID[0] = 0;
+	if (gsi->prot_id == USB_PROT_MBIM_IPA) {
+		kfree(f->os_desc_table);
+		f->os_desc_table = NULL;
+		f->os_desc_n = 0;
+	}
 
 	usb_free_all_descriptors(f);
 
@@ -3657,6 +3712,8 @@ static int gsi_set_inst_name(struct usb_function_instance *fi,
 	int name_len, prot_id, ret = 0;
 	struct gsi_opts *opts;
 	struct f_gsi *gsi;
+	struct usb_os_desc *descs[1];
+	char *names[1];
 
 	opts = container_of(fi, struct gsi_opts, func_inst);
 
@@ -3676,6 +3733,16 @@ static int gsi_set_inst_name(struct usb_function_instance *fi,
 						fi->group.cg_item.ci_name,
 						&gsi_func_rndis_type);
 
+	if (prot_id == IPA_USB_MBIM) {
+		opts->os_desc.ext_compat_id = opts->ext_compat_id;
+		INIT_LIST_HEAD(&opts->os_desc.ext_prop);
+		descs[0] = &opts->os_desc;
+		names[0] = "MBIM";
+		opts->interf_group = usb_os_desc_prepare_interf_dir(
+						&opts->func_inst.group, 1,
+						descs, names, THIS_MODULE);
+	}
+
 	gsi = opts->gsi = __gsi[prot_id];
 	opts->gsi->prot_id = prot_id;
 	ret = gsi_function_ctrl_port_init(opts->gsi);
@@ -3688,17 +3755,32 @@ static int gsi_set_inst_name(struct usb_function_instance *fi,
 static void gsi_free_inst(struct usb_function_instance *f)
 {
 	struct gsi_opts *opts = container_of(f, struct gsi_opts, func_inst);
+	struct f_gsi *gsi;
 
 	if (opts && opts->gsi && opts->gsi->c_port.cdev.dev) {
 		struct cdev *cdev = &opts->gsi->c_port.cdev;
 		int minor = MINOR(cdev->dev);
+		gsi = opts->gsi;
+
+		if (gsi->c_port.dev)
+			dev_set_drvdata(gsi->c_port.dev, NULL);
+
+		if (gsi->c_port.uevent_wq) {
+			cancel_work_sync(&gsi->c_port.uevent_work);
+			destroy_workqueue(gsi->c_port.uevent_wq);
+			gsi->c_port.uevent_wq = NULL;
+		}
+
 
 		device_destroy(gsi_class, cdev->dev);
 		cdev_del(cdev);
 		cdev->dev = 0;
+		gsi->c_port.dev = NULL;
 		ida_simple_remove(&gsi_ida, minor);
 	}
 
+	if (opts && opts->interf_group)
+		kfree(opts->interf_group);
 	kfree(opts);
 }
 
@@ -3736,6 +3818,43 @@ DECLARE_USB_FUNCTION(gsi, gsi_alloc_inst, gsi_alloc);
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("GSI function driver");
 
+static int usb_gsi_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct gsi_ctrl_port *c_port = dev_get_drvdata(dev);
+	struct f_gsi *gsi;
+	char *str = "undefined";
+
+	if (!c_port) {
+		dev_dbg(dev, "%s: gsi is not initialized\n", __func__);
+		add_uevent_var(env, "STATE=%s", str);
+		return 0;
+	}
+
+	gsi = c_port_to_gsi(c_port);
+
+	switch (gsi->prot_id) {
+	case USB_PROT_RMNET_IPA:
+	case USB_PROT_RMNET_ETHER:
+		str = gsi->rmnet_dtr_status ? "connected" : "disconnected";
+		break;
+	case USB_PROT_MBIM_IPA:
+	case USB_PROT_DIAG_IPA:
+	case USB_PROT_DPL_ETHER:
+	case USB_PROT_GPS_CTRL:
+		str = atomic_read(&gsi->connected) ?
+					"connected" : "disconnected";
+		break;
+	default:
+		return 0;
+	}
+
+	add_uevent_var(env, "STATE=%s", str);
+
+	log_event_dbg("%s:STATE=%s\n", c_port->name, str);
+
+	return 0;
+}
+
 static int fgsi_init(void)
 {
 	int i;
@@ -3766,6 +3885,7 @@ static int fgsi_init(void)
 		pr_err("%s: class_create() failed:%d\n", __func__, ret);
 		return ret;
 	}
+	gsi_class->dev_uevent = usb_gsi_uevent;
 
 	ret = alloc_chrdev_region(&dev, 0, MAX_CDEV_INSTANCES, "gsi_usb");
 	if (ret) {
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index 8e6c64d..cfb5566 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -30,6 +30,8 @@
 
 #include "u_ether.h"
 
+#include "configfs.h"
+
 #define GSI_RMNET_CTRL_NAME "rmnet_ctrl"
 #define GSI_MBIM_CTRL_NAME "android_mbim"
 #define GSI_DPL_CTRL_NAME "dpl_ctrl"
@@ -220,6 +222,10 @@ struct gsi_ctrl_port {
 	unsigned int modem_to_host;
 	unsigned int cpkt_drop_cnt;
 	unsigned int get_encap_cnt;
+
+	struct device *dev;
+	struct work_struct uevent_work;
+	struct workqueue_struct *uevent_wq;
 };
 
 struct gsi_data_port {
@@ -278,6 +284,8 @@ struct f_gsi {
 	struct gsi_ctrl_port c_port;
 	bool rmnet_dtr_status;
 
+	bool rwake_inprogress;
+
 	/* To test remote wakeup using debugfs */
 	struct timer_list gsi_rw_timer;
 	u8 debugfs_rw_timer_enable;
@@ -306,6 +314,11 @@ static inline struct f_gsi *c_port_to_gsi(struct gsi_ctrl_port *d)
 struct gsi_opts {
 	struct usb_function_instance func_inst;
 	struct f_gsi *gsi;
+
+	/* os desc support */
+	struct config_group *interf_group;
+	char ext_compat_id[16];
+	struct usb_os_desc os_desc;
 };
 
 static inline struct gsi_opts *to_gsi_opts(struct config_item *item)
@@ -1057,50 +1070,6 @@ static struct usb_gadget_strings *mbim_gsi_strings[] = {
 	NULL,
 };
 
-/* Microsoft OS Descriptors */
-
-/*
- * We specify our own bMS_VendorCode byte which Windows will use
- * as the bRequest value in subsequent device get requests.
- */
-#define MBIM_VENDOR_CODE	0xA5
-
-/* Microsoft Extended Configuration Descriptor Header Section */
-struct mbim_gsi_ext_config_desc_header {
-	__le32	dwLength;
-	__u16	bcdVersion;
-	__le16	wIndex;
-	__u8	bCount;
-	__u8	reserved[7];
-};
-
-/* Microsoft Extended Configuration Descriptor Function Section */
-struct mbim_gsi_ext_config_desc_function {
-	__u8	bFirstInterfaceNumber;
-	__u8	bInterfaceCount;
-	__u8	compatibleID[8];
-	__u8	subCompatibleID[8];
-	__u8	reserved[6];
-};
-
-/* Microsoft Extended Configuration Descriptor */
-static struct {
-	struct mbim_gsi_ext_config_desc_header	header;
-	struct mbim_gsi_ext_config_desc_function    function;
-} mbim_gsi_ext_config_desc = {
-	.header = {
-		.dwLength = cpu_to_le32(sizeof(mbim_gsi_ext_config_desc)),
-		.bcdVersion = cpu_to_le16(0x0100),
-		.wIndex = cpu_to_le16(4),
-		.bCount = 1,
-	},
-	.function = {
-		.bFirstInterfaceNumber = 0,
-		.bInterfaceCount = 1,
-		.compatibleID = { 'A', 'L', 'T', 'R', 'C', 'F', 'G' },
-		/* .subCompatibleID = DYNAMIC */
-	},
-};
 /* ecm device descriptors */
 #define ECM_QC_LOG2_STATUS_INTERVAL_MSEC	5
 #define ECM_QC_STATUS_BYTECOUNT			16 /* 8 byte header + data */
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index 8e1f945..0e3a582 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -137,6 +137,7 @@ struct mtp_dev {
 	} perf[MAX_ITERATION];
 	unsigned int dbg_read_index;
 	unsigned int dbg_write_index;
+	struct mutex  read_mutex;
 };
 
 static struct usb_interface_descriptor mtp_interface_desc = {
@@ -634,11 +635,18 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
 	dev->state = STATE_BUSY;
 	spin_unlock_irq(&dev->lock);
 
+	mutex_lock(&dev->read_mutex);
+	if (dev->state == STATE_OFFLINE) {
+		r = -EIO;
+		mutex_unlock(&dev->read_mutex);
+		goto done;
+	}
 requeue_req:
 	/* queue a request */
 	req = dev->rx_req[0];
 	req->length = len;
 	dev->rx_done = 0;
+	mutex_unlock(&dev->read_mutex);
 	ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL);
 	if (ret < 0) {
 		r = -EIO;
@@ -664,6 +672,7 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
 		usb_ep_dequeue(dev->ep_out, req);
 		goto done;
 	}
+	mutex_lock(&dev->read_mutex);
 	if (dev->state == STATE_BUSY) {
 		/* If we got a 0-len packet, throw it back and try again. */
 		if (req->actual == 0)
@@ -677,6 +686,7 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
 	} else
 		r = -EIO;
 
+	mutex_unlock(&dev->read_mutex);
 done:
 	spin_lock_irq(&dev->lock);
 	if (dev->state == STATE_CANCELED)
@@ -928,6 +938,12 @@ static void receive_file_work(struct work_struct *data)
 
 	while (count > 0 || write_req) {
 		if (count > 0) {
+			mutex_lock(&dev->read_mutex);
+			if (dev->state == STATE_OFFLINE) {
+				r = -EIO;
+				mutex_unlock(&dev->read_mutex);
+				break;
+			}
 			/* queue a request */
 			read_req = dev->rx_req[cur_buf];
 			cur_buf = (cur_buf + 1) % RX_REQ_MAX;
@@ -936,6 +952,7 @@ static void receive_file_work(struct work_struct *data)
 			read_req->length = mtp_rx_req_len;
 
 			dev->rx_done = 0;
+			mutex_unlock(&dev->read_mutex);
 			ret = usb_ep_queue(dev->ep_out, read_req, GFP_KERNEL);
 			if (ret < 0) {
 				r = -EIO;
@@ -948,15 +965,25 @@ static void receive_file_work(struct work_struct *data)
 		if (write_req) {
 			DBG(cdev, "rx %pK %d\n", write_req, write_req->actual);
 			start_time = ktime_get();
+			mutex_lock(&dev->read_mutex);
+			if (dev->state == STATE_OFFLINE) {
+				r = -EIO;
+				mutex_unlock(&dev->read_mutex);
+				break;
+			}
 			ret = vfs_write(filp, write_req->buf, write_req->actual,
 				&offset);
 			DBG(cdev, "vfs_write %d\n", ret);
 			if (ret != write_req->actual) {
 				r = -EIO;
+				mutex_unlock(&dev->read_mutex);
 				if (dev->state != STATE_OFFLINE)
 					dev->state = STATE_ERROR;
+				if (read_req && !dev->rx_done)
+					usb_ep_dequeue(dev->ep_out, read_req);
 				break;
 			}
+			mutex_unlock(&dev->read_mutex);
 			dev->perf[dev->dbg_write_index].vfs_wtime =
 				ktime_to_us(ktime_sub(ktime_get(), start_time));
 			dev->perf[dev->dbg_write_index].vfs_wbytes = ret;
@@ -984,6 +1011,12 @@ static void receive_file_work(struct work_struct *data)
 				break;
 			}
 
+			mutex_lock(&dev->read_mutex);
+			if (dev->state == STATE_OFFLINE) {
+				r = -EIO;
+				mutex_unlock(&dev->read_mutex);
+				break;
+			}
 			/* Check if we aligned the size due to MTU constraint */
 			if (count < read_req->length)
 				read_req->actual = (read_req->actual > count ?
@@ -1004,6 +1037,7 @@ static void receive_file_work(struct work_struct *data)
 
 			write_req = read_req;
 			read_req = NULL;
+			mutex_unlock(&dev->read_mutex);
 		}
 	}
 
@@ -1456,12 +1490,14 @@ mtp_function_unbind(struct usb_configuration *c, struct usb_function *f)
 	int i;
 	fi_mtp = container_of(f->fi, struct mtp_instance, func_inst);
 	mtp_string_defs[INTERFACE_STRING_INDEX].id = 0;
+	mutex_lock(&dev->read_mutex);
 	while ((req = mtp_req_get(dev, &dev->tx_idle)))
 		mtp_request_free(req, dev->ep_in);
 	for (i = 0; i < RX_REQ_MAX; i++)
 		mtp_request_free(dev->rx_req[i], dev->ep_out);
 	while ((req = mtp_req_get(dev, &dev->intr_idle)))
 		mtp_request_free(req, dev->ep_intr);
+	mutex_unlock(&dev->read_mutex);
 	spin_lock_irq(&dev->lock);
 	dev->state = STATE_OFFLINE;
 	dev->cdev = NULL;
@@ -1807,6 +1843,8 @@ struct usb_function_instance *alloc_inst_mtp_ptp(bool mtp_config)
 	usb_os_desc_prepare_interf_dir(&fi_mtp->func_inst.group, 1,
 					descs, names, THIS_MODULE);
 
+	mutex_init(&fi_mtp->dev->read_mutex);
+
 	return  &fi_mtp->func_inst;
 }
 EXPORT_SYMBOL_GPL(alloc_inst_mtp_ptp);
diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c
index 8784fa1..6e9d9580 100644
--- a/drivers/usb/gadget/function/f_sourcesink.c
+++ b/drivers/usb/gadget/function/f_sourcesink.c
@@ -842,7 +842,7 @@ static struct usb_function *source_sink_alloc_func(
 
 	ss = kzalloc(sizeof(*ss), GFP_KERNEL);
 	if (!ss)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	ss_opts =  container_of(fi, struct f_ss_opts, func_inst);
 
diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
index 8f85a51..e0759a8 100644
--- a/drivers/usb/gadget/udc/net2272.c
+++ b/drivers/usb/gadget/udc/net2272.c
@@ -2096,7 +2096,7 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
 #if defined(PLX_PCI_RDK2)
 	/* see if PCI int for us by checking irqstat */
 	intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
-	if (!intcsr & (1 << NET2272_PCI_IRQ)) {
+	if (!(intcsr & (1 << NET2272_PCI_IRQ))) {
 		spin_unlock(&dev->lock);
 		return IRQ_NONE;
 	}
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index ade0723..e5355ede 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -352,6 +352,7 @@ struct renesas_usb3 {
 	bool extcon_host;		/* check id and set EXTCON_USB_HOST */
 	bool extcon_usb;		/* check vbus and set EXTCON_USB */
 	bool forced_b_device;
+	bool start_to_connect;
 };
 
 #define gadget_to_renesas_usb3(_gadget)	\
@@ -470,7 +471,8 @@ static void usb3_init_axi_bridge(struct renesas_usb3 *usb3)
 static void usb3_init_epc_registers(struct renesas_usb3 *usb3)
 {
 	usb3_write(usb3, ~0, USB3_USB_INT_STA_1);
-	usb3_enable_irq_1(usb3, USB_INT_1_VBUS_CNG);
+	if (!usb3->workaround_for_vbus)
+		usb3_enable_irq_1(usb3, USB_INT_1_VBUS_CNG);
 }
 
 static bool usb3_wakeup_usb2_phy(struct renesas_usb3 *usb3)
@@ -676,8 +678,7 @@ static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev)
 	usb3_set_mode(usb3, host);
 	usb3_vbus_out(usb3, a_dev);
 	/* for A-Peripheral or forced B-device mode */
-	if ((!host && a_dev) ||
-	    (usb3->workaround_for_vbus && usb3->forced_b_device))
+	if ((!host && a_dev) || usb3->start_to_connect)
 		usb3_connect(usb3);
 	spin_unlock_irqrestore(&usb3->lock, flags);
 }
@@ -2369,7 +2370,11 @@ static ssize_t renesas_usb3_b_device_write(struct file *file,
 	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
 		return -EFAULT;
 
-	if (!strncmp(buf, "1", 1))
+	usb3->start_to_connect = false;
+	if (usb3->workaround_for_vbus && usb3->forced_b_device &&
+	    !strncmp(buf, "2", 1))
+		usb3->start_to_connect = true;
+	else if (!strncmp(buf, "1", 1))
 		usb3->forced_b_device = true;
 	else
 		usb3->forced_b_device = false;
@@ -2377,7 +2382,7 @@ static ssize_t renesas_usb3_b_device_write(struct file *file,
 	if (usb3->workaround_for_vbus)
 		usb3_disconnect(usb3);
 
-	/* Let this driver call usb3_connect() anyway */
+	/* Let this driver call usb3_connect() if needed */
 	usb3_check_id(usb3);
 
 	return count;
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index b08774db..03a9dbd 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1857,7 +1857,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
 
 	/* poll for U0 link state complete, both USB2 and USB3 */
 	for_each_set_bit(port_index, &bus_state->bus_suspended, BITS_PER_LONG) {
-		sret = xhci_handshake(xhci, port_array[port_index], PORT_PLC,
+		sret = xhci_handshake(port_array[port_index], PORT_PLC,
 				      PORT_PLC, 10 * 1000);
 		if (sret) {
 			xhci_warn(xhci, "port %d resume PLC timeout\n",
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 510d28a9d..35aecbc 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -724,14 +724,16 @@ static int xhci_mtk_remove(struct platform_device *dev)
 	struct xhci_hcd_mtk *mtk = platform_get_drvdata(dev);
 	struct usb_hcd	*hcd = mtk->hcd;
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	struct usb_hcd  *shared_hcd = xhci->shared_hcd;
 
-	usb_remove_hcd(xhci->shared_hcd);
+	usb_remove_hcd(shared_hcd);
+	xhci->shared_hcd = NULL;
 	xhci_mtk_phy_power_off(mtk);
 	xhci_mtk_phy_exit(mtk);
 	device_init_wakeup(&dev->dev, false);
 
 	usb_remove_hcd(hcd);
-	usb_put_hcd(xhci->shared_hcd);
+	usb_put_hcd(shared_hcd);
 	usb_put_hcd(hcd);
 	xhci_mtk_sch_exit(mtk);
 	xhci_mtk_clks_disable(mtk);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 0fbc549..1de006a 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -370,6 +370,7 @@ static void xhci_pci_remove(struct pci_dev *dev)
 	if (xhci->shared_hcd) {
 		usb_remove_hcd(xhci->shared_hcd);
 		usb_put_hcd(xhci->shared_hcd);
+		xhci->shared_hcd = NULL;
 	}
 
 	/* Workaround for spurious wakeups at shutdown with HSW */
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 153d6eb..8550605 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -428,15 +428,17 @@ static int xhci_plat_remove(struct platform_device *dev)
 	struct usb_hcd	*hcd = platform_get_drvdata(dev);
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	struct clk *clk = xhci->clk;
+	struct usb_hcd *shared_hcd = xhci->shared_hcd;
 
 	xhci->xhc_state |= XHCI_STATE_REMOVING;
 
 	device_remove_file(&dev->dev, &dev_attr_config_imod);
-	usb_remove_hcd(xhci->shared_hcd);
+	usb_remove_hcd(shared_hcd);
 	usb_phy_shutdown(hcd->usb_phy);
 
 	usb_remove_hcd(hcd);
-	usb_put_hcd(xhci->shared_hcd);
+	xhci->shared_hcd = NULL;
+	usb_put_hcd(shared_hcd);
 
 	if (!IS_ERR(clk))
 		clk_disable_unprepare(clk);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 815a590..ebdd7c7 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -367,7 +367,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
 	 * In the future we should distinguish between -ENODEV and -ETIMEDOUT
 	 * and try to recover a -ETIMEDOUT with a host controller reset.
 	 */
-	ret = xhci_handshake(xhci, &xhci->op_regs->cmd_ring,
+	ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring,
 			CMD_RING_RUNNING, 0, 1000 * 1000);
 	if (ret < 0) {
 		xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret);
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 32ddafe..28df32d 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1178,6 +1178,7 @@ static int tegra_xusb_remove(struct platform_device *pdev)
 
 	usb_remove_hcd(xhci->shared_hcd);
 	usb_put_hcd(xhci->shared_hcd);
+	xhci->shared_hcd = NULL;
 	usb_remove_hcd(tegra->hcd);
 	usb_put_hcd(tegra->hcd);
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 4df5939..44242f4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -76,8 +76,7 @@ static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
  * handshake done).  There are two failure modes:  "usec" have passed (major
  * hardware flakeout), or the register reads as all-ones (hardware removed).
  */
-int xhci_handshake(struct xhci_hcd *xhci,
-		void __iomem *ptr, u32 mask, u32 done, int usec)
+int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
 {
 	u32	result;
 
@@ -85,6 +84,24 @@ int xhci_handshake(struct xhci_hcd *xhci,
 		result = readl(ptr);
 		if (result == ~(u32)0)		/* card removed */
 			return -ENODEV;
+		result &= mask;
+		if (result == done)
+			return 0;
+		udelay(1);
+		usec--;
+	} while (usec > 0);
+	return -ETIMEDOUT;
+}
+
+int xhci_handshake_check_state(struct xhci_hcd *xhci,
+		void __iomem *ptr, u32 mask, u32 done, int usec)
+{
+	u32	result;
+
+	do {
+		result = readl_relaxed(ptr);
+		if (result == ~(u32)0)	/* card removed */
+			return -ENODEV;
 		/* host removed. Bail out */
 		if (xhci->xhc_state & XHCI_STATE_REMOVING)
 			return -ENODEV;
@@ -130,7 +147,7 @@ int xhci_halt(struct xhci_hcd *xhci)
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Halt the HC");
 	xhci_quiesce(xhci);
 
-	ret = xhci_handshake(xhci, &xhci->op_regs->status,
+	ret = xhci_handshake(&xhci->op_regs->status,
 			STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
 	if (ret) {
 		xhci_warn(xhci, "Host halt failed, %d\n", ret);
@@ -165,7 +182,7 @@ int xhci_start(struct xhci_hcd *xhci)
 	 * Wait for the HCHalted Status bit to be 0 to indicate the host is
 	 * running.
 	 */
-	ret = xhci_handshake(xhci, &xhci->op_regs->status,
+	ret = xhci_handshake(&xhci->op_regs->status,
 			STS_HALT, 0, XHCI_MAX_HALT_USEC);
 	if (ret == -ETIMEDOUT)
 		xhci_err(xhci, "Host took too long to start, "
@@ -220,7 +237,7 @@ int xhci_reset(struct xhci_hcd *xhci)
 	if (xhci->quirks & XHCI_INTEL_HOST)
 		udelay(1000);
 
-	ret = xhci_handshake(xhci, &xhci->op_regs->command,
+	ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command,
 			CMD_RESET, 0, 10 * 1000 * 1000);
 	if (ret)
 		return ret;
@@ -234,7 +251,7 @@ int xhci_reset(struct xhci_hcd *xhci)
 	 * xHCI cannot write to any doorbells or operational registers other
 	 * than status until the "Controller Not Ready" flag is cleared.
 	 */
-	ret = xhci_handshake(xhci, &xhci->op_regs->status,
+	ret = xhci_handshake(&xhci->op_regs->status,
 			STS_CNR, 0, 10 * 1000 * 1000);
 
 	for (i = 0; i < 2; i++) {
@@ -965,7 +982,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
 	/* Some chips from Fresco Logic need an extraordinary delay */
 	delay *= (xhci->quirks & XHCI_SLOW_SUSPEND) ? 10 : 1;
 
-	if (xhci_handshake(xhci, &xhci->op_regs->status,
+	if (xhci_handshake(&xhci->op_regs->status,
 		      STS_HALT, STS_HALT, delay)) {
 		xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
 		spin_unlock_irq(&xhci->lock);
@@ -981,7 +998,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
 	command |= CMD_CSS;
 	writel(command, &xhci->op_regs->command);
 	xhci->broken_suspend = 0;
-	if (xhci_handshake(xhci, &xhci->op_regs->status,
+	if (xhci_handshake(&xhci->op_regs->status,
 				STS_SAVE, 0, 10 * 1000)) {
 	/*
 	 * AMD SNPS xHC 3.0 occasionally does not clear the
@@ -1072,7 +1089,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 		 * restore so setting the timeout to 100ms. Xhci specification
 		 * doesn't mention any timeout value.
 		 */
-		if (xhci_handshake(xhci, &xhci->op_regs->status,
+		if (xhci_handshake(&xhci->op_regs->status,
 			      STS_RESTORE, 0, 100 * 1000)) {
 			xhci_warn(xhci, "WARN: xHC restore state timeout\n");
 			spin_unlock_irq(&xhci->lock);
@@ -1143,7 +1160,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 	command = readl(&xhci->op_regs->command);
 	command |= CMD_RUN;
 	writel(command, &xhci->op_regs->command);
-	xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT,
+	xhci_handshake(&xhci->op_regs->status, STS_HALT,
 		  0, 250 * 1000);
 
 	/* step 5: walk topology and initialize portsc,
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 8983d8b..ac66d15 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -2026,7 +2026,8 @@ int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num);
 
 /* xHCI host controller glue */
 typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
-int xhci_handshake(struct xhci_hcd *xhci,
+int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec);
+int xhci_handshake_check_state(struct xhci_hcd *xhci,
 		void __iomem *ptr, u32 mask, u32 done, int usec);
 void xhci_quiesce(struct xhci_hcd *xhci);
 int xhci_halt(struct xhci_hcd *xhci);
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 3118935..f6f15ed 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -287,3 +287,14 @@
 	help
 	  Say Y here if you want to use NXP CC Logic Type-C Chipset NXP5150A
 	  for CC detection and Mux control.
+
+config USB_QCOM_DIAG_BRIDGE
+	tristate "USB QTI diagnostic bridge driver"
+	depends on USB
+	help
+	  Say Y here if you have a QTI modem device connected via USB that
+	  will be bridged in kernel space. This driver communicates with the
+	  diagnostic interface and allows for bridging with the diag forwarding
+	  driver.
+	  To compile this driver as a module, choose M here: the
+	  module will be called diag_bridge.  If unsure, choose N.
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 37baeaa..2ee3530 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -33,3 +33,4 @@
 obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
 obj-$(CONFIG_USB_LINK_LAYER_TEST)	+= lvstest.o
 obj-$(CONFIG_USB_REDRIVER_NB7VPQ904M)	+= ssusb-redriver-nb7vpq904m.o
+obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE)	+= diag_bridge.o
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
new file mode 100644
index 0000000..7a38941
--- /dev/null
+++ b/drivers/usb/misc/diag_bridge.c
@@ -0,0 +1,679 @@
+/* Copyright (c) 2011-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.
+ */
+
+/* add additional information to our printk's */
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/ratelimit.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/debugfs.h>
+#include <linux/usb/diag_bridge.h>
+
+#define DRIVER_DESC	"USB host diag bridge driver"
+#define DRIVER_VERSION	"1.0"
+
+#define MAX_DIAG_BRIDGE_DEVS	2
+#define AUTOSUSP_DELAY_WITH_USB 1000
+
+struct diag_bridge {
+	struct usb_device	*udev;
+	struct usb_interface	*ifc;
+	struct usb_anchor	submitted;
+	__u8			in_epAddr;
+	__u8			out_epAddr;
+	int			err;
+	struct kref		kref;
+	struct mutex		ifc_mutex;
+	struct diag_bridge_ops	*ops;
+	struct platform_device	*pdev;
+	unsigned int		default_autosusp_delay;
+	int			id;
+
+	/* Support INT IN instead of BULK IN */
+	bool			use_int_in_pipe;
+	unsigned int		period;
+
+	/* debugging counters */
+	unsigned long		bytes_to_host;
+	unsigned long		bytes_to_mdm;
+	unsigned int		pending_reads;
+	unsigned int		pending_writes;
+	unsigned int		drop_count;
+};
+struct diag_bridge *__dev[MAX_DIAG_BRIDGE_DEVS];
+
+int diag_bridge_open(int id, struct diag_bridge_ops *ops)
+{
+	struct diag_bridge	*dev;
+
+	if (id < 0 || id >= MAX_DIAG_BRIDGE_DEVS) {
+		pr_err("Invalid device ID\n");
+		return -ENODEV;
+	}
+
+	dev = __dev[id];
+	if (!dev) {
+		pr_err("dev is null\n");
+		return -ENODEV;
+	}
+
+	if (dev->ops) {
+		pr_err("bridge already opened\n");
+		return -EALREADY;
+	}
+
+	dev_dbg(&dev->ifc->dev, "%s\n", __func__);
+	dev->ops = ops;
+	dev->err = 0;
+
+	if (!id) {
+#ifdef CONFIG_PM_RUNTIME
+		dev->default_autosusp_delay =
+			dev->udev->dev.power.autosuspend_delay;
+#endif
+		pm_runtime_set_autosuspend_delay(&dev->udev->dev,
+				AUTOSUSP_DELAY_WITH_USB);
+	}
+
+	kref_get(&dev->kref);
+
+	return 0;
+}
+EXPORT_SYMBOL(diag_bridge_open);
+
+static void diag_bridge_delete(struct kref *kref)
+{
+	struct diag_bridge *dev = container_of(kref, struct diag_bridge, kref);
+	struct usb_interface *ifc = dev->ifc;
+	int id = dev->id;
+
+	dev_dbg(&dev->ifc->dev, "%s\n", __func__);
+	usb_set_intfdata(ifc, NULL);
+	usb_put_intf(ifc);
+	usb_put_dev(dev->udev);
+	__dev[id] = 0;
+	kfree(dev);
+}
+
+void diag_bridge_close(int id)
+{
+	struct diag_bridge	*dev;
+
+	if (id < 0 || id >= MAX_DIAG_BRIDGE_DEVS) {
+		pr_err("Invalid device ID\n");
+		return;
+	}
+
+	dev = __dev[id];
+	if (!dev) {
+		pr_err("dev is null\n");
+		return;
+	}
+
+	if (!dev->ops) {
+		pr_err("can't close bridge that was not open\n");
+		return;
+	}
+
+	dev_dbg(&dev->ifc->dev, "%s\n", __func__);
+
+	usb_kill_anchored_urbs(&dev->submitted);
+	dev->ops = 0;
+
+
+	if (!id) {
+		pm_runtime_set_autosuspend_delay(&dev->udev->dev,
+			dev->default_autosusp_delay);
+	}
+
+	kref_put(&dev->kref, diag_bridge_delete);
+}
+EXPORT_SYMBOL(diag_bridge_close);
+
+static void diag_bridge_read_cb(struct urb *urb)
+{
+	struct diag_bridge	*dev = urb->context;
+	struct diag_bridge_ops	*cbs = dev->ops;
+
+	dev_dbg(&dev->ifc->dev, "%s: status:%d actual:%d\n", __func__,
+			urb->status, urb->actual_length);
+
+	/* save error so that subsequent read/write returns ENODEV */
+	if (urb->status == -EPROTO)
+		dev->err = urb->status;
+
+	if (cbs && cbs->read_complete_cb)
+		cbs->read_complete_cb(cbs->ctxt,
+			urb->transfer_buffer,
+			urb->transfer_buffer_length,
+			urb->status < 0 ? urb->status : urb->actual_length);
+
+	dev->bytes_to_host += urb->actual_length;
+	dev->pending_reads--;
+	kref_put(&dev->kref, diag_bridge_delete);
+}
+
+int diag_bridge_read(int id, char *data, int size)
+{
+	struct urb		*urb = NULL;
+	unsigned int		pipe;
+	struct diag_bridge	*dev;
+	int			ret;
+
+	if (id < 0 || id >= MAX_DIAG_BRIDGE_DEVS) {
+		pr_err("Invalid device ID\n");
+		return -ENODEV;
+	}
+
+	pr_debug("reading %d bytes\n", size);
+
+	dev = __dev[id];
+	if (!dev) {
+		pr_err("device is disconnected\n");
+		return -ENODEV;
+	}
+
+	mutex_lock(&dev->ifc_mutex);
+	if (!dev->ifc) {
+		pr_err("device is disconnected\n");
+		ret = -ENODEV;
+		goto error;
+	}
+
+	if (!dev->ops) {
+		pr_err("bridge is not open\n");
+		ret = -ENODEV;
+		goto error;
+	}
+
+	if (!size) {
+		dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
+		dev->drop_count++;
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* if there was a previous unrecoverable error, just quit */
+	if (dev->err) {
+		pr_err("EPROTO error occurred, or device disconnected\n");
+		ret = -ENODEV;
+		goto error;
+	}
+
+	kref_get(&dev->kref);
+
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb) {
+		dev_err(&dev->ifc->dev, "unable to allocate urb\n");
+		ret = -ENOMEM;
+		goto put_error;
+	}
+
+	ret = usb_autopm_get_interface(dev->ifc);
+	if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
+		pr_err_ratelimited("read: autopm_get failed:%d\n", ret);
+		goto free_error;
+	}
+
+	if (dev->use_int_in_pipe) {
+		pipe = usb_rcvintpipe(dev->udev, dev->in_epAddr);
+		usb_fill_int_urb(urb, dev->udev, pipe, data, size,
+		diag_bridge_read_cb, dev, dev->period);
+	} else {
+		pipe = usb_rcvbulkpipe(dev->udev, dev->in_epAddr);
+		usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
+				diag_bridge_read_cb, dev);
+	}
+
+	usb_anchor_urb(urb, &dev->submitted);
+	dev->pending_reads++;
+
+	ret = usb_submit_urb(urb, GFP_KERNEL);
+	if (ret) {
+		pr_err_ratelimited("submitting urb failed err:%d\n", ret);
+		dev->pending_reads--;
+		usb_unanchor_urb(urb);
+		usb_autopm_put_interface(dev->ifc);
+		goto free_error;
+	}
+
+	usb_autopm_put_interface(dev->ifc);
+	usb_free_urb(urb);
+	mutex_unlock(&dev->ifc_mutex);
+	return ret;
+
+free_error:
+	usb_free_urb(urb);
+put_error:
+	/* If URB submit successful, this is done in the completion handler */
+	kref_put(&dev->kref, diag_bridge_delete);
+error:
+	mutex_unlock(&dev->ifc_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(diag_bridge_read);
+
+static void diag_bridge_write_cb(struct urb *urb)
+{
+	struct diag_bridge	*dev = urb->context;
+	struct diag_bridge_ops	*cbs = dev->ops;
+
+	dev_dbg(&dev->ifc->dev, "%s\n", __func__);
+
+	usb_autopm_put_interface_async(dev->ifc);
+
+	/* save error so that subsequent read/write returns ENODEV */
+	if (urb->status == -EPROTO)
+		dev->err = urb->status;
+
+	if (cbs && cbs->write_complete_cb)
+		cbs->write_complete_cb(cbs->ctxt,
+			urb->transfer_buffer,
+			urb->transfer_buffer_length,
+			urb->status < 0 ? urb->status : urb->actual_length);
+
+	dev->bytes_to_mdm += urb->actual_length;
+	dev->pending_writes--;
+	kref_put(&dev->kref, diag_bridge_delete);
+}
+
+int diag_bridge_write(int id, char *data, int size)
+{
+	struct urb		*urb = NULL;
+	unsigned int		pipe;
+	struct diag_bridge	*dev;
+	int			ret;
+
+	if (id < 0 || id >= MAX_DIAG_BRIDGE_DEVS) {
+		pr_err("Invalid device ID\n");
+		return -ENODEV;
+	}
+
+	pr_debug("writing %d bytes\n", size);
+
+	dev = __dev[id];
+	if (!dev) {
+		pr_err("device is disconnected\n");
+		return -ENODEV;
+	}
+
+	mutex_lock(&dev->ifc_mutex);
+	if (!dev->ifc) {
+		pr_err("device is disconnected\n");
+		ret = -ENODEV;
+		goto error;
+	}
+
+	if (!dev->ops) {
+		pr_err("bridge is not open\n");
+		ret = -ENODEV;
+		goto error;
+	}
+
+	if (!size) {
+		dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* if there was a previous unrecoverable error, just quit */
+	if (dev->err) {
+		pr_err("EPROTO error occurred, or device disconnected\n");
+		ret = -ENODEV;
+		goto error;
+	}
+
+	kref_get(&dev->kref);
+
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb) {
+		dev_err(&dev->ifc->dev, "unable to allocate urb\n");
+		ret = -ENOMEM;
+		goto put_error;
+	}
+
+	ret = usb_autopm_get_interface(dev->ifc);
+	if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
+		pr_err_ratelimited("write: autopm_get failed:%d\n", ret);
+		goto free_error;
+	}
+
+	pipe = usb_sndbulkpipe(dev->udev, dev->out_epAddr);
+	usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
+				diag_bridge_write_cb, dev);
+	urb->transfer_flags |= URB_ZERO_PACKET;
+	usb_anchor_urb(urb, &dev->submitted);
+	dev->pending_writes++;
+
+	ret = usb_submit_urb(urb, GFP_KERNEL);
+	if (ret) {
+		pr_err_ratelimited("submitting urb failed err:%d\n", ret);
+		dev->pending_writes--;
+		usb_unanchor_urb(urb);
+		usb_autopm_put_interface(dev->ifc);
+		goto free_error;
+	}
+
+	usb_free_urb(urb);
+	mutex_unlock(&dev->ifc_mutex);
+	return ret;
+
+free_error:
+	usb_free_urb(urb);
+put_error:
+	/* If URB submit successful, this is done in the completion handler */
+	kref_put(&dev->kref, diag_bridge_delete);
+error:
+	mutex_unlock(&dev->ifc_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(diag_bridge_write);
+
+#if defined(CONFIG_DEBUG_FS)
+#define DEBUG_BUF_SIZE	512
+static ssize_t diag_read_stats(struct file *file, char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	char			*buf;
+	int			i, ret = 0;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (i = 0; i < MAX_DIAG_BRIDGE_DEVS; i++) {
+		struct diag_bridge *dev = __dev[i];
+
+		if (!dev)
+			continue;
+
+		ret += scnprintf(buf, DEBUG_BUF_SIZE,
+				"epin:%d, epout:%d\n"
+				"bytes to host: %lu\n"
+				"bytes to mdm: %lu\n"
+				"pending reads: %u\n"
+				"pending writes: %u\n"
+				"drop count:%u\n"
+				"last error: %d\n",
+				dev->in_epAddr, dev->out_epAddr,
+				dev->bytes_to_host, dev->bytes_to_mdm,
+				dev->pending_reads, dev->pending_writes,
+				dev->drop_count,
+				dev->err);
+	}
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t diag_reset_stats(struct file *file, const char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	int i;
+
+	for (i = 0; i < MAX_DIAG_BRIDGE_DEVS; i++) {
+		struct diag_bridge *dev = __dev[i];
+
+		if (dev) {
+			dev->bytes_to_host = dev->bytes_to_mdm = 0;
+			dev->pending_reads = dev->pending_writes = 0;
+			dev->drop_count = 0;
+		}
+	}
+
+	return count;
+}
+
+const struct file_operations diag_stats_ops = {
+	.read = diag_read_stats,
+	.write = diag_reset_stats,
+};
+
+static struct dentry *dent;
+
+static void diag_bridge_debugfs_init(void)
+{
+	struct dentry *dfile;
+
+	dent = debugfs_create_dir("diag_bridge", 0);
+	if (IS_ERR(dent))
+		return;
+
+	dfile = debugfs_create_file("status", 0444, dent, 0, &diag_stats_ops);
+	if (!dfile || IS_ERR(dfile))
+		debugfs_remove(dent);
+}
+
+static void diag_bridge_debugfs_cleanup(void)
+{
+	debugfs_remove_recursive(dent);
+	dent = NULL;
+}
+#else
+static inline void diag_bridge_debugfs_init(void) { }
+static inline void diag_bridge_debugfs_cleanup(void) { }
+#endif
+
+static int
+diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
+{
+	struct diag_bridge		*dev;
+	struct usb_host_interface	*ifc_desc;
+	struct usb_endpoint_descriptor	*ep_desc;
+	int				i, devid, ret = -ENOMEM;
+
+	pr_debug("id:%lu\n", id->driver_info);
+
+	devid = id->driver_info & 0xFF;
+	if (devid < 0 || devid >= MAX_DIAG_BRIDGE_DEVS) {
+		pr_err("Invalid device ID\n");
+		return -ENODEV;
+	}
+
+	/* already probed? */
+	if (__dev[devid]) {
+		pr_err("Diag device already probed\n");
+		return -ENODEV;
+	}
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	__dev[devid] = dev;
+	dev->id = devid;
+
+	dev->udev = usb_get_dev(interface_to_usbdev(ifc));
+	dev->ifc = usb_get_intf(ifc);
+	kref_init(&dev->kref);
+	mutex_init(&dev->ifc_mutex);
+	init_usb_anchor(&dev->submitted);
+
+	ifc_desc = ifc->cur_altsetting;
+	for (i = 0; i < ifc_desc->desc.bNumEndpoints; i++) {
+		ep_desc = &ifc_desc->endpoint[i].desc;
+		if (!dev->in_epAddr && (usb_endpoint_is_bulk_in(ep_desc) ||
+			usb_endpoint_is_int_in(ep_desc))) {
+			dev->in_epAddr = ep_desc->bEndpointAddress;
+			if (usb_endpoint_is_int_in(ep_desc)) {
+				dev->use_int_in_pipe = 1;
+				dev->period = ep_desc->bInterval;
+			}
+		}
+		if (!dev->out_epAddr && usb_endpoint_is_bulk_out(ep_desc))
+			dev->out_epAddr = ep_desc->bEndpointAddress;
+	}
+
+	if (!(dev->in_epAddr && dev->out_epAddr)) {
+		pr_err("could not find bulk in and bulk out endpoints\n");
+		ret = -ENODEV;
+		goto error;
+	}
+
+	usb_set_intfdata(ifc, dev);
+	diag_bridge_debugfs_init();
+	dev->pdev = platform_device_register_simple("diag_bridge", devid,
+						    NULL, 0);
+	if (IS_ERR(dev->pdev)) {
+		pr_err("unable to allocate platform device\n");
+		ret = PTR_ERR(dev->pdev);
+		goto clean_debugfs;
+	}
+
+	dev_dbg(&dev->ifc->dev, "%s: complete\n", __func__);
+
+	return 0;
+
+clean_debugfs:
+	diag_bridge_debugfs_cleanup();
+error:
+	if (dev)
+		kref_put(&dev->kref, diag_bridge_delete);
+
+	return ret;
+}
+
+static void diag_bridge_disconnect(struct usb_interface *ifc)
+{
+	struct diag_bridge	*dev = usb_get_intfdata(ifc);
+
+	dev_dbg(&dev->ifc->dev, "%s\n", __func__);
+
+	platform_device_unregister(dev->pdev);
+	diag_bridge_debugfs_cleanup();
+	dev->err = -ENODEV;
+	kref_put(&dev->kref, diag_bridge_delete);
+}
+
+static int diag_bridge_suspend(struct usb_interface *ifc, pm_message_t message)
+{
+	struct diag_bridge	*dev = usb_get_intfdata(ifc);
+	struct diag_bridge_ops	*cbs = dev->ops;
+	int ret = 0;
+
+	if (cbs && cbs->suspend) {
+		ret = cbs->suspend(cbs->ctxt);
+		if (ret) {
+			dev_dbg(&dev->ifc->dev,
+				"%s: diag veto'd suspend\n", __func__);
+			return ret;
+		}
+
+		usb_kill_anchored_urbs(&dev->submitted);
+	}
+
+	return ret;
+}
+
+static int diag_bridge_resume(struct usb_interface *ifc)
+{
+	struct diag_bridge	*dev = usb_get_intfdata(ifc);
+	struct diag_bridge_ops	*cbs = dev->ops;
+
+
+	if (cbs && cbs->resume)
+		cbs->resume(cbs->ctxt);
+
+	return 0;
+}
+
+#define DEV_ID(n)		(n)
+
+static const struct usb_device_id diag_bridge_ids[] = {
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9001, 0),
+	.driver_info =  DEV_ID(0), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9034, 0),
+	.driver_info =  DEV_ID(0), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 0),
+	.driver_info =  DEV_ID(0), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x904C, 0),
+	.driver_info =  DEV_ID(0), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9075, 0),
+	.driver_info =  DEV_ID(0), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9079, 0),
+	.driver_info =  DEV_ID(1), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x908A, 0),
+	.driver_info =  DEV_ID(0), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x908E, 0),
+	.driver_info =  DEV_ID(0), },
+	/* 908E, ifc#1 refers to diag client interface */
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x908E, 1),
+	.driver_info =  DEV_ID(1), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909C, 0),
+	.driver_info =  DEV_ID(0), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909D, 0),
+	.driver_info =  DEV_ID(0), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909E, 0),
+	.driver_info =  DEV_ID(0), },
+	/* 909E, ifc#1 refers to diag client interface */
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909E, 1),
+	.driver_info =  DEV_ID(1), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x909F, 0),
+	.driver_info =	DEV_ID(0), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x90A0, 0),
+	.driver_info =  DEV_ID(0), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x90A4, 0),
+	.driver_info =	DEV_ID(0), },
+	/* 909E, ifc#1 refers to diag client interface */
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x90A4, 1),
+	.driver_info =	DEV_ID(1), },
+	{ USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x90F3, 0),
+	.driver_info =	DEV_ID(0), },
+
+	{} /* terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, diag_bridge_ids);
+
+static struct usb_driver diag_bridge_driver = {
+	.name =		"diag_bridge",
+	.probe =	diag_bridge_probe,
+	.disconnect =	diag_bridge_disconnect,
+	.suspend =	diag_bridge_suspend,
+	.resume =	diag_bridge_resume,
+	.reset_resume =	diag_bridge_resume,
+	.id_table =	diag_bridge_ids,
+	.supports_autosuspend = 1,
+};
+
+static int __init diag_bridge_init(void)
+{
+	int ret;
+
+	ret = usb_register(&diag_bridge_driver);
+	if (ret) {
+		pr_err("unable to register diag driver\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit diag_bridge_exit(void)
+{
+	usb_deregister(&diag_bridge_driver);
+}
+
+module_init(diag_bridge_init);
+module_exit(diag_bridge_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c
index 9475798..95978e3 100644
--- a/drivers/usb/mtu3/mtu3_core.c
+++ b/drivers/usb/mtu3/mtu3_core.c
@@ -564,8 +564,10 @@ static void mtu3_regs_init(struct mtu3 *mtu)
 	if (mtu->is_u3_ip) {
 		/* disable LGO_U1/U2 by default */
 		mtu3_clrbits(mbase, U3D_LINK_POWER_CONTROL,
-				SW_U1_ACCEPT_ENABLE | SW_U2_ACCEPT_ENABLE |
 				SW_U1_REQUEST_ENABLE | SW_U2_REQUEST_ENABLE);
+		/* enable accept LGO_U1/U2 link command from host */
+		mtu3_setbits(mbase, U3D_LINK_POWER_CONTROL,
+				SW_U1_ACCEPT_ENABLE | SW_U2_ACCEPT_ENABLE);
 		/* device responses to u3_exit from host automatically */
 		mtu3_clrbits(mbase, U3D_LTSSM_CTRL, SOFT_U3_EXIT_EN);
 		/* automatically build U2 link when U3 detect fail */
diff --git a/drivers/usb/mtu3/mtu3_gadget_ep0.c b/drivers/usb/mtu3/mtu3_gadget_ep0.c
index 958d74d..7997cf5 100644
--- a/drivers/usb/mtu3/mtu3_gadget_ep0.c
+++ b/drivers/usb/mtu3/mtu3_gadget_ep0.c
@@ -335,9 +335,9 @@ static int ep0_handle_feature_dev(struct mtu3 *mtu,
 
 		lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL);
 		if (set)
-			lpc |= SW_U1_ACCEPT_ENABLE;
+			lpc |= SW_U1_REQUEST_ENABLE;
 		else
-			lpc &= ~SW_U1_ACCEPT_ENABLE;
+			lpc &= ~SW_U1_REQUEST_ENABLE;
 		mtu3_writel(mbase, U3D_LINK_POWER_CONTROL, lpc);
 
 		mtu->u1_enable = !!set;
@@ -350,9 +350,9 @@ static int ep0_handle_feature_dev(struct mtu3 *mtu,
 
 		lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL);
 		if (set)
-			lpc |= SW_U2_ACCEPT_ENABLE;
+			lpc |= SW_U2_REQUEST_ENABLE;
 		else
-			lpc &= ~SW_U2_ACCEPT_ENABLE;
+			lpc &= ~SW_U2_REQUEST_ENABLE;
 		mtu3_writel(mbase, U3D_LINK_POWER_CONTROL, lpc);
 
 		mtu->u2_enable = !!set;
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index dbb482b..b7d460a 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -242,8 +242,13 @@ static int dsps_check_status(struct musb *musb, void *unused)
 
 	switch (musb->xceiv->otg->state) {
 	case OTG_STATE_A_WAIT_VRISE:
-		dsps_mod_timer_optional(glue);
-		break;
+		if (musb->port_mode == MUSB_HOST) {
+			musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
+			dsps_mod_timer_optional(glue);
+			break;
+		}
+		/* fall through */
+
 	case OTG_STATE_A_WAIT_BCON:
 		/* keep VBUS on for host-only mode */
 		if (musb->port_mode == MUSB_PORT_MODE_HOST) {
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 87f932d..1e43163 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -477,13 +477,10 @@ void musb_g_tx(struct musb *musb, u8 epnum)
 	}
 
 	if (request) {
-		u8	is_dma = 0;
-		bool	short_packet = false;
 
 		trace_musb_req_tx(req);
 
 		if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
-			is_dma = 1;
 			csr |= MUSB_TXCSR_P_WZC_BITS;
 			csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
 				 MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET);
@@ -501,16 +498,8 @@ void musb_g_tx(struct musb *musb, u8 epnum)
 		 */
 		if ((request->zero && request->length)
 			&& (request->length % musb_ep->packet_sz == 0)
-			&& (request->actual == request->length))
-				short_packet = true;
+			&& (request->actual == request->length)) {
 
-		if ((musb_dma_inventra(musb) || musb_dma_ux500(musb)) &&
-			(is_dma && (!dma->desired_mode ||
-				(request->actual &
-					(musb_ep->packet_sz - 1)))))
-				short_packet = true;
-
-		if (short_packet) {
 			/*
 			 * On DMA completion, FIFO may not be
 			 * available yet...
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 3620073..512108e 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -320,12 +320,10 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
 				channel->status = MUSB_DMA_STATUS_FREE;
 
 				/* completed */
-				if ((devctl & MUSB_DEVCTL_HM)
-					&& (musb_channel->transmit)
-					&& ((channel->desired_mode == 0)
-					    || (channel->actual_len &
-					    (musb_channel->max_packet_sz - 1)))
-				    ) {
+				if (musb_channel->transmit &&
+					(!channel->desired_mode ||
+					(channel->actual_len %
+					    musb_channel->max_packet_sz))) {
 					u8  epnum  = musb_channel->epnum;
 					int offset = musb->io.ep_offset(epnum,
 								    MUSB_TXCSR);
@@ -337,11 +335,14 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
 					 */
 					musb_ep_select(mbase, epnum);
 					txcsr = musb_readw(mbase, offset);
-					txcsr &= ~(MUSB_TXCSR_DMAENAB
+					if (channel->desired_mode == 1) {
+						txcsr &= ~(MUSB_TXCSR_DMAENAB
 							| MUSB_TXCSR_AUTOSET);
-					musb_writew(mbase, offset, txcsr);
-					/* Send out the packet */
-					txcsr &= ~MUSB_TXCSR_DMAMODE;
+						musb_writew(mbase, offset, txcsr);
+						/* Send out the packet */
+						txcsr &= ~MUSB_TXCSR_DMAMODE;
+						txcsr |= MUSB_TXCSR_DMAENAB;
+					}
 					txcsr |=  MUSB_TXCSR_TXPKTRDY;
 					musb_writew(mbase, offset, txcsr);
 				}
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 77e7f5c..6f202b2 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -463,6 +463,7 @@ struct usbpd {
 	struct mutex		svid_handler_lock;
 	struct list_head	svid_handlers;
 	ktime_t			svdm_start_time;
+	bool			vdm_in_suspend;
 
 	struct list_head	instance;
 
@@ -509,6 +510,21 @@ enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd)
 }
 EXPORT_SYMBOL(usbpd_get_plug_orientation);
 
+static unsigned int get_connector_type(struct usbpd *pd)
+{
+	int ret;
+	union power_supply_propval val;
+
+	ret = power_supply_get_property(pd->usb_psy,
+		POWER_SUPPLY_PROP_CONNECTOR_TYPE, &val);
+
+	if (ret) {
+		dev_err(&pd->dev, "Unable to read CONNECTOR TYPE: %d\n", ret);
+		return ret;
+	}
+	return val.intval;
+}
+
 static inline void stop_usb_host(struct usbpd *pd)
 {
 	extcon_set_state_sync(pd->extcon, EXTCON_USB_HOST, 0);
@@ -643,15 +659,21 @@ static struct usbpd_svid_handler *find_svid_handler(struct usbpd *pd, u16 svid)
 {
 	struct usbpd_svid_handler *handler;
 
-	mutex_lock(&pd->svid_handler_lock);
+	/* in_interrupt() == true when handling VDM RX during suspend */
+	if (!in_interrupt())
+		mutex_lock(&pd->svid_handler_lock);
+
 	list_for_each_entry(handler, &pd->svid_handlers, entry) {
 		if (svid == handler->svid) {
-			mutex_unlock(&pd->svid_handler_lock);
+			if (!in_interrupt())
+				mutex_unlock(&pd->svid_handler_lock);
 			return handler;
 		}
 	}
 
-	mutex_unlock(&pd->svid_handler_lock);
+	if (!in_interrupt())
+		mutex_unlock(&pd->svid_handler_lock);
+
 	return NULL;
 }
 
@@ -884,10 +906,12 @@ static void kick_sm(struct usbpd *pd, int ms)
 	pm_stay_awake(&pd->dev);
 	pd->sm_queued = true;
 
-	if (ms)
+	if (ms) {
+		usbpd_dbg(&pd->dev, "delay %d ms", ms);
 		hrtimer_start(&pd->timer, ms_to_ktime(ms), HRTIMER_MODE_REL);
-	else
+	} else {
 		queue_work(pd->wq, &pd->sm_work);
+	}
 }
 
 static void phy_sig_received(struct usbpd *pd, enum pd_sig_type sig)
@@ -1056,6 +1080,8 @@ static struct rx_msg *pd_ext_msg_received(struct usbpd *pd, u16 header, u8 *buf,
 	return rx_msg;	/* queue it for usbpd_sm */
 }
 
+static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg);
+
 static void phy_msg_received(struct usbpd *pd, enum pd_sop_type sop,
 		u8 *buf, size_t len)
 {
@@ -1128,6 +1154,13 @@ static void phy_msg_received(struct usbpd *pd, enum pd_sop_type sop,
 			return;
 	}
 
+	if (pd->vdm_in_suspend && msg_type == MSG_VDM) {
+		usbpd_dbg(&pd->dev, "Skip wq and handle VDM directly\n");
+		handle_vdm_rx(pd, rx_msg);
+		kfree(rx_msg);
+		return;
+	}
+
 	spin_lock_irqsave(&pd->rx_lock, flags);
 	list_add_tail(&rx_msg->entry, &pd->rx_q);
 	spin_unlock_irqrestore(&pd->rx_lock, flags);
@@ -1154,7 +1187,6 @@ static enum hrtimer_restart pd_timeout(struct hrtimer *timer)
 {
 	struct usbpd *pd = container_of(timer, struct usbpd, timer);
 
-	usbpd_dbg(&pd->dev, "timeout");
 	queue_work(pd->wq, &pd->sm_work);
 
 	return HRTIMER_NORESTART;
@@ -1256,6 +1288,7 @@ static void reset_vdm_state(struct usbpd *pd)
 	kfree(pd->vdm_tx);
 	pd->vdm_tx = NULL;
 	pd->ss_lane_svid = 0x0;
+	pd->vdm_in_suspend = false;
 }
 
 static inline void rx_msg_cleanup(struct usbpd *pd)
@@ -1466,9 +1499,12 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
 				!pd->in_explicit_contract)
 			stop_usb_host(pd);
 
+		if (!pd->in_explicit_contract)
+			dual_role_instance_changed(pd->dual_role);
+
 		pd->in_explicit_contract = true;
 
-		if (pd->vdm_tx)
+		if (pd->vdm_tx && !pd->sm_queued)
 			kick_sm(pd, 0);
 		else if (pd->current_dr == DR_DFP && pd->vdm_state == VDM_NONE)
 			usbpd_send_svdm(pd, USBPD_SID,
@@ -1479,7 +1515,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
 
 		kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE);
 		complete(&pd->is_ready);
-		dual_role_instance_changed(pd->dual_role);
 		break;
 
 	case PE_PRS_SRC_SNK_TRANSITION_TO_OFF:
@@ -1654,6 +1689,9 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
 		break;
 
 	case PE_SNK_READY:
+		if (!pd->in_explicit_contract)
+			dual_role_instance_changed(pd->dual_role);
+
 		pd->in_explicit_contract = true;
 
 		if (pd->vdm_tx)
@@ -1665,7 +1703,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
 
 		kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE);
 		complete(&pd->is_ready);
-		dual_role_instance_changed(pd->dual_role);
 		break;
 
 	case PE_SNK_TRANSITION_TO_DEFAULT:
@@ -1788,6 +1825,7 @@ int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos, int num_vdos)
 
 	/* VDM will get sent in PE_SRC/SNK_READY state handling */
 	pd->vdm_tx = vdm_tx;
+	pd->vdm_in_suspend = false;
 
 	/* slight delay before queuing to prioritize handling of incoming VDM */
 	if (pd->in_explicit_contract)
@@ -1810,6 +1848,14 @@ int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd,
 }
 EXPORT_SYMBOL(usbpd_send_svdm);
 
+void usbpd_vdm_in_suspend(struct usbpd *pd, bool in_suspend)
+{
+	usbpd_dbg(&pd->dev, "VDM in_suspend:%d\n", in_suspend);
+
+	pd->vdm_in_suspend = in_suspend;
+}
+EXPORT_SYMBOL(usbpd_vdm_in_suspend);
+
 static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg)
 {
 	int ret;
@@ -1859,6 +1905,10 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg)
 		return;
 	}
 
+	if (cmd_type != SVDM_CMD_TYPE_INITIATOR &&
+			pd->current_state != PE_SRC_STARTUP_WAIT_FOR_VDM_RESP)
+		start_src_ams(pd, false);
+
 	if (handler && handler->svdm_received) {
 		handler->svdm_received(handler, cmd, cmd_type, vdos, num_vdos);
 
@@ -2714,8 +2764,6 @@ static void usbpd_sm(struct work_struct *w)
 			vconn_swap(pd);
 		} else if (IS_DATA(rx_msg, MSG_VDM)) {
 			handle_vdm_rx(pd, rx_msg);
-			if (!pd->vdm_tx)
-				start_src_ams(pd, false);
 		} else if (IS_CTRL(rx_msg, MSG_GET_SOURCE_CAP_EXTENDED)) {
 			handle_get_src_cap_extended(pd);
 		} else if (IS_EXT(rx_msg, MSG_GET_BATTERY_CAP)) {
@@ -3550,6 +3598,8 @@ static int usbpd_dr_set_property(struct dual_role_phy_instance *dual_role,
 		enum dual_role_property prop, const unsigned int *val)
 {
 	struct usbpd *pd = dual_role_get_drvdata(dual_role);
+	union power_supply_propval value;
+	int wait_count = 5;
 	bool do_swap = false;
 
 	if (!pd)
@@ -3572,9 +3622,33 @@ static int usbpd_dr_set_property(struct dual_role_phy_instance *dual_role,
 		set_power_role(pd, PR_NONE);
 
 		/* wait until it takes effect */
-		while (pd->forced_pr != POWER_SUPPLY_TYPEC_PR_NONE)
+		while (pd->forced_pr != POWER_SUPPLY_TYPEC_PR_NONE &&
+				--wait_count)
 			msleep(20);
 
+		if (!wait_count) {
+			usbpd_err(&pd->dev, "setting mode timed out\n");
+			/* Setting it to DRP. HW can figure out new mode */
+			value.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
+			power_supply_set_property(pd->usb_psy,
+				POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &value);
+			return -ETIMEDOUT;
+		}
+
+		/* if we cannot have a valid connection, fallback to old role */
+		wait_count = 5;
+		while (pd->current_pr == PR_NONE && --wait_count)
+			msleep(300);
+
+		if (!wait_count) {
+			usbpd_err(&pd->dev, "setting mode timed out\n");
+			/* Setting it to DRP. HW can figure out new mode */
+			value.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
+			power_supply_set_property(pd->usb_psy,
+				POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &value);
+			return -ETIMEDOUT;
+		}
+
 		break;
 
 	case DUAL_ROLE_PROP_DR:
@@ -3598,12 +3672,6 @@ static int usbpd_dr_set_property(struct dual_role_phy_instance *dual_role,
 				return -EAGAIN;
 			}
 
-			if (pd->current_state == PE_SNK_READY &&
-					!is_sink_tx_ok(pd)) {
-				usbpd_err(&pd->dev, "Rp indicates SinkTxNG\n");
-				return -EAGAIN;
-			}
-
 			mutex_lock(&pd->swap_lock);
 			reinit_completion(&pd->is_ready);
 			pd->send_dr_swap = true;
@@ -3658,12 +3726,6 @@ static int usbpd_dr_set_property(struct dual_role_phy_instance *dual_role,
 				return -EAGAIN;
 			}
 
-			if (pd->current_state == PE_SNK_READY &&
-					!is_sink_tx_ok(pd)) {
-				usbpd_err(&pd->dev, "Rp indicates SinkTxNG\n");
-				return -EAGAIN;
-			}
-
 			mutex_lock(&pd->swap_lock);
 			reinit_completion(&pd->is_ready);
 			pd->send_pr_swap = true;
@@ -3959,7 +4021,7 @@ static ssize_t select_pdo_store(struct device *dev,
 	mutex_lock(&pd->swap_lock);
 
 	/* Only allowed if we are already in explicit sink contract */
-	if (pd->current_state != PE_SNK_READY || !is_sink_tx_ok(pd)) {
+	if (pd->current_state != PE_SNK_READY) {
 		usbpd_err(&pd->dev, "select_pdo: Cannot select new PDO yet\n");
 		ret = -EBUSY;
 		goto out;
@@ -4005,7 +4067,7 @@ static ssize_t select_pdo_store(struct device *dev,
 	if (pd->selected_pdo != pd->requested_pdo ||
 			pd->current_voltage != pd->requested_voltage) {
 		usbpd_err(&pd->dev, "select_pdo: request rejected\n");
-		ret = -EINVAL;
+		ret = -ECONNREFUSED;
 	}
 
 out:
@@ -4111,7 +4173,7 @@ static int trigger_tx_msg(struct usbpd *pd, bool *msg_tx_flag)
 	int ret = 0;
 
 	/* Only allowed if we are already in explicit sink contract */
-	if (pd->current_state != PE_SNK_READY || !is_sink_tx_ok(pd)) {
+	if (pd->current_state != PE_SNK_READY) {
 		usbpd_err(&pd->dev, "%s: Cannot send msg\n", __func__);
 		ret = -EBUSY;
 		goto out;
@@ -4526,12 +4588,19 @@ struct usbpd *usbpd_create(struct device *parent)
 	pd->dr_desc.set_property = usbpd_dr_set_property;
 	pd->dr_desc.property_is_writeable = usbpd_dr_prop_writeable;
 
-	pd->dual_role = devm_dual_role_instance_register(&pd->dev,
-			&pd->dr_desc);
-	if (IS_ERR(pd->dual_role)) {
-		usbpd_err(&pd->dev, "could not register dual_role instance\n");
+	ret = get_connector_type(pd);
+
+	if (ret < 0)
 		goto put_psy;
-	} else {
+
+	/* For non-TypeC connector, it will be handled elsewhere */
+	if (ret != POWER_SUPPLY_CONNECTOR_MICRO_USB) {
+		pd->dual_role = devm_dual_role_instance_register(&pd->dev,
+				&pd->dr_desc);
+		if (IS_ERR(pd->dual_role)) {
+			usbpd_err(&pd->dev, "could not register dual_role instance\n");
+			goto put_psy;
+		}
 		pd->dual_role->drv_data = pd;
 	}
 
diff --git a/drivers/usb/phy/class-dual-role.c b/drivers/usb/phy/class-dual-role.c
index 51fcb54..27f6784 100644
--- a/drivers/usb/phy/class-dual-role.c
+++ b/drivers/usb/phy/class-dual-role.c
@@ -82,6 +82,9 @@ static void dual_role_changed_work(struct work_struct *work)
 
 void dual_role_instance_changed(struct dual_role_phy_instance *dual_role)
 {
+	if (!dual_role)
+		return;
+
 	dev_dbg(&dual_role->dev, "%s\n", __func__);
 	pm_wakeup_event(&dual_role->dev, DUAL_ROLE_NOTIFICATION_TIMEOUT);
 	schedule_work(&dual_role->changed_work);
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index 7e5aece..cb1382a 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -60,9 +60,6 @@ static int am335x_phy_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
-	if (ret)
-		return ret;
 	am_phy->usb_phy_gen.phy.init = am335x_init;
 	am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;
 
@@ -81,7 +78,7 @@ static int am335x_phy_probe(struct platform_device *pdev)
 	device_set_wakeup_enable(dev, false);
 	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, false);
 
-	return 0;
+	return usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
 }
 
 static int am335x_phy_remove(struct platform_device *pdev)
diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c
index 5e733c4..b443a83 100644
--- a/drivers/usb/phy/phy-msm-qusb.c
+++ b/drivers/usb/phy/phy-msm-qusb.c
@@ -127,6 +127,7 @@ struct qusb_phy {
 	void __iomem		*tune2_efuse_reg;
 	void __iomem		*ref_clk_base;
 	void __iomem		*tcsr_clamp_dig_n;
+	void __iomem		*tcsr_conn_box_spare;
 
 	struct clk		*ref_clk_src;
 	struct clk		*ref_clk;
@@ -143,6 +144,8 @@ struct qusb_phy {
 	int			init_seq_len;
 	int			*qusb_phy_init_seq;
 	u32			major_rev;
+	u32			usb_hs_ac_bitmask;
+	u32			usb_hs_ac_value;
 
 	u32			tune2_val;
 	int			tune2_efuse_bit_pos;
@@ -904,6 +907,7 @@ static int qusb_phy_probe(struct platform_device *pdev)
 	int ret = 0, size = 0;
 	const char *phy_type;
 	bool hold_phy_reset;
+	u32 temp;
 
 	qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
 	if (!qphy)
@@ -989,6 +993,32 @@ static int qusb_phy_probe(struct platform_device *pdev)
 		}
 	}
 
+	ret = of_property_read_u32(dev->of_node, "qcom,usb-hs-ac-bitmask",
+					&qphy->usb_hs_ac_bitmask);
+	if (!ret) {
+		ret = of_property_read_u32(dev->of_node, "qcom,usb-hs-ac-value",
+						&qphy->usb_hs_ac_value);
+		if (ret) {
+			dev_err(dev, "usb_hs_ac_value not passed\n", __func__);
+			return ret;
+		}
+
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						"tcsr_conn_box_spare_0");
+		if (!res) {
+			dev_err(dev, "tcsr_conn_box_spare_0 not passed\n",
+								__func__);
+			return -ENOENT;
+		}
+
+		qphy->tcsr_conn_box_spare = devm_ioremap_nocache(dev,
+						res->start, resource_size(res));
+		if (IS_ERR(qphy->tcsr_conn_box_spare)) {
+			dev_err(dev, "err reading tcsr_conn_box_spare\n");
+			return PTR_ERR(qphy->tcsr_conn_box_spare);
+		}
+	}
+
 	qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src");
 	if (IS_ERR(qphy->ref_clk_src))
 		dev_dbg(dev, "clk get failed for ref_clk_src\n");
@@ -1212,6 +1242,17 @@ static int qusb_phy_probe(struct platform_device *pdev)
 	if (qphy->tcsr_clamp_dig_n)
 		writel_relaxed(0x0, qphy->tcsr_clamp_dig_n);
 
+	/*
+	 * Write the usb_hs_ac_value to usb_hs_ac_bitmask of tcsr_conn_box_spare
+	 * reg to enable AC/DC coupling
+	 */
+	if (qphy->tcsr_conn_box_spare) {
+		temp = readl_relaxed(qphy->tcsr_conn_box_spare) &
+						~qphy->usb_hs_ac_bitmask;
+		writel_relaxed(temp | qphy->usb_hs_ac_value,
+						qphy->tcsr_conn_box_spare);
+	}
+
 	qphy->suspended = true;
 
 	return ret;
diff --git a/drivers/usb/phy/phy-msm-ssusb.c b/drivers/usb/phy/phy-msm-ssusb.c
index 0b8f500..c25efdc 100644
--- a/drivers/usb/phy/phy-msm-ssusb.c
+++ b/drivers/usb/phy/phy-msm-ssusb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014,2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014,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
@@ -24,12 +24,19 @@
 #include <linux/regulator/consumer.h>
 #include <linux/usb/phy.h>
 #include <linux/reset.h>
+#include <linux/iopoll.h>
 
 /* SSPHY control registers */
 #define SS_PHY_CTRL0			0x6C
 #define SS_PHY_CTRL1			0x70
 #define SS_PHY_CTRL2			0x74
 #define SS_PHY_CTRL4			0x7C
+#define PHY_CR_REG_CTRL1		0x60
+#define PHY_CR_REG_CTRL2		0x64
+#define PHY_CR_REG_CTRL3		0x68
+#define PHY_CR_DATA_STATUS0		0x30
+#define PHY_CR_DATA_STATUS1		0x34
+#define PHY_CR_DATA_STATUS2		0x38
 
 #define PHY_HOST_MODE			BIT(2)
 #define PHY_VBUS_VALID_OVERRIDE		BIT(4)
@@ -46,6 +53,8 @@
 #define USB_SSPHY_1P8_VOL_MAX		1800000 /* uV */
 #define USB_SSPHY_1P8_HPM_LOAD		23000	/* uA */
 
+#define SS_OVRD_EN			0x0013
+#define SS_OVRD_VAL			0x0C00
 struct msm_ssphy {
 	struct usb_phy		phy;
 	void __iomem		*base;
@@ -192,6 +201,94 @@ static void msm_usb_write_readback(void *base, u32 offset,
 			__func__, val, offset);
 }
 
+static int __maybe_unused msm_ssphy_control_reg_read(struct usb_phy *uphy,
+								u16 address)
+{
+	struct msm_ssphy *phy = container_of(uphy, struct msm_ssphy, phy);
+	u16 val;
+	int ret;
+
+	/* Write address */
+	writeb_relaxed((address & 0xFF), phy->base + PHY_CR_REG_CTRL2);
+	writeb_relaxed(((address >> 0x8) & 0xFF), phy->base + PHY_CR_REG_CTRL3);
+	/* Set CR_ADDR */
+	writeb_relaxed(0x1, phy->base + PHY_CR_REG_CTRL1);
+	/* Do a polled read up to 1ms */
+	ret = readl_poll_timeout(phy->base + PHY_CR_DATA_STATUS2, val,
+							val, 1000, 0);
+	if (ret) {
+		dev_err(phy->phy.dev, "Write address failed:%d\n", ret);
+		return ret;
+	}
+	/* Clear CR_ADDR */
+	writeb_relaxed(0x0, phy->base + PHY_CR_REG_CTRL1);
+
+	/* Set CR_READ */
+	writeb_relaxed(0x4, phy->base + PHY_CR_REG_CTRL1);
+	ret = readl_poll_timeout(phy->base + PHY_CR_DATA_STATUS2, val,
+							val, 1000, 0);
+	if (ret) {
+		dev_err(phy->phy.dev, "Read from address failed:%d\n", ret);
+		return ret;
+	}
+	/* Clear CR_READ */
+	writeb_relaxed(0x0, phy->base + PHY_CR_REG_CTRL1);
+
+	/* Read Data */
+	val = readb_relaxed(phy->base + PHY_CR_DATA_STATUS0);
+	val |= (readb_relaxed(phy->base + PHY_CR_DATA_STATUS1) << 0x8);
+
+	return val;
+}
+
+static int msm_ssphy_control_reg_write(struct usb_phy *uphy,
+						u16 address, u16 value)
+{
+	struct msm_ssphy *phy = container_of(uphy, struct msm_ssphy, phy);
+	u16 val;
+	int ret;
+
+	/* Write address */
+	writeb_relaxed((address & 0xFF), phy->base + PHY_CR_REG_CTRL2);
+	writeb_relaxed(((address >> 0x8) & 0xFF), phy->base + PHY_CR_REG_CTRL3);
+	/* Set CR_ADDR */
+	writeb_relaxed(0x1, phy->base + PHY_CR_REG_CTRL1);
+	ret = readl_poll_timeout(phy->base + PHY_CR_DATA_STATUS2, val,
+							val, 1000, 0);
+	if (ret) {
+		dev_err(phy->phy.dev, "Write address failed:%d\n", ret);
+		return ret;
+	}
+	/* Clear CR_ADDR */
+	writeb_relaxed(0x0, phy->base + PHY_CR_REG_CTRL1);
+
+	/* Write data */
+	writeb_relaxed((value & 0xFF), phy->base + PHY_CR_REG_CTRL2);
+	writeb_relaxed(((value >> 0x8) & 0xFF), phy->base + PHY_CR_REG_CTRL3);
+	/* Set CR_DATA */
+	writeb_relaxed(0x2, phy->base + PHY_CR_REG_CTRL1);
+	ret = readl_poll_timeout(phy->base + PHY_CR_DATA_STATUS2, val,
+							val, 1000, 0);
+	if (ret) {
+		dev_err(phy->phy.dev, "Write data failed:%d\n", ret);
+		return ret;
+	}
+	/* Clear CR_DATA */
+	writeb_relaxed(0x0, phy->base + PHY_CR_REG_CTRL1);
+
+	/* Set CR_WRITE */
+	writeb_relaxed(0x8, phy->base + PHY_CR_REG_CTRL1);
+	ret = readl_poll_timeout(phy->base + PHY_CR_DATA_STATUS2, val,
+							val, 1000, 0);
+	if (ret) {
+		dev_err(phy->phy.dev, "Write data to address failed:%d\n", ret);
+		return ret;
+	}
+	/* Clear CR_WRITE */
+	writeb_relaxed(0x0, phy->base + PHY_CR_REG_CTRL1);
+	return 0;
+}
+
 /* SSPHY Initialization */
 static int msm_ssphy_init(struct usb_phy *uphy)
 {
@@ -230,6 +327,11 @@ static int msm_ssphy_init(struct usb_phy *uphy)
 
 	writeb_relaxed(REF_SS_PHY_EN, phy->base + SS_PHY_CTRL2);
 
+	/* Enable SSC override in SSC_OVRD_IN register */
+	rc = msm_ssphy_control_reg_write(uphy, SS_OVRD_EN, SS_OVRD_VAL);
+	if (rc)
+		dev_err(phy->phy.dev, "Write to PHY reg failed: %d\n", rc);
+
 	return 0;
 }
 
@@ -402,6 +504,17 @@ static int msm_ssphy_probe(struct platform_device *pdev)
 	if (of_property_read_bool(dev->of_node, "qcom,vbus-valid-override"))
 		phy->phy.flags |= PHY_VBUS_VALID_OVERRIDE;
 
+	/* Power down PHY to avoid leakage at 1.8V LDO */
+	if (of_property_read_bool(dev->of_node, "qcom,keep-powerdown")) {
+		msm_ssusb_ldo_enable(phy, 1);
+		msm_ssusb_enable_clocks(phy);
+		msm_usb_write_readback(phy->base, SS_PHY_CTRL4,
+					TEST_POWERDOWN, TEST_POWERDOWN);
+		msm_ssusb_disable_clocks(phy);
+		msm_ssusb_ldo_enable(phy, 0);
+		msm_ssusb_config_vdd(phy, 0);
+	}
+
 	phy->phy.init			= msm_ssphy_init;
 	phy->phy.set_suspend		= msm_ssphy_set_suspend;
 	phy->phy.notify_connect		= msm_ssphy_notify_connect;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 5fa1e6f..5e86be8 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -49,6 +49,7 @@ static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) },
+	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_TB) },
 	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
 	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
 	{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID),
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index b46e74a..f21445a 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -13,6 +13,7 @@
 
 #define PL2303_VENDOR_ID	0x067b
 #define PL2303_PRODUCT_ID	0x2303
+#define PL2303_PRODUCT_ID_TB		0x2304
 #define PL2303_PRODUCT_ID_RSAQ2		0x04bb
 #define PL2303_PRODUCT_ID_DCU11		0x1234
 #define PL2303_PRODUCT_ID_PHAROS	0xaaa0
@@ -25,6 +26,7 @@
 #define PL2303_PRODUCT_ID_MOTOROLA	0x0307
 #define PL2303_PRODUCT_ID_ZTEK		0xe1f1
 
+
 #define ATEN_VENDOR_ID		0x0557
 #define ATEN_VENDOR_ID2		0x0547
 #define ATEN_PRODUCT_ID		0x2008
diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c
index 6d6acf2..5112421 100644
--- a/drivers/usb/serial/usb-serial-simple.c
+++ b/drivers/usb/serial/usb-serial-simple.c
@@ -88,7 +88,8 @@ DEVICE(moto_modem, MOTO_IDS);
 /* Motorola Tetra driver */
 #define MOTOROLA_TETRA_IDS()			\
 	{ USB_DEVICE(0x0cad, 0x9011) },	/* Motorola Solutions TETRA PEI */ \
-	{ USB_DEVICE(0x0cad, 0x9012) }	/* MTP6550 */
+	{ USB_DEVICE(0x0cad, 0x9012) },	/* MTP6550 */ \
+	{ USB_DEVICE(0x0cad, 0x9016) }	/* TPG2200 */
 DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
 
 /* Novatel Wireless GPS driver */
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 344ec86..13f2c05 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -251,8 +251,12 @@ static int slave_configure(struct scsi_device *sdev)
 		if (!(us->fflags & US_FL_NEEDS_CAP16))
 			sdev->try_rc_10_first = 1;
 
-		/* assume SPC3 or latter devices support sense size > 18 */
-		if (sdev->scsi_level > SCSI_SPC_2)
+		/*
+		 * assume SPC3 or latter devices support sense size > 18
+		 * unless US_FL_BAD_SENSE quirk is specified.
+		 */
+		if (sdev->scsi_level > SCSI_SPC_2 &&
+		    !(us->fflags & US_FL_BAD_SENSE))
 			us->fflags |= US_FL_SANE_SENSE;
 
 		/*
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 5e9b35a..0fa88da 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1285,6 +1285,18 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
 		US_FL_FIX_CAPACITY ),
 
 /*
+ * Reported by Icenowy Zheng <icenowy@aosc.io>
+ * The SMI SM3350 USB-UFS bridge controller will enter a wrong state
+ * that do not process read/write command if a long sense is requested,
+ * so force to use 18-byte sense.
+ */
+UNUSUAL_DEV(  0x090c, 0x3350, 0x0000, 0xffff,
+		"SMI",
+		"SM3350 UFS-to-USB-Mass-Storage bridge",
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+		US_FL_BAD_SENSE ),
+
+/*
  * Reported by Paul Hartman <paul.hartman+linux@gmail.com>
  * This card reader returns "Illegal Request, Logical Block Address
  * Out of Range" for the first READ(10) after a new card is inserted.
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 6123b4d..4eba9ee 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -851,7 +851,8 @@ static void handle_rx(struct vhost_net *net)
 		vhost_add_used_and_signal_n(&net->dev, vq, vq->heads,
 					    headcount);
 		if (unlikely(vq_log))
-			vhost_log_write(vq, vq_log, log, vhost_len);
+			vhost_log_write(vq, vq_log, log, vhost_len,
+					vq->iov, in);
 		total_len += vhost_len;
 		if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
 			vhost_poll_queue(&vq->poll);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 9751868..d7c22ae 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1726,13 +1726,87 @@ static int log_write(void __user *log_base,
 	return r;
 }
 
+static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len)
+{
+	struct vhost_umem *umem = vq->umem;
+	struct vhost_umem_node *u;
+	u64 start, end, l, min;
+	int r;
+	bool hit = false;
+
+	while (len) {
+		min = len;
+		/* More than one GPAs can be mapped into a single HVA. So
+		 * iterate all possible umems here to be safe.
+		 */
+		list_for_each_entry(u, &umem->umem_list, link) {
+			if (u->userspace_addr > hva - 1 + len ||
+			    u->userspace_addr - 1 + u->size < hva)
+				continue;
+			start = max(u->userspace_addr, hva);
+			end = min(u->userspace_addr - 1 + u->size,
+				  hva - 1 + len);
+			l = end - start + 1;
+			r = log_write(vq->log_base,
+				      u->start + start - u->userspace_addr,
+				      l);
+			if (r < 0)
+				return r;
+			hit = true;
+			min = min(l, min);
+		}
+
+		if (!hit)
+			return -EFAULT;
+
+		len -= min;
+		hva += min;
+	}
+
+	return 0;
+}
+
+static int log_used(struct vhost_virtqueue *vq, u64 used_offset, u64 len)
+{
+	struct iovec iov[64];
+	int i, ret;
+
+	if (!vq->iotlb)
+		return log_write(vq->log_base, vq->log_addr + used_offset, len);
+
+	ret = translate_desc(vq, (uintptr_t)vq->used + used_offset,
+			     len, iov, 64, VHOST_ACCESS_WO);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ret; i++) {
+		ret = log_write_hva(vq,	(uintptr_t)iov[i].iov_base,
+				    iov[i].iov_len);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
-		    unsigned int log_num, u64 len)
+		    unsigned int log_num, u64 len, struct iovec *iov, int count)
 {
 	int i, r;
 
 	/* Make sure data written is seen before log. */
 	smp_wmb();
+
+	if (vq->iotlb) {
+		for (i = 0; i < count; i++) {
+			r = log_write_hva(vq, (uintptr_t)iov[i].iov_base,
+					  iov[i].iov_len);
+			if (r < 0)
+				return r;
+		}
+		return 0;
+	}
+
 	for (i = 0; i < log_num; ++i) {
 		u64 l = min(log[i].len, len);
 		r = log_write(vq->log_base, log[i].addr, l);
@@ -1762,9 +1836,8 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)
 		smp_wmb();
 		/* Log used flag write. */
 		used = &vq->used->flags;
-		log_write(vq->log_base, vq->log_addr +
-			  (used - (void __user *)vq->used),
-			  sizeof vq->used->flags);
+		log_used(vq, (used - (void __user *)vq->used),
+			 sizeof vq->used->flags);
 		if (vq->log_ctx)
 			eventfd_signal(vq->log_ctx, 1);
 	}
@@ -1782,9 +1855,8 @@ static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
 		smp_wmb();
 		/* Log avail event write */
 		used = vhost_avail_event(vq);
-		log_write(vq->log_base, vq->log_addr +
-			  (used - (void __user *)vq->used),
-			  sizeof *vhost_avail_event(vq));
+		log_used(vq, (used - (void __user *)vq->used),
+			 sizeof *vhost_avail_event(vq));
 		if (vq->log_ctx)
 			eventfd_signal(vq->log_ctx, 1);
 	}
@@ -2189,10 +2261,8 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq,
 		/* Make sure data is seen before log. */
 		smp_wmb();
 		/* Log used ring entry write. */
-		log_write(vq->log_base,
-			  vq->log_addr +
-			   ((void __user *)used - (void __user *)vq->used),
-			  count * sizeof *used);
+		log_used(vq, ((void __user *)used - (void __user *)vq->used),
+			 count * sizeof *used);
 	}
 	old = vq->last_used_idx;
 	new = (vq->last_used_idx += count);
@@ -2234,9 +2304,8 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
 		/* Make sure used idx is seen before log. */
 		smp_wmb();
 		/* Log used index update. */
-		log_write(vq->log_base,
-			  vq->log_addr + offsetof(struct vring_used, idx),
-			  sizeof vq->used->idx);
+		log_used(vq, offsetof(struct vring_used, idx),
+			 sizeof vq->used->idx);
 		if (vq->log_ctx)
 			eventfd_signal(vq->log_ctx, 1);
 	}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 79c6e7a..75d21d4 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -208,7 +208,8 @@ bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *);
 bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
 
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
-		    unsigned int log_num, u64 len);
+		    unsigned int log_num, u64 len,
+		    struct iovec *iov, int count);
 int vq_iotlb_prefetch(struct vhost_virtqueue *vq);
 
 struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type);
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 248533c..8317583 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -522,6 +522,8 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
 		goto out;
 	}
 
+	vsock->guest_cid = 0; /* no CID assigned yet */
+
 	atomic_set(&vsock->queued_replies, 0);
 
 	vqs[VSOCK_VQ_TX] = &vsock->vqs[VSOCK_VQ_TX];
diff --git a/drivers/video/fbdev/clps711x-fb.c b/drivers/video/fbdev/clps711x-fb.c
index ff56107..42f9096 100644
--- a/drivers/video/fbdev/clps711x-fb.c
+++ b/drivers/video/fbdev/clps711x-fb.c
@@ -287,14 +287,17 @@ static int clps711x_fb_probe(struct platform_device *pdev)
 	}
 
 	ret = of_get_fb_videomode(disp, &cfb->mode, OF_USE_NATIVE_MODE);
-	if (ret)
+	if (ret) {
+		of_node_put(disp);
 		goto out_fb_release;
+	}
 
 	of_property_read_u32(disp, "ac-prescale", &cfb->ac_prescale);
 	cfb->cmap_invert = of_property_read_bool(disp, "cmap-invert");
 
 	ret = of_property_read_u32(disp, "bits-per-pixel",
 				   &info->var.bits_per_pixel);
+	of_node_put(disp);
 	if (ret)
 		goto out_fb_release;
 
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 235d549..553763a 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -3042,7 +3042,7 @@ static int fbcon_fb_unbind(int idx)
 	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		if (con2fb_map[i] != idx &&
 		    con2fb_map[i] != -1) {
-			new_idx = i;
+			new_idx = con2fb_map[i];
 			break;
 		}
 	}
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index f7f5612..d5aecb1 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -435,7 +435,9 @@ static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
 			image->dx += image->width + 8;
 		}
 	} else if (rotate == FB_ROTATE_UD) {
-		for (x = 0; x < num; x++) {
+		u32 dx = image->dx;
+
+		for (x = 0; x < num && image->dx <= dx; x++) {
 			info->fbops->fb_imageblit(info, image);
 			image->dx -= image->width + 8;
 		}
@@ -447,7 +449,9 @@ static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
 			image->dy += image->height + 8;
 		}
 	} else if (rotate == FB_ROTATE_CCW) {
-		for (x = 0; x < num; x++) {
+		u32 dy = image->dy;
+
+		for (x = 0; x < num && image->dy <= dy; x++) {
 			info->fbops->fb_imageblit(info, image);
 			image->dy -= image->height + 8;
 		}
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
index a3edb20..a846d32 100644
--- a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
@@ -609,6 +609,8 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
 	int r = 0;
 
+	memset(&p, 0, sizeof(p));
+
 	switch (cmd) {
 	case OMAPFB_SYNC_GFX:
 		DBG("ioctl SYNC_GFX\n");
diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c
index 831ef83..c4a17d7 100644
--- a/drivers/watchdog/renesas_wdt.c
+++ b/drivers/watchdog/renesas_wdt.c
@@ -74,12 +74,17 @@ static int rwdt_init_timeout(struct watchdog_device *wdev)
 static int rwdt_start(struct watchdog_device *wdev)
 {
 	struct rwdt_priv *priv = watchdog_get_drvdata(wdev);
+	u8 val;
 
 	pm_runtime_get_sync(wdev->parent);
 
-	rwdt_write(priv, 0, RWTCSRB);
-	rwdt_write(priv, priv->cks, RWTCSRA);
+	/* Stop the timer before we modify any register */
+	val = readb_relaxed(priv->base + RWTCSRA) & ~RWTCSRA_TME;
+	rwdt_write(priv, val, RWTCSRA);
+
 	rwdt_init_timeout(wdev);
+	rwdt_write(priv, priv->cks, RWTCSRA);
+	rwdt_write(priv, 0, RWTCSRB);
 
 	while (readb_relaxed(priv->base + RWTCSRA) & RWTCSRA_WRFLG)
 		cpu_relax();
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index e6c1934..fe1f163 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -1650,7 +1650,7 @@ void xen_callback_vector(void)
 			xen_have_vector_callback = 0;
 			return;
 		}
-		pr_info("Xen HVM callback vector for event delivery is enabled\n");
+		pr_info_once("Xen HVM callback vector for event delivery is enabled\n");
 		alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
 				xen_hvm_callback_vector);
 	}
diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c
index 169293c..abd6dbc 100644
--- a/drivers/xen/pvcalls-back.c
+++ b/drivers/xen/pvcalls-back.c
@@ -164,9 +164,10 @@ static void pvcalls_conn_back_read(void *opaque)
 
 	/* write the data, then modify the indexes */
 	virt_wmb();
-	if (ret < 0)
+	if (ret < 0) {
+		atomic_set(&map->read, 0);
 		intf->in_error = ret;
-	else
+	} else
 		intf->in_prod = prod + ret;
 	/* update the indexes, then notify the other end */
 	virt_wmb();
@@ -290,13 +291,11 @@ static int pvcalls_back_socket(struct xenbus_device *dev,
 static void pvcalls_sk_state_change(struct sock *sock)
 {
 	struct sock_mapping *map = sock->sk_user_data;
-	struct pvcalls_data_intf *intf;
 
 	if (map == NULL)
 		return;
 
-	intf = map->ring;
-	intf->in_error = -ENOTCONN;
+	atomic_inc(&map->read);
 	notify_remote_via_irq(map->irq);
 }
 
diff --git a/fs/aio.c b/fs/aio.c
index a2de58f7..2bb6285 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -558,13 +558,12 @@ void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
 	struct kioctx *ctx = req->ki_ctx;
 	unsigned long flags;
 
+	if (WARN_ON_ONCE(!list_empty(&req->ki_list)))
+		return;
+
 	spin_lock_irqsave(&ctx->ctx_lock, flags);
-
-	if (!req->ki_list.next)
-		list_add(&req->ki_list, &ctx->active_reqs);
-
+	list_add_tail(&req->ki_list, &ctx->active_reqs);
 	req->ki_cancel = cancel;
-
 	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
 }
 EXPORT_SYMBOL(kiocb_set_cancel_fn);
@@ -1051,7 +1050,7 @@ static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx)
 		goto out_put;
 
 	percpu_ref_get(&ctx->reqs);
-
+	INIT_LIST_HEAD(&req->ki_list);
 	req->ki_ctx = ctx;
 	return req;
 out_put:
@@ -1120,16 +1119,7 @@ static void aio_complete(struct kiocb *kiocb, long res, long res2)
 		file_end_write(file);
 	}
 
-	/*
-	 * Special case handling for sync iocbs:
-	 *  - events go directly into the iocb for fast handling
-	 *  - the sync task with the iocb in its stack holds the single iocb
-	 *    ref, no other paths have a way to get another ref
-	 *  - the sync task helpfully left a reference to itself in the iocb
-	 */
-	BUG_ON(is_sync_kiocb(kiocb));
-
-	if (iocb->ki_list.next) {
+	if (!list_empty_careful(&iocb->ki_list)) {
 		unsigned long flags;
 
 		spin_lock_irqsave(&ctx->ctx_lock, flags);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 3323eec5..3911c1a 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -116,6 +116,20 @@ void invalidate_bdev(struct block_device *bdev)
 }
 EXPORT_SYMBOL(invalidate_bdev);
 
+static void set_init_blocksize(struct block_device *bdev)
+{
+	unsigned bsize = bdev_logical_block_size(bdev);
+	loff_t size = i_size_read(bdev->bd_inode);
+
+	while (bsize < PAGE_SIZE) {
+		if (size & bsize)
+			break;
+		bsize <<= 1;
+	}
+	bdev->bd_block_size = bsize;
+	bdev->bd_inode->i_blkbits = blksize_bits(bsize);
+}
+
 int set_blocksize(struct block_device *bdev, int size)
 {
 	/* Size must be a power of two, and between 512 and PAGE_SIZE */
@@ -1393,18 +1407,9 @@ EXPORT_SYMBOL(check_disk_change);
 
 void bd_set_size(struct block_device *bdev, loff_t size)
 {
-	unsigned bsize = bdev_logical_block_size(bdev);
-
 	inode_lock(bdev->bd_inode);
 	i_size_write(bdev->bd_inode, size);
 	inode_unlock(bdev->bd_inode);
-	while (bsize < PAGE_SIZE) {
-		if (size & bsize)
-			break;
-		bsize <<= 1;
-	}
-	bdev->bd_block_size = bsize;
-	bdev->bd_inode->i_blkbits = blksize_bits(bsize);
 }
 EXPORT_SYMBOL(bd_set_size);
 
@@ -1482,8 +1487,10 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
 				}
 			}
 
-			if (!ret)
+			if (!ret) {
 				bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
+				set_init_blocksize(bdev);
+			}
 
 			/*
 			 * If the device is invalidated, rescan partition
@@ -1518,6 +1525,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
 				goto out_clear;
 			}
 			bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
+			set_init_blocksize(bdev);
 		}
 
 		if (bdev->bd_bdi == &noop_backing_dev_info)
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index dd80a1b..f864577 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -351,6 +351,7 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
 		break;
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
+		ASSERT(0);
 		ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED;
 		goto leave;
 	}
@@ -395,6 +396,10 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
 	if (IS_ERR(trans)) {
 		ret = PTR_ERR(trans);
 		btrfs_dev_replace_lock(dev_replace, 1);
+		dev_replace->replace_state =
+			BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED;
+		dev_replace->srcdev = NULL;
+		dev_replace->tgtdev = NULL;
 		goto leave;
 	}
 
@@ -416,8 +421,6 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
 	return ret;
 
 leave:
-	dev_replace->srcdev = NULL;
-	dev_replace->tgtdev = NULL;
 	btrfs_dev_replace_unlock(dev_replace, 1);
 	btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device);
 	return ret;
@@ -801,6 +804,8 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
 			   "cannot continue dev_replace, tgtdev is missing");
 		btrfs_info(fs_info,
 			   "you may cancel the operation after 'mount -o degraded'");
+		dev_replace->replace_state =
+					BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED;
 		btrfs_dev_replace_unlock(dev_replace, 1);
 		return 0;
 	}
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 858d581..e0bdc0c 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4115,6 +4115,14 @@ static void btrfs_destroy_all_ordered_extents(struct btrfs_fs_info *fs_info)
 		spin_lock(&fs_info->ordered_root_lock);
 	}
 	spin_unlock(&fs_info->ordered_root_lock);
+
+	/*
+	 * We need this here because if we've been flipped read-only we won't
+	 * get sync() from the umount, so we need to make sure any ordered
+	 * extents that haven't had their dirty pages IO start writeout yet
+	 * actually get run and error out properly.
+	 */
+	btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
 }
 
 static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 09829e8..7e28851 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3170,9 +3170,6 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
 	/* once for the tree */
 	btrfs_put_ordered_extent(ordered_extent);
 
-	/* Try to release some metadata so we don't get an OOM but don't wait */
-	btrfs_btree_balance_dirty_nodelay(fs_info);
-
 	return ret;
 }
 
@@ -6597,14 +6594,19 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
 		err = btrfs_del_root_ref(trans, fs_info, key.objectid,
 					 root->root_key.objectid, parent_ino,
 					 &local_index, name, name_len);
-
+		if (err)
+			btrfs_abort_transaction(trans, err);
 	} else if (add_backref) {
 		u64 local_index;
 		int err;
 
 		err = btrfs_del_inode_ref(trans, root, name, name_len,
 					  ino, parent_ino, &local_index);
+		if (err)
+			btrfs_abort_transaction(trans, err);
 	}
+
+	/* Return the original error code */
 	return ret;
 }
 
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index ff5d32c..92eb9c3 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -3438,7 +3438,6 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
 			tcap->cap_id = t_cap_id;
 			tcap->seq = t_seq - 1;
 			tcap->issue_seq = t_seq - 1;
-			tcap->mseq = t_mseq;
 			tcap->issued |= issued;
 			tcap->implemented |= issued;
 			if (cap == ci->i_auth_cap)
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 8a2ca41..9b6207c 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -616,7 +616,8 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
 	     capsnap->size);
 
 	spin_lock(&mdsc->snap_flush_lock);
-	list_add_tail(&ci->i_snap_flush_item, &mdsc->snap_flush_list);
+	if (list_empty(&ci->i_snap_flush_item))
+		list_add_tail(&ci->i_snap_flush_item, &mdsc->snap_flush_list);
 	spin_unlock(&mdsc->snap_flush_lock);
 	return 1;  /* caller may want to ceph_flush_snaps */
 }
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index 7b95e79..a78c413 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -66,9 +66,24 @@
 	  Unless you are a developer or are doing network performance analysis
 	  or tuning, say N.
 
+config CIFS_ALLOW_INSECURE_LEGACY
+	bool "Support legacy servers which use less secure dialects"
+	depends on CIFS
+	default y
+	help
+	  Modern dialects, SMB2.1 and later (including SMB3 and 3.1.1), have
+	  additional security features, including protection against
+	  man-in-the-middle attacks and stronger crypto hashes, so the use
+	  of legacy dialects (SMB1/CIFS and SMB2.0) is discouraged.
+
+	  Disabling this option prevents users from using vers=1.0 or vers=2.0
+	  on mounts with cifs.ko
+
+	  If unsure, say Y.
+
 config CIFS_WEAK_PW_HASH
 	bool "Support legacy servers which use weaker LANMAN security"
-	depends on CIFS
+	depends on CIFS && CIFS_ALLOW_INSECURE_LEGACY
 	help
 	  Modern CIFS servers including Samba and most Windows versions
 	  (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 2e936f9..905d0fa 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1445,18 +1445,26 @@ cifs_discard_remaining_data(struct TCP_Server_Info *server)
 }
 
 static int
-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
+		     bool malformed)
 {
 	int length;
-	struct cifs_readdata *rdata = mid->callback_data;
 
 	length = cifs_discard_remaining_data(server);
-	dequeue_mid(mid, rdata->result);
+	dequeue_mid(mid, malformed);
 	mid->resp_buf = server->smallbuf;
 	server->smallbuf = NULL;
 	return length;
 }
 
+static int
+cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+	struct cifs_readdata *rdata = mid->callback_data;
+
+	return  __cifs_readv_discard(server, mid, rdata->result);
+}
+
 int
 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 {
@@ -1496,12 +1504,23 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 		return -1;
 	}
 
+	/* set up first two iov for signature check and to get credits */
+	rdata->iov[0].iov_base = buf;
+	rdata->iov[0].iov_len = 4;
+	rdata->iov[1].iov_base = buf + 4;
+	rdata->iov[1].iov_len = server->total_read - 4;
+	cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+		 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+	cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
+		 rdata->iov[1].iov_base, rdata->iov[1].iov_len);
+
 	/* Was the SMB read successful? */
 	rdata->result = server->ops->map_error(buf, false);
 	if (rdata->result != 0) {
 		cifs_dbg(FYI, "%s: server returned error %d\n",
 			 __func__, rdata->result);
-		return cifs_readv_discard(server, mid);
+		/* normal error on read response */
+		return __cifs_readv_discard(server, mid, false);
 	}
 
 	/* Is there enough to get to the rest of the READ_RSP header? */
@@ -1544,14 +1563,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 		server->total_read += length;
 	}
 
-	/* set up first iov for signature check */
-	rdata->iov[0].iov_base = buf;
-	rdata->iov[0].iov_len = 4;
-	rdata->iov[1].iov_base = buf + 4;
-	rdata->iov[1].iov_len = server->total_read - 4;
-	cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
-		 rdata->iov[0].iov_base, server->total_read);
-
 	/* how much data is in the response? */
 	data_len = server->ops->read_data_length(buf);
 	if (data_offset + data_len > buflen) {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index fd24c72..48aa854 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -51,6 +51,7 @@
 #include "cifs_unicode.h"
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
+#include "dns_resolve.h"
 #include "ntlmssp.h"
 #include "nterr.h"
 #include "rfc1002pdu.h"
@@ -314,6 +315,53 @@ static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
 					const char *devname);
 
 /*
+ * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
+ * get their ip addresses changed at some point.
+ *
+ * This should be called with server->srv_mutex held.
+ */
+#ifdef CONFIG_CIFS_DFS_UPCALL
+static int reconn_set_ipaddr(struct TCP_Server_Info *server)
+{
+	int rc;
+	int len;
+	char *unc, *ipaddr = NULL;
+
+	if (!server->hostname)
+		return -EINVAL;
+
+	len = strlen(server->hostname) + 3;
+
+	unc = kmalloc(len, GFP_KERNEL);
+	if (!unc) {
+		cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
+		return -ENOMEM;
+	}
+	snprintf(unc, len, "\\\\%s", server->hostname);
+
+	rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
+	kfree(unc);
+
+	if (rc < 0) {
+		cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
+			 __func__, server->hostname, rc);
+		return rc;
+	}
+
+	rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
+				  strlen(ipaddr));
+	kfree(ipaddr);
+
+	return !rc ? -1 : 0;
+}
+#else
+static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
+{
+	return 0;
+}
+#endif
+
+/*
  * cifs tcp session reconnection
  *
  * mark tcp session as reconnecting so temporarily locked
@@ -408,6 +456,11 @@ cifs_reconnect(struct TCP_Server_Info *server)
 		rc = generic_ip_connect(server);
 		if (rc) {
 			cifs_dbg(FYI, "reconnect error %d\n", rc);
+			rc = reconn_set_ipaddr(server);
+			if (rc) {
+				cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
+					 __func__, rc);
+			}
 			mutex_unlock(&server->srv_mutex);
 			msleep(3000);
 		} else {
@@ -524,6 +577,21 @@ server_unresponsive(struct TCP_Server_Info *server)
 	return false;
 }
 
+static inline bool
+zero_credits(struct TCP_Server_Info *server)
+{
+	int val;
+
+	spin_lock(&server->req_lock);
+	val = server->credits + server->echo_credits + server->oplock_credits;
+	if (server->in_flight == 0 && val == 0) {
+		spin_unlock(&server->req_lock);
+		return true;
+	}
+	spin_unlock(&server->req_lock);
+	return false;
+}
+
 static int
 cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
 {
@@ -536,6 +604,12 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
 	for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
 		try_to_freeze();
 
+		/* reconnect if no credits and no requests in flight */
+		if (zero_credits(server)) {
+			cifs_reconnect(server);
+			return -ECONNABORTED;
+		}
+
 		if (server_unresponsive(server))
 			return -ECONNABORTED;
 
@@ -1130,6 +1204,7 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
 	substring_t args[MAX_OPT_ARGS];
 
 	switch (match_token(value, cifs_smb_version_tokens, args)) {
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
 	case Smb_1:
 		vol->ops = &smb1_operations;
 		vol->vals = &smb1_values;
@@ -1138,6 +1213,14 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
 		vol->ops = &smb20_operations;
 		vol->vals = &smb20_values;
 		break;
+#else
+	case Smb_1:
+		cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
+		return 1;
+	case Smb_20:
+		cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
+		return 1;
+#endif /* CIFS_ALLOW_INSECURE_LEGACY */
 	case Smb_21:
 		vol->ops = &smb21_operations;
 		vol->vals = &smb21_values;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 7d6539a..852d7d1 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1120,14 +1120,18 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
 
 	/*
 	 * Accessing maxBuf is racy with cifs_reconnect - need to store value
-	 * and check it for zero before using.
+	 * and check it before using.
 	 */
 	max_buf = tcon->ses->server->maxBuf;
-	if (!max_buf) {
+	if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) {
 		free_xid(xid);
 		return -EINVAL;
 	}
 
+	BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) >
+		     PAGE_SIZE);
+	max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr),
+			PAGE_SIZE);
 	max_num = (max_buf - sizeof(struct smb_hdr)) /
 						sizeof(LOCKING_ANDX_RANGE);
 	buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
@@ -1460,12 +1464,16 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
 
 	/*
 	 * Accessing maxBuf is racy with cifs_reconnect - need to store value
-	 * and check it for zero before using.
+	 * and check it before using.
 	 */
 	max_buf = tcon->ses->server->maxBuf;
-	if (!max_buf)
+	if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE)))
 		return -EINVAL;
 
+	BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) >
+		     PAGE_SIZE);
+	max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr),
+			PAGE_SIZE);
 	max_num = (max_buf - sizeof(struct smb_hdr)) /
 						sizeof(LOCKING_ANDX_RANGE);
 	buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index ef24b45..6818387 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -655,7 +655,14 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
 		/* scan and find it */
 		int i;
 		char *cur_ent;
-		char *end_of_smb = cfile->srch_inf.ntwrk_buf_start +
+		char *end_of_smb;
+
+		if (cfile->srch_inf.ntwrk_buf_start == NULL) {
+			cifs_dbg(VFS, "ntwrk_buf_start is NULL during readdir\n");
+			return -EIO;
+		}
+
+		end_of_smb = cfile->srch_inf.ntwrk_buf_start +
 			server->ops->calc_smb_size(
 					cfile->srch_inf.ntwrk_buf_start);
 
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
index b4b1f03..1add4046 100644
--- a/fs/cifs/smb2file.c
+++ b/fs/cifs/smb2file.c
@@ -124,12 +124,14 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
 
 	/*
 	 * Accessing maxBuf is racy with cifs_reconnect - need to store value
-	 * and check it for zero before using.
+	 * and check it before using.
 	 */
 	max_buf = tcon->ses->server->maxBuf;
-	if (!max_buf)
+	if (max_buf < sizeof(struct smb2_lock_element))
 		return -EINVAL;
 
+	BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
+	max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
 	max_num = max_buf / sizeof(struct smb2_lock_element);
 	buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
 	if (!buf)
@@ -266,6 +268,8 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
 		return -EINVAL;
 	}
 
+	BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
+	max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
 	max_num = max_buf / sizeof(struct smb2_lock_element);
 	buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
 	if (!buf) {
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 3372eed..fb1c65f 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -33,6 +33,7 @@
 #include "smb2glob.h"
 #include "cifs_ioctl.h"
 
+/* Change credits for different ops and return the total number of credits */
 static int
 change_conf(struct TCP_Server_Info *server)
 {
@@ -40,17 +41,15 @@ change_conf(struct TCP_Server_Info *server)
 	server->oplock_credits = server->echo_credits = 0;
 	switch (server->credits) {
 	case 0:
-		return -1;
+		return 0;
 	case 1:
 		server->echoes = false;
 		server->oplocks = false;
-		cifs_dbg(VFS, "disabling echoes and oplocks\n");
 		break;
 	case 2:
 		server->echoes = true;
 		server->oplocks = false;
 		server->echo_credits = 1;
-		cifs_dbg(FYI, "disabling oplocks\n");
 		break;
 	default:
 		server->echoes = true;
@@ -63,14 +62,15 @@ change_conf(struct TCP_Server_Info *server)
 		server->echo_credits = 1;
 	}
 	server->credits -= server->echo_credits + server->oplock_credits;
-	return 0;
+	return server->credits + server->echo_credits + server->oplock_credits;
 }
 
 static void
 smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
 		 const int optype)
 {
-	int *val, rc = 0;
+	int *val, rc = -1;
+
 	spin_lock(&server->req_lock);
 	val = server->ops->get_credits_field(server, optype);
 	*val += add;
@@ -94,8 +94,26 @@ smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
 	}
 	spin_unlock(&server->req_lock);
 	wake_up(&server->request_q);
-	if (rc)
-		cifs_reconnect(server);
+
+	if (server->tcpStatus == CifsNeedReconnect)
+		return;
+
+	switch (rc) {
+	case -1:
+		/* change_conf hasn't been executed */
+		break;
+	case 0:
+		cifs_dbg(VFS, "Possible client or server bug - zero credits\n");
+		break;
+	case 1:
+		cifs_dbg(VFS, "disabling echoes and oplocks\n");
+		break;
+	case 2:
+		cifs_dbg(FYI, "disabling oplocks\n");
+		break;
+	default:
+		cifs_dbg(FYI, "add %u credits total=%d\n", add, rc);
+	}
 }
 
 static void
@@ -153,14 +171,14 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
 
 			scredits = server->credits;
 			/* can deadlock with reopen */
-			if (scredits == 1) {
+			if (scredits <= 8) {
 				*num = SMB2_MAX_BUFFER_SIZE;
 				*credits = 0;
 				break;
 			}
 
-			/* leave one credit for a possible reopen */
-			scredits--;
+			/* leave some credits for reopen and other ops */
+			scredits -= 8;
 			*num = min_t(unsigned int, size,
 				     scredits * SMB2_MAX_BUFFER_SIZE);
 
@@ -2531,11 +2549,23 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
 			server->ops->is_status_pending(buf, server, 0))
 		return -1;
 
-	rdata->result = server->ops->map_error(buf, false);
+	/* set up first two iov to get credits */
+	rdata->iov[0].iov_base = buf;
+	rdata->iov[0].iov_len = 4;
+	rdata->iov[1].iov_base = buf + 4;
+	rdata->iov[1].iov_len =
+		min_t(unsigned int, buf_len, server->vals->read_rsp_size) - 4;
+	cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+		 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+	cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
+		 rdata->iov[1].iov_base, rdata->iov[1].iov_len);
+
+	rdata->result = server->ops->map_error(buf, true);
 	if (rdata->result != 0) {
 		cifs_dbg(FYI, "%s: server returned error %d\n",
 			 __func__, rdata->result);
-		dequeue_mid(mid, rdata->result);
+		/* normal error on read response */
+		dequeue_mid(mid, false);
 		return 0;
 	}
 
@@ -2605,14 +2635,6 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
 		return 0;
 	}
 
-	/* set up first iov for signature check */
-	rdata->iov[0].iov_base = buf;
-	rdata->iov[0].iov_len = 4;
-	rdata->iov[1].iov_base = buf + 4;
-	rdata->iov[1].iov_len = server->vals->read_rsp_size - 4;
-	cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
-		 rdata->iov[0].iov_base, server->vals->read_rsp_size);
-
 	length = rdata->copy_into_pages(server, rdata, &iter);
 
 	kfree(bvec);
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 1581e86..fd2d199 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2632,12 +2632,14 @@ smb2_async_readv(struct cifs_readdata *rdata)
 	if (rdata->credits) {
 		shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
 						SMB2_MAX_BUFFER_SIZE));
-		shdr->CreditRequest = shdr->CreditCharge;
+		shdr->CreditRequest =
+			cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1);
 		spin_lock(&server->req_lock);
 		server->credits += rdata->credits -
 						le16_to_cpu(shdr->CreditCharge);
 		spin_unlock(&server->req_lock);
 		wake_up(&server->request_q);
+		rdata->credits = le16_to_cpu(shdr->CreditCharge);
 		flags |= CIFS_HAS_CREDITS;
 	}
 
@@ -2842,12 +2844,14 @@ smb2_async_writev(struct cifs_writedata *wdata,
 	if (wdata->credits) {
 		shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
 						    SMB2_MAX_BUFFER_SIZE));
-		shdr->CreditRequest = shdr->CreditCharge;
+		shdr->CreditRequest =
+			cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1);
 		spin_lock(&server->req_lock);
 		server->credits += wdata->credits -
 						le16_to_cpu(shdr->CreditCharge);
 		spin_unlock(&server->req_lock);
 		wake_up(&server->request_q);
+		wdata->credits = le16_to_cpu(shdr->CreditCharge);
 		flags |= CIFS_HAS_CREDITS;
 	}
 
@@ -3067,8 +3071,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
 		    rsp->hdr.sync_hdr.Status == STATUS_NO_MORE_FILES) {
 			srch_inf->endOfSearch = true;
 			rc = 0;
-		}
-		cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
+		} else
+			cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
 		goto qdir_exit;
 	}
 
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index a10f51d..ffc8757 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -318,7 +318,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 	if (rc < 0 && rc != -EINTR)
 		cifs_dbg(VFS, "Error %d sending data on socket to server\n",
 			 rc);
-	else
+	else if (rc > 0)
 		rc = 0;
 
 	return rc;
diff --git a/fs/dcache.c b/fs/dcache.c
index 8d603ab..c04352b 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1183,15 +1183,11 @@ static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,
  */
 void shrink_dcache_sb(struct super_block *sb)
 {
-	long freed;
-
 	do {
 		LIST_HEAD(dispose);
 
-		freed = list_lru_walk(&sb->s_dentry_lru,
+		list_lru_walk(&sb->s_dentry_lru,
 			dentry_lru_isolate_shrink, &dispose, 1024);
-
-		this_cpu_sub(nr_dentry_unused, freed);
 		shrink_dentry_list(&dispose);
 		cond_resched();
 	} while (list_lru_count(&sb->s_dentry_lru) > 0);
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 9dca4da..5f790df 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -794,6 +794,13 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
 	struct dentry *dentry = NULL, *trap;
 	struct name_snapshot old_name;
 
+	if (IS_ERR(old_dir))
+		return old_dir;
+	if (IS_ERR(new_dir))
+		return new_dir;
+	if (IS_ERR_OR_NULL(old_dentry))
+		return old_dentry;
+
 	trap = lock_rename(new_dir, old_dir);
 	/* Source or destination directories don't exist? */
 	if (d_really_is_negative(old_dir) || d_really_is_negative(new_dir))
diff --git a/fs/direct-io.c b/fs/direct-io.c
index c96245a..552c503 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -699,6 +699,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
 	unsigned long fs_count;	/* Number of filesystem-sized blocks */
 	int create;
 	unsigned int i_blkbits = sdio->blkbits + sdio->blkfactor;
+	loff_t i_size;
 
 	/*
 	 * If there was a memory error and we've overwritten all the
@@ -728,8 +729,8 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
 		 */
 		create = dio->op == REQ_OP_WRITE;
 		if (dio->flags & DIO_SKIP_HOLES) {
-			if (fs_startblk <= ((i_size_read(dio->inode) - 1) >>
-							i_blkbits))
+			i_size = i_size_read(dio->inode);
+			if (i_size && fs_startblk <= (i_size - 1) >> i_blkbits)
 				create = 0;
 		}
 
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
index 07fed83..15fa423 100644
--- a/fs/dlm/ast.c
+++ b/fs/dlm/ast.c
@@ -290,6 +290,8 @@ void dlm_callback_suspend(struct dlm_ls *ls)
 		flush_workqueue(ls->ls_callback_wq);
 }
 
+#define MAX_CB_QUEUE 25
+
 void dlm_callback_resume(struct dlm_ls *ls)
 {
 	struct dlm_lkb *lkb, *safe;
@@ -300,15 +302,23 @@ void dlm_callback_resume(struct dlm_ls *ls)
 	if (!ls->ls_callback_wq)
 		return;
 
+more:
 	mutex_lock(&ls->ls_cb_mutex);
 	list_for_each_entry_safe(lkb, safe, &ls->ls_cb_delay, lkb_cb_list) {
 		list_del_init(&lkb->lkb_cb_list);
 		queue_work(ls->ls_callback_wq, &lkb->lkb_cb_work);
 		count++;
+		if (count == MAX_CB_QUEUE)
+			break;
 	}
 	mutex_unlock(&ls->ls_cb_mutex);
 
 	if (count)
 		log_rinfo(ls, "dlm_callback_resume %d", count);
+	if (count == MAX_CB_QUEUE) {
+		count = 0;
+		cond_resched();
+		goto more;
+	}
 }
 
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index d4aadde..21643d2 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -1210,6 +1210,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
 
 	if (rv < 0) {
 		log_error(ls, "create_lkb idr error %d", rv);
+		dlm_free_lkb(lkb);
 		return rv;
 	}
 
@@ -4176,6 +4177,7 @@ static int receive_convert(struct dlm_ls *ls, struct dlm_message *ms)
 			  (unsigned long long)lkb->lkb_recover_seq,
 			  ms->m_header.h_nodeid, ms->m_lkid);
 		error = -ENOENT;
+		dlm_put_lkb(lkb);
 		goto fail;
 	}
 
@@ -4229,6 +4231,7 @@ static int receive_unlock(struct dlm_ls *ls, struct dlm_message *ms)
 			  lkb->lkb_id, lkb->lkb_remid,
 			  ms->m_header.h_nodeid, ms->m_lkid);
 		error = -ENOENT;
+		dlm_put_lkb(lkb);
 		goto fail;
 	}
 
@@ -5789,20 +5792,20 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
 			goto out;
 		}
 	}
-
-	/* After ua is attached to lkb it will be freed by dlm_free_lkb().
-	   When DLM_IFL_USER is set, the dlm knows that this is a userspace
-	   lock and that lkb_astparam is the dlm_user_args structure. */
-
 	error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs,
 			      fake_astfn, ua, fake_bastfn, &args);
-	lkb->lkb_flags |= DLM_IFL_USER;
-
 	if (error) {
+		kfree(ua->lksb.sb_lvbptr);
+		ua->lksb.sb_lvbptr = NULL;
+		kfree(ua);
 		__put_lkb(ls, lkb);
 		goto out;
 	}
 
+	/* After ua is attached to lkb it will be freed by dlm_free_lkb().
+	   When DLM_IFL_USER is set, the dlm knows that this is a userspace
+	   lock and that lkb_astparam is the dlm_user_args structure. */
+	lkb->lkb_flags |= DLM_IFL_USER;
 	error = request_lock(ls, lkb, name, namelen, &args);
 
 	switch (error) {
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 78a7c85..610f72a 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -680,11 +680,11 @@ static int new_lockspace(const char *name, const char *cluster,
 	kfree(ls->ls_recover_buf);
  out_lkbidr:
 	idr_destroy(&ls->ls_lkbidr);
+ out_rsbtbl:
 	for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) {
 		if (ls->ls_remove_names[i])
 			kfree(ls->ls_remove_names[i]);
 	}
- out_rsbtbl:
 	vfree(ls->ls_rsbtbl);
  out_lsfree:
 	if (do_unreg)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index a7d3947..9a309f7 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1168,7 +1168,7 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v
 	 * semantics). All the events that happen during that period of time are
 	 * chained in ep->ovflist and requeued later on.
 	 */
-	if (unlikely(ep->ovflist != EP_UNACTIVE_PTR)) {
+	if (ep->ovflist != EP_UNACTIVE_PTR) {
 		if (epi->next == EP_UNACTIVE_PTR) {
 			epi->next = ep->ovflist;
 			ep->ovflist = epi;
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
index 26a7fe5..5508baa 100644
--- a/fs/ext4/fsync.c
+++ b/fs/ext4/fsync.c
@@ -159,6 +159,9 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 			ret = err;
 	}
 out:
+	err = file_check_and_advance_wb_err(file);
+	if (ret == 0)
+		ret = err;
 	trace_ext4_sync_file_exit(inode, ret);
 	return ret;
 }
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 3c0042d0..3344bd8 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -1878,12 +1878,12 @@ int ext4_inline_data_fiemap(struct inode *inode,
 	physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data;
 	physical += offsetof(struct ext4_inode, i_block);
 
-	if (physical)
-		error = fiemap_fill_next_extent(fieinfo, start, physical,
-						inline_len, flags);
 	brelse(iloc.bh);
 out:
 	up_read(&EXT4_I(inode)->xattr_sem);
+	if (physical)
+		error = fiemap_fill_next_extent(fieinfo, start, physical,
+						inline_len, flags);
 	return (error < 0 ? error : 0);
 }
 
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 2934fc9..9c4301f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2791,7 +2791,8 @@ static int ext4_writepages(struct address_space *mapping,
 		 * We may need to convert up to one extent per block in
 		 * the page and we may dirty the inode.
 		 */
-		rsv_blocks = 1 + (PAGE_SIZE >> inode->i_blkbits);
+		rsv_blocks = 1 + ext4_chunk_trans_blocks(inode,
+						PAGE_SIZE >> inode->i_blkbits);
 	}
 
 	/*
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 4fe93a6d..ad4cff1 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4851,7 +4851,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
 	ext4_superblock_csum_set(sb);
 	if (sync)
 		lock_buffer(sbh);
-	if (buffer_write_io_error(sbh)) {
+	if (buffer_write_io_error(sbh) || !buffer_uptodate(sbh)) {
 		/*
 		 * Oh, dear.  A previous attempt to write the
 		 * superblock failed.  This could happen because the
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 1118241..b9fe937 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -352,12 +352,14 @@ static int f2fs_acl_create(struct inode *dir, umode_t *mode,
 		return PTR_ERR(p);
 
 	clone = f2fs_acl_clone(p, GFP_NOFS);
-	if (!clone)
-		goto no_mem;
+	if (!clone) {
+		ret = -ENOMEM;
+		goto release_acl;
+	}
 
 	ret = f2fs_acl_create_masq(clone, mode);
 	if (ret < 0)
-		goto no_mem_clone;
+		goto release_clone;
 
 	if (ret == 0)
 		posix_acl_release(clone);
@@ -371,11 +373,11 @@ static int f2fs_acl_create(struct inode *dir, umode_t *mode,
 
 	return 0;
 
-no_mem_clone:
+release_clone:
 	posix_acl_release(clone);
-no_mem:
+release_acl:
 	posix_acl_release(p);
-	return -ENOMEM;
+	return ret;
 }
 
 int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage,
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index f758ef5..49c0d38 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2273,6 +2273,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 	bool locked = false;
 	struct extent_info ei = {0,0,0};
 	int err = 0;
+	int flag;
 
 	/*
 	 * we already allocated all the blocks, so we don't need to get
@@ -2282,9 +2283,15 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 			!is_inode_flag_set(inode, FI_NO_PREALLOC))
 		return 0;
 
+	/* f2fs_lock_op avoids race between write CP and convert_inline_page */
+	if (f2fs_has_inline_data(inode) && pos + len > MAX_INLINE_DATA(inode))
+		flag = F2FS_GET_BLOCK_DEFAULT;
+	else
+		flag = F2FS_GET_BLOCK_PRE_AIO;
+
 	if (f2fs_has_inline_data(inode) ||
 			(pos & PAGE_MASK) >= i_size_read(inode)) {
-		__do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true);
+		__do_map_lock(sbi, flag, true);
 		locked = true;
 	}
 restart:
@@ -2322,6 +2329,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 				f2fs_put_dnode(&dn);
 				__do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO,
 								true);
+				WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO);
 				locked = true;
 				goto restart;
 			}
@@ -2335,7 +2343,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 	f2fs_put_dnode(&dn);
 unlock_out:
 	if (locked)
-		__do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false);
+		__do_map_lock(sbi, flag, false);
 	return err;
 }
 
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index d7db68b..b5f56f4 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2516,10 +2516,19 @@ static inline bool is_dot_dotdot(const struct qstr *str)
 
 static inline bool f2fs_may_extent_tree(struct inode *inode)
 {
-	if (!test_opt(F2FS_I_SB(inode), EXTENT_CACHE) ||
+	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+
+	if (!test_opt(sbi, EXTENT_CACHE) ||
 			is_inode_flag_set(inode, FI_NO_EXTENT))
 		return false;
 
+	/*
+	 * for recovered files during mount do not create extents
+	 * if shrinker is not registered.
+	 */
+	if (list_empty(&sbi->s_list))
+		return false;
+
 	return S_ISREG(inode->i_mode);
 }
 
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index d942f3e..4344544 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -216,6 +216,9 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
 
 	trace_f2fs_sync_file_enter(inode);
 
+	if (S_ISDIR(inode->i_mode))
+		goto go_write;
+
 	/* if fdatasync is triggered, let's do in-place-update */
 	if (datasync || get_dirty_pages(inode) <= SM_I(sbi)->min_fsync_blocks)
 		set_inode_flag(inode, FI_NEED_IPU);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 0c01b23..7240bdb 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -740,6 +740,7 @@ static int truncate_node(struct dnode_of_data *dn)
 	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
 	struct node_info ni;
 	int err;
+	pgoff_t index;
 
 	err = get_node_info(sbi, dn->nid, &ni);
 	if (err)
@@ -759,10 +760,11 @@ static int truncate_node(struct dnode_of_data *dn)
 	clear_node_page_dirty(dn->node_page);
 	set_sbi_flag(sbi, SBI_IS_DIRTY);
 
+	index = dn->node_page->index;
 	f2fs_put_page(dn->node_page, 1);
 
 	invalidate_mapping_pages(NODE_MAPPING(sbi),
-			dn->node_page->index, dn->node_page->index);
+			index, index);
 
 	dn->node_page = NULL;
 	trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr);
diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c
index 75e353b..bab02e2 100644
--- a/fs/f2fs/shrinker.c
+++ b/fs/f2fs/shrinker.c
@@ -138,6 +138,6 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi)
 	f2fs_shrink_extent_tree(sbi, __count_extent_cache(sbi));
 
 	spin_lock(&f2fs_list_lock);
-	list_del(&sbi->s_list);
+	list_del_init(&sbi->s_list);
 	spin_unlock(&f2fs_list_lock);
 }
diff --git a/fs/f2fs/trace.c b/fs/f2fs/trace.c
index a1fcd00..8ac1851 100644
--- a/fs/f2fs/trace.c
+++ b/fs/f2fs/trace.c
@@ -17,7 +17,7 @@
 #include "trace.h"
 
 static RADIX_TREE(pids, GFP_ATOMIC);
-static struct mutex pids_lock;
+static spinlock_t pids_lock;
 static struct last_io_info last_io;
 
 static inline void __print_last_io(void)
@@ -61,23 +61,29 @@ void f2fs_trace_pid(struct page *page)
 
 	set_page_private(page, (unsigned long)pid);
 
+retry:
 	if (radix_tree_preload(GFP_NOFS))
 		return;
 
-	mutex_lock(&pids_lock);
+	spin_lock(&pids_lock);
 	p = radix_tree_lookup(&pids, pid);
 	if (p == current)
 		goto out;
 	if (p)
 		radix_tree_delete(&pids, pid);
 
-	f2fs_radix_tree_insert(&pids, pid, current);
+	if (radix_tree_insert(&pids, pid, current)) {
+		spin_unlock(&pids_lock);
+		radix_tree_preload_end();
+		cond_resched();
+		goto retry;
+	}
 
 	trace_printk("%3x:%3x %4x %-16s\n",
 			MAJOR(inode->i_sb->s_dev), MINOR(inode->i_sb->s_dev),
 			pid, current->comm);
 out:
-	mutex_unlock(&pids_lock);
+	spin_unlock(&pids_lock);
 	radix_tree_preload_end();
 }
 
@@ -122,7 +128,7 @@ void f2fs_trace_ios(struct f2fs_io_info *fio, int flush)
 
 void f2fs_build_trace_ios(void)
 {
-	mutex_init(&pids_lock);
+	spin_lock_init(&pids_lock);
 }
 
 #define PIDVEC_SIZE	128
@@ -150,7 +156,7 @@ void f2fs_destroy_trace_ios(void)
 	pid_t next_pid = 0;
 	unsigned int found;
 
-	mutex_lock(&pids_lock);
+	spin_lock(&pids_lock);
 	while ((found = gang_lookup_pids(pid, next_pid, PIDVEC_SIZE))) {
 		unsigned idx;
 
@@ -158,5 +164,5 @@ void f2fs_destroy_trace_ios(void)
 		for (idx = 0; idx < found; idx++)
 			radix_tree_delete(&pids, pid[idx]);
 	}
-	mutex_unlock(&pids_lock);
+	spin_unlock(&pids_lock);
 }
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 8e1b9b1..a8562c9 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -331,11 +331,22 @@ struct inode_switch_wbs_context {
 	struct work_struct	work;
 };
 
+static void bdi_down_write_wb_switch_rwsem(struct backing_dev_info *bdi)
+{
+	down_write(&bdi->wb_switch_rwsem);
+}
+
+static void bdi_up_write_wb_switch_rwsem(struct backing_dev_info *bdi)
+{
+	up_write(&bdi->wb_switch_rwsem);
+}
+
 static void inode_switch_wbs_work_fn(struct work_struct *work)
 {
 	struct inode_switch_wbs_context *isw =
 		container_of(work, struct inode_switch_wbs_context, work);
 	struct inode *inode = isw->inode;
+	struct backing_dev_info *bdi = inode_to_bdi(inode);
 	struct address_space *mapping = inode->i_mapping;
 	struct bdi_writeback *old_wb = inode->i_wb;
 	struct bdi_writeback *new_wb = isw->new_wb;
@@ -344,6 +355,12 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
 	void **slot;
 
 	/*
+	 * If @inode switches cgwb membership while sync_inodes_sb() is
+	 * being issued, sync_inodes_sb() might miss it.  Synchronize.
+	 */
+	down_read(&bdi->wb_switch_rwsem);
+
+	/*
 	 * By the time control reaches here, RCU grace period has passed
 	 * since I_WB_SWITCH assertion and all wb stat update transactions
 	 * between unlocked_inode_to_wb_begin/end() are guaranteed to be
@@ -435,6 +452,8 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
 	spin_unlock(&new_wb->list_lock);
 	spin_unlock(&old_wb->list_lock);
 
+	up_read(&bdi->wb_switch_rwsem);
+
 	if (switched) {
 		wb_wakeup(new_wb);
 		wb_put(old_wb);
@@ -475,9 +494,18 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
 	if (inode->i_state & I_WB_SWITCH)
 		return;
 
+	/*
+	 * Avoid starting new switches while sync_inodes_sb() is in
+	 * progress.  Otherwise, if the down_write protected issue path
+	 * blocks heavily, we might end up starting a large number of
+	 * switches which will block on the rwsem.
+	 */
+	if (!down_read_trylock(&bdi->wb_switch_rwsem))
+		return;
+
 	isw = kzalloc(sizeof(*isw), GFP_ATOMIC);
 	if (!isw)
-		return;
+		goto out_unlock;
 
 	/* find and pin the new wb */
 	rcu_read_lock();
@@ -511,12 +539,14 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
 	 * Let's continue after I_WB_SWITCH is guaranteed to be visible.
 	 */
 	call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn);
-	return;
+	goto out_unlock;
 
 out_free:
 	if (isw->new_wb)
 		wb_put(isw->new_wb);
 	kfree(isw);
+out_unlock:
+	up_read(&bdi->wb_switch_rwsem);
 }
 
 /**
@@ -894,6 +924,9 @@ fs_initcall(cgroup_writeback_init);
 
 #else	/* CONFIG_CGROUP_WRITEBACK */
 
+static void bdi_down_write_wb_switch_rwsem(struct backing_dev_info *bdi) { }
+static void bdi_up_write_wb_switch_rwsem(struct backing_dev_info *bdi) { }
+
 static struct bdi_writeback *
 locked_inode_to_wb_and_lock_list(struct inode *inode)
 	__releases(&inode->i_lock)
@@ -2408,8 +2441,11 @@ void sync_inodes_sb(struct super_block *sb)
 		return;
 	WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
+	/* protect against inode wb switch, see inode_switch_wbs_work_fn() */
+	bdi_down_write_wb_switch_rwsem(bdi);
 	bdi_split_work_to_wbs(bdi, &work, false);
 	wb_wait_for_completion(bdi, &done);
+	bdi_up_write_wb_switch_rwsem(bdi);
 
 	wait_sb_inodes(sb);
 }
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 608d823..9fdb027 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1695,7 +1695,6 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
 	req->in.h.nodeid = outarg->nodeid;
 	req->in.numargs = 2;
 	req->in.argpages = 1;
-	req->page_descs[0].offset = offset;
 	req->end = fuse_retrieve_end;
 
 	index = outarg->offset >> PAGE_SHIFT;
@@ -1710,6 +1709,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
 
 		this_num = min_t(unsigned, num, PAGE_SIZE - offset);
 		req->pages[req->num_pages] = page;
+		req->page_descs[req->num_pages].offset = offset;
 		req->page_descs[req->num_pages].length = this_num;
 		req->num_pages++;
 
@@ -2034,8 +2034,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 
 	ret = fuse_dev_do_write(fud, &cs, len);
 
+	pipe_lock(pipe);
 	for (idx = 0; idx < nbuf; idx++)
 		pipe_buf_release(pipe, &bufs[idx]);
+	pipe_unlock(pipe);
 
 out:
 	kfree(bufs);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index e6a27fd..d4eb4a2 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1777,7 +1777,7 @@ static bool fuse_writepage_in_flight(struct fuse_req *new_req,
 		spin_unlock(&fc->lock);
 
 		dec_wb_stat(&bdi->wb, WB_WRITEBACK);
-		dec_node_page_state(page, NR_WRITEBACK_TEMP);
+		dec_node_page_state(new_req->pages[0], NR_WRITEBACK_TEMP);
 		wb_writeout_inc(&bdi->wb);
 		fuse_writepage_free(fc, new_req);
 		fuse_request_free(new_req);
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 863749e..c850579 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -743,17 +743,19 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 			       the gfs2 structures. */
 	if (default_acl) {
 		error = __gfs2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+		if (error)
+			goto fail_gunlock3;
 		posix_acl_release(default_acl);
+		default_acl = NULL;
 	}
 	if (acl) {
-		if (!error)
-			error = __gfs2_set_acl(inode, acl, ACL_TYPE_ACCESS);
+		error = __gfs2_set_acl(inode, acl, ACL_TYPE_ACCESS);
+		if (error)
+			goto fail_gunlock3;
 		posix_acl_release(acl);
+		acl = NULL;
 	}
 
-	if (error)
-		goto fail_gunlock3;
-
 	error = security_inode_init_security(&ip->i_inode, &dip->i_inode, name,
 					     &gfs2_initxattrs, NULL);
 	if (error)
@@ -788,10 +790,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	}
 	gfs2_rsqa_delete(ip, NULL);
 fail_free_acls:
-	if (default_acl)
-		posix_acl_release(default_acl);
-	if (acl)
-		posix_acl_release(acl);
+	posix_acl_release(default_acl);
+	posix_acl_release(acl);
 fail_gunlock:
 	gfs2_dir_no_add(&da);
 	gfs2_glock_dq_uninit(ghs);
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index bc00cc3..8334049 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -101,7 +101,8 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
-	cancel_delayed_work_sync(&c->wbuf_dwork);
+	if (jffs2_is_writebuffered(c))
+		cancel_delayed_work_sync(&c->wbuf_dwork);
 #endif
 
 	mutex_lock(&c->alloc_sem);
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 066ac31..84857ff 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -442,7 +442,7 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
 			fl->fl_start = req->a_res.lock.fl.fl_start;
 			fl->fl_end = req->a_res.lock.fl.fl_end;
 			fl->fl_type = req->a_res.lock.fl.fl_type;
-			fl->fl_pid = 0;
+			fl->fl_pid = -req->a_res.lock.fl.fl_pid;
 			break;
 		default:
 			status = nlm_stat_to_errno(req->a_res.status);
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 7147e4a..9846f7e 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -127,7 +127,7 @@ nlm_decode_lock(__be32 *p, struct nlm_lock *lock)
 
 	locks_init_lock(fl);
 	fl->fl_owner = current->files;
-	fl->fl_pid   = (pid_t)lock->svid;
+	fl->fl_pid   = current->tgid;
 	fl->fl_flags = FL_POSIX;
 	fl->fl_type  = F_RDLCK;		/* as good as anything else */
 	start = ntohl(*p++);
@@ -269,7 +269,7 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
 	memset(lock, 0, sizeof(*lock));
 	locks_init_lock(&lock->fl);
 	lock->svid = ~(u32) 0;
-	lock->fl.fl_pid = (pid_t)lock->svid;
+	lock->fl.fl_pid = current->tgid;
 
 	if (!(p = nlm_decode_cookie(p, &argp->cookie))
 	 || !(p = xdr_decode_string_inplace(p, &lock->caller,
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 7ed9edf..70154f3 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -119,7 +119,7 @@ nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
 
 	locks_init_lock(fl);
 	fl->fl_owner = current->files;
-	fl->fl_pid   = (pid_t)lock->svid;
+	fl->fl_pid   = current->tgid;
 	fl->fl_flags = FL_POSIX;
 	fl->fl_type  = F_RDLCK;		/* as good as anything else */
 	p = xdr_decode_hyper(p, &start);
@@ -266,7 +266,7 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
 	memset(lock, 0, sizeof(*lock));
 	locks_init_lock(&lock->fl);
 	lock->svid = ~(u32) 0;
-	lock->fl.fl_pid = (pid_t)lock->svid;
+	lock->fl.fl_pid = current->tgid;
 
 	if (!(p = nlm4_decode_cookie(p, &argp->cookie))
 	 || !(p = xdr_decode_string_inplace(p, &lock->caller,
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 22880ef..7d6ddfd 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -291,12 +291,23 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
 	const struct sockaddr *sap = data->addr;
 	struct nfs_net *nn = net_generic(data->net, nfs_net_id);
 
+again:
 	list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
 	        const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
 		/* Don't match clients that failed to initialise properly */
 		if (clp->cl_cons_state < 0)
 			continue;
 
+		/* If a client is still initializing then we need to wait */
+		if (clp->cl_cons_state > NFS_CS_READY) {
+			atomic_inc(&clp->cl_count);
+			spin_unlock(&nn->nfs_client_lock);
+			nfs_wait_client_init_complete(clp);
+			nfs_put_client(clp);
+			spin_lock(&nn->nfs_client_lock);
+			goto again;
+		}
+
 		/* Different NFS versions cannot share the same nfs_client */
 		if (clp->rpc_ops != data->nfs_mod->rpc_ops)
 			continue;
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index fed9c80..8f96f65 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -404,15 +404,19 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
 	if (error < 0)
 		goto error;
 
-	if (!nfs4_has_session(clp))
-		nfs_mark_client_ready(clp, NFS_CS_READY);
-
 	error = nfs4_discover_server_trunking(clp, &old);
 	if (error < 0)
 		goto error;
 
-	if (clp != old)
+	if (clp != old) {
 		clp->cl_preserve_clid = true;
+		/*
+		 * Mark the client as having failed initialization so other
+		 * processes walking the nfs_client_list in nfs_match_client()
+		 * won't try to use it.
+		 */
+		nfs_mark_client_ready(clp, -EPERM);
+	}
 	nfs_put_client(clp);
 	clear_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags);
 	return old;
@@ -539,6 +543,9 @@ int nfs40_walk_client_list(struct nfs_client *new,
 	spin_lock(&nn->nfs_client_lock);
 	list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
 
+		if (pos == new)
+			goto found;
+
 		status = nfs4_match_client(pos, new, &prev, nn);
 		if (status < 0)
 			goto out_unlock;
@@ -559,6 +566,7 @@ int nfs40_walk_client_list(struct nfs_client *new,
 		 * way that a SETCLIENTID_CONFIRM to pos can succeed is
 		 * if new and pos point to the same server:
 		 */
+found:
 		atomic_inc(&pos->cl_count);
 		spin_unlock(&nn->nfs_client_lock);
 
@@ -572,6 +580,7 @@ int nfs40_walk_client_list(struct nfs_client *new,
 		case 0:
 			nfs4_swap_callback_idents(pos, new);
 			pos->cl_confirm = new->cl_confirm;
+			nfs_mark_client_ready(pos, NFS_CS_READY);
 
 			prev = NULL;
 			*result = pos;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 38de09b..3c4aeb8 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2401,8 +2401,7 @@ static int nfs_compare_mount_options(const struct super_block *s, const struct n
 		goto Ebusy;
 	if (a->acdirmax != b->acdirmax)
 		goto Ebusy;
-	if (b->auth_info.flavor_len > 0 &&
-	   clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
+	if (clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
 		goto Ebusy;
 	return 1;
 Ebusy:
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 19e6ea8..2d956a7 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -618,11 +618,12 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
 	nfs_set_page_writeback(page);
 	WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
 
-	ret = 0;
+	ret = req->wb_context->error;
 	/* If there is a fatal error that covers this write, just exit */
-	if (nfs_error_is_fatal_on_server(req->wb_context->error))
+	if (nfs_error_is_fatal_on_server(ret))
 		goto out_launder;
 
+	ret = 0;
 	if (!nfs_pageio_add_request(pgio, req)) {
 		ret = pgio->pg_error;
 		/*
@@ -632,9 +633,9 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
 			nfs_context_set_write_error(req->wb_context, ret);
 			if (nfs_error_is_fatal_on_server(ret))
 				goto out_launder;
-		}
+		} else
+			ret = -EAGAIN;
 		nfs_redirty_request(req);
-		ret = -EAGAIN;
 	} else
 		nfs_add_stats(page_file_mapping(page)->host,
 				NFSIOS_WRITEPAGES, 1);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 3cef6bf..9412864 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1472,8 +1472,10 @@ free_session_slots(struct nfsd4_session *ses)
 {
 	int i;
 
-	for (i = 0; i < ses->se_fchannel.maxreqs; i++)
+	for (i = 0; i < ses->se_fchannel.maxreqs; i++) {
+		free_svc_cred(&ses->se_slots[i]->sl_cred);
 		kfree(ses->se_slots[i]);
+	}
 }
 
 /*
@@ -2331,14 +2333,18 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp)
 
 	dprintk("--> %s slot %p\n", __func__, slot);
 
+	slot->sl_flags |= NFSD4_SLOT_INITIALIZED;
 	slot->sl_opcnt = resp->opcnt;
 	slot->sl_status = resp->cstate.status;
+	free_svc_cred(&slot->sl_cred);
+	copy_cred(&slot->sl_cred, &resp->rqstp->rq_cred);
 
-	slot->sl_flags |= NFSD4_SLOT_INITIALIZED;
-	if (nfsd4_not_cached(resp)) {
-		slot->sl_datalen = 0;
+	if (!nfsd4_cache_this(resp)) {
+		slot->sl_flags &= ~NFSD4_SLOT_CACHED;
 		return;
 	}
+	slot->sl_flags |= NFSD4_SLOT_CACHED;
+
 	base = resp->cstate.data_offset;
 	slot->sl_datalen = buf->len - base;
 	if (read_bytes_from_xdr_buf(buf, base, slot->sl_data, slot->sl_datalen))
@@ -2365,8 +2371,16 @@ nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args,
 	op = &args->ops[resp->opcnt - 1];
 	nfsd4_encode_operation(resp, op);
 
-	/* Return nfserr_retry_uncached_rep in next operation. */
-	if (args->opcnt > 1 && !(slot->sl_flags & NFSD4_SLOT_CACHETHIS)) {
+	if (slot->sl_flags & NFSD4_SLOT_CACHED)
+		return op->status;
+	if (args->opcnt == 1) {
+		/*
+		 * The original operation wasn't a solo sequence--we
+		 * always cache those--so this retry must not match the
+		 * original:
+		 */
+		op->status = nfserr_seq_false_retry;
+	} else {
 		op = &args->ops[resp->opcnt++];
 		op->status = nfserr_retry_uncached_rep;
 		nfsd4_encode_operation(resp, op);
@@ -3030,6 +3044,34 @@ static bool nfsd4_request_too_big(struct svc_rqst *rqstp,
 	return xb->len > session->se_fchannel.maxreq_sz;
 }
 
+static bool replay_matches_cache(struct svc_rqst *rqstp,
+		 struct nfsd4_sequence *seq, struct nfsd4_slot *slot)
+{
+	struct nfsd4_compoundargs *argp = rqstp->rq_argp;
+
+	if ((bool)(slot->sl_flags & NFSD4_SLOT_CACHETHIS) !=
+	    (bool)seq->cachethis)
+		return false;
+	/*
+	 * If there's an error than the reply can have fewer ops than
+	 * the call.  But if we cached a reply with *more* ops than the
+	 * call you're sending us now, then this new call is clearly not
+	 * really a replay of the old one:
+	 */
+	if (slot->sl_opcnt < argp->opcnt)
+		return false;
+	/* This is the only check explicitly called by spec: */
+	if (!same_creds(&rqstp->rq_cred, &slot->sl_cred))
+		return false;
+	/*
+	 * There may be more comparisons we could actually do, but the
+	 * spec doesn't require us to catch every case where the calls
+	 * don't match (that would require caching the call as well as
+	 * the reply), so we don't bother.
+	 */
+	return true;
+}
+
 __be32
 nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		union nfsd4_op_u *u)
@@ -3089,6 +3131,9 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		status = nfserr_seq_misordered;
 		if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED))
 			goto out_put_session;
+		status = nfserr_seq_false_retry;
+		if (!replay_matches_cache(rqstp, seq, slot))
+			goto out_put_session;
 		cstate->slot = slot;
 		cstate->session = session;
 		cstate->clp = clp;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 6493df6..4b8ebcc 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1126,6 +1126,8 @@ static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size)
 		case 'Y':
 		case 'y':
 		case '1':
+			if (nn->nfsd_serv)
+				return -EBUSY;
 			nfsd4_end_grace(nn);
 			break;
 		default:
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 005c911..86aa92d 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -169,11 +169,13 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s)
 struct nfsd4_slot {
 	u32	sl_seqid;
 	__be32	sl_status;
+	struct svc_cred sl_cred;
 	u32	sl_datalen;
 	u16	sl_opcnt;
 #define NFSD4_SLOT_INUSE	(1 << 0)
 #define NFSD4_SLOT_CACHETHIS	(1 << 1)
 #define NFSD4_SLOT_INITIALIZED	(1 << 2)
+#define NFSD4_SLOT_CACHED	(1 << 3)
 	u8	sl_flags;
 	char	sl_data[];
 };
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index aa4375e..f47c392 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -651,9 +651,18 @@ static inline bool nfsd4_is_solo_sequence(struct nfsd4_compoundres *resp)
 	return resp->opcnt == 1 && args->ops[0].opnum == OP_SEQUENCE;
 }
 
-static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
+/*
+ * The session reply cache only needs to cache replies that the client
+ * actually asked us to.  But it's almost free for us to cache compounds
+ * consisting of only a SEQUENCE op, so we may as well cache those too.
+ * Also, the protocol doesn't give us a convenient response in the case
+ * of a replay of a solo SEQUENCE op that wasn't cached
+ * (RETRY_UNCACHED_REP can only be returned in the second op of a
+ * compound).
+ */
+static inline bool nfsd4_cache_this(struct nfsd4_compoundres *resp)
 {
-	return !(resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS)
+	return (resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS)
 		|| nfsd4_is_solo_sequence(resp);
 }
 
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 2bc61e7..506da82 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -158,9 +158,9 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask
 	parent = dget_parent(dentry);
 	p_inode = parent->d_inode;
 
-	if (unlikely(!fsnotify_inode_watches_children(p_inode)))
+	if (unlikely(!fsnotify_inode_watches_children(p_inode))) {
 		__fsnotify_update_child_dentry_flags(p_inode);
-	else if (p_inode->i_fsnotify_mask & mask) {
+	} else if (p_inode->i_fsnotify_mask & mask & ~FS_EVENT_ON_CHILD) {
 		struct name_snapshot name;
 
 		/* we are notifying a parent so come up with the new mask which
@@ -264,6 +264,10 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 	else
 		mnt = NULL;
 
+	/* An event "on child" is not intended for a mount mark */
+	if (mask & FS_EVENT_ON_CHILD)
+		mnt = NULL;
+
 	/*
 	 * Optimization: srcu_read_lock() has a memory barrier which can
 	 * be expensive.  It protects walking the *_fsnotify_marks lists.
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index 99ee093..cc9b32b 100644
--- a/fs/ocfs2/Makefile
+++ b/fs/ocfs2/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-ccflags-y := -Ifs/ocfs2
+ccflags-y := -I$(src)
 
 obj-$(CONFIG_OCFS2_FS) += 	\
 	ocfs2.o			\
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c
index 1d098c3..9f8250d 100644
--- a/fs/ocfs2/buffer_head_io.c
+++ b/fs/ocfs2/buffer_head_io.c
@@ -152,7 +152,6 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
 #endif
 		}
 
-		clear_buffer_uptodate(bh);
 		get_bh(bh); /* for end_buffer_read_sync() */
 		bh->b_end_io = end_buffer_read_sync;
 		submit_bh(REQ_OP_READ, 0, bh);
@@ -306,7 +305,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
 				continue;
 			}
 
-			clear_buffer_uptodate(bh);
 			get_bh(bh); /* for end_buffer_read_sync() */
 			if (validate)
 				set_buffer_needs_validate(bh);
diff --git a/fs/ocfs2/dlm/Makefile b/fs/ocfs2/dlm/Makefile
index bd1aab1f..ef28544 100644
--- a/fs/ocfs2/dlm/Makefile
+++ b/fs/ocfs2/dlm/Makefile
@@ -1,4 +1,4 @@
-ccflags-y := -Ifs/ocfs2
+ccflags-y := -I$(src)/..
 
 obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o
 
diff --git a/fs/ocfs2/dlmfs/Makefile b/fs/ocfs2/dlmfs/Makefile
index eed3db8c..33431a0 100644
--- a/fs/ocfs2/dlmfs/Makefile
+++ b/fs/ocfs2/dlmfs/Makefile
@@ -1,4 +1,4 @@
-ccflags-y := -Ifs/ocfs2
+ccflags-y := -I$(src)/..
 
 obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o
 
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index fe0d1f9..5d53d0d 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -345,13 +345,18 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
 	if (num_used
 	    || alloc->id1.bitmap1.i_used
 	    || alloc->id1.bitmap1.i_total
-	    || la->la_bm_off)
-		mlog(ML_ERROR, "Local alloc hasn't been recovered!\n"
+	    || la->la_bm_off) {
+		mlog(ML_ERROR, "inconsistent detected, clean journal with"
+		     " unrecovered local alloc, please run fsck.ocfs2!\n"
 		     "found = %u, set = %u, taken = %u, off = %u\n",
 		     num_used, le32_to_cpu(alloc->id1.bitmap1.i_used),
 		     le32_to_cpu(alloc->id1.bitmap1.i_total),
 		     OCFS2_LOCAL_ALLOC(alloc)->la_bm_off);
 
+		status = -EINVAL;
+		goto bail;
+	}
+
 	osb->local_alloc_bh = alloc_bh;
 	osb->local_alloc_state = OCFS2_LA_ENABLED;
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 498dc83..db3cf5c 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1067,10 +1067,6 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
 
 			task_lock(p);
 			if (!p->vfork_done && process_shares_mm(p, mm)) {
-				pr_info("updating oom_score_adj for %d (%s) from %d to %d because it shares mm with %d (%s). Report if this is unexpected.\n",
-						task_pid_nr(p), p->comm,
-						p->signal->oom_score_adj, oom_adj,
-						task_pid_nr(task), task->comm);
 				p->signal->oom_score_adj = oom_adj;
 				if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
 					p->signal->oom_score_adj_min = (short)oom_adj;
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 6bb20f8..d9d50d3 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -132,7 +132,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
 	show_val_kb(m, "Committed_AS:   ", committed);
 	seq_printf(m, "VmallocTotal:   %8lu kB\n",
 		   (unsigned long)VMALLOC_TOTAL >> 10);
-	show_val_kb(m, "VmallocUsed:    ", 0ul);
+	show_val_kb(m, "VmallocUsed:    ", vmalloc_nr_pages());
 	show_val_kb(m, "VmallocChunk:   ", 0ul);
 
 #ifdef CONFIG_MEMORY_FAILURE
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 3424d23..5001e93 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -518,7 +518,7 @@ struct mem_size_stats {
 };
 
 static void smaps_account(struct mem_size_stats *mss, struct page *page,
-		bool compound, bool young, bool dirty)
+		bool compound, bool young, bool dirty, bool locked)
 {
 	int i, nr = compound ? 1 << compound_order(page) : 1;
 	unsigned long size = nr * PAGE_SIZE;
@@ -545,24 +545,31 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,
 		else
 			mss->private_clean += size;
 		mss->pss += (u64)size << PSS_SHIFT;
+		if (locked)
+			mss->pss_locked += (u64)size << PSS_SHIFT;
 		return;
 	}
 
 	for (i = 0; i < nr; i++, page++) {
 		int mapcount = page_mapcount(page);
+		unsigned long pss = (PAGE_SIZE << PSS_SHIFT);
 
 		if (mapcount >= 2) {
 			if (dirty || PageDirty(page))
 				mss->shared_dirty += PAGE_SIZE;
 			else
 				mss->shared_clean += PAGE_SIZE;
-			mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount;
+			mss->pss += pss / mapcount;
+			if (locked)
+				mss->pss_locked += pss / mapcount;
 		} else {
 			if (dirty || PageDirty(page))
 				mss->private_dirty += PAGE_SIZE;
 			else
 				mss->private_clean += PAGE_SIZE;
-			mss->pss += PAGE_SIZE << PSS_SHIFT;
+			mss->pss += pss;
+			if (locked)
+				mss->pss_locked += pss;
 		}
 	}
 }
@@ -585,6 +592,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
 {
 	struct mem_size_stats *mss = walk->private;
 	struct vm_area_struct *vma = walk->vma;
+	bool locked = !!(vma->vm_flags & VM_LOCKED);
 	struct page *page = NULL;
 
 	if (pte_present(*pte)) {
@@ -627,7 +635,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
 	if (!page)
 		return;
 
-	smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte));
+	smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte), locked);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -636,6 +644,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
 {
 	struct mem_size_stats *mss = walk->private;
 	struct vm_area_struct *vma = walk->vma;
+	bool locked = !!(vma->vm_flags & VM_LOCKED);
 	struct page *page;
 
 	/* FOLL_DUMP will return -EFAULT on huge zero page */
@@ -650,7 +659,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
 		/* pass */;
 	else
 		VM_BUG_ON_PAGE(1, page);
-	smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd));
+	smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd), locked);
 }
 #else
 static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
@@ -851,11 +860,8 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
 		}
 	}
 #endif
-
 	/* mmap_sem is held in m_start */
 	walk_page_vma(vma, &smaps_walk);
-	if (vma->vm_flags & VM_LOCKED)
-		mss->pss_locked += mss->pss;
 
 	if (!rollup_mode) {
 		show_map_vma(m, vma, is_pid);
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 0b24e3c..0db2b69 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -717,18 +717,15 @@ static int ramoops_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct ramoops_platform_data *pdata = dev->platform_data;
+	struct ramoops_platform_data pdata_local;
 	struct ramoops_context *cxt = &oops_cxt;
 	size_t dump_mem_sz;
 	phys_addr_t paddr;
 	int err = -EINVAL;
 
 	if (dev_of_node(dev) && !pdata) {
-		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-		if (!pdata) {
-			pr_err("cannot allocate platform data buffer\n");
-			err = -ENOMEM;
-			goto fail_out;
-		}
+		pdata = &pdata_local;
+		memset(pdata, 0, sizeof(*pdata));
 
 		err = ramoops_parse_dt(pdev, pdata);
 		if (err < 0)
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index ecdb3ba..11e558ef 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -488,6 +488,11 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
 	sig ^= PERSISTENT_RAM_SIG;
 
 	if (prz->buffer->sig == sig) {
+		if (buffer_size(prz) == 0) {
+			pr_debug("found existing empty buffer\n");
+			return 0;
+		}
+
 		if (buffer_size(prz) > prz->buffer_size ||
 		    buffer_start(prz) > buffer_size(prz))
 			pr_info("found existing invalid buffer, size %zu, start %zu\n",
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 3f02bab0..a89c1f0 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -793,7 +793,8 @@ static int quotactl_cmd_write(int cmd)
 /* Return true if quotactl command is manipulating quota on/off state */
 static bool quotactl_cmd_onoff(int cmd)
 {
-	return (cmd == Q_QUOTAON) || (cmd == Q_QUOTAOFF);
+	return (cmd == Q_QUOTAON) || (cmd == Q_QUOTAOFF) ||
+		 (cmd == Q_XQUOTAON) || (cmd == Q_XQUOTAOFF);
 }
 
 /*
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 8dacf4f..28b9d7c 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1357,6 +1357,12 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
 
 	iinfo->i_alloc_type = le16_to_cpu(fe->icbTag.flags) &
 							ICBTAG_FLAG_AD_MASK;
+	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_SHORT &&
+	    iinfo->i_alloc_type != ICBTAG_FLAG_AD_LONG &&
+	    iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+		ret = -EIO;
+		goto out;
+	}
 	iinfo->i_unique = 0;
 	iinfo->i_lenEAttr = 0;
 	iinfo->i_lenExtents = 0;
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 77f205e..57c54e9 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -124,6 +124,7 @@
 # define DP_DPCD_DISPLAY_CONTROL_CAPABLE     (1 << 3) /* edp v1.2 or higher */
 
 #define DP_TRAINING_AUX_RD_INTERVAL         0x00e   /* XXX 1.2? */
+# define DP_TRAINING_AUX_RD_MASK            0x7F    /* XXX 1.2? */
 
 #define DP_ADAPTER_CAP			    0x00f   /* 1.2 */
 # define DP_FORCE_LOAD_SENSE_CAP	    (1 << 0)
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 7f78d26..a72efa0 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -634,4 +634,12 @@ int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
 int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
 				 struct drm_dp_mst_port *port, bool power_up);
 
+int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
+			   struct drm_dp_mst_port *port,
+			   int offset, int size, u8 *bytes);
+
+int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
+				 struct drm_dp_mst_port *port,
+				 int offset, int size, u8 *bytes);
+
 #endif
diff --git a/include/dt-bindings/clock/qcom,gcc-sm6150.h b/include/dt-bindings/clock/qcom,gcc-sm6150.h
index 57a79d3..77a7fe9 100644
--- a/include/dt-bindings/clock/qcom,gcc-sm6150.h
+++ b/include/dt-bindings/clock/qcom,gcc-sm6150.h
@@ -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
@@ -16,181 +16,183 @@
 
 /* Hardware and dummy clocks for rate measurement */
 #define GPLL0_OUT_AUX2				0
-#define MEASURE_ONLY_SNOC_CLK			1
-#define MEASURE_ONLY_CNOC_CLK			2
-#define MEASURE_ONLY_MMCC_CLK			3
-#define MEASURE_ONLY_IPA_2X_CLK			4
+#define GPLL6_OUT_MAIN				1
+#define GPLL8_OUT_MAIN				2
+#define MEASURE_ONLY_SNOC_CLK			3
+#define MEASURE_ONLY_CNOC_CLK			4
+#define MEASURE_ONLY_MMCC_CLK			5
+#define MEASURE_ONLY_IPA_2X_CLK			6
 
 /* GCC clock registers */
-#define GPLL0_OUT_MAIN				5
-#define GPLL6_OUT_MAIN				6
-#define GPLL7_OUT_MAIN				7
-#define GPLL8_OUT_MAIN				8
-#define GCC_AGGRE_UFS_PHY_AXI_CLK		9
-#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK	10
-#define GCC_AGGRE_USB2_SEC_AXI_CLK		11
-#define GCC_AGGRE_USB3_PRIM_AXI_CLK		12
-#define GCC_AHB2PHY_EAST_CLK			13
-#define GCC_AHB2PHY_WEST_CLK			14
-#define GCC_APC_VS_CLK				15
-#define GCC_BOOT_ROM_AHB_CLK			16
-#define GCC_CAMERA_AHB_CLK			17
-#define GCC_CAMERA_HF_AXI_CLK			18
-#define GCC_CE1_AHB_CLK				19
-#define GCC_CE1_AXI_CLK				20
-#define GCC_CE1_CLK				21
-#define GCC_CFG_NOC_USB2_SEC_AXI_CLK		22
-#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK		23
-#define GCC_CPUSS_AHB_CLK			24
-#define GCC_CPUSS_AHB_CLK_SRC			25
-#define GCC_DDRSS_GPU_AXI_CLK			26
-#define GCC_DISP_AHB_CLK			27
-#define GCC_DISP_GPLL0_DIV_CLK_SRC		28
-#define GCC_DISP_HF_AXI_CLK			29
-#define GCC_EMAC_AXI_CLK			30
-#define GCC_EMAC_PTP_CLK			31
-#define GCC_EMAC_PTP_CLK_SRC			32
-#define GCC_EMAC_RGMII_CLK			33
-#define GCC_EMAC_RGMII_CLK_SRC			34
-#define GCC_EMAC_SLV_AHB_CLK			35
-#define GCC_GP1_CLK				36
-#define GCC_GP1_CLK_SRC				37
-#define GCC_GP2_CLK				38
-#define GCC_GP2_CLK_SRC				39
-#define GCC_GP3_CLK				40
-#define GCC_GP3_CLK_SRC				41
-#define GCC_GPU_CFG_AHB_CLK			42
-#define GCC_GPU_GPLL0_CLK_SRC			43
-#define GCC_GPU_GPLL0_DIV_CLK_SRC		44
-#define GCC_GPU_IREF_CLK			45
-#define GCC_GPU_MEMNOC_GFX_CLK			46
-#define GCC_GPU_SNOC_DVM_GFX_CLK		47
-#define GCC_MSS_AXIS2_CLK			48
-#define GCC_MSS_CFG_AHB_CLK			49
-#define GCC_MSS_GPLL0_DIV_CLK_SRC		50
-#define GCC_MSS_MFAB_AXIS_CLK			51
-#define GCC_MSS_Q6_MEMNOC_AXI_CLK		52
-#define GCC_MSS_SNOC_AXI_CLK			53
-#define GCC_MSS_VS_CLK				54
-#define GCC_PCIE0_PHY_REFGEN_CLK		55
-#define GCC_PCIE_0_AUX_CLK			56
-#define GCC_PCIE_0_AUX_CLK_SRC			57
-#define GCC_PCIE_0_CFG_AHB_CLK			58
-#define GCC_PCIE_0_CLKREF_CLK			59
-#define GCC_PCIE_0_MSTR_AXI_CLK			60
-#define GCC_PCIE_0_PIPE_CLK			61
-#define GCC_PCIE_0_SLV_AXI_CLK			62
-#define GCC_PCIE_0_SLV_Q2A_AXI_CLK		63
-#define GCC_PCIE_PHY_AUX_CLK			64
-#define GCC_PCIE_PHY_REFGEN_CLK_SRC		65
-#define GCC_PDM2_CLK				66
-#define GCC_PDM2_CLK_SRC			67
-#define GCC_PDM_AHB_CLK				68
-#define GCC_PDM_XO4_CLK				69
-#define GCC_PRNG_AHB_CLK			70
-#define GCC_QMIP_CAMERA_NRT_AHB_CLK		71
-#define GCC_QMIP_DISP_AHB_CLK			72
-#define GCC_QMIP_PCIE_AHB_CLK			73
-#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK		74
-#define GCC_QSPI_CNOC_PERIPH_AHB_CLK		75
-#define GCC_QSPI_CORE_CLK			76
-#define GCC_QSPI_CORE_CLK_SRC			77
-#define GCC_QUPV3_WRAP0_CORE_2X_CLK		78
-#define GCC_QUPV3_WRAP0_CORE_CLK		79
-#define GCC_QUPV3_WRAP0_S0_CLK			80
-#define GCC_QUPV3_WRAP0_S0_CLK_SRC		81
-#define GCC_QUPV3_WRAP0_S1_CLK			82
-#define GCC_QUPV3_WRAP0_S1_CLK_SRC		83
-#define GCC_QUPV3_WRAP0_S2_CLK			84
-#define GCC_QUPV3_WRAP0_S2_CLK_SRC		85
-#define GCC_QUPV3_WRAP0_S3_CLK			86
-#define GCC_QUPV3_WRAP0_S3_CLK_SRC		87
-#define GCC_QUPV3_WRAP0_S4_CLK			88
-#define GCC_QUPV3_WRAP0_S4_CLK_SRC		89
-#define GCC_QUPV3_WRAP0_S5_CLK			90
-#define GCC_QUPV3_WRAP0_S5_CLK_SRC		91
-#define GCC_QUPV3_WRAP1_CORE_2X_CLK		92
-#define GCC_QUPV3_WRAP1_CORE_CLK		93
-#define GCC_QUPV3_WRAP1_S0_CLK			94
-#define GCC_QUPV3_WRAP1_S0_CLK_SRC		95
-#define GCC_QUPV3_WRAP1_S1_CLK			96
-#define GCC_QUPV3_WRAP1_S1_CLK_SRC		97
-#define GCC_QUPV3_WRAP1_S2_CLK			98
-#define GCC_QUPV3_WRAP1_S2_CLK_SRC		99
-#define GCC_QUPV3_WRAP1_S3_CLK			100
-#define GCC_QUPV3_WRAP1_S3_CLK_SRC		101
-#define GCC_QUPV3_WRAP1_S4_CLK			102
-#define GCC_QUPV3_WRAP1_S4_CLK_SRC		103
-#define GCC_QUPV3_WRAP1_S5_CLK			104
-#define GCC_QUPV3_WRAP1_S5_CLK_SRC		105
-#define GCC_QUPV3_WRAP_0_M_AHB_CLK		106
-#define GCC_QUPV3_WRAP_0_S_AHB_CLK		107
-#define GCC_QUPV3_WRAP_1_M_AHB_CLK		108
-#define GCC_QUPV3_WRAP_1_S_AHB_CLK		109
-#define GCC_SDCC1_AHB_CLK			110
-#define GCC_SDCC1_APPS_CLK			111
-#define GCC_SDCC1_APPS_CLK_SRC			112
-#define GCC_SDCC1_ICE_CORE_CLK			113
-#define GCC_SDCC1_ICE_CORE_CLK_SRC		114
-#define GCC_SDCC2_AHB_CLK			115
-#define GCC_SDCC2_APPS_CLK			116
-#define GCC_SDCC2_APPS_CLK_SRC			117
-#define GCC_SYS_NOC_CPUSS_AHB_CLK		118
-#define GCC_UFS_CARD_CLKREF_CLK			119
-#define GCC_UFS_MEM_CLKREF_CLK			120
-#define GCC_UFS_PHY_AHB_CLK			121
-#define GCC_UFS_PHY_AXI_CLK			122
-#define GCC_UFS_PHY_AXI_CLK_SRC			123
-#define GCC_UFS_PHY_AXI_HW_CTL_CLK		124
-#define GCC_UFS_PHY_ICE_CORE_CLK		125
-#define GCC_UFS_PHY_ICE_CORE_CLK_SRC		126
-#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK		127
-#define GCC_UFS_PHY_PHY_AUX_CLK			128
-#define GCC_UFS_PHY_PHY_AUX_CLK_SRC		129
-#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK		130
-#define GCC_UFS_PHY_RX_SYMBOL_0_CLK		131
-#define GCC_UFS_PHY_TX_SYMBOL_0_CLK		132
-#define GCC_UFS_PHY_UNIPRO_CORE_CLK		133
-#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC		134
-#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK	135
-#define GCC_USB20_SEC_MASTER_CLK		136
-#define GCC_USB20_SEC_MASTER_CLK_SRC		137
-#define GCC_USB20_SEC_MOCK_UTMI_CLK		138
-#define GCC_USB20_SEC_MOCK_UTMI_CLK_SRC		139
-#define GCC_USB20_SEC_SLEEP_CLK			140
-#define GCC_USB2_SEC_PHY_AUX_CLK		141
-#define GCC_USB2_SEC_PHY_AUX_CLK_SRC		142
-#define GCC_USB2_SEC_PHY_COM_AUX_CLK		143
-#define GCC_USB2_SEC_PHY_PIPE_CLK		144
-#define GCC_USB30_PRIM_MASTER_CLK		145
-#define GCC_USB30_PRIM_MASTER_CLK_SRC		146
-#define GCC_USB30_PRIM_MOCK_UTMI_CLK		147
-#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC	148
-#define GCC_USB30_PRIM_SLEEP_CLK		149
-#define GCC_USB3_PRIM_CLKREF_CLK		150
-#define GCC_USB3_PRIM_PHY_AUX_CLK		151
-#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC		152
-#define GCC_USB3_PRIM_PHY_COM_AUX_CLK		153
-#define GCC_USB3_PRIM_PHY_PIPE_CLK		154
-#define GCC_USB3_SEC_CLKREF_CLK			155
-#define GCC_VDDA_VS_CLK				156
-#define GCC_VDDCX_VS_CLK			157
-#define GCC_VDDMX_VS_CLK			158
-#define GCC_VIDEO_AHB_CLK			159
-#define GCC_VIDEO_AXI0_CLK			160
-#define GCC_VS_CTRL_AHB_CLK			161
-#define GCC_VS_CTRL_CLK				162
-#define GCC_VS_CTRL_CLK_SRC			163
-#define GCC_VSENSOR_CLK_SRC			164
-#define GCC_WCSS_VS_CLK				165
-#define GCC_CAMERA_XO_CLK			166
-#define GCC_CPUSS_GNOC_CLK			167
-#define GCC_DISP_XO_CLK				168
-#define GCC_VIDEO_XO_CLK			169
-#define GCC_RX1_USB2_CLKREF_CLK			170
-#define GCC_USB2_PRIM_CLKREF_CLK		171
-#define GCC_USB2_SEC_CLKREF_CLK			172
-#define GCC_RX3_USB2_CLKREF_CLK			173
+#define GPLL0_OUT_MAIN				7
+#define GPLL6_OUT_EARLY				8
+#define GPLL7_OUT_MAIN				9
+#define GPLL8_OUT_EARLY				10
+#define GCC_AGGRE_UFS_PHY_AXI_CLK		11
+#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK	12
+#define GCC_AGGRE_USB2_SEC_AXI_CLK		13
+#define GCC_AGGRE_USB3_PRIM_AXI_CLK		14
+#define GCC_AHB2PHY_EAST_CLK			15
+#define GCC_AHB2PHY_WEST_CLK			16
+#define GCC_APC_VS_CLK				17
+#define GCC_BOOT_ROM_AHB_CLK			18
+#define GCC_CAMERA_AHB_CLK			19
+#define GCC_CAMERA_HF_AXI_CLK			20
+#define GCC_CE1_AHB_CLK				21
+#define GCC_CE1_AXI_CLK				22
+#define GCC_CE1_CLK				23
+#define GCC_CFG_NOC_USB2_SEC_AXI_CLK		24
+#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK		25
+#define GCC_CPUSS_AHB_CLK			26
+#define GCC_CPUSS_AHB_CLK_SRC			27
+#define GCC_DDRSS_GPU_AXI_CLK			28
+#define GCC_DISP_AHB_CLK			29
+#define GCC_DISP_GPLL0_DIV_CLK_SRC		30
+#define GCC_DISP_HF_AXI_CLK			31
+#define GCC_EMAC_AXI_CLK			32
+#define GCC_EMAC_PTP_CLK			33
+#define GCC_EMAC_PTP_CLK_SRC			34
+#define GCC_EMAC_RGMII_CLK			35
+#define GCC_EMAC_RGMII_CLK_SRC			36
+#define GCC_EMAC_SLV_AHB_CLK			37
+#define GCC_GP1_CLK				38
+#define GCC_GP1_CLK_SRC				39
+#define GCC_GP2_CLK				40
+#define GCC_GP2_CLK_SRC				41
+#define GCC_GP3_CLK				42
+#define GCC_GP3_CLK_SRC				43
+#define GCC_GPU_CFG_AHB_CLK			44
+#define GCC_GPU_GPLL0_CLK_SRC			45
+#define GCC_GPU_GPLL0_DIV_CLK_SRC		46
+#define GCC_GPU_IREF_CLK			47
+#define GCC_GPU_MEMNOC_GFX_CLK			48
+#define GCC_GPU_SNOC_DVM_GFX_CLK		49
+#define GCC_MSS_AXIS2_CLK			50
+#define GCC_MSS_CFG_AHB_CLK			51
+#define GCC_MSS_GPLL0_DIV_CLK_SRC		52
+#define GCC_MSS_MFAB_AXIS_CLK			53
+#define GCC_MSS_Q6_MEMNOC_AXI_CLK		54
+#define GCC_MSS_SNOC_AXI_CLK			55
+#define GCC_MSS_VS_CLK				56
+#define GCC_PCIE0_PHY_REFGEN_CLK		57
+#define GCC_PCIE_0_AUX_CLK			58
+#define GCC_PCIE_0_AUX_CLK_SRC			59
+#define GCC_PCIE_0_CFG_AHB_CLK			60
+#define GCC_PCIE_0_CLKREF_CLK			61
+#define GCC_PCIE_0_MSTR_AXI_CLK			62
+#define GCC_PCIE_0_PIPE_CLK			63
+#define GCC_PCIE_0_SLV_AXI_CLK			64
+#define GCC_PCIE_0_SLV_Q2A_AXI_CLK		65
+#define GCC_PCIE_PHY_AUX_CLK			66
+#define GCC_PCIE_PHY_REFGEN_CLK_SRC		67
+#define GCC_PDM2_CLK				68
+#define GCC_PDM2_CLK_SRC			69
+#define GCC_PDM_AHB_CLK				70
+#define GCC_PDM_XO4_CLK				71
+#define GCC_PRNG_AHB_CLK			72
+#define GCC_QMIP_CAMERA_NRT_AHB_CLK		73
+#define GCC_QMIP_DISP_AHB_CLK			74
+#define GCC_QMIP_PCIE_AHB_CLK			75
+#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK		76
+#define GCC_QSPI_CNOC_PERIPH_AHB_CLK		77
+#define GCC_QSPI_CORE_CLK			78
+#define GCC_QSPI_CORE_CLK_SRC			79
+#define GCC_QUPV3_WRAP0_CORE_2X_CLK		80
+#define GCC_QUPV3_WRAP0_CORE_CLK		81
+#define GCC_QUPV3_WRAP0_S0_CLK			82
+#define GCC_QUPV3_WRAP0_S0_CLK_SRC		83
+#define GCC_QUPV3_WRAP0_S1_CLK			84
+#define GCC_QUPV3_WRAP0_S1_CLK_SRC		85
+#define GCC_QUPV3_WRAP0_S2_CLK			86
+#define GCC_QUPV3_WRAP0_S2_CLK_SRC		87
+#define GCC_QUPV3_WRAP0_S3_CLK			88
+#define GCC_QUPV3_WRAP0_S3_CLK_SRC		89
+#define GCC_QUPV3_WRAP0_S4_CLK			90
+#define GCC_QUPV3_WRAP0_S4_CLK_SRC		91
+#define GCC_QUPV3_WRAP0_S5_CLK			92
+#define GCC_QUPV3_WRAP0_S5_CLK_SRC		93
+#define GCC_QUPV3_WRAP1_CORE_2X_CLK		94
+#define GCC_QUPV3_WRAP1_CORE_CLK		95
+#define GCC_QUPV3_WRAP1_S0_CLK			96
+#define GCC_QUPV3_WRAP1_S0_CLK_SRC		97
+#define GCC_QUPV3_WRAP1_S1_CLK			98
+#define GCC_QUPV3_WRAP1_S1_CLK_SRC		99
+#define GCC_QUPV3_WRAP1_S2_CLK			100
+#define GCC_QUPV3_WRAP1_S2_CLK_SRC		101
+#define GCC_QUPV3_WRAP1_S3_CLK			102
+#define GCC_QUPV3_WRAP1_S3_CLK_SRC		103
+#define GCC_QUPV3_WRAP1_S4_CLK			104
+#define GCC_QUPV3_WRAP1_S4_CLK_SRC		105
+#define GCC_QUPV3_WRAP1_S5_CLK			106
+#define GCC_QUPV3_WRAP1_S5_CLK_SRC		107
+#define GCC_QUPV3_WRAP_0_M_AHB_CLK		108
+#define GCC_QUPV3_WRAP_0_S_AHB_CLK		109
+#define GCC_QUPV3_WRAP_1_M_AHB_CLK		110
+#define GCC_QUPV3_WRAP_1_S_AHB_CLK		111
+#define GCC_SDCC1_AHB_CLK			112
+#define GCC_SDCC1_APPS_CLK			113
+#define GCC_SDCC1_APPS_CLK_SRC			114
+#define GCC_SDCC1_ICE_CORE_CLK			115
+#define GCC_SDCC1_ICE_CORE_CLK_SRC		116
+#define GCC_SDCC2_AHB_CLK			117
+#define GCC_SDCC2_APPS_CLK			118
+#define GCC_SDCC2_APPS_CLK_SRC			119
+#define GCC_SYS_NOC_CPUSS_AHB_CLK		120
+#define GCC_UFS_CARD_CLKREF_CLK			121
+#define GCC_UFS_MEM_CLKREF_CLK			122
+#define GCC_UFS_PHY_AHB_CLK			123
+#define GCC_UFS_PHY_AXI_CLK			124
+#define GCC_UFS_PHY_AXI_CLK_SRC			125
+#define GCC_UFS_PHY_AXI_HW_CTL_CLK		126
+#define GCC_UFS_PHY_ICE_CORE_CLK		127
+#define GCC_UFS_PHY_ICE_CORE_CLK_SRC		128
+#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK		129
+#define GCC_UFS_PHY_PHY_AUX_CLK			130
+#define GCC_UFS_PHY_PHY_AUX_CLK_SRC		131
+#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK		132
+#define GCC_UFS_PHY_RX_SYMBOL_0_CLK		133
+#define GCC_UFS_PHY_TX_SYMBOL_0_CLK		134
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK		135
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC		136
+#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK	137
+#define GCC_USB20_SEC_MASTER_CLK		138
+#define GCC_USB20_SEC_MASTER_CLK_SRC		139
+#define GCC_USB20_SEC_MOCK_UTMI_CLK		140
+#define GCC_USB20_SEC_MOCK_UTMI_CLK_SRC		141
+#define GCC_USB20_SEC_SLEEP_CLK			142
+#define GCC_USB2_SEC_PHY_AUX_CLK		143
+#define GCC_USB2_SEC_PHY_AUX_CLK_SRC		144
+#define GCC_USB2_SEC_PHY_COM_AUX_CLK		145
+#define GCC_USB2_SEC_PHY_PIPE_CLK		146
+#define GCC_USB30_PRIM_MASTER_CLK		147
+#define GCC_USB30_PRIM_MASTER_CLK_SRC		148
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK		149
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC	150
+#define GCC_USB30_PRIM_SLEEP_CLK		151
+#define GCC_USB3_PRIM_CLKREF_CLK		152
+#define GCC_USB3_PRIM_PHY_AUX_CLK		153
+#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC		154
+#define GCC_USB3_PRIM_PHY_COM_AUX_CLK		155
+#define GCC_USB3_PRIM_PHY_PIPE_CLK		156
+#define GCC_USB3_SEC_CLKREF_CLK			157
+#define GCC_VDDA_VS_CLK				158
+#define GCC_VDDCX_VS_CLK			159
+#define GCC_VDDMX_VS_CLK			160
+#define GCC_VIDEO_AHB_CLK			161
+#define GCC_VIDEO_AXI0_CLK			162
+#define GCC_VS_CTRL_AHB_CLK			163
+#define GCC_VS_CTRL_CLK				164
+#define GCC_VS_CTRL_CLK_SRC			165
+#define GCC_VSENSOR_CLK_SRC			166
+#define GCC_WCSS_VS_CLK				167
+#define GCC_CAMERA_XO_CLK			168
+#define GCC_CPUSS_GNOC_CLK			169
+#define GCC_DISP_XO_CLK				170
+#define GCC_VIDEO_XO_CLK			171
+#define GCC_RX1_USB2_CLKREF_CLK			172
+#define GCC_USB2_PRIM_CLKREF_CLK		173
+#define GCC_USB2_SEC_CLKREF_CLK			174
+#define GCC_RX3_USB2_CLKREF_CLK			175
 
 /* GCC Resets */
 #define GCC_QUSB2PHY_PRIM_BCR			0
diff --git a/include/dt-bindings/clock/qcom,gcc-trinket.h b/include/dt-bindings/clock/qcom,gcc-trinket.h
index 2b16468..8e5f948 100644
--- a/include/dt-bindings/clock/qcom,gcc-trinket.h
+++ b/include/dt-bindings/clock/qcom,gcc-trinket.h
@@ -17,219 +17,218 @@
 #define GPLL0_OUT_AUX2				0
 #define GPLL0_OUT_MAIN				1
 #define GPLL6_OUT_MAIN				2
-#define GPLL8_OUT_MAIN				3
-#define GPLL9_OUT_MAIN				4
-#define MEASURE_ONLY_MMCC_CLK			5
-#define MEASURE_ONLY_IPA_2X_CLK			6
-#define GPLL0_OUT_EARLY				7
-#define GPLL3_OUT_EARLY				8
-#define GPLL4_OUT_MAIN				9
-#define GPLL5_OUT_MAIN				10
-#define GPLL6_OUT_EARLY				11
-#define GPLL7_OUT_MAIN				12
-#define GPLL8_OUT_EARLY				13
-#define GPLL9_OUT_EARLY				14
-#define GCC_AHB2PHY_CSI_CLK			15
-#define GCC_AHB2PHY_USB_CLK			16
-#define GCC_APC_VS_CLK				17
-#define GCC_BOOT_ROM_AHB_CLK			18
-#define GCC_CAMERA_AHB_CLK			19
-#define GCC_CAMERA_XO_CLK			20
-#define GCC_CAMSS_AHB_CLK_SRC			21
-#define GCC_CAMSS_CCI_AHB_CLK			22
-#define GCC_CAMSS_CCI_CLK			23
-#define GCC_CAMSS_CCI_CLK_SRC			24
-#define GCC_CAMSS_CPHY_CSID0_CLK		25
-#define GCC_CAMSS_CPHY_CSID1_CLK		26
-#define GCC_CAMSS_CPHY_CSID2_CLK		27
-#define GCC_CAMSS_CPHY_CSID3_CLK		28
-#define GCC_CAMSS_CPP_AHB_CLK			29
-#define GCC_CAMSS_CPP_AXI_CLK			30
-#define GCC_CAMSS_CPP_CLK			31
-#define GCC_CAMSS_CPP_CLK_SRC			32
-#define GCC_CAMSS_CPP_VBIF_AHB_CLK		33
-#define GCC_CAMSS_CSI0_AHB_CLK			34
-#define GCC_CAMSS_CSI0_CLK			35
-#define GCC_CAMSS_CSI0_CLK_SRC			36
-#define GCC_CAMSS_CSI0PHYTIMER_CLK		37
-#define GCC_CAMSS_CSI0PHYTIMER_CLK_SRC		38
-#define GCC_CAMSS_CSI0PIX_CLK			39
-#define GCC_CAMSS_CSI0RDI_CLK			40
-#define GCC_CAMSS_CSI1_AHB_CLK			41
-#define GCC_CAMSS_CSI1_CLK			42
-#define GCC_CAMSS_CSI1_CLK_SRC			43
-#define GCC_CAMSS_CSI1PHYTIMER_CLK		44
-#define GCC_CAMSS_CSI1PHYTIMER_CLK_SRC		45
-#define GCC_CAMSS_CSI1PIX_CLK			46
-#define GCC_CAMSS_CSI1RDI_CLK			47
-#define GCC_CAMSS_CSI2_AHB_CLK			48
-#define GCC_CAMSS_CSI2_CLK			49
-#define GCC_CAMSS_CSI2_CLK_SRC			50
-#define GCC_CAMSS_CSI2PHYTIMER_CLK		51
-#define GCC_CAMSS_CSI2PHYTIMER_CLK_SRC		52
-#define GCC_CAMSS_CSI2PIX_CLK			53
-#define GCC_CAMSS_CSI2RDI_CLK			54
-#define GCC_CAMSS_CSI3_AHB_CLK			55
-#define GCC_CAMSS_CSI3_CLK			56
-#define GCC_CAMSS_CSI3_CLK_SRC			57
-#define GCC_CAMSS_CSI3PIX_CLK			58
-#define GCC_CAMSS_CSI3RDI_CLK			59
-#define GCC_CAMSS_CSI_VFE0_CLK			60
-#define GCC_CAMSS_CSI_VFE1_CLK			61
-#define GCC_CAMSS_CSIPHY0_CLK			62
-#define GCC_CAMSS_CSIPHY1_CLK			63
-#define GCC_CAMSS_CSIPHY2_CLK			64
-#define GCC_CAMSS_CSIPHY3_CLK			65
-#define GCC_CAMSS_CSIPHY_CLK_SRC		66
-#define GCC_CAMSS_GP0_CLK			67
-#define GCC_CAMSS_GP0_CLK_SRC			68
-#define GCC_CAMSS_GP1_CLK			69
-#define GCC_CAMSS_GP1_CLK_SRC			70
-#define GCC_CAMSS_ISPIF_AHB_CLK			71
-#define GCC_CAMSS_JPEG_AHB_CLK			72
-#define GCC_CAMSS_JPEG_AXI_CLK			73
-#define GCC_CAMSS_JPEG_CLK			74
-#define GCC_CAMSS_JPEG_CLK_SRC			75
-#define GCC_CAMSS_MCLK0_CLK			76
-#define GCC_CAMSS_MCLK0_CLK_SRC			77
-#define GCC_CAMSS_MCLK1_CLK			78
-#define GCC_CAMSS_MCLK1_CLK_SRC			79
-#define GCC_CAMSS_MCLK2_CLK			80
-#define GCC_CAMSS_MCLK2_CLK_SRC			81
-#define GCC_CAMSS_MCLK3_CLK			82
-#define GCC_CAMSS_MCLK3_CLK_SRC			83
-#define GCC_CAMSS_MICRO_AHB_CLK			84
-#define GCC_CAMSS_THROTTLE_NRT_AXI_CLK		85
-#define GCC_CAMSS_THROTTLE_RT_AXI_CLK		86
-#define GCC_CAMSS_TOP_AHB_CLK			87
-#define GCC_CAMSS_VFE0_AHB_CLK			88
-#define GCC_CAMSS_VFE0_CLK			89
-#define GCC_CAMSS_VFE0_CLK_SRC			90
-#define GCC_CAMSS_VFE0_STREAM_CLK		91
-#define GCC_CAMSS_VFE1_AHB_CLK			92
-#define GCC_CAMSS_VFE1_CLK			93
-#define GCC_CAMSS_VFE1_CLK_SRC			94
-#define GCC_CAMSS_VFE1_STREAM_CLK		95
-#define GCC_CAMSS_VFE_TSCTR_CLK			96
-#define GCC_CAMSS_VFE_VBIF_AHB_CLK		97
-#define GCC_CAMSS_VFE_VBIF_AXI_CLK		98
-#define GCC_CE1_AHB_CLK				99
-#define GCC_CE1_AXI_CLK				100
-#define GCC_CE1_CLK				101
-#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK		102
-#define GCC_CPUSS_AHB_CLK			103
-#define GCC_CPUSS_AHB_CLK_SRC			104
-#define GCC_CPUSS_GNOC_CLK			105
-#define GCC_CPUSS_THROTTLE_CORE_CLK		106
-#define GCC_CPUSS_THROTTLE_XO_CLK		107
-#define GCC_DISP_AHB_CLK			108
-#define GCC_DISP_GPLL0_DIV_CLK_SRC		109
-#define GCC_DISP_HF_AXI_CLK			110
-#define GCC_DISP_THROTTLE_CORE_CLK		111
-#define GCC_DISP_XO_CLK				112
-#define GCC_GP1_CLK				113
-#define GCC_GP1_CLK_SRC				114
-#define GCC_GP2_CLK				115
-#define GCC_GP2_CLK_SRC				116
-#define GCC_GP3_CLK				117
-#define GCC_GP3_CLK_SRC				118
-#define GCC_GPU_CFG_AHB_CLK			119
-#define GCC_GPU_GPLL0_CLK_SRC			120
-#define GCC_GPU_GPLL0_DIV_CLK_SRC		121
-#define GCC_GPU_MEMNOC_GFX_CLK			122
-#define GCC_GPU_SNOC_DVM_GFX_CLK		123
-#define GCC_GPU_THROTTLE_CORE_CLK		124
-#define GCC_GPU_THROTTLE_XO_CLK			125
-#define GCC_MSS_VS_CLK				126
-#define GCC_PDM2_CLK				127
-#define GCC_PDM2_CLK_SRC			128
-#define GCC_PDM_AHB_CLK				129
-#define GCC_PDM_XO4_CLK				130
-#define GCC_PRNG_AHB_CLK			131
-#define GCC_QMIP_CAMERA_NRT_AHB_CLK		132
-#define GCC_QMIP_CAMERA_RT_AHB_CLK		133
-#define GCC_QMIP_CPUSS_CFG_AHB_CLK		134
-#define GCC_QMIP_DISP_AHB_CLK			135
-#define GCC_QMIP_GPU_CFG_AHB_CLK		136
-#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK		137
-#define GCC_QUPV3_WRAP0_CORE_2X_CLK		138
-#define GCC_QUPV3_WRAP0_CORE_CLK		139
-#define GCC_QUPV3_WRAP0_S0_CLK			140
-#define GCC_QUPV3_WRAP0_S0_CLK_SRC		141
-#define GCC_QUPV3_WRAP0_S1_CLK			142
-#define GCC_QUPV3_WRAP0_S1_CLK_SRC		143
-#define GCC_QUPV3_WRAP0_S2_CLK			144
-#define GCC_QUPV3_WRAP0_S2_CLK_SRC		145
-#define GCC_QUPV3_WRAP0_S3_CLK			146
-#define GCC_QUPV3_WRAP0_S3_CLK_SRC		147
-#define GCC_QUPV3_WRAP0_S4_CLK			148
-#define GCC_QUPV3_WRAP0_S4_CLK_SRC		149
-#define GCC_QUPV3_WRAP0_S5_CLK			150
-#define GCC_QUPV3_WRAP0_S5_CLK_SRC		151
-#define GCC_QUPV3_WRAP1_CORE_2X_CLK		152
-#define GCC_QUPV3_WRAP1_CORE_CLK		153
-#define GCC_QUPV3_WRAP1_S0_CLK			154
-#define GCC_QUPV3_WRAP1_S0_CLK_SRC		155
-#define GCC_QUPV3_WRAP1_S1_CLK			156
-#define GCC_QUPV3_WRAP1_S1_CLK_SRC		157
-#define GCC_QUPV3_WRAP1_S2_CLK			158
-#define GCC_QUPV3_WRAP1_S2_CLK_SRC		159
-#define GCC_QUPV3_WRAP1_S3_CLK			160
-#define GCC_QUPV3_WRAP1_S3_CLK_SRC		161
-#define GCC_QUPV3_WRAP1_S4_CLK			162
-#define GCC_QUPV3_WRAP1_S4_CLK_SRC		163
-#define GCC_QUPV3_WRAP1_S5_CLK			164
-#define GCC_QUPV3_WRAP1_S5_CLK_SRC		165
-#define GCC_QUPV3_WRAP_0_M_AHB_CLK		166
-#define GCC_QUPV3_WRAP_0_S_AHB_CLK		167
-#define GCC_QUPV3_WRAP_1_M_AHB_CLK		168
-#define GCC_QUPV3_WRAP_1_S_AHB_CLK		169
-#define GCC_SDCC1_AHB_CLK			170
-#define GCC_SDCC1_APPS_CLK			171
-#define GCC_SDCC1_APPS_CLK_SRC			172
-#define GCC_SDCC1_ICE_CORE_CLK			173
-#define GCC_SDCC1_ICE_CORE_CLK_SRC		174
-#define GCC_SDCC2_AHB_CLK			175
-#define GCC_SDCC2_APPS_CLK			176
-#define GCC_SDCC2_APPS_CLK_SRC			177
-#define GCC_SYS_NOC_CPUSS_AHB_CLK		178
-#define GCC_SYS_NOC_UFS_PHY_AXI_CLK		179
-#define GCC_SYS_NOC_USB3_PRIM_AXI_CLK		180
-#define GCC_UFS_PHY_AHB_CLK			181
-#define GCC_UFS_PHY_AXI_CLK			182
-#define GCC_UFS_PHY_AXI_CLK_SRC			183
-#define GCC_UFS_PHY_ICE_CORE_CLK		184
-#define GCC_UFS_PHY_ICE_CORE_CLK_SRC		185
-#define GCC_UFS_PHY_PHY_AUX_CLK			186
-#define GCC_UFS_PHY_PHY_AUX_CLK_SRC		187
-#define GCC_UFS_PHY_RX_SYMBOL_0_CLK		188
-#define GCC_UFS_PHY_TX_SYMBOL_0_CLK		189
-#define GCC_UFS_PHY_UNIPRO_CORE_CLK		190
-#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC		191
-#define GCC_USB30_PRIM_MASTER_CLK		192
-#define GCC_USB30_PRIM_MASTER_CLK_SRC		193
-#define GCC_USB30_PRIM_MOCK_UTMI_CLK		194
-#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC	195
-#define GCC_USB30_PRIM_SLEEP_CLK		196
-#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC		197
-#define GCC_USB3_PRIM_PHY_COM_AUX_CLK		198
-#define GCC_USB3_PRIM_PHY_PIPE_CLK		199
-#define GCC_VDDA_VS_CLK				200
-#define GCC_VDDCX_VS_CLK			201
-#define GCC_VDDMX_VS_CLK			202
-#define GCC_VIDEO_AHB_CLK			203
-#define GCC_VIDEO_AXI0_CLK			204
-#define GCC_VIDEO_THROTTLE_CORE_CLK		205
-#define GCC_VIDEO_XO_CLK			206
-#define GCC_VS_CTRL_AHB_CLK			207
-#define GCC_VS_CTRL_CLK				208
-#define GCC_VS_CTRL_CLK_SRC			209
-#define GCC_VSENSOR_CLK_SRC			210
-#define GCC_WCSS_VS_CLK				211
-#define GCC_USB3_PRIM_CLKREF_CLK		212
-#define GCC_SYS_NOC_COMPUTE_SF_AXI_CLK		213
-#define GCC_BIMC_GPU_AXI_CLK			214
-#define GCC_UFS_MEM_CLKREF_CLK			215
+#define GPLL7_OUT_MAIN				3
+#define GPLL8_OUT_MAIN				4
+#define GPLL9_OUT_MAIN				5
+#define MEASURE_ONLY_MMCC_CLK			6
+#define MEASURE_ONLY_IPA_2X_CLK			7
+#define GPLL0_OUT_EARLY				8
+#define GPLL3_OUT_EARLY				9
+#define GPLL4_OUT_MAIN				10
+#define GPLL5_OUT_MAIN				11
+#define GPLL6_OUT_EARLY				12
+#define GPLL7_OUT_EARLY				13
+#define GPLL8_OUT_EARLY				14
+#define GPLL9_OUT_EARLY				15
+#define GCC_AHB2PHY_CSI_CLK			16
+#define GCC_AHB2PHY_USB_CLK			17
+#define GCC_APC_VS_CLK				18
+#define GCC_BOOT_ROM_AHB_CLK			19
+#define GCC_CAMERA_AHB_CLK			20
+#define GCC_CAMERA_XO_CLK			21
+#define GCC_CAMSS_AHB_CLK_SRC			22
+#define GCC_CAMSS_CCI_AHB_CLK			23
+#define GCC_CAMSS_CCI_CLK			24
+#define GCC_CAMSS_CCI_CLK_SRC			25
+#define GCC_CAMSS_CPHY_CSID0_CLK		26
+#define GCC_CAMSS_CPHY_CSID1_CLK		27
+#define GCC_CAMSS_CPHY_CSID2_CLK		28
+#define GCC_CAMSS_CPHY_CSID3_CLK		29
+#define GCC_CAMSS_CPP_AHB_CLK			30
+#define GCC_CAMSS_CPP_AXI_CLK			31
+#define GCC_CAMSS_CPP_CLK			32
+#define GCC_CAMSS_CPP_CLK_SRC			33
+#define GCC_CAMSS_CPP_VBIF_AHB_CLK		34
+#define GCC_CAMSS_CSI0_AHB_CLK			35
+#define GCC_CAMSS_CSI0_CLK			36
+#define GCC_CAMSS_CSI0_CLK_SRC			37
+#define GCC_CAMSS_CSI0PHYTIMER_CLK		38
+#define GCC_CAMSS_CSI0PHYTIMER_CLK_SRC		39
+#define GCC_CAMSS_CSI0PIX_CLK			40
+#define GCC_CAMSS_CSI0RDI_CLK			41
+#define GCC_CAMSS_CSI1_AHB_CLK			42
+#define GCC_CAMSS_CSI1_CLK			43
+#define GCC_CAMSS_CSI1_CLK_SRC			44
+#define GCC_CAMSS_CSI1PHYTIMER_CLK		45
+#define GCC_CAMSS_CSI1PHYTIMER_CLK_SRC		46
+#define GCC_CAMSS_CSI1PIX_CLK			47
+#define GCC_CAMSS_CSI1RDI_CLK			48
+#define GCC_CAMSS_CSI2_AHB_CLK			49
+#define GCC_CAMSS_CSI2_CLK			50
+#define GCC_CAMSS_CSI2_CLK_SRC			51
+#define GCC_CAMSS_CSI2PHYTIMER_CLK		52
+#define GCC_CAMSS_CSI2PHYTIMER_CLK_SRC		53
+#define GCC_CAMSS_CSI2PIX_CLK			54
+#define GCC_CAMSS_CSI2RDI_CLK			55
+#define GCC_CAMSS_CSI3_AHB_CLK			56
+#define GCC_CAMSS_CSI3_CLK			57
+#define GCC_CAMSS_CSI3_CLK_SRC			58
+#define GCC_CAMSS_CSI3PIX_CLK			59
+#define GCC_CAMSS_CSI3RDI_CLK			60
+#define GCC_CAMSS_CSI_VFE0_CLK			61
+#define GCC_CAMSS_CSI_VFE1_CLK			62
+#define GCC_CAMSS_CSIPHY0_CLK			63
+#define GCC_CAMSS_CSIPHY1_CLK			64
+#define GCC_CAMSS_CSIPHY2_CLK			65
+#define GCC_CAMSS_CSIPHY3_CLK			66
+#define GCC_CAMSS_CSIPHY_CLK_SRC		67
+#define GCC_CAMSS_GP0_CLK			68
+#define GCC_CAMSS_GP0_CLK_SRC			69
+#define GCC_CAMSS_GP1_CLK			70
+#define GCC_CAMSS_GP1_CLK_SRC			71
+#define GCC_CAMSS_ISPIF_AHB_CLK			72
+#define GCC_CAMSS_JPEG_AHB_CLK			73
+#define GCC_CAMSS_JPEG_AXI_CLK			74
+#define GCC_CAMSS_JPEG_CLK			75
+#define GCC_CAMSS_JPEG_CLK_SRC			76
+#define GCC_CAMSS_MCLK0_CLK			77
+#define GCC_CAMSS_MCLK0_CLK_SRC			78
+#define GCC_CAMSS_MCLK1_CLK			79
+#define GCC_CAMSS_MCLK1_CLK_SRC			80
+#define GCC_CAMSS_MCLK2_CLK			81
+#define GCC_CAMSS_MCLK2_CLK_SRC			82
+#define GCC_CAMSS_MCLK3_CLK			83
+#define GCC_CAMSS_MCLK3_CLK_SRC			84
+#define GCC_CAMSS_MICRO_AHB_CLK			85
+#define GCC_CAMSS_THROTTLE_NRT_AXI_CLK		86
+#define GCC_CAMSS_THROTTLE_RT_AXI_CLK		87
+#define GCC_CAMSS_TOP_AHB_CLK			88
+#define GCC_CAMSS_VFE0_AHB_CLK			89
+#define GCC_CAMSS_VFE0_CLK			90
+#define GCC_CAMSS_VFE0_CLK_SRC			91
+#define GCC_CAMSS_VFE0_STREAM_CLK		92
+#define GCC_CAMSS_VFE1_AHB_CLK			93
+#define GCC_CAMSS_VFE1_CLK			94
+#define GCC_CAMSS_VFE1_CLK_SRC			95
+#define GCC_CAMSS_VFE1_STREAM_CLK		96
+#define GCC_CAMSS_VFE_TSCTR_CLK			97
+#define GCC_CAMSS_VFE_VBIF_AHB_CLK		98
+#define GCC_CAMSS_VFE_VBIF_AXI_CLK		99
+#define GCC_CE1_AHB_CLK				100
+#define GCC_CE1_AXI_CLK				101
+#define GCC_CE1_CLK				102
+#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK		103
+#define GCC_CPUSS_GNOC_CLK			104
+#define GCC_CPUSS_THROTTLE_CORE_CLK		105
+#define GCC_CPUSS_THROTTLE_XO_CLK		106
+#define GCC_DISP_AHB_CLK			107
+#define GCC_DISP_GPLL0_DIV_CLK_SRC		108
+#define GCC_DISP_HF_AXI_CLK			109
+#define GCC_DISP_THROTTLE_CORE_CLK		110
+#define GCC_DISP_XO_CLK				111
+#define GCC_GP1_CLK				112
+#define GCC_GP1_CLK_SRC				113
+#define GCC_GP2_CLK				114
+#define GCC_GP2_CLK_SRC				115
+#define GCC_GP3_CLK				116
+#define GCC_GP3_CLK_SRC				117
+#define GCC_GPU_CFG_AHB_CLK			118
+#define GCC_GPU_GPLL0_CLK_SRC			119
+#define GCC_GPU_GPLL0_DIV_CLK_SRC		120
+#define GCC_GPU_MEMNOC_GFX_CLK			121
+#define GCC_GPU_SNOC_DVM_GFX_CLK		122
+#define GCC_GPU_THROTTLE_CORE_CLK		123
+#define GCC_GPU_THROTTLE_XO_CLK			124
+#define GCC_MSS_VS_CLK				125
+#define GCC_PDM2_CLK				126
+#define GCC_PDM2_CLK_SRC			127
+#define GCC_PDM_AHB_CLK				128
+#define GCC_PDM_XO4_CLK				129
+#define GCC_PRNG_AHB_CLK			130
+#define GCC_QMIP_CAMERA_NRT_AHB_CLK		131
+#define GCC_QMIP_CAMERA_RT_AHB_CLK		132
+#define GCC_QMIP_CPUSS_CFG_AHB_CLK		133
+#define GCC_QMIP_DISP_AHB_CLK			134
+#define GCC_QMIP_GPU_CFG_AHB_CLK		135
+#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK		136
+#define GCC_QUPV3_WRAP0_CORE_2X_CLK		137
+#define GCC_QUPV3_WRAP0_CORE_CLK		138
+#define GCC_QUPV3_WRAP0_S0_CLK			139
+#define GCC_QUPV3_WRAP0_S0_CLK_SRC		140
+#define GCC_QUPV3_WRAP0_S1_CLK			141
+#define GCC_QUPV3_WRAP0_S1_CLK_SRC		142
+#define GCC_QUPV3_WRAP0_S2_CLK			143
+#define GCC_QUPV3_WRAP0_S2_CLK_SRC		144
+#define GCC_QUPV3_WRAP0_S3_CLK			145
+#define GCC_QUPV3_WRAP0_S3_CLK_SRC		146
+#define GCC_QUPV3_WRAP0_S4_CLK			147
+#define GCC_QUPV3_WRAP0_S4_CLK_SRC		148
+#define GCC_QUPV3_WRAP0_S5_CLK			149
+#define GCC_QUPV3_WRAP0_S5_CLK_SRC		150
+#define GCC_QUPV3_WRAP1_CORE_2X_CLK		151
+#define GCC_QUPV3_WRAP1_CORE_CLK		152
+#define GCC_QUPV3_WRAP1_S0_CLK			153
+#define GCC_QUPV3_WRAP1_S0_CLK_SRC		154
+#define GCC_QUPV3_WRAP1_S1_CLK			155
+#define GCC_QUPV3_WRAP1_S1_CLK_SRC		156
+#define GCC_QUPV3_WRAP1_S2_CLK			157
+#define GCC_QUPV3_WRAP1_S2_CLK_SRC		158
+#define GCC_QUPV3_WRAP1_S3_CLK			159
+#define GCC_QUPV3_WRAP1_S3_CLK_SRC		160
+#define GCC_QUPV3_WRAP1_S4_CLK			161
+#define GCC_QUPV3_WRAP1_S4_CLK_SRC		162
+#define GCC_QUPV3_WRAP1_S5_CLK			163
+#define GCC_QUPV3_WRAP1_S5_CLK_SRC		164
+#define GCC_QUPV3_WRAP_0_M_AHB_CLK		165
+#define GCC_QUPV3_WRAP_0_S_AHB_CLK		166
+#define GCC_QUPV3_WRAP_1_M_AHB_CLK		167
+#define GCC_QUPV3_WRAP_1_S_AHB_CLK		168
+#define GCC_SDCC1_AHB_CLK			169
+#define GCC_SDCC1_APPS_CLK			170
+#define GCC_SDCC1_APPS_CLK_SRC			171
+#define GCC_SDCC1_ICE_CORE_CLK			172
+#define GCC_SDCC1_ICE_CORE_CLK_SRC		173
+#define GCC_SDCC2_AHB_CLK			174
+#define GCC_SDCC2_APPS_CLK			175
+#define GCC_SDCC2_APPS_CLK_SRC			176
+#define GCC_SYS_NOC_CPUSS_AHB_CLK		177
+#define GCC_SYS_NOC_UFS_PHY_AXI_CLK		178
+#define GCC_SYS_NOC_USB3_PRIM_AXI_CLK		179
+#define GCC_UFS_PHY_AHB_CLK			180
+#define GCC_UFS_PHY_AXI_CLK			181
+#define GCC_UFS_PHY_AXI_CLK_SRC			182
+#define GCC_UFS_PHY_ICE_CORE_CLK		183
+#define GCC_UFS_PHY_ICE_CORE_CLK_SRC		184
+#define GCC_UFS_PHY_PHY_AUX_CLK			185
+#define GCC_UFS_PHY_PHY_AUX_CLK_SRC		186
+#define GCC_UFS_PHY_RX_SYMBOL_0_CLK		187
+#define GCC_UFS_PHY_TX_SYMBOL_0_CLK		188
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK		189
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC		190
+#define GCC_USB30_PRIM_MASTER_CLK		191
+#define GCC_USB30_PRIM_MASTER_CLK_SRC		192
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK		193
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC	194
+#define GCC_USB30_PRIM_SLEEP_CLK		195
+#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC		196
+#define GCC_USB3_PRIM_PHY_COM_AUX_CLK		197
+#define GCC_USB3_PRIM_PHY_PIPE_CLK		198
+#define GCC_VDDA_VS_CLK				199
+#define GCC_VDDCX_VS_CLK			200
+#define GCC_VDDMX_VS_CLK			201
+#define GCC_VIDEO_AHB_CLK			202
+#define GCC_VIDEO_AXI0_CLK			203
+#define GCC_VIDEO_THROTTLE_CORE_CLK		204
+#define GCC_VIDEO_XO_CLK			205
+#define GCC_VS_CTRL_AHB_CLK			206
+#define GCC_VS_CTRL_CLK				207
+#define GCC_VS_CTRL_CLK_SRC			208
+#define GCC_VSENSOR_CLK_SRC			209
+#define GCC_WCSS_VS_CLK				210
+#define GCC_USB3_PRIM_CLKREF_CLK		211
+#define GCC_SYS_NOC_COMPUTE_SF_AXI_CLK		212
+#define GCC_BIMC_GPU_AXI_CLK			213
+#define GCC_UFS_MEM_CLKREF_CLK			214
 
 /* GCC Resets */
 #define GCC_QUSB2PHY_PRIM_BCR			0
diff --git a/include/dt-bindings/clock/qcom,gpucc-trinket.h b/include/dt-bindings/clock/qcom,gpucc-trinket.h
index 1e70d9b..e57f203 100644
--- a/include/dt-bindings/clock/qcom,gpucc-trinket.h
+++ b/include/dt-bindings/clock/qcom,gpucc-trinket.h
@@ -30,5 +30,6 @@
 #define GPU_CC_GX_GFX3D_CLK			12
 #define GPU_CC_GX_GFX3D_CLK_SRC			13
 #define GPU_CC_AHB_CLK			14
+#define GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK		15
 
 #endif
diff --git a/include/dt-bindings/msm/msm-bus-ids.h b/include/dt-bindings/msm/msm-bus-ids.h
index c3f7f56..95694a1 100644
--- a/include/dt-bindings/msm/msm-bus-ids.h
+++ b/include/dt-bindings/msm/msm-bus-ids.h
@@ -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
@@ -47,6 +47,9 @@
 #define	MSM_BUS_FAB_COMP_NOC 6155
 #define	MSM_BUS_FAB_GEM_NOC 6156
 #define	MSM_BUS_FAB_QUP_VIRT 6157
+#define	MSM_BUS_FAB_GPU_VIRT 6158
+#define	MSM_BUS_FAB_MMNRT_VIRT 6159
+#define	MSM_BUS_FAB_MMRT_VIRT 6160
 
 #define	MSM_BUS_FAB_MC_VIRT_DISPLAY 26000
 #define	MSM_BUS_FAB_MEM_NOC_DISPLAY 26001
diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index e098cbe..12babe9 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -31,7 +31,7 @@
 struct user_key_payload {
 	struct rcu_head	rcu;		/* RCU destructor */
 	unsigned short	datalen;	/* length of this data */
-	char		data[0];	/* actual data */
+	char		data[0] __aligned(__alignof__(u64)); /* actual data */
 };
 
 extern struct key_type key_type_user;
diff --git a/include/linux/adc-tm-clients.h b/include/linux/adc-tm-clients.h
new file mode 100644
index 0000000..8f9ea00
--- /dev/null
+++ b/include/linux/adc-tm-clients.h
@@ -0,0 +1,99 @@
+/* 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
+ * 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 __QCOM_ADC_TM_H_CLIENTS__
+#define __QCOM_ADC_TM_H_CLIENTS__
+
+struct adc_tm_chip;
+
+/**
+ * enum adc_tm_state - This lets the client know whether the threshold
+ *		that was crossed was high/low.
+ * %ADC_TM_HIGH_STATE: Client is notified of crossing the requested high
+ *			voltage threshold.
+ * %ADC_TM_COOL_STATE: Client is notified of crossing the requested cool
+ *			temperature threshold.
+ * %ADC_TM_LOW_STATE: Client is notified of crossing the requested low
+ *			voltage threshold.
+ * %ADC_TM_WARM_STATE: Client is notified of crossing the requested high
+ *			temperature threshold.
+ */
+enum adc_tm_state {
+	ADC_TM_HIGH_STATE = 0,
+	ADC_TM_COOL_STATE = ADC_TM_HIGH_STATE,
+	ADC_TM_LOW_STATE,
+	ADC_TM_WARM_STATE = ADC_TM_LOW_STATE,
+	ADC_TM_STATE_NUM,
+};
+
+/**
+ * enum adc_tm_state_request - Request to enable/disable the corresponding
+ *			high/low voltage/temperature thresholds.
+ * %ADC_TM_HIGH_THR_ENABLE: Enable high voltage threshold.
+ * %ADC_TM_COOL_THR_ENABLE = Enables cool temperature threshold.
+ * %ADC_TM_LOW_THR_ENABLE: Enable low voltage/temperature threshold.
+ * %ADC_TM_WARM_THR_ENABLE = Enables warm temperature threshold.
+ * %ADC_TM_HIGH_LOW_THR_ENABLE: Enable high and low voltage/temperature
+ *				threshold.
+ * %ADC_TM_HIGH_THR_DISABLE: Disable high voltage/temperature threshold.
+ * %ADC_TM_COOL_THR_ENABLE = Disables cool temperature threshold.
+ * %ADC_TM_LOW_THR_DISABLE: Disable low voltage/temperature threshold.
+ * %ADC_TM_WARM_THR_ENABLE = Disables warm temperature threshold.
+ * %ADC_TM_HIGH_THR_DISABLE: Disable high and low voltage/temperature
+ *				threshold.
+ */
+enum adc_tm_state_request {
+	ADC_TM_HIGH_THR_ENABLE = 0,
+	ADC_TM_COOL_THR_ENABLE = ADC_TM_HIGH_THR_ENABLE,
+	ADC_TM_LOW_THR_ENABLE,
+	ADC_TM_WARM_THR_ENABLE = ADC_TM_LOW_THR_ENABLE,
+	ADC_TM_HIGH_LOW_THR_ENABLE,
+	ADC_TM_HIGH_THR_DISABLE,
+	ADC_TM_COOL_THR_DISABLE = ADC_TM_HIGH_THR_DISABLE,
+	ADC_TM_LOW_THR_DISABLE,
+	ADC_TM_WARM_THR_DISABLE = ADC_TM_LOW_THR_DISABLE,
+	ADC_TM_HIGH_LOW_THR_DISABLE,
+	ADC_TM_THR_NUM,
+};
+
+struct adc_tm_param {
+	int			low_thr;
+	int			high_thr;
+	uint32_t				channel;
+	enum adc_tm_state_request	state_request;
+	void					*btm_ctx;
+	void	(*threshold_notification)(enum adc_tm_state state,
+						void *ctx);
+};
+
+/* Public API */
+#if defined(CONFIG_QTI_ADC_TM)
+struct adc_tm_chip *get_adc_tm(struct device *dev, const char *name);
+int32_t adc_tm5_channel_measure(struct adc_tm_chip *chip,
+					struct adc_tm_param *param);
+int32_t adc_tm5_disable_chan_meas(struct adc_tm_chip *chip,
+					struct adc_tm_param *param);
+#else
+static inline struct adc_tm_chip *get_adc_tm(
+	struct device *dev, const char *name)
+{ return ERR_PTR(-ENXIO); }
+static inline int32_t adc_tm5_channel_measure(
+					struct adc_tm_chip *chip,
+					struct adc_tm_param *param)
+{ return -ENXIO; }
+static inline int32_t adc_tm5_disable_chan_meas(
+					struct adc_tm_chip *chip,
+					struct adc_tm_param *param)
+{ return -ENXIO; }
+#endif
+
+#endif /* __QCOM_ADC_TM_H_CLIENTS__ */
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index 3c1beff..b186c4b 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -165,6 +165,7 @@ struct backing_dev_info {
 	struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */
 	struct rb_root cgwb_congested_tree; /* their congested states */
 	struct mutex cgwb_release_mutex;  /* protect shutdown of wb structs */
+	struct rw_semaphore wb_switch_rwsem; /* no cgwb switch while syncing */
 #else
 	struct bdi_writeback_congested *wb_congested;
 #endif
@@ -233,6 +234,14 @@ static inline void wb_get(struct bdi_writeback *wb)
  */
 static inline void wb_put(struct bdi_writeback *wb)
 {
+	if (WARN_ON_ONCE(!wb->bdi)) {
+		/*
+		 * A driver bug might cause a file to be removed before bdi was
+		 * initialized.
+		 */
+		return;
+	}
+
 	if (wb != &wb->bdi->wb)
 		percpu_ref_put(&wb->refcnt);
 }
diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
index c456227..6c5b4d7 100644
--- a/include/linux/compiler-clang.h
+++ b/include/linux/compiler-clang.h
@@ -33,3 +33,17 @@
 
 #define __nocfi		__attribute__((no_sanitize("cfi")))
 #endif
+
+/*
+ * Not all versions of clang implement the the type-generic versions
+ * of the builtin overflow checkers. Fortunately, clang implements
+ * __has_builtin allowing us to avoid awkward version
+ * checks. Unfortunately, we don't know which version of gcc clang
+ * pretends to be, so the macro may or may not be defined.
+ */
+#undef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
+#if __has_builtin(__builtin_mul_overflow) && \
+    __has_builtin(__builtin_add_overflow) && \
+    __has_builtin(__builtin_sub_overflow)
+#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
+#endif
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index c11032b..4816355 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -108,7 +108,7 @@
 #define __weak		__attribute__((weak))
 #define __alias(symbol)	__attribute__((alias(#symbol)))
 
-#ifdef RETPOLINE
+#ifdef CONFIG_RETPOLINE
 #define __noretpoline __attribute__((indirect_branch("keep")))
 #endif
 
@@ -358,3 +358,7 @@
  * code
  */
 #define uninitialized_var(x) x = x
+
+#if GCC_VERSION >= 50100
+#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
+#endif
diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h
index bfa0816..547cdc92 100644
--- a/include/linux/compiler-intel.h
+++ b/include/linux/compiler-intel.h
@@ -44,3 +44,7 @@
 #define __builtin_bswap16 _bswap16
 #endif
 
+/*
+ * icc defines __GNUC__, but does not implement the builtin overflow checkers.
+ */
+#undef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 2a13ae6..feb4e42 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -85,6 +85,20 @@ struct coresight_dev_subtype {
 };
 
 /**
+ * struct coresight_reg_clk - regulators and clocks need by coresight
+ * @nr_reg:	number of regulators
+ * @nr_clk:	number of clocks
+ * @reg:	regulator list
+ * @clk:	clock list
+ */
+struct coresight_reg_clk {
+	int nr_reg;
+	int nr_clk;
+	struct regulator **reg;
+	struct clk **clk;
+};
+
+/**
  * struct coresight_platform_data - data harvested from the DT specification
  * @cpu:	the CPU a source belongs to. Only applicable for ETM/PTMs.
  * @name:	name of the component as shown under sysfs.
@@ -95,6 +109,7 @@ struct coresight_dev_subtype {
 		connected  to.
  * @nr_outport:	number of output ports for this component.
  * @clk:	The clock this component is associated to.
+ * @reg_clk:	as defined by @coresight_reg_clk.
  */
 struct coresight_platform_data {
 	int cpu;
@@ -105,6 +120,7 @@ struct coresight_platform_data {
 	int *child_ports;
 	int nr_outport;
 	struct clk *clk;
+	struct coresight_reg_clk *reg_clk;
 };
 
 /**
@@ -159,6 +175,7 @@ struct coresight_connection {
 		activated but not yet enabled.  Enabling for a _sink_
 		happens when a source has been selected for that it.
  * @abort:     captures sink trace on abort.
+ * @reg_clk:	as defined by @coresight_reg_clk.
  */
 struct coresight_device {
 	struct coresight_connection *conns;
@@ -173,6 +190,7 @@ struct coresight_device {
 	bool orphan;
 	bool enable;	/* true only if configured as part of a path */
 	bool activated;	/* true only if a sink is part of a path */
+	struct coresight_reg_clk *reg_clk;
 };
 
 #define to_coresight_device(d) container_of(d, struct coresight_device, dev)
@@ -255,6 +273,8 @@ extern void coresight_disable(struct coresight_device *csdev);
 extern int coresight_timeout(void __iomem *addr, u32 offset,
 			     int position, int value);
 extern void coresight_abort(void);
+extern void coresight_disable_reg_clk(struct coresight_device *csdev);
+extern void coresight_enable_reg_clk(struct coresight_device *csdev);
 #else
 static inline struct coresight_device *
 coresight_register(struct coresight_desc *desc) { return NULL; }
@@ -265,6 +285,8 @@ static inline void coresight_disable(struct coresight_device *csdev) {}
 static inline int coresight_timeout(void __iomem *addr, u32 offset,
 				     int position, int value) { return 1; }
 static inline void coresight_abort(void) {}
+static inline void coresight_disable_reg_clk(struct coresight_device *csdev) {}
+static inline void coresight_enable_reg_clk(struct coresight_device *csdev) {}
 #endif
 
 #ifdef CONFIG_OF
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index edcb1e4..ecf161a 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -195,12 +195,10 @@ enum cpuhp_smt_control {
 #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
 extern enum cpuhp_smt_control cpu_smt_control;
 extern void cpu_smt_disable(bool force);
-extern void cpu_smt_check_topology_early(void);
 extern void cpu_smt_check_topology(void);
 #else
 # define cpu_smt_control		(CPU_SMT_ENABLED)
 static inline void cpu_smt_disable(bool force) { }
-static inline void cpu_smt_check_topology_early(void) { }
 static inline void cpu_smt_check_topology(void) { }
 #endif
 
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 6230fba..ad01ca0 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -139,9 +139,9 @@ enum cpuhp_state {
 	/* Must be the last timer callback */
 	CPUHP_AP_DUMMY_TIMER_STARTING,
 	CPUHP_AP_ARM_XEN_STARTING,
-	CPUHP_AP_ARM_CORESIGHT_STARTING,
 	CPUHP_AP_ARM_SAVE_RESTORE_CORESIGHT4_STARTING,
 	CPUHP_AP_ARM_MM_CORESIGHT4_STARTING,
+	CPUHP_AP_ARM_CORESIGHT_STARTING,
 	CPUHP_AP_ARM64_ISNDEP_STARTING,
 	CPUHP_AP_SMPCFD_DYING,
 	CPUHP_AP_X86_TBOOT_DYING,
diff --git a/include/linux/genl_magic_struct.h b/include/linux/genl_magic_struct.h
index 5972e49..eeae59d 100644
--- a/include/linux/genl_magic_struct.h
+++ b/include/linux/genl_magic_struct.h
@@ -191,6 +191,7 @@ static inline void ct_assert_unique_operations(void)
 {
 	switch (0) {
 #include GENL_MAGIC_INCLUDE_FILE
+	case 0:
 		;
 	}
 }
@@ -209,6 +210,7 @@ static inline void ct_assert_unique_top_level_attributes(void)
 {
 	switch (0) {
 #include GENL_MAGIC_INCLUDE_FILE
+	case 0:
 		;
 	}
 }
@@ -218,7 +220,8 @@ static inline void ct_assert_unique_top_level_attributes(void)
 static inline void ct_assert_unique_ ## s_name ## _attributes(void)	\
 {									\
 	switch (0) {							\
-		s_fields						\
+	s_fields							\
+	case 0:								\
 			;						\
 	}								\
 }
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
index af36a68..ce54f37 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
@@ -18,6 +18,7 @@
 
 enum hdcp2_app_cmd {
 	HDCP2_CMD_START,
+	HDCP2_CMD_START_AUTH,
 	HDCP2_CMD_STOP,
 	HDCP2_CMD_PROCESS_MSG,
 	HDCP2_CMD_TIMEOUT,
@@ -42,6 +43,8 @@ static inline const char *hdcp2_app_cmd_str(enum hdcp2_app_cmd cmd)
 	switch (cmd) {
 	case HDCP2_CMD_START:
 		return HDCP_QSEECOM_ENUM_STR(HDCP2_CMD_START);
+	case HDCP2_CMD_START_AUTH:
+		return HDCP_QSEECOM_ENUM_STR(HDCP2_CMD_START_AUTH);
 	case HDCP2_CMD_STOP:
 		return HDCP_QSEECOM_ENUM_STR(HDCP2_CMD_STOP);
 	case HDCP2_CMD_PROCESS_MSG:
diff --git a/include/linux/hid-debug.h b/include/linux/hid-debug.h
index 8663f21..2d6100e 100644
--- a/include/linux/hid-debug.h
+++ b/include/linux/hid-debug.h
@@ -24,7 +24,10 @@
 
 #ifdef CONFIG_DEBUG_FS
 
+#include <linux/kfifo.h>
+
 #define HID_DEBUG_BUFSIZE 512
+#define HID_DEBUG_FIFOSIZE 512
 
 void hid_dump_input(struct hid_device *, struct hid_usage *, __s32);
 void hid_dump_report(struct hid_device *, int , u8 *, int);
@@ -37,11 +40,8 @@ void hid_debug_init(void);
 void hid_debug_exit(void);
 void hid_debug_event(struct hid_device *, char *);
 
-
 struct hid_debug_list {
-	char *hid_debug_buf;
-	int head;
-	int tail;
+	DECLARE_KFIFO_PTR(hid_debug_fifo, char);
 	struct fasync_struct *fasync;
 	struct hid_device *hdev;
 	struct list_head node;
@@ -64,4 +64,3 @@ struct hid_debug_list {
 #endif
 
 #endif
-
diff --git a/include/linux/hmm.h b/include/linux/hmm.h
index 96e6997..7d799c4 100644
--- a/include/linux/hmm.h
+++ b/include/linux/hmm.h
@@ -437,8 +437,7 @@ struct hmm_devmem {
  * enough and allocate struct page for it.
  *
  * The device driver can wrap the hmm_devmem struct inside a private device
- * driver struct. The device driver must call hmm_devmem_remove() before the
- * device goes away and before freeing the hmm_devmem struct memory.
+ * driver struct.
  */
 struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 				  struct device *device,
@@ -446,7 +445,6 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
 					   struct device *device,
 					   struct resource *res);
-void hmm_devmem_remove(struct hmm_devmem *devmem);
 
 /*
  * hmm_devmem_page_set_drvdata - set per-page driver data field
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index d1324d3..8d3ca6d 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1130,8 +1130,9 @@ struct hv_ring_buffer_debug_info {
 	u32 bytes_avail_towrite;
 };
 
-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
-			    struct hv_ring_buffer_debug_info *debug_info);
+
+int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
+				struct hv_ring_buffer_debug_info *debug_info);
 
 /* Vmbus interface */
 #define vmbus_driver_register(driver)	\
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index 3355efc..4125f60 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -54,6 +54,7 @@ static inline bool dev_is_mac_header_xmit(const struct net_device *dev)
 	case ARPHRD_IPGRE:
 	case ARPHRD_VOID:
 	case ARPHRD_NONE:
+	case ARPHRD_RAWIP:
 		return false;
 	default:
 		return true;
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 8062e6cc..4e799be 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -236,6 +236,7 @@ extern struct cred init_cred;
 	.policy		= SCHED_NORMAL,					\
 	.cpus_allowed	= CPU_MASK_ALL,					\
 	.nr_cpus_allowed= NR_CPUS,					\
+	.cpus_requested	= CPU_MASK_ALL,					\
 	.mm		= NULL,						\
 	.active_mm	= &init_mm,					\
 	.restart_block = {						\
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index b3058a1..4e50abb 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -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
@@ -1185,6 +1185,7 @@ struct ipa_tz_unlock_reg_info {
 
 enum ipa_smmu_client_type {
 	IPA_SMMU_WLAN_CLIENT,
+	IPA_SMMU_AP_CLIENT,
 	IPA_SMMU_CLIENT_MAX
 };
 
diff --git a/include/linux/ipa_eth.h b/include/linux/ipa_eth.h
new file mode 100644
index 0000000..85dcf268
--- /dev/null
+++ b/include/linux/ipa_eth.h
@@ -0,0 +1,745 @@
+/* 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 _IPA_ETH_H_
+#define _IPA_ETH_H_
+
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/debugfs.h>
+#include <linux/ipc_logging.h>
+
+#include <linux/netdevice.h>
+#include <linux/netdev_features.h>
+
+#include <linux/msm_ipa.h>
+#include <linux/msm_gsi.h>
+
+/**
+ * enum ipa_eth_dev_features - Features supported by an ethernet device or
+ *                             driver that may be requested via offload APIs
+ * @IPA_ETH_DEV_F_L2_CSUM_BIT: Ethernet L2 checksum offload
+ * @IPA_ETH_DEV_F_L3_CSUM_BIT: Ethernet L2 checksum offload
+ * @IPA_ETH_DEV_F_TCP_CSUM_BIT: TCP checksum offload
+ * @IPA_ETH_DEV_F_UDP_CSUM_BIT: UDP checksum offload
+ * @IPA_ETH_DEV_F_LSO_BIT: Large Send Offload / TCP Segmentation Offload
+ * @IPA_ETH_DEV_F_LRO_BIT: Large Receive Offload / Receive Side Coalescing
+ * @IPA_ETH_DEV_F_VLAN_BIT: VLAN Offload
+ * @IPA_ETH_DEV_F_MODC_BIT: Counter based event moderation
+ * @IPA_ETH_DEV_F_MODT_BIT: Timer based event moderation
+ *
+ * Ethernet hardware features represented as bit numbers below are used in
+ * IPA_ETH_DEV_F_* feature flags that are to be used in offload APIs.
+ */
+enum ipa_eth_dev_features {
+	IPA_ETH_DEV_F_L2_CSUM_BIT,
+	IPA_ETH_DEV_F_L3_CSUM_BIT,
+	IPA_ETH_DEV_F_TCP_CSUM_BIT,
+	IPA_ETH_DEV_F_UDP_CSUM_BIT,
+	IPA_ETH_DEV_F_LSO_BIT,
+	IPA_ETH_DEV_F_LRO_BIT,
+	IPA_ETH_DEV_F_VLAN_BIT,
+	IPA_ETH_DEV_F_MODC_BIT,
+	IPA_ETH_DEV_F_MODT_BIT,
+};
+
+#define ipa_eth_dev_f(f) BIT(IPA_ETH_DEV_F_##f##_BIT)
+
+#define IPA_ETH_DEV_F_L2_CSUM  ipa_eth_dev_f(L2_CSUM)
+#define IPA_ETH_DEV_F_L3_CSUM  ipa_eth_dev_f(L3_CSUM)
+#define IPA_ETH_DEV_F_TCP_CSUM ipa_eth_dev_f(TCP_CSUM)
+#define IPA_ETH_DEV_F_UDP_CSUM ipa_eth_dev_f(UDP_CSUM)
+#define IPA_ETH_DEV_F_LSO      ipa_eth_dev_f(LSO)
+#define IPA_ETH_DEV_F_LRO      ipa_eth_dev_f(LRO)
+#define IPA_ETH_DEV_F_VLAN     ipa_eth_dev_f(VLAN)
+#define IPA_ETH_DEV_F_MODC     ipa_eth_dev_f(MODC)
+#define IPA_ETH_DEV_F_MODT     ipa_eth_dev_f(MODT)
+
+/**
+ * enum ipa_eth_dev_events - Events supported by an ethernet device that may be
+ *                           requested via offload APIs
+ * @IPA_ETH_DEV_EV_RX_INT_BIT: Rx interrupt
+ * @IPA_ETH_DEV_EV_TX_INT_BIT: Tx interrupt
+ * @IPA_ETH_DEV_EV_RX_PTR_BIT: Rx (head) pointer write-back
+ * @IPA_ETH_DEV_EV_TX_PTR_BIT: Tx (head) pointer write-back
+ */
+enum ipa_eth_dev_events {
+	IPA_ETH_DEV_EV_RX_INT_BIT,
+	IPA_ETH_DEV_EV_TX_INT_BIT,
+	IPA_ETH_DEV_EV_RX_PTR_BIT,
+	IPA_ETH_DEV_EV_TX_PTR_BIT
+};
+
+#define ipa_eth_dev_ev(ev) BIT(IPA_ETH_DEV_EV_##ev##_BIT)
+
+#define IPA_ETH_DEV_EV_RX_INT ipa_eth_dev_ev(RX_INT)
+#define IPA_ETH_DEV_EV_TX_INT ipa_eth_dev_ev(TX_INT)
+#define IPA_ETH_DEV_EV_RX_PTR ipa_eth_dev_ev(RX_PTR)
+#define IPA_ETH_DEV_EV_TX_PTR ipa_eth_dev_ev(TX_PTR)
+
+/**
+ * enum ipa_eth_channel_dir - Direction of a ring / channel
+ * @IPA_ETH_DIR_RX: Traffic flowing from device to IPA
+ * @IPA_ETH_DIR_TX: Traffic flowing from IPA to device
+ * @IPA_ETH_DIR_BI: Bi-direction traffic flow
+ */
+enum ipa_eth_channel_dir {
+	IPA_ETH_DIR_RX,
+	IPA_ETH_DIR_TX,
+	IPA_ETH_DIR_BI
+};
+
+/**
+ * enum ipa_eth_state - Offload state of an ethernet device
+ * @IPA_ETH_ST_DEINITED: No offload path resources are allocated
+ * @IPA_ETH_ST_INITED: Offload path resources are allocated, but not started
+ * @IPA_ETH_ST_STARTED: Offload path is started and ready to handle traffic
+ * @IPA_ETH_ST_ERROR: One or more offload path components are in error state
+ * @IPA_ETH_ST_RECOVERY: Offload path is attempting to recover from error
+ */
+enum ipa_eth_state {
+	IPA_ETH_ST_DEINITED = 0,
+	IPA_ETH_ST_INITED,
+	IPA_ETH_ST_STARTED,
+	IPA_ETH_ST_ERROR,
+	IPA_ETH_ST_RECOVERY,
+};
+
+struct ipa_eth_device;
+struct ipa_eth_net_driver;
+
+/**
+ * struct ipa_eth_resource - Memory based resource info
+ * @size: Size of the memory accessible
+ * @vaddr: Kernel mapped address of the resource
+ * @daddr: DMA address of the resource
+ * @paddr: Physical address of the resource
+ */
+struct ipa_eth_resource {
+	size_t size;
+
+	void *vaddr;
+	dma_addr_t daddr;
+	phys_addr_t paddr;
+
+};
+
+/**
+ * struct ipa_eth_channel - Represents a network device channel
+ * @nd_priv: Private field for use by network driver
+ * @events: Events supported by the channel
+ * @features: Features enabled in the channel
+ * @direction: Channel direction
+ * @queue: Network device queue/ring number
+ * @desc_size: Size of each descriptor
+ * @desc_count: Number of descriptors in the ring
+ * @desc_mem: Descriptor ring memory base
+ * @buff_size: Size of each data buffer
+ * @buff_count: Number of data buffers
+ * @buff_mem: Data buffer memory base
+ * @od_priv: Private field for use by offload driver
+ * @eth_dev: Associated ipa_eth_device
+ * @ipa_client: IPA client type enum to be used for the channel
+ * @ipa_ep_num: IPA endpoint number configured for the client type
+ * @process_skb: Callback to be called for processing IPA exception
+ *               packets received from the IPA endpoint
+ * @ipa_priv: Private field to be used by offload subsystem
+ * @exception_total: Total number of exception packets received
+ * @exception_drops: Total number of dropped exception packets
+ * @exception_loopback: Total number of exception packets looped back
+ *                      into IPA
+ */
+struct ipa_eth_channel {
+	/* fields managed by network driver */
+	void *nd_priv;
+
+	unsigned long events;
+	unsigned long features;
+	enum ipa_eth_channel_dir direction;
+
+	int queue;
+
+	u16 desc_size;
+	u32 desc_count;
+	struct ipa_eth_resource desc_mem;
+
+	u16 buff_size;
+	u32 buff_count;
+	struct ipa_eth_resource buff_mem;
+
+	/* fields managed by offload driver */
+	void *od_priv;
+	struct ipa_eth_device *eth_dev;
+
+	enum ipa_client_type ipa_client;
+	int ipa_ep_num;
+
+	int (*process_skb)(struct ipa_eth_channel *ch, struct sk_buff *skb);
+
+	/* fields managed by offload subsystem */
+	void *ipa_priv;
+
+	u64 exception_total;
+	u64 exception_drops;
+	u64 exception_loopback;
+};
+
+#define IPA_ETH_CH_IS_RX(ch) ((ch)->direction != IPA_ETH_DIR_TX)
+#define IPA_ETH_CH_IS_TX(ch) ((ch)->direction != IPA_ETH_DIR_RX)
+
+/**
+ * struct ipa_eth_device - Represents an ethernet device
+ * @net_dev: Netdev registered by the network driver
+ * @nd_priv: Private field for use by network driver
+ * @ch_rx: Rx channel allocated for the offload path
+ * @ch_tx: Tx channel allocated for the offload path
+ * @od_priv: Private field for use by offload driver
+ * @device_list: Entry in the global offload device list
+ * @bus_device_list: Entry in the per-bus offload device list
+ * @state: Offload state of the device
+ * @dev: Pointer to struct device
+ * @nd: IPA offload net driver associated with the device
+ * @od: IPA offload driver that is managing the device
+ * @netdevice_nb: Notifier block for receiving netdev events from the
+ *                network device (to monitor link state changes)
+ * @init: Allowed to initialize offload path for the device
+ * @start: Allowed to start offload data path for the device
+ * @link_up: Carrier is detected by the PHY (link is active)
+ * @pm_handle: IPA PM client handle for the device
+ * @bus_priv: Private field for use by offload subsystem bus layer
+ * @ipa_priv: Private field for use by offload subsystem
+ * @debugfs: Debugfs root for the device
+ */
+struct ipa_eth_device {
+	/* fields managed by the network driver */
+	struct net_device *net_dev;
+	void *nd_priv;
+
+	/* fields managed by offload driver */
+	struct ipa_eth_channel *ch_rx;
+	struct ipa_eth_channel *ch_tx;
+	void *od_priv;
+
+	/* fields managed by offload subsystem */
+	struct list_head device_list;
+	struct list_head bus_device_list;
+
+	enum ipa_eth_state state;
+
+	struct device *dev;
+	struct ipa_eth_net_driver *nd;
+	struct ipa_eth_offload_driver *od;
+
+	struct notifier_block netdevice_nb;
+
+	bool init;
+	bool start;
+	bool link_up;
+
+	u32 pm_handle;
+
+	void *bus_priv;
+	void *ipa_priv;
+	struct dentry *debugfs;
+};
+
+/**
+ * struct ipa_eth_net_ops - Network device operations required for IPA offload
+ */
+struct ipa_eth_net_ops {
+	/**
+	 * .open_device() - Initialize the network device if needed before
+	 *                  channels and events are configured.
+	 * @eth_dev: Device to initialize
+	 *
+	 * Typically this is API is functionally equivalent to .ndo_open()
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*open_device)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .close_device() Deinitialize the device if required
+	 * @eth_dev: Device to deinitialize
+	 *
+	 * This is called when the offload data path is deinitialized and the
+	 * offload subsystem do not see any offload drivers registered to
+	 * handle the device anymore. Typically the device is maintained in
+	 * the initialized state until both Linux and IPA data paths are
+	 * deinitialized.
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	void (*close_device)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .request_channel() - Allocate a channel/ring for IPA offload data
+	 *                      path to use
+	 * @eth_dev: Device from which to allocate channel
+	 * @dir: Requested channel direction
+	 * @events: Device events requested for the channel. Value is zero or
+	 *            more IPA_ETH_DEV_EV_* flags.
+	 * @features: Device featured requested for the channel. Value is zero
+	 *            or more IPA_ETH_DEV_F_* feature flags.
+	 *
+	 * Arguments @dir, @features and @events are used to inform the network
+	 * driver about the capabilities of the offload subsystem/driver. The
+	 * API implementation may choose to allocate a channel with only a
+	 * subset of capablities enabled. Caller of this API need to check the
+	 * corresponding values in returned the channel and proceed only if the
+	 * allocated capability set is acceptable for data path operation.
+	 *
+	 * The allocated channel is expected to be in disabled state with no
+	 * events allocated or enabled.
+	 *
+	 * Return: Channel object pointer, or NULL if the channel allocation
+	 *         failed
+	 */
+	struct ipa_eth_channel * (*request_channel)(
+		struct ipa_eth_device *eth_dev, enum ipa_eth_channel_dir dir,
+		unsigned long events, unsigned long features);
+
+	/**
+	 * .release_channel() - Free a channel/ring previously allocated using
+	 *                      .request_channel()
+	 * @ch: Channel to be freed
+	 */
+	void (*release_channel)(struct ipa_eth_channel *ch);
+
+	/**
+	 * .enable_channel() - Enable a channel, allowing data to flow
+	 *
+	 * @ch: Channel to be enabled
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*enable_channel)(struct ipa_eth_channel *ch);
+
+	/**
+	 * .disable_channel() - Disable a channel, stopping the data flow
+	 *
+	 * @ch: Channel to be disabled
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*disable_channel)(struct ipa_eth_channel *ch);
+
+	/**
+	 * .request_event() - Allocate an event for a channel
+	 *
+	 * @ch: Channel for which event need to be allocated
+	 * @event: Event to be allocated
+	 * @addr: Address to which the event need to be reported
+	 * @data: Data value to be associated with the event
+	 *
+	 * The allocated event is expected to be unmoderated.
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*request_event)(struct ipa_eth_channel *ch, unsigned long event,
+		phys_addr_t addr, u64 data);
+
+	/**
+	 * .release_event() - Deallocate a channel event
+	 *
+	 * @ch: Channel for which event need to be deallocated
+	 * @event: Event to be deallocated
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	void (*release_event)(struct ipa_eth_channel *ch, unsigned long event);
+
+	/**
+	 * .enable_event() - Enable a channel event
+	 *
+	 * @ch: Channel for which event need to be enabled
+	 * @event: Event to be enabled
+	 *
+	 * This API is called when IPA or GIC is ready to receive events from
+	 * the network device.
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*enable_event)(struct ipa_eth_channel *ch, unsigned long event);
+
+	/**
+	 * .disable_event() - Disable a channel event
+	 *
+	 * @ch: Channel for which event need to be disabled
+	 * @event: Event to be disabled
+	 *
+	 * Once this API is called, events may no more be reported to IPA/GIC
+	 * although they may still be queued in the device for later delivery.
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*disable_event)(struct ipa_eth_channel *ch, unsigned long event);
+
+	/**
+	 * .moderate_event() - Moderate a channel event
+	 *
+	 * @ch: Channel for which event need to be disabled
+	 * @event: Event to be disabled
+	 * @min_count: Min threshold for counter based moderation
+	 * @max_count: Max threshold for counter based moderation
+	 * @min_usecs: Min microseconds for timer based moderation
+	 * @max_usecs: Max microseconds for timer based moderation
+	 *
+	 * This API enables event moderation when supported by the device. A
+	 * value of 0 in either of the @max_* arguments would disable moderation
+	 * of that specific type. If both types of moderation are enabled, the
+	 * event is triggered with either of them expires.
+	 *
+	 * It is expected from the device/driver to make sure there is always a
+	 * default min_X value for each moderation type such that there would
+	 * be no data stalls or queue overflow when a moderation target is not
+	 * reached.
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*moderate_event)(struct ipa_eth_channel *ch, unsigned long event,
+		u64 min_count, u64 max_count,
+		u64 min_usecs, u64 max_usecs);
+
+	/**
+	 * .receive_skb() - Receive an skb from IPA and push it to Linux network
+	 *                  stack
+	 * @eth_dev: Device to which the skb need to belong
+	 * @skb: Skb to be provided to Linux network stack
+	 *
+	 * When a network packet received by the IPA connected device queue can
+	 * not be routed within IPA, it will be sent to Linux as an exception
+	 * skb. Offload subsystem receives such packets and forwards to this API
+	 * to be provided to Linux network stack to perform the necessary packet
+	 * routing/filtering in the software path.
+	 *
+	 * Network packets received by this API is expected to emerge from the
+	 * device's Linux network interface as it would have, had the packet
+	 * arrived directly to the Linux connected queues.
+	 *
+	 * Return: 0 on success, negative errno otherwise. On error, skb is NOT
+	 * expected to have been freed.
+	 */
+	int (*receive_skb)(struct ipa_eth_device *eth_dev,
+		struct sk_buff *skb);
+
+	/**
+	 * .transmit_skb() - Transmit an skb given IPA
+	 * @eth_dev: Device through which the packet need to be transmitted
+	 * @skb: Skb to be transmitted
+	 *
+	 * Return: 0 on success, negative errno otherwise. On error, skb is NOT
+	 * expected to have been freed.
+	 */
+	int (*transmit_skb)(struct ipa_eth_device *eth_dev,
+		struct sk_buff *skb);
+};
+
+/**
+ * struct ipa_eth_net_driver - Network driver to be registered with IPA offload
+ *                             subsystem
+ * @name: Name of the network driver
+ * @driver: Pointer to the device_driver object embedded within a PCI/plaform
+ *          driver object used by the network driver
+ * @events: Events supported by the network device
+ * @features: Capabilities of the network device
+ * @bus: Pointer to the bus object. Must use &pci_bus_type for PCI and
+ *       &platform_bus_type for platform drivers. This property is used by the
+ *       offload subsystem to deduce the network driver's original pci_driver
+ *       or plaform_driver object from the @driver argument during driver
+ *       registration.
+ *       Beyond registration, the bus type is also used to deduce a pci_dev or
+ *       platform_device object from a `struct device` pointer.
+ * @ops: Network device operations
+ * @debugfs: Debugfs directory for the device
+ */
+struct ipa_eth_net_driver {
+	const char *name;
+	struct device_driver *driver;
+
+	unsigned long events;
+	unsigned long features;
+
+	struct bus_type *bus;
+	struct ipa_eth_net_ops *ops;
+
+	struct dentry *debugfs;
+};
+
+int ipa_eth_register_net_driver(struct ipa_eth_net_driver *nd);
+void ipa_eth_unregister_net_driver(struct ipa_eth_net_driver *nd);
+
+/**
+ * struct ipa_eth_bus_ops - Offload driver callbacks for bus operations
+ *
+ * These APIS are implemented by the offload driver for receiving bus level
+ * notifications like probe, remove, suspend, resume, etc.
+ */
+struct ipa_eth_bus_ops {
+	/**
+	 * .probe() - Probe new device for offload ability
+	 * @eth_dev: Device being probed
+	 *
+	 * This API is implemented by the offload driver and called immediately
+	 * after the network driver (PCI/plaform) probe. Offload driver is
+	 * expected to check if the device is compatible with the driver and
+	 * that the driver has enough offload resources for offloading the
+	 * device to IPA.
+	 *
+	 * The API implementation can expect the eth_dev->dev and eth_dev->nd
+	 * to have been already initialized by the offload subsystem. The API
+	 * is expected to perform at least the following:
+	 *
+	 * 1. Ensure the device is compatible with the offload driver. For
+	 *    plaform drivers, the .compatible DT property could be used while
+	 *    PCI IDs could be used for matching with a PCI device.
+	 * 2. If multiple network devices of the same type can be managed by the
+	 *    offload driver, it may attempt to pair @eth_dev with an available
+	 *    resource set for a single instance.
+	 * 3. Initialize the network device, typically by calling open_device()
+	 *    callback provided by the network driver.
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*probe)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .remove() - Handle device removal
+	 * @eth_dev: Device being removed
+	 *
+	 * The API implementation should assume the device to be no more
+	 * physically connected.
+	 */
+	void (*remove)(struct ipa_eth_device *eth_dev);
+
+	/* dev_pm_ops go here */
+};
+
+/**
+ * struct ipa_eth_offload_link_stats - Stats for each link within an
+ *                                     offload data path
+ * @valid: Stats are not available for the link
+ * @events: Number of events reported to the link
+ * @frames: Number of frames received by the link
+ * @packets: Number of packets received by the link
+ * @octets: Number of bytes received by the link
+ */
+struct ipa_eth_offload_link_stats {
+	bool valid;
+	u64 events;
+	u64 frames;
+	u64 packets;
+	u64 octets;
+};
+
+struct ipa_eth_offload_ch_stats {
+	struct ipa_eth_offload_link_stats ndev;
+	struct ipa_eth_offload_link_stats host;
+	struct ipa_eth_offload_link_stats uc;
+	struct ipa_eth_offload_link_stats gsi;
+	struct ipa_eth_offload_link_stats ipa;
+};
+
+struct ipa_eth_offload_stats {
+	struct ipa_eth_offload_ch_stats rx;
+	struct ipa_eth_offload_ch_stats tx;
+};
+
+/**
+ * struct ipa_eth_offload_ops - Offload operations provided by an offload driver
+ */
+struct ipa_eth_offload_ops {
+	/**
+	 * .init_tx() - Initialize offload path in Tx direction
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*init_tx)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .start_tx() - Start offload path in Tx direction
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*start_tx)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .stop_tx() - Stop offload path in Tx direction
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*stop_tx)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .deinit_tx() - Deinitialize offload path in Tx direction
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*deinit_tx)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .init_rx() - Initialize offload path in Rx direction
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*init_rx)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .start_rx() - Start offload path in Rx direction
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*start_rx)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .stop_rx() - Stop offload path in Rx direction
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*stop_rx)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .deinit_rx() - Deinitialize offload path in Rx direction
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*deinit_rx)(struct ipa_eth_device *eth_dev);
+
+	/**
+	 * .get_stats() - Get offload statistics
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*get_stats)(struct ipa_eth_device *eth_dev,
+		struct ipa_eth_offload_stats *stats);
+
+	/**
+	 * .clear_stats() - Clear offload statistics
+	 *
+	 * Return: 0 on success, negative errno otherwise
+	 */
+	int (*clear_stats)(struct ipa_eth_device *eth_dev);
+};
+
+/**
+ * struct ipa_eth_offload_driver - Offload driver to be registered with the
+ *                                 offload sub-system
+ * @driver_list: Entry in the global offload driver list
+ * @name: Name of the offload driver
+ * @bus: Supported network device bus type
+ * @ops: Offload operations
+ * @bus_ops: Bus level callbacks and operations for the offload driver
+ * @debugfs: Debugfs directory for the offload driver
+ */
+struct ipa_eth_offload_driver {
+	struct list_head driver_list;
+
+	const char *name;
+	struct bus_type *bus;
+
+	struct ipa_eth_offload_ops *ops;
+	struct ipa_eth_bus_ops *bus_ops;
+
+	struct dentry *debugfs;
+};
+
+int ipa_eth_register_offload_driver(struct ipa_eth_offload_driver *od);
+void ipa_eth_unregister_offload_driver(struct ipa_eth_offload_driver *od);
+
+int ipa_eth_ep_init(struct ipa_eth_channel *ch);
+int ipa_eth_ep_start(struct ipa_eth_channel *ch);
+int ipa_eth_ep_stop(struct ipa_eth_channel *ch);
+
+int ipa_eth_gsi_alloc(struct ipa_eth_channel *ch,
+	struct gsi_evt_ring_props *gsi_ev_props,
+	union gsi_evt_scratch *gsi_ev_scratch,
+	phys_addr_t *gsi_ev_db,
+	struct gsi_chan_props *gsi_ch_props,
+	union gsi_channel_scratch *gsi_ch_scratch,
+	phys_addr_t *gsi_ch_db);
+int ipa_eth_gsi_dealloc(struct ipa_eth_channel *ch);
+int ipa_eth_gsi_ring_evtring(struct ipa_eth_channel *ch, u64 value);
+int ipa_eth_gsi_ring_channel(struct ipa_eth_channel *ch, u64 value);
+int ipa_eth_gsi_start(struct ipa_eth_channel *ch);
+int ipa_eth_gsi_stop(struct ipa_eth_channel *ch);
+
+int ipa_eth_gsi_iommu_pamap(dma_addr_t daddr, phys_addr_t paddr,
+	size_t size, int prot, bool split);
+int ipa_eth_gsi_iommu_vamap(dma_addr_t daddr, void *vaddr,
+	size_t size, int prot, bool split);
+int ipa_eth_gsi_iommu_unmap(dma_addr_t daddr, size_t size, bool split);
+
+/* IPA uC interface for ethernet devices */
+
+enum ipa_eth_uc_op {
+	IPA_ETH_UC_OP_NOP         = 0,
+	IPA_ETH_UC_OP_CH_SETUP    = 1,
+	IPA_ETH_UC_OP_CH_TEARDOWN = 2,
+	IPA_ETH_UC_OP_PER_INIT    = 3,
+	IPA_ETH_UC_OP_PER_DEINIT  = 4,
+	IPA_ETH_UC_OP_MAX,
+};
+
+enum ipa_eth_uc_resp {
+	IPA_ETH_UC_RSP_SUCCESS                     = 0,
+	IPA_ETH_UC_RSP_MAX_TX_CHANNELS             = 1,
+	IPA_ETH_UC_RSP_TX_RING_OVERRUN_POSSIBILITY = 2,
+	IPA_ETH_UC_RSP_TX_RING_SET_UP_FAILURE      = 3,
+	IPA_ETH_UC_RSP_TX_RING_PARAMS_UNALIGNED    = 4,
+	IPA_ETH_UC_RSP_UNKNOWN_TX_CHANNEL          = 5,
+	IPA_ETH_UC_RSP_TX_INVALID_FSM_TRANSITION   = 6,
+	IPA_ETH_UC_RSP_TX_FSM_TRANSITION_ERROR     = 7,
+	IPA_ETH_UC_RSP_MAX_RX_CHANNELS             = 8,
+	IPA_ETH_UC_RSP_RX_RING_PARAMS_UNALIGNED    = 9,
+	IPA_ETH_UC_RSP_RX_RING_SET_UP_FAILURE      = 10,
+	IPA_ETH_UC_RSP_UNKNOWN_RX_CHANNEL          = 11,
+	IPA_ETH_UC_RSP_RX_INVALID_FSM_TRANSITION   = 12,
+	IPA_ETH_UC_RSP_RX_FSM_TRANSITION_ERROR     = 13,
+	IPA_ETH_UC_RSP_RX_RING_OVERRUN_POSSIBILITY = 14,
+};
+
+int ipa_eth_uc_send_cmd(enum ipa_eth_uc_op op, u32 protocol,
+	const void *prot_data, size_t datasz);
+
+int ipa_eth_uc_iommu_pamap(dma_addr_t daddr, phys_addr_t paddr,
+	size_t size, int prot, bool split);
+int ipa_eth_uc_iommu_vamap(dma_addr_t daddr, void *vaddr,
+	size_t size, int prot, bool split);
+int ipa_eth_uc_iommu_unmap(dma_addr_t daddr, size_t size, bool split);
+
+/* IPC logging interface */
+
+#define ipa_eth_ipc_do_log(ipcbuf, fmt, args...) \
+	do { \
+		void *__buf = (ipcbuf); \
+		if (__buf) \
+			ipc_log_string(__buf, " %s:%d " fmt "\n", \
+				__func__, __LINE__, ## args); \
+	} while (0)
+
+#define ipa_eth_ipc_log(fmt, args...) \
+	do { \
+		void *ipa_eth_get_ipc_logbuf(void); \
+		ipa_eth_ipc_do_log(ipa_eth_get_ipc_logbuf(), \
+					fmt, ## args); \
+	} while (0)
+
+#define ipa_eth_ipc_dbg(fmt, args...) \
+	do { \
+		void *ipa_eth_get_ipc_logbuf_dbg(void); \
+		ipa_eth_ipc_do_log(ipa_eth_get_ipc_logbuf_dbg(), \
+					fmt, ## args); \
+	} while (0)
+
+#endif // _IPA_ETH_H_
diff --git a/include/linux/ipa_wdi3.h b/include/linux/ipa_wdi3.h
index e893ba8..a6367ba 100644
--- a/include/linux/ipa_wdi3.h
+++ b/include/linux/ipa_wdi3.h
@@ -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
@@ -104,10 +104,12 @@ struct ipa_wdi_reg_intf_in_params {
  * @transfer_ring_size:  size of the transfer ring
  * @transfer_ring_doorbell_pa:  physical address of the doorbell that
 	IPA uC will update the tailpointer of the transfer ring
+ * @is_txr_rn_db_pcie_addr: Bool indicated txr ring DB is pcie or not
  * @event_ring_base_pa:  physical address of the base of the event ring
  * @event_ring_size:  event ring size
  * @event_ring_doorbell_pa:  physical address of the doorbell that IPA uC
 	will update the headpointer of the event ring
+ * @is_evt_rn_db_pcie_addr: Bool indicated evt ring DB is pcie or not
  * @num_pkt_buffers:  Number of pkt buffers allocated. The size of the event
 	ring and the transfer ring has to be atleast ( num_pkt_buffers + 1)
  * @pkt_offset: packet offset (wdi header length)
@@ -120,10 +122,12 @@ struct ipa_wdi_pipe_setup_info {
 	phys_addr_t  transfer_ring_base_pa;
 	u32  transfer_ring_size;
 	phys_addr_t  transfer_ring_doorbell_pa;
+	bool is_txr_rn_db_pcie_addr;
 
 	phys_addr_t  event_ring_base_pa;
 	u32  event_ring_size;
 	phys_addr_t  event_ring_doorbell_pa;
+	bool is_evt_rn_db_pcie_addr;
 	u16  num_pkt_buffers;
 
 	u16 pkt_offset;
@@ -139,10 +143,12 @@ struct ipa_wdi_pipe_setup_info {
  * @transfer_ring_size:  size of the transfer ring
  * @transfer_ring_doorbell_pa:  physical address of the doorbell that
 	IPA uC will update the tailpointer of the transfer ring
+ * @is_txr_rn_db_pcie_addr: Bool indicated  txr ring DB is pcie or not
  * @event_ring_base_pa:  physical address of the base of the event ring
  * @event_ring_size:  event ring size
  * @event_ring_doorbell_pa:  physical address of the doorbell that IPA uC
 	will update the headpointer of the event ring
+ * @is_evt_rn_db_pcie_addr: Bool indicated evt ring DB is pcie or not
  * @num_pkt_buffers:  Number of pkt buffers allocated. The size of the event
 	ring and the transfer ring has to be atleast ( num_pkt_buffers + 1)
  * @pkt_offset: packet offset (wdi header length)
@@ -155,10 +161,12 @@ struct ipa_wdi_pipe_setup_info_smmu {
 	struct sg_table  transfer_ring_base;
 	u32  transfer_ring_size;
 	phys_addr_t  transfer_ring_doorbell_pa;
+	bool is_txr_rn_db_pcie_addr;
 
 	struct sg_table  event_ring_base;
 	u32  event_ring_size;
 	phys_addr_t  event_ring_doorbell_pa;
+	bool is_evt_rn_db_pcie_addr;
 	u16  num_pkt_buffers;
 
 	u16 pkt_offset;
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index c8be15c..af47767 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -117,6 +117,23 @@ extern void kobject_put(struct kobject *kobj);
 extern const void *kobject_namespace(struct kobject *kobj);
 extern char *kobject_get_path(struct kobject *kobj, gfp_t flag);
 
+/**
+ * kobject_has_children - Returns whether a kobject has children.
+ * @kobj: the object to test
+ *
+ * This will return whether a kobject has other kobjects as children.
+ *
+ * It does NOT account for the presence of attribute files, only sub
+ * directories. It also assumes there is no concurrent addition or
+ * removal of such children, and thus relies on external locking.
+ */
+static inline bool kobject_has_children(struct kobject *kobj)
+{
+	WARN_ON_ONCE(kref_read(&kobj->kref) == 0);
+
+	return kobj->sd && kobj->sd->dir.subdirs;
+}
+
 struct kobj_type {
 	void (*release)(struct kobject *kobj);
 	const struct sysfs_ops *sysfs_ops;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index b81d458..4f7f19c 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -232,7 +232,7 @@ struct kvm_vcpu {
 	struct mutex mutex;
 	struct kvm_run *run;
 
-	int guest_fpu_loaded, guest_xcr0_loaded;
+	int guest_xcr0_loaded;
 	struct swait_queue_head wq;
 	struct pid __rcu *pid;
 	int sigset_active;
@@ -685,7 +685,8 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data,
 int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 			   void *data, unsigned long len);
 int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
-			   void *data, int offset, unsigned long len);
+				  void *data, unsigned int offset,
+				  unsigned long len);
 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 			      gpa_t gpa, unsigned long len);
 int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index fb677e4..88f0c53 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -1195,7 +1195,7 @@ enum {
 static inline const struct cpumask *
 mlx5_get_vector_affinity_hint(struct mlx5_core_dev *dev, int vector)
 {
-	return dev->priv.irq_info[vector].mask;
+	return dev->priv.irq_info[vector + MLX5_EQ_VEC_COMP_BASE].mask;
 }
 
 #endif /* MLX5_DRIVER_H */
diff --git a/include/linux/mm_types_task.h b/include/linux/mm_types_task.h
index d7016dc..4a49e8f 100644
--- a/include/linux/mm_types_task.h
+++ b/include/linux/mm_types_task.h
@@ -41,6 +41,7 @@ enum {
 	MM_ANONPAGES,	/* Resident anonymous pages */
 	MM_SWAPENTS,	/* Anonymous swap entries */
 	MM_SHMEMPAGES,	/* Resident shared memory pages */
+	MM_UNRECLAIMABLE,	/* Unreclaimable pages, e.g. shared with HW */
 	NR_MM_COUNTERS
 };
 
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 5bf820c..1964564 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -623,6 +623,8 @@ struct mmc_host {
 
 	bool			err_occurred;
 	u32			err_stats[MMC_ERR_MAX];
+	ktime_t			last_failed_rq_time;
+	ktime_t			last_completed_rq_time;
 
 	struct mmc_async_req	*areq;		/* active async req */
 	struct mmc_context_info	context_info;	/* async synchronization info */
@@ -708,6 +710,7 @@ struct mmc_host {
 	struct mmc_request	*err_mrq;
 
 	bool inlinecrypt_support;  /* Inline encryption support */
+	bool inlinecrypt_reset_needed;  /* Inline crypto reset */
 
 	atomic_t rpmb_req_pending;
 	struct mutex		rpmb_req_mutex;
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 68b4d97..fa5300c 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -183,6 +183,7 @@ enum node_stat_item {
 	NR_DIRTIED,		/* page dirtyings since bootup */
 	NR_WRITTEN,		/* page writings since bootup */
 	NR_INDIRECTLY_RECLAIMABLE_BYTES, /* measured in bytes */
+	NR_UNRECLAIMABLE_PAGES,
 	NR_VM_NODE_STAT_ITEMS
 };
 
diff --git a/include/linux/module.h b/include/linux/module.h
index b28e094..2d01e23 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -799,7 +799,7 @@ static inline void module_bug_finalize(const Elf_Ehdr *hdr,
 static inline void module_bug_cleanup(struct module *mod) {}
 #endif	/* CONFIG_GENERIC_BUG */
 
-#ifdef RETPOLINE
+#ifdef CONFIG_RETPOLINE
 extern bool retpoline_module_ok(bool has_retpoline);
 #else
 static inline bool retpoline_module_ok(bool has_retpoline)
diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h
index 6069245..42724b2 100644
--- a/include/linux/msm_gsi.h
+++ b/include/linux/msm_gsi.h
@@ -708,6 +708,21 @@ struct __packed gsi_wdi_channel_scratch {
 };
 
 /**
+* gsi_mhip_channel_scratch - MHI PRIME protocol SW config area of
+* channel scratch
+* @assert_bit_40: Valid only for non-host channels.
+* Set to 1 for MHIÂ’ channels when running over PCIe.
+* @host_channel: Set to 1 for MHIP channel running on host.
+*
+*/
+struct __packed gsi_mhip_channel_scratch {
+	uint32_t assert_bit_40:1;
+	uint32_t host_channel:1;
+	uint32_t resvd1:30;
+};
+
+
+/**
 * gsi_11ad_rx_channel_scratch - 11AD protocol SW config area of
 * RX channel scratch
 *
@@ -795,6 +810,7 @@ union __packed gsi_channel_scratch {
 	struct __packed gsi_11ad_rx_channel_scratch rx_11ad;
 	struct __packed gsi_11ad_tx_channel_scratch tx_11ad;
 	struct __packed gsi_wdi3_channel_scratch wdi3;
+	struct __packed gsi_mhip_channel_scratch mhip;
 	struct __packed {
 		uint32_t word1;
 		uint32_t word2;
@@ -835,6 +851,22 @@ struct __packed gsi_mhi_evt_scratch {
 };
 
 /**
+* gsi_mhip_evt_scratch - MHI PRIME protocol SW config area of
+* event scratch
+*/
+struct __packed gsi_mhip_evt_scratch {
+	uint32_t rp_mod_threshold:8;
+	uint32_t rp_mod_timer:4;
+	uint32_t rp_mod_counter:8;
+	uint32_t rp_mod_timer_id:4;
+	uint32_t rp_mod_timer_running:1;
+	uint32_t resvd1:7;
+	uint32_t fixed_buffer_sz:16;
+	uint32_t resvd2:16;
+};
+
+
+/**
  * gsi_xdci_evt_scratch - xDCI protocol SW config area of
  * event scratch
  *
@@ -899,6 +931,7 @@ union __packed gsi_evt_scratch {
 	struct __packed gsi_wdi_evt_scratch wdi;
 	struct __packed gsi_11ad_evt_scratch w11ad;
 	struct __packed gsi_wdi3_evt_scratch wdi3;
+	struct __packed gsi_mhip_evt_scratch mhip;
 	struct __packed {
 		uint32_t word1;
 		uint32_t word2;
diff --git a/include/linux/msm_mhi_dev.h b/include/linux/msm_mhi_dev.h
index c020a32..ba4ac43 100644
--- a/include/linux/msm_mhi_dev.h
+++ b/include/linux/msm_mhi_dev.h
@@ -67,7 +67,7 @@ struct mhi_req {
 	u32                             snd_cmpl;
 	void                            *context;
 	size_t                          len;
-	size_t                          actual_len;
+	size_t                          transfer_len;
 	uint32_t                        rd_offset;
 	struct mhi_dev_client           *client;
 	struct list_head                list;
@@ -132,6 +132,7 @@ enum mhi_client_channel {
 	MHI_CLIENT_RESERVED_1_UPPER = 99,
 	MHI_CLIENT_IP_HW_0_OUT = 100,
 	MHI_CLIENT_IP_HW_0_IN = 101,
+	MHI_CLIENT_ADPL_IN = 102,
 	MHI_CLIENT_RESERVED_2_LOWER = 102,
 	MHI_CLIENT_RESERVED_2_UPPER = 127,
 	MHI_MAX_CHANNELS = 102,
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 844a606..1bfd0dd 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -11,6 +11,8 @@
 #define _LINUX_NETDEV_FEATURES_H
 
 #include <linux/types.h>
+#include <linux/bitops.h>
+#include <asm/byteorder.h>
 
 typedef u64 netdev_features_t;
 
@@ -148,8 +150,26 @@ enum {
 #define	NETIF_F_RX_UDP_TUNNEL_PORT  __NETIF_F(RX_UDP_TUNNEL_PORT)
 #define NETIF_F_GSO_UDP_L4	__NETIF_F(GSO_UDP_L4)
 
-#define for_each_netdev_feature(mask_addr, bit)	\
-	for_each_set_bit(bit, (unsigned long *)mask_addr, NETDEV_FEATURE_COUNT)
+/* Finds the next feature with the highest number of the range of start till 0.
+ */
+static inline int find_next_netdev_feature(u64 feature, unsigned long start)
+{
+	/* like BITMAP_LAST_WORD_MASK() for u64
+	 * this sets the most significant 64 - start to 0.
+	 */
+	feature &= ~0ULL >> (-start & ((sizeof(feature) * 8) - 1));
+
+	return fls64(feature) - 1;
+}
+
+/* This goes for the MSB to the LSB through the set feature bits,
+ * mask_addr should be a u64 and bit an int
+ */
+#define for_each_netdev_feature(mask_addr, bit)				\
+	for ((bit) = find_next_netdev_feature((mask_addr),		\
+					      NETDEV_FEATURE_COUNT);	\
+	     (bit) >= 0;						\
+	     (bit) = find_next_netdev_feature((mask_addr), (bit) - 1))
 
 /* Features valid for ethtool to change */
 /* = all defined minus driver/device-class-related */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index aa2e6b0..699eeb7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1356,6 +1356,7 @@ struct net_device_ops {
  * @IFF_PHONY_HEADROOM: the headroom value is controlled by an external
  *	entity (i.e. the master device for bridged veth)
  * @IFF_MACSEC: device is a MACsec device
+ * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device
  */
 enum netdev_priv_flags {
 	IFF_802_1Q_VLAN			= 1<<0,
@@ -1386,6 +1387,7 @@ enum netdev_priv_flags {
 	IFF_RXFH_CONFIGURED		= 1<<25,
 	IFF_PHONY_HEADROOM		= 1<<26,
 	IFF_MACSEC			= 1<<27,
+	IFF_L3MDEV_RX_HANDLER		= 1<<28,
 };
 
 #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
@@ -1415,6 +1417,7 @@ enum netdev_priv_flags {
 #define IFF_TEAM			IFF_TEAM
 #define IFF_RXFH_CONFIGURED		IFF_RXFH_CONFIGURED
 #define IFF_MACSEC			IFF_MACSEC
+#define IFF_L3MDEV_RX_HANDLER		IFF_L3MDEV_RX_HANDLER
 
 /**
  *	struct net_device - The DEVICE structure.
@@ -4208,6 +4211,11 @@ static inline bool netif_supports_nofcs(struct net_device *dev)
 	return dev->priv_flags & IFF_SUPP_NOFCS;
 }
 
+static inline bool netif_has_l3_rx_handler(const struct net_device *dev)
+{
+	return dev->priv_flags & IFF_L3MDEV_RX_HANDLER;
+}
+
 static inline bool netif_is_l3_master(const struct net_device *dev)
 {
 	return dev->priv_flags & IFF_L3MDEV_MASTER;
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index bf588a0..5f23aac 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -11,8 +11,7 @@ struct device_node;
 
 #ifdef CONFIG_OF_PCI
 int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq);
-struct device_node *of_pci_find_child_device(struct device_node *parent,
-					     unsigned int devfn);
+struct device_node *of_pci_find_child_device(struct pci_dev *dev);
 int of_pci_get_devfn(struct device_node *np);
 int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
@@ -28,8 +27,7 @@ static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle
 	return 0;
 }
 
-static inline struct device_node *of_pci_find_child_device(struct device_node *parent,
-					     unsigned int devfn)
+static inline struct device_node *of_pci_find_child_device(struct pci_dev *dev)
 {
 	return NULL;
 }
diff --git a/include/linux/overflow.h b/include/linux/overflow.h
new file mode 100644
index 0000000..c8890ec
--- /dev/null
+++ b/include/linux/overflow.h
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+#ifndef __LINUX_OVERFLOW_H
+#define __LINUX_OVERFLOW_H
+
+#include <linux/compiler.h>
+
+/*
+ * In the fallback code below, we need to compute the minimum and
+ * maximum values representable in a given type. These macros may also
+ * be useful elsewhere, so we provide them outside the
+ * COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW block.
+ *
+ * It would seem more obvious to do something like
+ *
+ * #define type_min(T) (T)(is_signed_type(T) ? (T)1 << (8*sizeof(T)-1) : 0)
+ * #define type_max(T) (T)(is_signed_type(T) ? ((T)1 << (8*sizeof(T)-1)) - 1 : ~(T)0)
+ *
+ * Unfortunately, the middle expressions, strictly speaking, have
+ * undefined behaviour, and at least some versions of gcc warn about
+ * the type_max expression (but not if -fsanitize=undefined is in
+ * effect; in that case, the warning is deferred to runtime...).
+ *
+ * The slightly excessive casting in type_min is to make sure the
+ * macros also produce sensible values for the exotic type _Bool. [The
+ * overflow checkers only almost work for _Bool, but that's
+ * a-feature-not-a-bug, since people shouldn't be doing arithmetic on
+ * _Bools. Besides, the gcc builtins don't allow _Bool* as third
+ * argument.]
+ *
+ * Idea stolen from
+ * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html -
+ * credit to Christian Biere.
+ */
+#define is_signed_type(type)       (((type)(-1)) < (type)1)
+#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
+#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
+#define type_min(T) ((T)((T)-type_max(T)-(T)1))
+
+
+#ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
+/*
+ * For simplicity and code hygiene, the fallback code below insists on
+ * a, b and *d having the same type (similar to the min() and max()
+ * macros), whereas gcc's type-generic overflow checkers accept
+ * different types. Hence we don't just make check_add_overflow an
+ * alias for __builtin_add_overflow, but add type checks similar to
+ * below.
+ */
+#define check_add_overflow(a, b, d) ({		\
+	typeof(a) __a = (a);			\
+	typeof(b) __b = (b);			\
+	typeof(d) __d = (d);			\
+	(void) (&__a == &__b);			\
+	(void) (&__a == __d);			\
+	__builtin_add_overflow(__a, __b, __d);	\
+})
+
+#define check_sub_overflow(a, b, d) ({		\
+	typeof(a) __a = (a);			\
+	typeof(b) __b = (b);			\
+	typeof(d) __d = (d);			\
+	(void) (&__a == &__b);			\
+	(void) (&__a == __d);			\
+	__builtin_sub_overflow(__a, __b, __d);	\
+})
+
+#define check_mul_overflow(a, b, d) ({		\
+	typeof(a) __a = (a);			\
+	typeof(b) __b = (b);			\
+	typeof(d) __d = (d);			\
+	(void) (&__a == &__b);			\
+	(void) (&__a == __d);			\
+	__builtin_mul_overflow(__a, __b, __d);	\
+})
+
+#else
+
+
+/* Checking for unsigned overflow is relatively easy without causing UB. */
+#define __unsigned_add_overflow(a, b, d) ({	\
+	typeof(a) __a = (a);			\
+	typeof(b) __b = (b);			\
+	typeof(d) __d = (d);			\
+	(void) (&__a == &__b);			\
+	(void) (&__a == __d);			\
+	*__d = __a + __b;			\
+	*__d < __a;				\
+})
+#define __unsigned_sub_overflow(a, b, d) ({	\
+	typeof(a) __a = (a);			\
+	typeof(b) __b = (b);			\
+	typeof(d) __d = (d);			\
+	(void) (&__a == &__b);			\
+	(void) (&__a == __d);			\
+	*__d = __a - __b;			\
+	__a < __b;				\
+})
+/*
+ * If one of a or b is a compile-time constant, this avoids a division.
+ */
+#define __unsigned_mul_overflow(a, b, d) ({		\
+	typeof(a) __a = (a);				\
+	typeof(b) __b = (b);				\
+	typeof(d) __d = (d);				\
+	(void) (&__a == &__b);				\
+	(void) (&__a == __d);				\
+	*__d = __a * __b;				\
+	__builtin_constant_p(__b) ?			\
+	  __b > 0 && __a > type_max(typeof(__a)) / __b : \
+	  __a > 0 && __b > type_max(typeof(__b)) / __a;	 \
+})
+
+/*
+ * For signed types, detecting overflow is much harder, especially if
+ * we want to avoid UB. But the interface of these macros is such that
+ * we must provide a result in *d, and in fact we must produce the
+ * result promised by gcc's builtins, which is simply the possibly
+ * wrapped-around value. Fortunately, we can just formally do the
+ * operations in the widest relevant unsigned type (u64) and then
+ * truncate the result - gcc is smart enough to generate the same code
+ * with and without the (u64) casts.
+ */
+
+/*
+ * Adding two signed integers can overflow only if they have the same
+ * sign, and overflow has happened iff the result has the opposite
+ * sign.
+ */
+#define __signed_add_overflow(a, b, d) ({	\
+	typeof(a) __a = (a);			\
+	typeof(b) __b = (b);			\
+	typeof(d) __d = (d);			\
+	(void) (&__a == &__b);			\
+	(void) (&__a == __d);			\
+	*__d = (u64)__a + (u64)__b;		\
+	(((~(__a ^ __b)) & (*__d ^ __a))	\
+		& type_min(typeof(__a))) != 0;	\
+})
+
+/*
+ * Subtraction is similar, except that overflow can now happen only
+ * when the signs are opposite. In this case, overflow has happened if
+ * the result has the opposite sign of a.
+ */
+#define __signed_sub_overflow(a, b, d) ({	\
+	typeof(a) __a = (a);			\
+	typeof(b) __b = (b);			\
+	typeof(d) __d = (d);			\
+	(void) (&__a == &__b);			\
+	(void) (&__a == __d);			\
+	*__d = (u64)__a - (u64)__b;		\
+	((((__a ^ __b)) & (*__d ^ __a))		\
+		& type_min(typeof(__a))) != 0;	\
+})
+
+/*
+ * Signed multiplication is rather hard. gcc always follows C99, so
+ * division is truncated towards 0. This means that we can write the
+ * overflow check like this:
+ *
+ * (a > 0 && (b > MAX/a || b < MIN/a)) ||
+ * (a < -1 && (b > MIN/a || b < MAX/a) ||
+ * (a == -1 && b == MIN)
+ *
+ * The redundant casts of -1 are to silence an annoying -Wtype-limits
+ * (included in -Wextra) warning: When the type is u8 or u16, the
+ * __b_c_e in check_mul_overflow obviously selects
+ * __unsigned_mul_overflow, but unfortunately gcc still parses this
+ * code and warns about the limited range of __b.
+ */
+
+#define __signed_mul_overflow(a, b, d) ({				\
+	typeof(a) __a = (a);						\
+	typeof(b) __b = (b);						\
+	typeof(d) __d = (d);						\
+	typeof(a) __tmax = type_max(typeof(a));				\
+	typeof(a) __tmin = type_min(typeof(a));				\
+	(void) (&__a == &__b);						\
+	(void) (&__a == __d);						\
+	*__d = (u64)__a * (u64)__b;					\
+	(__b > 0   && (__a > __tmax/__b || __a < __tmin/__b)) ||	\
+	(__b < (typeof(__b))-1  && (__a > __tmin/__b || __a < __tmax/__b)) || \
+	(__b == (typeof(__b))-1 && __a == __tmin);			\
+})
+
+
+#define check_add_overflow(a, b, d)					\
+	__builtin_choose_expr(is_signed_type(typeof(a)),		\
+			__signed_add_overflow(a, b, d),			\
+			__unsigned_add_overflow(a, b, d))
+
+#define check_sub_overflow(a, b, d)					\
+	__builtin_choose_expr(is_signed_type(typeof(a)),		\
+			__signed_sub_overflow(a, b, d),			\
+			__unsigned_sub_overflow(a, b, d))
+
+#define check_mul_overflow(a, b, d)					\
+	__builtin_choose_expr(is_signed_type(typeof(a)),		\
+			__signed_mul_overflow(a, b, d),			\
+			__unsigned_mul_overflow(a, b, d))
+
+
+#endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
+
+#endif /* __LINUX_OVERFLOW_H */
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 51a9a0a..ac4cd09 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -256,6 +256,7 @@ pgoff_t page_cache_prev_hole(struct address_space *mapping,
 #define FGP_WRITE		0x00000008
 #define FGP_NOFS		0x00000010
 #define FGP_NOWAIT		0x00000020
+#define FGP_FOR_MMAP		0x00000040
 
 struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset,
 		int fgp_flags, gfp_t cache_gfp_mask);
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index c41878b..feb0fdf 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -448,6 +448,11 @@ struct pmu {
 	 * Filter events for PMU-specific reasons.
 	 */
 	int (*filter_match)		(struct perf_event *event); /* optional */
+
+	/*
+	 * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
+	 */
+	int (*check_period)		(struct perf_event *event, u64 value); /* optional */
 };
 
 /**
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 16ea771..42e194b 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -324,6 +324,9 @@ enum power_supply_property {
 	POWER_SUPPLY_PROP_BATT_AGE_LEVEL,
 	POWER_SUPPLY_PROP_VOLTAGE_VPH,
 	POWER_SUPPLY_PROP_CHIP_VERSION,
+	POWER_SUPPLY_PROP_THERM_ICL_LIMIT,
+	POWER_SUPPLY_PROP_DC_RESET,
+	POWER_SUPPLY_PROP_SCALE_MODE_EN,
 	/* Charge pump properties */
 	POWER_SUPPLY_PROP_CP_STATUS1,
 	POWER_SUPPLY_PROP_CP_STATUS2,
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index 9063cb4..f853b68 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -82,6 +82,7 @@ struct se_geni_rsc {
 };
 
 #define PINCTRL_DEFAULT	"default"
+#define PINCTRL_ACTIVE	"active"
 #define PINCTRL_SLEEP	"sleep"
 
 #define KHz(freq) (1000 * (freq))
diff --git a/include/linux/qed/qed_chain.h b/include/linux/qed/qed_chain.h
index 59ddf9a..2dd0a9e 100644
--- a/include/linux/qed/qed_chain.h
+++ b/include/linux/qed/qed_chain.h
@@ -663,6 +663,37 @@ static inline void *qed_chain_get_last_elem(struct qed_chain *p_chain)
 static inline void qed_chain_set_prod(struct qed_chain *p_chain,
 				      u32 prod_idx, void *p_prod_elem)
 {
+	if (p_chain->mode == QED_CHAIN_MODE_PBL) {
+		u32 cur_prod, page_mask, page_cnt, page_diff;
+
+		cur_prod = is_chain_u16(p_chain) ? p_chain->u.chain16.prod_idx :
+			   p_chain->u.chain32.prod_idx;
+
+		/* Assume that number of elements in a page is power of 2 */
+		page_mask = ~p_chain->elem_per_page_mask;
+
+		/* Use "cur_prod - 1" and "prod_idx - 1" since producer index
+		 * reaches the first element of next page before the page index
+		 * is incremented. See qed_chain_produce().
+		 * Index wrap around is not a problem because the difference
+		 * between current and given producer indices is always
+		 * positive and lower than the chain's capacity.
+		 */
+		page_diff = (((cur_prod - 1) & page_mask) -
+			     ((prod_idx - 1) & page_mask)) /
+			    p_chain->elem_per_page;
+
+		page_cnt = qed_chain_get_page_cnt(p_chain);
+		if (is_chain_u16(p_chain))
+			p_chain->pbl.c.u16.prod_page_idx =
+				(p_chain->pbl.c.u16.prod_page_idx -
+				 page_diff + page_cnt) % page_cnt;
+		else
+			p_chain->pbl.c.u32.prod_page_idx =
+				(p_chain->pbl.c.u32.prod_page_idx -
+				 page_diff + page_cnt) % page_cnt;
+	}
+
 	if (is_chain_u16(p_chain))
 		p_chain->u.chain16.prod_idx = (u16) prod_idx;
 	else
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6661fdd..6d8dd7c 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -810,6 +810,7 @@ struct task_struct {
 	unsigned int			policy;
 	int				nr_cpus_allowed;
 	cpumask_t			cpus_allowed;
+	cpumask_t			cpus_requested;
 
 #ifdef CONFIG_PREEMPT_RCU
 	int				rcu_read_lock_nesting;
diff --git a/include/linux/sched/coredump.h b/include/linux/sched/coredump.h
index ec912d0..ecdc654 100644
--- a/include/linux/sched/coredump.h
+++ b/include/linux/sched/coredump.h
@@ -71,6 +71,7 @@ static inline int get_dumpable(struct mm_struct *mm)
 #define MMF_HUGE_ZERO_PAGE	23      /* mm has ever used the global huge zero page */
 #define MMF_DISABLE_THP		24	/* disable THP for all VMAs */
 #define MMF_OOM_VICTIM		25	/* mm is the oom victim */
+#define MMF_OOM_REAP_QUEUED	26	/* mm was queued for oom_reaper */
 #define MMF_DISABLE_THP_MASK	(1 << MMF_DISABLE_THP)
 
 #define MMF_INIT_MASK		(MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK |\
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index efce73b..07d2284 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2383,7 +2383,7 @@ static inline void skb_probe_transport_header(struct sk_buff *skb,
 		return;
 	else if (skb_flow_dissect_flow_keys(skb, &keys, 0))
 		skb_set_transport_header(skb, keys.control.thoff);
-	else
+	else if (offset_hint >= 0)
 		skb_set_transport_header(skb, offset_hint);
 }
 
@@ -3169,6 +3169,7 @@ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len);
  *
  *	This is exactly the same as pskb_trim except that it ensures the
  *	checksum of received packets are still valid after the operation.
+ *	It can change skb pointers.
  */
 
 static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
@@ -3322,6 +3323,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
 void skb_scrub_packet(struct sk_buff *skb, bool xnet);
 unsigned int skb_gso_transport_seglen(const struct sk_buff *skb);
 bool skb_gso_validate_mtu(const struct sk_buff *skb, unsigned int mtu);
+bool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len);
 struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features);
 struct sk_buff *skb_vlan_untag(struct sk_buff *skb);
 int skb_ensure_writable(struct sk_buff *skb, int write_len);
@@ -4092,6 +4094,21 @@ static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
 	return hdr_len + skb_gso_transport_seglen(skb);
 }
 
+/**
+ * skb_gso_mac_seglen - Return length of individual segments of a gso packet
+ *
+ * @skb: GSO skb
+ *
+ * skb_gso_mac_seglen is used to determine the real size of the
+ * individual segments, including MAC/L2, Layer3 (IP, IPv6) and L4
+ * headers (TCP/UDP).
+ */
+static inline unsigned int skb_gso_mac_seglen(const struct sk_buff *skb)
+{
+	unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
+	return hdr_len + skb_gso_transport_seglen(skb);
+}
+
 /* Local Checksum Offload.
  * Compute outer checksum based on the assumption that the
  * inner checksum will be offloaded later.
diff --git a/include/linux/soc/qcom/qmi.h b/include/linux/soc/qcom/qmi.h
index df41a61..8a0fa18f 100644
--- a/include/linux/soc/qcom/qmi.h
+++ b/include/linux/soc/qcom/qmi.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017, Linaro Ltd.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -275,5 +275,6 @@ int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn,
 		 struct qmi_elem_info *ei, void *c_struct);
 int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout);
 void qmi_txn_cancel(struct qmi_txn *txn);
+void qmi_set_sndtimeo(struct qmi_handle *qmi, long timeo);
 
 #endif
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 3b9f0d1..e1aa80c4 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -292,9 +292,12 @@ struct svc_rqst {
 	struct svc_cacherep *	rq_cacherep;	/* cache info */
 	struct task_struct	*rq_task;	/* service thread */
 	spinlock_t		rq_lock;	/* per-request lock */
+	struct net		*rq_bc_net;	/* pointer to backchannel's
+						 * net namespace
+						 */
 };
 
-#define SVC_NET(svc_rqst)	(svc_rqst->rq_xprt->xpt_net)
+#define SVC_NET(rqst) (rqst->rq_xprt ? rqst->rq_xprt->xpt_net : rqst->rq_bc_net)
 
 /*
  * Rigorous type checking on sockaddr type conversions
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 827aa3d..c3ba7a3 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -233,7 +233,6 @@ struct swap_info_struct {
 	unsigned long	flags;		/* SWP_USED etc: see above */
 	signed short	prio;		/* swap priority of this type */
 	struct plist_node list;		/* entry in swap_active_head */
-	struct plist_node avail_lists[MAX_NUMNODES];/* entry in swap_avail_heads */
 	signed char	type;		/* strange name for an index */
 	unsigned int	max;		/* extent of the swap_map */
 	unsigned char *swap_map;	/* vmalloc'ed array of usage counts */
@@ -276,6 +275,16 @@ struct swap_info_struct {
 	struct swap_cluster_list discard_clusters; /* discard clusters list */
 	unsigned int write_pending;
 	unsigned int max_writes;
+	struct plist_node avail_lists[0]; /*
+					   * entries in swap_avail_heads, one
+					   * entry per node.
+					   * Must be last as the number of the
+					   * array is nr_node_ids, which is not
+					   * a fixed value so have to allocate
+					   * dynamically.
+					   * And it has to be an array so that
+					   * plist_for_each_* can work.
+					   */
 };
 
 #ifdef CONFIG_64BIT
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 449a954..9bddc45 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -143,6 +143,9 @@ struct thermal_zone_device_ops {
 			  enum thermal_trend *);
 	int (*notify) (struct thermal_zone_device *, int,
 		       enum thermal_trip_type);
+	bool (*is_wakeable)(struct thermal_zone_device *);
+	int (*set_polling_delay)(struct thermal_zone_device *, int);
+	int (*set_passive_delay)(struct thermal_zone_device *, int);
 };
 
 struct thermal_cooling_device_ops {
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h
index 3c85c81..6f8b68c 100644
--- a/include/linux/uio_driver.h
+++ b/include/linux/uio_driver.h
@@ -14,6 +14,7 @@
 #ifndef _UIO_DRIVER_H_
 #define _UIO_DRIVER_H_
 
+#include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 
@@ -68,12 +69,13 @@ struct uio_port {
 
 struct uio_device {
         struct module           *owner;
-        struct device           *dev;
+	struct device		dev;
         int                     minor;
         atomic_t                event;
         struct fasync_struct    *async_queue;
         wait_queue_head_t       wait;
         struct uio_info         *info;
+	struct mutex		info_lock;
         struct kobject          *map_dir;
         struct kobject          *portio_dir;
 };
diff --git a/include/linux/usb/diag_bridge.h b/include/linux/usb/diag_bridge.h
new file mode 100644
index 0000000..806b380
--- /dev/null
+++ b/include/linux/usb/diag_bridge.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2011, 2013, 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.
+ */
+
+#ifndef __LINUX_USB_DIAG_BRIDGE_H__
+#define __LINUX_USB_DIAG_BRIDGE_H__
+
+struct diag_bridge_ops {
+	void *ctxt;
+	void (*read_complete_cb)(void *ctxt, char *buf,
+			int buf_size, int actual);
+	void (*write_complete_cb)(void *ctxt, char *buf,
+			int buf_size, int actual);
+	int (*suspend)(void *ctxt);
+	void (*resume)(void *ctxt);
+};
+
+#if IS_ENABLED(CONFIG_USB_QCOM_DIAG_BRIDGE)
+
+extern int diag_bridge_read(int id, char *data, int size);
+extern int diag_bridge_write(int id, char *data, int size);
+extern int diag_bridge_open(int id, struct diag_bridge_ops *ops);
+extern void diag_bridge_close(int id);
+
+#else
+
+static int __maybe_unused diag_bridge_read(int id, char *data, int size)
+{
+	return -ENODEV;
+}
+
+static int __maybe_unused diag_bridge_write(int id, char *data, int size)
+{
+	return -ENODEV;
+}
+
+static int __maybe_unused diag_bridge_open(int id, struct diag_bridge_ops *ops)
+{
+	return -ENODEV;
+}
+
+static void __maybe_unused diag_bridge_close(int id) { }
+
+#endif
+
+#endif
diff --git a/include/linux/usb/usbpd.h b/include/linux/usb/usbpd.h
index e1c39e1..20ce9aa 100644
--- a/include/linux/usb/usbpd.h
+++ b/include/linux/usb/usbpd.h
@@ -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
@@ -105,6 +105,8 @@ int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd,
  *         otherwise ORIENTATION_NONE if not attached
  */
 enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd);
+
+void usbpd_vdm_in_suspend(struct usbpd *pd, bool in_suspend);
 #else
 static inline struct usbpd *devm_usbpd_get_by_phandle(struct device *dev,
 		const char *phandle)
@@ -140,6 +142,8 @@ static inline enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd)
 {
 	return ORIENTATION_NONE;
 }
+
+static inline void usbpd_vdm_in_suspend(struct usbpd *pd, bool in_suspend) { }
 #endif /* IS_ENABLED(CONFIG_USB_PD_POLICY) */
 
 /*
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index cb462f9..e0348cb 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -57,6 +57,25 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
 
 		if (!skb_partial_csum_set(skb, start, off))
 			return -EINVAL;
+	} else {
+		/* gso packets without NEEDS_CSUM do not set transport_offset.
+		 * probe and drop if does not match one of the above types.
+		 */
+		if (gso_type && skb->network_header) {
+			if (!skb->protocol)
+				virtio_net_hdr_set_proto(skb, hdr);
+retry:
+			skb_probe_transport_header(skb, -1);
+			if (!skb_transport_header_was_set(skb)) {
+				/* UFO does not specify ipv4 or 6: try both */
+				if (gso_type & SKB_GSO_UDP &&
+				    skb->protocol == htons(ETH_P_IP)) {
+					skb->protocol = htons(ETH_P_IPV6);
+					goto retry;
+				}
+				return -EINVAL;
+			}
+		}
 	}
 
 	if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 1e5d8c3..3c4ebcf 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -62,10 +62,12 @@ extern void vm_unmap_aliases(void);
 
 #ifdef CONFIG_MMU
 extern void __init vmalloc_init(void);
+extern unsigned long vmalloc_nr_pages(void);
 #else
 static inline void vmalloc_init(void)
 {
 }
+static inline unsigned long vmalloc_nr_pages(void) { return 0; }
 #endif
 
 extern void *vmalloc(unsigned long size);
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index bd817a3..599b8d0 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -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
@@ -84,6 +84,7 @@ struct msm_camera_csid_params32 {
 	uint32_t csi_clk;
 	struct msm_camera_csid_lut_params32 lut_params;
 	uint8_t csi_3p_sel;
+	uint8_t is_secure;
 };
 
 struct msm_camera_csi2_params32 {
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 76fb39c..e667bca 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -200,6 +200,18 @@ static inline void ax25_hold_route(ax25_route *ax25_rt)
 
 void __ax25_put_route(ax25_route *ax25_rt);
 
+extern rwlock_t ax25_route_lock;
+
+static inline void ax25_route_lock_use(void)
+{
+	read_lock(&ax25_route_lock);
+}
+
+static inline void ax25_route_lock_unuse(void)
+{
+	read_unlock(&ax25_route_lock);
+}
+
 static inline void ax25_put_route(ax25_route *ax25_rt)
 {
 	if (refcount_dec_and_test(&ax25_rt->refcount))
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 54a221e..0aee0d2 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -47,6 +47,9 @@
 /* Indicate backport support for per chain rssi scan */
 #define CFG80211_SCAN_PER_CHAIN_RSSI_SUPPORT 1
 
+/* Indicate backport support for oce scan capability flags */
+#define CFG80211_SCAN_OCE_CAPABILITY_SUPPORT 1
+
 /**
  * DOC: Introduction
  *
@@ -755,6 +758,17 @@ struct cfg80211_bitrate_mask {
 };
 
 /**
+ * enum cfg80211_ap_settings_flags - AP settings flags
+ *
+ * Used by cfg80211_ap_settings
+ *
+ * @AP_SETTINGS_EXTERNAL_AUTH_SUPPORT: AP supports external authentication
+ */
+enum cfg80211_ap_settings_flags {
+	AP_SETTINGS_EXTERNAL_AUTH_SUPPORT = BIT(0),
+};
+
+/**
  * struct cfg80211_ap_settings - AP configuration
  *
  * Used to configure an AP interface.
@@ -783,6 +797,7 @@ struct cfg80211_bitrate_mask {
  * @vht_cap: VHT capabilities (or %NULL if VHT isn't enabled)
  * @ht_required: stations must support HT
  * @vht_required: stations must support VHT
+ * @flags: flags, as defined in enum cfg80211_ap_settings_flags
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_chan_def chandef;
@@ -807,6 +822,7 @@ struct cfg80211_ap_settings {
 	const struct ieee80211_ht_cap *ht_cap;
 	const struct ieee80211_vht_cap *vht_cap;
 	bool ht_required, vht_required;
+	u32 flags;
 };
 
 /**
@@ -2655,6 +2671,7 @@ struct cfg80211_pmk_conf {
  *	use %WLAN_STATUS_UNSPECIFIED_FAILURE if user space cannot give you
  *	the real status code for failures. Used only for the authentication
  *	response command interface (user space to driver).
+ * @pmkid: The identifier to refer a PMKSA.
  */
 struct cfg80211_external_auth_params {
 	enum nl80211_external_auth_action action;
@@ -2662,6 +2679,7 @@ struct cfg80211_external_auth_params {
 	struct cfg80211_ssid ssid;
 	unsigned int key_mgmt_suite;
 	u16 status;
+	const u8 *pmkid;
 };
 
 /**
diff --git a/include/net/cnss2.h b/include/net/cnss2.h
index 8a1772e..1fe1e07 100644
--- a/include/net/cnss2.h
+++ b/include/net/cnss2.h
@@ -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
@@ -14,6 +14,7 @@
 #define _NET_CNSS2_H
 
 #include <linux/pci.h>
+#include <linux/usb.h>
 
 #define CNSS_MAX_FILE_NAME		20
 #define CNSS_MAX_TIMESTAMP_LEN		32
@@ -83,6 +84,21 @@ struct cnss_wlan_driver {
 	const struct pci_device_id *id_table;
 };
 
+struct cnss_usb_wlan_driver {
+	char *name;
+	int  (*probe)(struct usb_interface *pintf, const struct usb_device_id
+		      *id);
+	void (*remove)(struct usb_interface *pintf);
+	int  (*reinit)(struct usb_interface *pintf, const struct usb_device_id
+		       *id);
+	void (*shutdown)(struct usb_interface *pintf);
+	void (*crash_shutdown)(struct usb_interface *pintf);
+	int  (*suspend)(struct usb_interface *pintf, pm_message_t state);
+	int  (*resume)(struct usb_interface *pintf);
+	int  (*reset_resume)(struct usb_interface *pintf);
+	const struct usb_device_id *id_table;
+};
+
 enum cnss_driver_status {
 	CNSS_UNINITIALIZED,
 	CNSS_INITIALIZED,
@@ -205,5 +221,7 @@ extern int cnss_athdiag_write(struct device *dev, uint32_t offset,
 			      uint32_t mem_type, uint32_t data_len,
 			      uint8_t *input);
 extern int cnss_set_fw_log_mode(struct device *dev, uint8_t fw_log_mode);
-
+extern int cnss_usb_wlan_register_driver(struct cnss_usb_wlan_driver *driver);
+extern void cnss_usb_wlan_unregister_driver(struct cnss_usb_wlan_driver *
+					    driver);
 #endif /* _NET_CNSS2_H */
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 00b5e78..74ff688 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -39,6 +39,7 @@ struct inet_peer {
 
 	u32			metrics[RTAX_MAX];
 	u32			rate_tokens;	/* rate limiting for ICMP */
+	u32			n_redirects;
 	unsigned long		rate_last;
 	/*
 	 * Once inet_peer is queued for deletion (refcnt == 0), following field
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 32df528..b711317 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -233,7 +233,7 @@ int fib_table_delete(struct net *, struct fib_table *, struct fib_config *,
 		     struct netlink_ext_ack *extack);
 int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
 		   struct netlink_callback *cb);
-int fib_table_flush(struct net *net, struct fib_table *table);
+int fib_table_flush(struct net *net, struct fib_table *table, bool flush_all);
 struct fib_table *fib_trie_unmerge(struct fib_table *main_tb);
 void fib_table_flush_external(struct fib_table *table);
 void fib_free_table(struct fib_table *tb);
diff --git a/include/net/l3mdev.h b/include/net/l3mdev.h
index 3832099..1284876 100644
--- a/include/net/l3mdev.h
+++ b/include/net/l3mdev.h
@@ -142,7 +142,8 @@ struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto)
 
 	if (netif_is_l3_slave(skb->dev))
 		master = netdev_master_upper_dev_get_rcu(skb->dev);
-	else if (netif_is_l3_master(skb->dev))
+	else if (netif_is_l3_master(skb->dev) ||
+		 netif_has_l3_rx_handler(skb->dev))
 		master = skb->dev;
 
 	if (master && master->l3mdev_ops->l3mdev_l3_rcv)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index f42bd8a..fcf6eea 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1639,6 +1639,7 @@ static inline void tcp_write_queue_purge(struct sock *sk)
 	tcp_clear_all_retrans_hints(tcp_sk(sk));
 	tcp_init_send_head(sk);
 	tcp_sk(sk)->packets_out = 0;
+	inet_csk(sk)->icsk_backoff = 0;
 }
 
 static inline struct sk_buff *tcp_write_queue_head(const struct sock *sk)
diff --git a/include/soc/qcom/qmi_rmnet.h b/include/soc/qcom/qmi_rmnet.h
index 0bb1b9a..967d92f 100644
--- a/include/soc/qcom/qmi_rmnet.h
+++ b/include/soc/qcom/qmi_rmnet.h
@@ -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
@@ -28,6 +28,7 @@ struct qmi_rmnet_ps_ind {
 void qmi_rmnet_qmi_exit(void *qmi_pt, void *port);
 void qmi_rmnet_change_link(struct net_device *dev, void *port, void *tcm_pt);
 void qmi_rmnet_enable_all_flows(struct net_device *dev);
+bool qmi_rmnet_all_flows_enabled(struct net_device *dev);
 #else
 static inline void qmi_rmnet_qmi_exit(void *qmi_pt, void *port)
 {
@@ -42,6 +43,12 @@ static inline void
 qmi_rmnet_enable_all_flows(struct net_device *dev)
 {
 }
+
+static inline bool
+qmi_rmnet_all_flows_enabled(struct net_device *dev)
+{
+	return true;
+}
 #endif
 
 #ifdef CONFIG_QCOM_QMI_DFC
@@ -79,7 +86,7 @@ int qmi_rmnet_set_powersave_mode(void *port, uint8_t enable);
 void qmi_rmnet_work_init(void *port);
 void qmi_rmnet_work_exit(void *port);
 void qmi_rmnet_work_maybe_restart(void *port);
-void qmi_rmnet_work_restart(void *port);
+void qmi_rmnet_set_dl_msg_active(void *port);
 
 int qmi_rmnet_ps_ind_register(void *port,
 			      struct qmi_rmnet_ps_ind *ps_ind);
@@ -96,18 +103,16 @@ static inline int qmi_rmnet_set_powersave_mode(void *port, uint8_t enable)
 static inline void qmi_rmnet_work_init(void *port)
 {
 }
-static inline void qmi_rmnet_work_restart(void *port)
-{
-
-}
 static inline void qmi_rmnet_work_exit(void *port)
 {
 }
-
 static inline void qmi_rmnet_work_maybe_restart(void *port)
 {
 
 }
+static inline void qmi_rmnet_set_dl_msg_active(void *port)
+{
+}
 
 static inline int qmi_rmnet_ps_ind_register(struct rmnet_port *port,
 				     struct qmi_rmnet_ps_ind *ps_ind)
diff --git a/include/soc/qcom/rmnet_qmi.h b/include/soc/qcom/rmnet_qmi.h
index 241d95c..fcf48d9 100644
--- a/include/soc/qcom/rmnet_qmi.h
+++ b/include/soc/qcom/rmnet_qmi.h
@@ -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
@@ -27,6 +27,7 @@ struct net_device *rmnet_get_rmnet_dev(void *port, u8 mux_id);
 void rmnet_reset_qmi_pt(void *port);
 void rmnet_init_qmi_pt(void *port, void *qmi);
 void rmnet_enable_all_flows(void *port);
+bool rmnet_all_flows_enabled(void *port);
 void rmnet_set_powersave_format(void *port);
 void rmnet_clear_powersave_format(void *port);
 void rmnet_get_packets(void *port, u64 *rx, u64 *tx);
@@ -65,6 +66,11 @@ static inline void rmnet_enable_all_flows(void *port)
 {
 }
 
+static inline bool rmnet_all_flows_enabled(void *port)
+{
+	return true;
+}
+
 static inline void rmnet_set_port_format(void *port)
 {
 }
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index e26f8f8..cce7a16 100644
--- a/include/soc/qcom/socinfo.h
+++ b/include/soc/qcom/socinfo.h
@@ -69,6 +69,8 @@
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdmshrike")
 #define early_machine_is_sm6150()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sm6150")
+#define early_machine_is_sm6150p()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sm6150p")
 #define early_machine_is_qcs405()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,qcs405")
 #define early_machine_is_qcs403()	\
@@ -79,6 +81,8 @@
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdxprairie")
 #define early_machine_is_sdmmagpie()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdmmagpie")
+#define early_machine_is_sdmmagpiep()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdmmagpiep")
 #define early_machine_is_sa6155p()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sa6155p")
 #define early_machine_is_sa4155p()	\
@@ -87,6 +91,12 @@
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sa6155")
 #define early_machine_is_trinket()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,trinket")
+#define early_machine_is_qcs610()      \
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,qcs610")
+#define early_machine_is_qcs410()      \
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,qcs410")
+#define early_machine_is_atoll()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,atoll")
 #else
 #define of_board_is_sim()		0
 #define of_board_is_rumi()		0
@@ -111,15 +121,20 @@
 #define early_machine_is_sa8155p()	0
 #define early_machine_is_sdmshrike()	0
 #define early_machine_is_sm6150()	0
+#define early_machine_is_sm6150p()	0
 #define early_machine_is_qcs405()	0
 #define early_machine_is_qcs403()	0
 #define early_machine_is_qcs401()	0
 #define early_machine_is_sdxprairie()	0
 #define early_machine_is_sdmmagpie()	0
+#define early_machine_is_sdmmagpiep()	0
 #define early_machine_is_sa6155p()	0
 #define early_machine_is_sa4155p()	0
 #define early_machine_is_sa6155()	0
 #define early_machine_is_trinket()	0
+#define early_machine_is_qcs610()       0
+#define early_machine_is_qcs410()       0
+#define early_machine_is_atoll()	0
 #endif
 
 #define PLATFORM_SUBTYPE_MDM	1
@@ -146,15 +161,20 @@ enum msm_cpu {
 	MSM_CPU_SA8155P,
 	MSM_CPU_SDMSHRIKE,
 	MSM_CPU_SM6150,
+	MSM_CPU_SM6150P,
 	MSM_CPU_QCS405,
 	MSM_CPU_QCS403,
 	MSM_CPU_QCS401,
 	SDX_CPU_SDXPRAIRIE,
 	MSM_CPU_SDMMAGPIE,
+	MSM_CPU_SDMMAGPIEP,
 	MSM_CPU_SA6155P,
 	MSM_CPU_SA4155P,
 	MSM_CPU_SA6155,
 	MSM_CPU_TRINKET,
+	MSM_CPU_QCS610,
+	MSM_CPU_QCS410,
+	MSM_CPU_ATOLL,
 };
 
 struct msm_soc_info {
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
index e929c67..2fb98a40 100644
--- a/include/sound/compress_driver.h
+++ b/include/sound/compress_driver.h
@@ -192,7 +192,11 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
 	if (snd_BUG_ON(!stream))
 		return;
 
-	stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+	if (stream->direction == SND_COMPRESS_PLAYBACK)
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+	else
+		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+
 	wake_up(&stream->runtime->sleep);
 }
 
diff --git a/include/trace/events/dfc.h b/include/trace/events/dfc.h
index 10570cc..70eec10 100644
--- a/include/trace/events/dfc.h
+++ b/include/trace/events/dfc.h
@@ -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
@@ -218,6 +218,33 @@ TRACE_EVENT(dfc_qmap_cmd,
 		__entry->type, __entry->tran)
 );
 
+TRACE_EVENT(dfc_tx_link_status_ind,
+
+	TP_PROTO(int src, int idx, u8 status, u8 mux_id, u8 bearer_id),
+
+	TP_ARGS(src, idx, status, mux_id, bearer_id),
+
+	TP_STRUCT__entry(
+		__field(int, src)
+		__field(int, idx)
+		__field(u8, status)
+		__field(u8, mid)
+		__field(u8, bid)
+	),
+
+	TP_fast_assign(
+		__entry->src = src;
+		__entry->idx = idx;
+		__entry->status = status;
+		__entry->mid = mux_id;
+		__entry->bid = bearer_id;
+	),
+
+	TP_printk("src=%d [%d]: status=%u mux_id=%u bearer_id=%u",
+		__entry->src, __entry->idx, __entry->status,
+		__entry->mid, __entry->bid)
+);
+
 #endif /* _TRACE_DFC_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/irq.h b/include/trace/events/irq.h
index eeceafa..bd6ecf6 100644
--- a/include/trace/events/irq.h
+++ b/include/trace/events/irq.h
@@ -160,6 +160,51 @@ DEFINE_EVENT(softirq, softirq_raise,
 	TP_ARGS(vec_nr)
 );
 
+DECLARE_EVENT_CLASS(tasklet,
+
+	TP_PROTO(void *func),
+
+	TP_ARGS(func),
+
+	TP_STRUCT__entry(
+		__field( void *,	func)
+	),
+
+	TP_fast_assign(
+		__entry->func = func;
+	),
+
+	TP_printk("function=%pf", __entry->func)
+);
+
+DEFINE_EVENT(tasklet, tasklet_entry,
+
+	TP_PROTO(void *func),
+
+	TP_ARGS(func)
+);
+
+DEFINE_EVENT(tasklet, tasklet_exit,
+
+	TP_PROTO(void *func),
+
+	TP_ARGS(func)
+);
+
+DEFINE_EVENT(tasklet, tasklet_hi_entry,
+
+	TP_PROTO(void *func),
+
+	TP_ARGS(func)
+);
+
+DEFINE_EVENT(tasklet, tasklet_hi_exit,
+
+	TP_PROTO(void *func),
+
+	TP_ARGS(func)
+);
+
 #endif /*  _TRACE_IRQ_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/tgu.h b/include/trace/events/tgu.h
new file mode 100644
index 0000000..1fd02ae
--- /dev/null
+++ b/include/trace/events/tgu.h
@@ -0,0 +1,40 @@
+/* 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM tgu
+
+#if !defined(_TRACE_TGU_) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_TGU_H_
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(tgu_interrupt,
+
+	TP_PROTO(uint32_t irqs),
+
+	TP_ARGS(irqs),
+
+	TP_STRUCT__entry(
+		__field(uint32_t, irqs)
+	),
+
+	TP_fast_assign(
+		__entry->irqs = irqs;
+	),
+
+	TP_printk("irq:%u  ", __entry->irqs)
+);
+
+#endif
+#define TRACE_INCLUDE_FILE tgu
+#include <trace/define_trace.h>
diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h
index b4723e3..4fed615 100644
--- a/include/uapi/linux/android/binder.h
+++ b/include/uapi/linux/android/binder.h
@@ -88,6 +88,16 @@ enum flat_binder_object_flags {
 	 * scheduling policy from the caller (for synchronous transactions).
 	 */
 	FLAT_BINDER_FLAG_INHERIT_RT = 0x800,
+#ifdef __KERNEL__
+
+	/**
+	 * @FLAT_BINDER_FLAG_TXN_SECURITY_CTX: request security contexts
+	 *
+	 * Only when set, causes senders to include their security
+	 * context
+	 */
+	FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
+#endif /* __KERNEL__ */
 };
 
 #ifdef BINDER_IPC_32BIT
@@ -247,6 +257,15 @@ struct binder_node_debug_info {
 	__u32            has_weak_ref;
 };
 
+struct binder_node_info_for_ref {
+	__u32            handle;
+	__u32            strong_count;
+	__u32            weak_count;
+	__u32            reserved1;
+	__u32            reserved2;
+	__u32            reserved3;
+};
+
 #define BINDER_WRITE_READ		_IOWR('b', 1, struct binder_write_read)
 #define BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, __s64)
 #define BINDER_SET_MAX_THREADS		_IOW('b', 5, __u32)
@@ -255,6 +274,8 @@ struct binder_node_debug_info {
 #define BINDER_THREAD_EXIT		_IOW('b', 8, __s32)
 #define BINDER_VERSION			_IOWR('b', 9, struct binder_version)
 #define BINDER_GET_NODE_DEBUG_INFO	_IOWR('b', 11, struct binder_node_debug_info)
+#define BINDER_GET_NODE_INFO_FOR_REF	_IOWR('b', 12, struct binder_node_info_for_ref)
+#define BINDER_SET_CONTEXT_MGR_EXT	_IOW('b', 13, struct flat_binder_object)
 
 /*
  * NOTE: Two special error codes you should check for when calling
@@ -313,6 +334,13 @@ struct binder_transaction_data {
 	} data;
 };
 
+#ifdef __KERNEL__
+struct binder_transaction_data_secctx {
+	struct binder_transaction_data transaction_data;
+	binder_uintptr_t secctx;
+};
+
+#endif /* __KERNEL__ */
 struct binder_transaction_data_sg {
 	struct binder_transaction_data transaction_data;
 	binder_size_t buffers_size;
@@ -348,6 +376,13 @@ enum binder_driver_return_protocol {
 	BR_OK = _IO('r', 1),
 	/* No parameters! */
 
+#ifdef __KERNEL__
+	BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
+				      struct binder_transaction_data_secctx),
+	/*
+	 * binder_transaction_data_secctx: the received command.
+	 */
+#endif /* __KERNEL__ */
 	BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
 	BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
 	/*
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 244e321..1d1157e 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -150,11 +150,18 @@
  *	This is an Ethernet frame header.
  */
 
+/* allow libcs like musl to deactivate this, glibc does not implement this. */
+#ifndef __UAPI_DEF_ETHHDR
+#define __UAPI_DEF_ETHHDR		1
+#endif
+
+#if __UAPI_DEF_ETHHDR
 struct ethhdr {
 	unsigned char	h_dest[ETH_ALEN];	/* destination eth addr	*/
 	unsigned char	h_source[ETH_ALEN];	/* source ether addr	*/
 	__be16		h_proto;		/* packet type ID field	*/
 } __attribute__((packed));
+#endif
 
 
 #endif /* _UAPI_LINUX_IF_ETHER_H */
diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h
index 817d807..f7df51f 100644
--- a/include/uapi/linux/inet_diag.h
+++ b/include/uapi/linux/inet_diag.h
@@ -135,15 +135,21 @@ enum {
 	INET_DIAG_TCLASS,
 	INET_DIAG_SKMEMINFO,
 	INET_DIAG_SHUTDOWN,
-	INET_DIAG_DCTCPINFO,
-	INET_DIAG_PROTOCOL,  /* response attribute only */
+
+	/*
+	 * Next extenstions cannot be requested in struct inet_diag_req_v2:
+	 * its field idiag_ext has only 8 bits.
+	 */
+
+	INET_DIAG_DCTCPINFO,	/* request as INET_DIAG_VEGASINFO */
+	INET_DIAG_PROTOCOL,	/* response attribute only */
 	INET_DIAG_SKV6ONLY,
 	INET_DIAG_LOCALS,
 	INET_DIAG_PEERS,
 	INET_DIAG_PAD,
-	INET_DIAG_MARK,
-	INET_DIAG_BBRINFO,
-	INET_DIAG_CLASS_ID,
+	INET_DIAG_MARK,		/* only with CAP_NET_ADMIN */
+	INET_DIAG_BBRINFO,	/* request as INET_DIAG_VEGASINFO */
+	INET_DIAG_CLASS_ID,	/* request as INET_DIAG_TCLASS */
 	INET_DIAG_MD5SIG,
 	__INET_DIAG_MAX,
 };
diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
index 00a294a4..385c141 100644
--- a/include/uapi/linux/input-event-codes.h
+++ b/include/uapi/linux/input-event-codes.h
@@ -750,6 +750,15 @@
 
 #define ABS_MISC		0x28
 
+/*
+ * 0x2e is reserved and should not be used in input drivers.
+ * It was used by HID as ABS_MISC+6 and userspace needs to detect if
+ * the next ABS_* event is correct or is just ABS_MISC + n.
+ * We define here ABS_RESERVED so userspace can rely on it and detect
+ * the situation described above.
+ */
+#define ABS_RESERVED		0x2e
+
 #define ABS_MT_SLOT		0x2f	/* MT slot being modified */
 #define ABS_MT_TOUCH_MAJOR	0x30	/* Major axis of touching ellipse */
 #define ABS_MT_TOUCH_MINOR	0x31	/* Minor axis (omit if circular) */
diff --git a/include/uapi/linux/ipa_qmi_service_v01.h b/include/uapi/linux/ipa_qmi_service_v01.h
index 159799b..ee36a8a8 100644
--- a/include/uapi/linux/ipa_qmi_service_v01.h
+++ b/include/uapi/linux/ipa_qmi_service_v01.h
@@ -41,22 +41,23 @@
 
 #include <linux/types.h>
 
-#define QMI_IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS_V01 2
-#define QMI_IPA_IPFLTR_NUM_MEQ_32_EQNS_V01 2
-#define QMI_IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS_V01 2
-#define QMI_IPA_IPFLTR_NUM_MEQ_128_EQNS_V01 2
-#define QMI_IPA_MAX_FILTERS_V01 64
-#define QMI_IPA_MAX_FILTERS_EX_V01 128
-#define QMI_IPA_MAX_PIPES_V01 20
-#define QMI_IPA_MAX_APN_V01 8
-#define QMI_IPA_MAX_PER_CLIENTS_V01 64
 #define QMI_IPA_REMOTE_MHI_CHANNELS_NUM_MAX_V01 6
-#define QMI_IPA_REMOTE_MHI_MEMORY_MAPPING_NUM_MAX_V01 6
+#define QMI_IPA_MAX_FILTERS_EX_V01 128
+#define QMI_IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS_V01 2
+#define QMI_IPA_MAX_FILTERS_V01 64
+#define QMI_IPA_IPFLTR_NUM_MEQ_128_EQNS_V01 2
+#define QMI_IPA_ENDP_DESC_NUM_MAX_V01 31
+#define QMI_IPA_MAX_APN_V01 8
 /* Currently max we can use is only 1. But for scalability purpose
  * we are having max value as 8.
  */
 #define QMI_IPA_MAX_CLIENT_DST_PIPES_V01 8
+#define QMI_IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS_V01 2
 #define QMI_IPA_MAX_UL_FIREWALL_RULES_V01 64
+#define QMI_IPA_REMOTE_MHI_MEMORY_MAPPING_NUM_MAX_V01 6
+#define QMI_IPA_IPFLTR_NUM_MEQ_32_EQNS_V01 2
+#define QMI_IPA_MAX_PIPES_V01 20
+#define QMI_IPA_MAX_PER_CLIENTS_V01 64
 
 /*
  * Indicates presence of newly added member to support HW stats.
@@ -110,11 +111,16 @@ enum ipa_platform_type_enum_v01 {
 	QMI_IPA_PLATFORM_TYPE_MSM_WINDOWS_V01 = 4,
 	/*  Platform identifier -	MSM device with Windows HLOS */
 	QMI_IPA_PLATFORM_TYPE_MSM_QNX_V01 = 5,
+	/* Platform identifier - MDM device with LE HLOS, MHI data router */
+	QMI_IPA_PLATFORM_TYPE_LE_MHI_V01 = 6,
 	/*  Platform identifier -	MSM device with QNX HLOS */
 	IPA_PLATFORM_TYPE_ENUM_MAX_ENUM_VAL_V01 = 2147483647
 	/* To force a 32 bit signed enum.  Do not change or use */
 };
 
+#define QMI_IPA_PLATFORM_TYPE_LE_MHI_V01 \
+			QMI_IPA_PLATFORM_TYPE_LE_MHI_V01
+
 struct ipa_hdr_tbl_info_type_v01 {
 	uint32_t modem_offset_start;
 	/*	Offset from the start of IPA Shared memory from which
@@ -667,6 +673,116 @@ struct ipa_filter_rule_type_v01 {
 };  /* Type */
 
 
+struct ipa_filter_rule_req2_type_v01 {
+	uint16_t rule_eq_bitmap;
+	/* 16-bit Bitmask to indicate how many eqs are valid in this rule */
+
+	uint8_t pure_ack_eq_present;
+	/*
+	 *  specifies if a tcp pure ack check rule is present
+	 */
+
+	uint8_t pure_ack_eq;
+	/* The value to check against the type of service (ipv4) field */
+
+	uint8_t protocol_eq_present;
+	/* Specifies if a protocol check rule is present */
+
+	uint8_t protocol_eq;
+	/* The value to check against the protocol field */
+
+	uint8_t num_ihl_offset_range_16;
+	/*  The number of 16 bit range check rules at the location
+	 *	determined by IP header length plus a given offset offset
+	 *	in this rule. See the definition of the ipa_filter_range_eq_16
+	 *	for better understanding. The value of this field cannot exceed
+	 *	IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS which is set as 2
+	 */
+
+	struct ipa_ipfltr_range_eq_16_type_v01
+		ihl_offset_range_16[QMI_IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS_V01];
+	/*	Array of the registered IP header length offset 16 bit range
+	 *	check rules.
+	 */
+
+	uint8_t num_offset_meq_32;
+	/*  The number of 32 bit masked comparison rules present
+	 *  in this rule
+	 */
+
+	struct ipa_ipfltr_mask_eq_32_type_v01
+		offset_meq_32[QMI_IPA_IPFLTR_NUM_MEQ_32_EQNS_V01];
+	/*  An array of all the possible 32bit masked comparison rules
+	 *	in this rule
+	 */
+
+	uint8_t tc_eq_present;
+	/*  Specifies if the traffic class rule is present in this rule */
+
+	uint8_t tc_eq;
+	/* The value against which the IPV4 traffic class field has to
+	 * be checked
+	 */
+
+	uint8_t flow_eq_present;
+	/* Specifies if the "flow equals" rule is present in this rule */
+
+	uint32_t flow_eq;
+	/* The value against which the IPV6 flow field has to be checked */
+
+	uint8_t ihl_offset_eq_16_present;
+	/*	Specifies if there is a 16 bit comparison required at the
+	 *	location in	the packet determined by "Intenet Header length
+	 *	+ specified offset"
+	 */
+
+	struct ipa_ipfltr_eq_16_type_v01 ihl_offset_eq_16;
+	/* The 16 bit comparison equation */
+
+	uint8_t ihl_offset_eq_32_present;
+	/*	Specifies if there is a 32 bit comparison required at the
+	 *	location in the packet determined by "Intenet Header length
+	 *	+ specified offset"
+	 */
+
+	struct ipa_ipfltr_eq_32_type_v01 ihl_offset_eq_32;
+	/*	The 32 bit comparison equation */
+
+	uint8_t num_ihl_offset_meq_32;
+	/*	The number of 32 bit masked comparison equations in this
+	 *	rule. The location of the packet to be compared is
+	 *	determined by the IP Header length + the give offset
+	 */
+
+	struct ipa_ipfltr_mask_eq_32_type_v01
+		ihl_offset_meq_32[QMI_IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS_V01];
+	/*	Array of 32 bit masked comparison equations.
+	 */
+
+	uint8_t num_offset_meq_128;
+	/*	The number of 128 bit comparison equations in this rule */
+
+	struct ipa_ipfltr_mask_eq_128_type_v01
+		offset_meq_128[QMI_IPA_IPFLTR_NUM_MEQ_128_EQNS_V01];
+	/*	Array of 128 bit comparison equations. The location in the
+	 *	packet is determined by the specified offset
+	 */
+
+	uint8_t metadata_meq32_present;
+	/*  Boolean indicating if the 32 bit masked comparison equation
+	 *	is present or not. Comparison is done against the metadata
+	 *	in IPA. Metadata can either be extracted from the packet
+	 *	header or from the "metadata" register.
+	 */
+
+	struct ipa_ipfltr_mask_eq_32_type_v01
+			metadata_meq32;
+	/* The metadata  32 bit masked comparison equation */
+
+	uint8_t ipv4_frag_eq_present;
+	/* Specifies if the IPv4 Fragment equation is present in this rule */
+};  /* Type */
+
 enum ipa_ip_type_enum_v01 {
 	IPA_IP_TYPE_ENUM_MIN_ENUM_VAL_V01 = -2147483647,
 	/* To force a 32 bit signed enum.  Do not change or use*/
@@ -797,6 +913,55 @@ struct ipa_filter_spec_ex_type_v01 {
 	 */
 };  /* Type */
 
+struct ipa_filter_spec_ex2_type_v01 {
+	enum ipa_ip_type_enum_v01 ip_type;
+	/*	This field identifies the IP type for which this rule is
+	 *	applicable. The driver needs to identify the filter table
+	 *	(V6 or V4) and this field is essential for that
+	 */
+
+	struct ipa_filter_rule_req2_type_v01 filter_rule;
+	/*	This field specifies the rules in the filter spec. These rules
+	 *	are the ones that are matched against fields in the packet.
+	 */
+
+	enum ipa_filter_action_enum_v01 filter_action;
+	/*	This field specifies the action to be taken when a filter match
+	 *	occurs. The remote side should install this information into the
+	 *	hardware along with the filter equations.
+	 */
+
+	uint8_t is_routing_table_index_valid;
+	/*	Specifies whether the routing table index is present or not.
+	 *	If the action is "QMI_IPA_FILTER_ACTION_EXCEPTION", this
+	 *	parameter need not be provided.
+	 */
+
+	uint32_t route_table_index;
+	/*	This is the index in the routing table that should be used
+	 *	to route the packets if the filter rule is hit
+	 */
+
+	uint8_t is_mux_id_valid;
+	/*	Specifies whether the mux_id is valid */
+
+	uint32_t mux_id;
+	/*	This field identifies the QMAP MUX ID. As a part of QMAP
+	 *	protocol, several data calls may be multiplexed over the
+	 *	same physical transport channel. This identifier is used to
+	 *	identify one such data call. The maximum value for this
+	 *	identifier is 255.
+	 */
+
+	uint32_t rule_id;
+	/* Rule Id of the given filter. The Rule Id is populated in the rule
+	 * header when installing the rule in IPA.
+	 */
+
+	uint8_t is_rule_hashable;
+	/** Specifies whether the given rule is hashable.
+	 */
+};  /* Type */
 
 /*  Request Message; This is the message that is exchanged between the
  *	control point and the service in order to request the installation
@@ -860,7 +1025,7 @@ struct ipa_install_fltr_rule_req_msg_v01 {
 	 */
 
 	/* Optional */
-	/*  Extended Filter Specification  */
+	/*  Extended Filter Specification */
 	uint8_t filter_spec_ex_list_valid;
 	/* Must be set to true if filter_spec_ex_list is being passed */
 	uint32_t filter_spec_ex_list_len;
@@ -873,6 +1038,15 @@ struct ipa_install_fltr_rule_req_msg_v01 {
 	 *	The driver installing these rules must do so in the same
 	 *	order as specified in this list.
 	 */
+
+	/* Optional */
+	/*  Extended Type 2 Filter Specification */
+	uint8_t filter_spec_ex2_list_valid;
+	/* Must be set to true if filter_spec_ex2_list is being passed */
+	uint32_t filter_spec_ex2_list_len;
+	/* Must be set to # of elements in filter_spec_ex2_list */
+	struct ipa_filter_spec_ex2_type_v01
+		filter_spec_ex2_list[QMI_IPA_MAX_FILTERS_V01];
 };  /* Message */
 
 struct ipa_filter_rule_identifier_to_handle_map_v01 {
@@ -1671,6 +1845,15 @@ struct ipa_install_fltr_rule_req_ex_msg_v01 {
 	 * receiver if the PDN is XLAT before installing them on the associated
 	 * IPA consumer pipe.
 	 */
+
+	/* Optional */
+	/* Extended Type 2 Filter Specification */
+	uint8_t filter_spec_ex2_list_valid;
+	/* Must be set to true if filter_spec_ex2_list is being passed */
+	uint32_t filter_spec_ex2_list_len;
+	/* Must be set to # of elements in filter_spec_ex2_list */
+	struct ipa_filter_spec_ex2_type_v01
+		filter_spec_ex2_list[QMI_IPA_MAX_FILTERS_V01];
 };  /* Message */
 
 /* Response Message; Requests installation of filtering rules in the hardware
@@ -2206,6 +2389,175 @@ struct ipa_mhi_cleanup_resp_msg_v01 {
 };
 #define IPA_MHI_CLEANUP_RESP_MSG_V01_MAX_MSG_LEN 7
 
+enum ipa_ep_desc_type_enum_v01 {
+	/* To force a 32 bit signed enum. Do not change or use*/
+	IPA_EP_DESC_TYPE_ENUM_MIN_VAL_V01 = IPA_INT_MIN,
+	DATA_EP_DESC_TYPE_RESERVED_V01 = 0x00,
+	DATA_EP_DESC_TYPE_EMB_CONS_V01 = 0x01,
+	DATA_EP_DESC_TYPE_EMB_PROD_V01 = 0x02,
+	DATA_EP_DESC_TYPE_RSC_PROD_V01 = 0x03,
+	DATA_EP_DESC_TYPE_QDSS_PROD_V01 = 0x04,
+	DATA_EP_DESC_TYPE_DPL_PROD_V01 = 0x05,
+	DATA_EP_DESC_TYPE_TETH_CONS_V01 = 0x06,
+	DATA_EP_DESC_TYPE_TETH_PROD_V01 = 0x07,
+	DATA_EP_DESC_TYPE_TETH_RMNET_CONS_V01 = 0x08,
+	DATA_EP_DESC_TYPE_TETH_RMNET_PROD_V01 = 0x09,
+	IPA_EP_DESC_TYPE_ENUM_MAX_VAL_V01 = IPA_INT_MAX,
+};
+
+enum ipa_ic_type_enum_v01 {
+	/* To force a 32 bit signed enum. Do not change or use*/
+	IPA_IC_TYPE_ENUM_MIN_VAL_V01 = IPA_INT_MIN,
+	DATA_IC_TYPE_RESERVED_V01 = 0x00,
+	DATA_IC_TYPE_MHI_V01 = 0x01,
+	DATA_IC_TYPE_MHI_PRIME_V01 = 0x02,
+	DATA_IC_TYPE_USB_V01 = 0x03,
+	DATA_IC_TYPE_AP_V01 = 0x04,
+	DATA_IC_TYPE_Q6_V01 = 0x05,
+	DATA_IC_TYPE_UC_V01 = 0x06,
+	IPA_IC_TYPE_ENUM_MAX_VAL_V01 = IPA_INT_MAX,
+};
+
+enum ipa_ep_status_type_v01 {
+	/* To force a 32 bit signed enum. Do not change or use*/
+	IPA_EP_STATUS_TYPE_MIN_VAL_V01 = IPA_INT_MIN,
+	DATA_EP_STATUS_RESERVED_V01 = 0x00,
+	DATA_EP_STATUS_STATIC_V01 = 0x01,
+	DATA_EP_STATUS_CONNECTED_V01 = 0x02,
+	DATA_EP_STATUS_DISCONNECTED_V01 = 0x03,
+	IPA_EP_STATUS_TYPE_MAX_VAL_V01 = IPA_INT_MAX,
+};
+
+struct ipa_ep_id_type_v01 {
+	/* Interconnect type. See ipa_ic_desc_type_enum type */
+	enum ipa_ic_type_enum_v01 ic_type;
+	/* Peripheral end point type */
+	enum ipa_ep_desc_type_enum_v01 ep_type;
+	/* Peripheral interface number */
+	uint32_t ep_id;
+	/* Status of endpoint */
+	enum ipa_ep_status_type_v01 ep_status;
+};
+
+struct ipa_endp_desc_indication_msg_v01 {
+	/* Optional */
+	uint8_t ep_info_valid;
+	/* Must be set to true if type_arr is being passed */
+	uint32_t ep_info_len;
+	/* Must be set to # of elements in type_arr */
+	struct ipa_ep_id_type_v01 ep_info[QMI_IPA_ENDP_DESC_NUM_MAX_V01];
+	/* Optional */
+	uint8_t num_eps_valid;
+	/* Must be set to true if num_of_eps is being passed */
+	/* Must be set to # of elements of num_of_eps */
+	uint32_t num_eps;
+}; /* Message */
+#define IPA_ENDP_DESC_INDICATION_MSG_V01_MAX_MSG_LEN 507
+
+enum ipa_aggr_enum_type_v01 {
+	IPA_AGGR_ENUM_TYPE_MIN_VAL_V01 = IPA_INT_MIN,
+	DATA_AGGR_TYPE_RESERVED_V01 = 0x00,
+	DATA_AGGR_TYPE_QMAP_V01 = 0x01,
+	DATA_AGGR_TYPE_QMAPv5_V01 = 0x02,
+	DATA_AGGR_TYPE_INHERITED_V01 = 0x03,
+	IPA_AGGR_ENUM_TYPE_MAX_VAL_V01 = IPA_INT_MAX,
+};
+
+struct ipa_mhi_prime_aggr_info_type_v01 {
+	enum ipa_ic_type_enum_v01 ic_type;
+	/* Peripheral end point type */
+	enum ipa_ep_desc_type_enum_v01 ep_type;
+	/* Bytes count in KB */
+	uint32_t bytes_count;
+	/* packet count */
+	uint32_t pkt_count;
+	/* aggr_type */
+	enum ipa_aggr_enum_type_v01 aggr_type;
+}; /* Message */
+#define IPA_MHI_PRIME_AGGR_INFO_REQ_MSG_V01_MAX_MSG_LEN 631
+
+struct ipa_mhi_prime_aggr_info_req_msg_v01 {
+	/* optional */
+	uint8_t aggr_info_valid;
+	/* Aggregration info for MHI prime */
+	/* Must be set to true if aggr_info is being passed*/
+	uint32_t aggr_info_len;
+	/* Must be set to # of elements in aggr_info */
+	struct ipa_mhi_prime_aggr_info_type_v01
+		aggr_info[QMI_IPA_ENDP_DESC_NUM_MAX_V01];
+	/* optional */
+	/* Must be set to true if num_eps_valid is being passed*/
+	uint8_t num_eps_valid;
+	/* Must be set to # of num_eps */
+	uint32_t num_eps;
+}; /* Message */
+#define IPA_MHI_PRIME_AGGR_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
+
+struct ipa_mhi_prime_aggr_info_resp_msg_v01 {
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+}; /* Message */
+
+struct ipa_add_offload_connection_req_msg_v01 {
+	/* optional */
+	/* Must be set to true if num_ipv4_filters is being passed*/
+	uint8_t num_ipv4_filters_valid;
+	/* Must be set to # of ipv4_filters*/
+	uint32_t num_ipv4_filters;
+	/* optional */
+	/* Must be set to true if num_ipv6_filters is being passed*/
+	uint8_t num_ipv6_filters_valid;
+	/* Must be set to # of ipv6_filters*/
+	uint32_t num_ipv6_filters;
+	/* optional */
+	uint8_t xlat_filter_indices_list_valid;
+	/* Must be set to true if xlat_filter_indices_list is being passed*/
+	uint32_t xlat_filter_indices_list_len;
+	/* Must be set to # of  xlat_filter_indices_list*/
+	uint32_t xlat_filter_indices_list[QMI_IPA_MAX_FILTERS_V01];
+	/* optional */
+	/* Must be set to true if filter_spec_ex_list is being passed*/
+	uint8_t filter_spec_ex2_list_valid;
+	/* Must be set to # of  filter_spec_ex_list*/
+	uint32_t filter_spec_ex2_list_len;
+	struct ipa_filter_spec_ex2_type_v01
+		filter_spec_ex2_list[QMI_IPA_MAX_FILTERS_V01];
+}; /* Message */
+#define IPA_ADD_OFFLOAD_CONNECTION_REQ_MSG_V01_MAX_MSG_LEN 11350
+
+struct ipa_add_offload_connection_resp_msg_v01 {
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/* optional */
+	/* Must be set to true if filter_handle_list is being passed*/
+	uint8_t filter_handle_list_valid;
+	/* Must be set to # of  filter_handle_list*/
+	uint32_t filter_handle_list_len;
+	struct ipa_filter_rule_identifier_to_handle_map_v01
+		filter_handle_list[QMI_IPA_MAX_FILTERS_V01];
+}; /* Message */
+#define IPA_ADD_OFFLOAD_CONNECTION_RESP_MSG_V01_MAX_MSG_LEN 523
+
+struct ipa_remove_offload_connection_req_msg_v01 {
+	/* optional */
+	/* Must be set to true if filter_handle_list is being passed*/
+	uint8_t filter_handle_list_valid;
+	/* Must be set to # of  filter_handle_list*/
+	uint32_t filter_handle_list_len;
+	struct ipa_filter_rule_identifier_to_handle_map_v01
+		filter_handle_list[QMI_IPA_MAX_FILTERS_V01];
+}; /* Message */
+#define IPA_REMOVE_OFFLOAD_CONNECTION_REQ_MSG_V01_MAX_MSG_LEN 516
+
+struct ipa_remove_offload_connection_resp_msg_v01 {
+	/* optional */
+	/* Must be set to true if filter_handle_list is being passed*/
+	uint8_t resp_valid;
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+}; /* Message */
+#define IPA_REMOVE_OFFLOAD_CONNECTION_RESP_MSG_V01_MAX_MSG_LEN 7
+
 /*Service Message Definition*/
 #define QMI_IPA_INDICATION_REGISTER_REQ_V01 0x0020
 #define QMI_IPA_INDICATION_REGISTER_RESP_V01 0x0020
@@ -2253,13 +2605,21 @@ struct ipa_mhi_cleanup_resp_msg_v01 {
 #define QMI_IPA_MHI_ALLOC_CHANNEL_RESP_V01 0x003D
 #define QMI_IPA_MHI_CLEANUP_REQ_V01 0x003E
 #define QMI_IPA_MHI_CLEANUP_RESP_V01 0x003E
+#define QMI_IPA_ENDP_DESC_INDICATION_V01 0x003F
+#define QMI_IPA_MHI_PRIME_AGGR_INFO_REQ_V01 0x0040
+#define QMI_IPA_MHI_PRIME_AGGR_INFO_RESP_V01 0x0040
+#define QMI_IPA_ADD_OFFLOAD_CONNECTION_REQ_V01 0x0041
+#define QMI_IPA_ADD_OFFLOAD_CONNECTION_RESP_V01 0x0041
+#define QMI_IPA_REMOVE_OFFLOAD_CONNECTION_REQ_V01 0x0042
+#define QMI_IPA_REMOVE_OFFLOAD_CONNECTION_RESP_V01 0x0042
+
 
 /* add for max length*/
 #define QMI_IPA_INIT_MODEM_DRIVER_REQ_MAX_MSG_LEN_V01 162
 #define QMI_IPA_INIT_MODEM_DRIVER_RESP_MAX_MSG_LEN_V01 25
-#define QMI_IPA_INDICATION_REGISTER_REQ_MAX_MSG_LEN_V01 8
+#define QMI_IPA_INDICATION_REGISTER_REQ_MAX_MSG_LEN_V01 12
 #define QMI_IPA_INDICATION_REGISTER_RESP_MAX_MSG_LEN_V01 7
-#define QMI_IPA_INSTALL_FILTER_RULE_REQ_MAX_MSG_LEN_V01 22369
+#define QMI_IPA_INSTALL_FILTER_RULE_REQ_MAX_MSG_LEN_V01 33445
 #define QMI_IPA_INSTALL_FILTER_RULE_RESP_MAX_MSG_LEN_V01 783
 #define QMI_IPA_FILTER_INSTALLED_NOTIF_REQ_MAX_MSG_LEN_V01 870
 #define QMI_IPA_FILTER_INSTALLED_NOTIF_RESP_MAX_MSG_LEN_V01 7
@@ -2291,7 +2651,7 @@ struct ipa_mhi_cleanup_resp_msg_v01 {
 #define QMI_IPA_INIT_MODEM_DRIVER_CMPLT_REQ_MAX_MSG_LEN_V01 4
 #define QMI_IPA_INIT_MODEM_DRIVER_CMPLT_RESP_MAX_MSG_LEN_V01 7
 
-#define QMI_IPA_INSTALL_FILTER_RULE_EX_REQ_MAX_MSG_LEN_V01 22685
+#define QMI_IPA_INSTALL_FILTER_RULE_EX_REQ_MAX_MSG_LEN_V01 33761
 #define QMI_IPA_INSTALL_FILTER_RULE_EX_RESP_MAX_MSG_LEN_V01 523
 
 #define QMI_IPA_ENABLE_PER_CLIENT_STATS_REQ_MAX_MSG_LEN_V01 4
diff --git a/include/uapi/linux/mhi.h b/include/uapi/linux/mhi.h
index bfd0386..44216d2 100644
--- a/include/uapi/linux/mhi.h
+++ b/include/uapi/linux/mhi.h
@@ -32,5 +32,6 @@ struct ep_info {
 #define MHI_UCI_IOCTL_MAGIC	'm'
 
 #define MHI_UCI_EP_LOOKUP _IOR(MHI_UCI_IOCTL_MAGIC, 2, struct ep_info)
+#define MHI_UCI_DPL_EP_LOOKUP _IOR(MHI_UCI_IOCTL_MAGIC, 3, struct ep_info)
 
 #endif /* _UAPI_MHI_H */
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index cd71b4a..deab215 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -36,6 +36,11 @@
 #define IPA_DFLT_RT_TBL_NAME "ipa_dflt_rt"
 
 /**
+ * name for default value of invalid protocol of NAT
+ */
+#define IPAHAL_NAT_INVALID_PROTOCOL   0xFF
+
+/**
  * commands supported by IPA driver
  */
 #define IPA_IOCTL_ADD_HDR                       0
@@ -329,20 +334,30 @@ enum ipa_client_type {
 
 	/* RESERVED PROD			= 86, */
 	IPA_CLIENT_APPS_WAN_COAL_CONS		= 87,
+
 	IPA_CLIENT_WIGIG_PROD			= 88,
 	IPA_CLIENT_WIGIG1_CONS			= 89,
+
 	/* RESERVERD PROD			= 90, */
 	IPA_CLIENT_WIGIG2_CONS			= 91,
+
 	/* RESERVERD PROD			= 92, */
 	IPA_CLIENT_WIGIG3_CONS			= 93,
+
 	/* RESERVERD PROD			= 94, */
 	IPA_CLIENT_WIGIG4_CONS			= 95,
 
 	IPA_CLIENT_AQC_ETHERNET_PROD		= 96,
 	IPA_CLIENT_AQC_ETHERNET_CONS		= 97,
+
+	IPA_CLIENT_MHI_PRIME_TETH_PROD		= 98,
+	IPA_CLIENT_MHI_PRIME_TETH_CONS		= 99,
+	IPA_CLIENT_MHI_PRIME_RMNET_PROD		= 100,
+	IPA_CLIENT_MHI_PRIME_RMNET_CONS		= 101,
+	IPA_CLIENT_MHI_PRIME_DPL_PROD		= 102,
 };
 
-#define IPA_CLIENT_MAX (IPA_CLIENT_AQC_ETHERNET_CONS + 1)
+#define IPA_CLIENT_MAX (IPA_CLIENT_MHI_PRIME_DPL_PROD + 1)
 
 #define IPA_CLIENT_WLAN2_PROD IPA_CLIENT_A5_WLAN_AMPDU_PROD
 #define IPA_CLIENT_Q6_DL_NLO_DATA_PROD IPA_CLIENT_Q6_DL_NLO_DATA_PROD
@@ -358,10 +373,16 @@ enum ipa_client_type {
 #define IPA_CLIENT_WIGIG4_CONS IPA_CLIENT_WIGIG4_CONS
 #define IPA_CLIENT_AQC_ETHERNET_PROD IPA_CLIENT_AQC_ETHERNET_PROD
 #define IPA_CLIENT_AQC_ETHERNET_CONS IPA_CLIENT_AQC_ETHERNET_CONS
+#define IPA_CLIENT_MHI_PRIME_TETH_PROD IPA_CLIENT_MHI_PRIME_TETH_PROD
+#define IPA_CLIENT_MHI_PRIME_TETH_CONS IPA_CLIENT_MHI_PRIME_TETH_CONS
+#define IPA_CLIENT_MHI_PRIME_RMNET_PROD IPA_CLIENT_MHI_PRIME_RMNET_PROD
+#define IPA_CLIENT_MHI_PRIME_RMNET_CONS IPA_CLIENT_MHI_PRIME_RMNET_CONS
+#define IPA_CLIENT_MHI_PRIME_DPL_PROD IPA_CLIENT_MHI_PRIME_DPL_PROD
 
 #define IPA_CLIENT_IS_APPS_CONS(client) \
 	((client) == IPA_CLIENT_APPS_LAN_CONS || \
-	(client) == IPA_CLIENT_APPS_WAN_CONS)
+	(client) == IPA_CLIENT_APPS_WAN_CONS || \
+	(client) == IPA_CLIENT_APPS_WAN_COAL_CONS)
 
 #define IPA_CLIENT_IS_USB_CONS(client) \
 	((client) == IPA_CLIENT_USB_CONS || \
@@ -594,6 +615,7 @@ enum ipa_vlan_bridge_event {
 enum ipa_wlan_fw_ssr_event {
 	WLAN_FWR_SSR_BEFORE_SHUTDOWN = BRIDGE_VLAN_MAPPING_MAX,
 	IPA_WLAN_FW_SSR_EVENT_MAX,
+#define IPA_WLAN_FW_SSR_EVENT_MAX IPA_WLAN_FW_SSR_EVENT_MAX
 };
 
 enum ipa_gsb_event {
diff --git a/include/uapi/linux/msm_kgsl.h b/include/uapi/linux/msm_kgsl.h
index f877bc3..40991bd 100644
--- a/include/uapi/linux/msm_kgsl.h
+++ b/include/uapi/linux/msm_kgsl.h
@@ -336,6 +336,8 @@ enum kgsl_timestamp_type {
 #define KGSL_PROP_SECURE_BUFFER_ALIGNMENT 0x23
 #define KGSL_PROP_SECURE_CTXT_SUPPORT 0x24
 #define KGSL_PROP_SPEED_BIN		0x25
+#define KGSL_PROP_GAMING_BIN		0x26
+
 
 struct kgsl_shadowprop {
 	unsigned long gpuaddr;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index d226193..6c5788c 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2184,10 +2184,10 @@ enum nl80211_commands {
  *     &enum nl80211_external_auth_action value). This is used with the
  *     &NL80211_CMD_EXTERNAL_AUTH request event.
  * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user
- *     space supports external authentication. This attribute shall be used
- *     only with %NL80211_CMD_CONNECT request. The driver may offload
- *     authentication processing to user space if this capability is indicated
- *     in NL80211_CMD_CONNECT requests from the user space.
+ *	space supports external authentication. This attribute shall be used
+ *	with %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP request. The driver
+ *	may offload authentication processing to user space if this capability
+ *	is indicated in the respective requests from the user space.
  *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -5277,9 +5277,14 @@ enum nl80211_crit_proto_id {
  * Used by cfg80211_rx_mgmt()
  *
  * @NL80211_RXMGMT_FLAG_ANSWERED: frame was answered by device/driver.
+ * @NL80211_RXMGMT_FLAG_EXTERNAL_AUTH: Host driver intends to offload
+ *	the authentication. Exclusively defined for host drivers that
+ *	advertises the SME functionality but would like the userspace
+ *	to handle certain authentication algorithms (e.g. SAE).
  */
 enum nl80211_rxmgmt_flags {
 	NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0,
+	NL80211_RXMGMT_FLAG_EXTERNAL_AUTH = 1 << 1,
 };
 
 /*
diff --git a/include/uapi/linux/sysstats.h b/include/uapi/linux/sysstats.h
new file mode 100644
index 0000000..0343554
--- /dev/null
+++ b/include/uapi/linux/sysstats.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _LINUX_SYSSTATS_H
+#define _LINUX_SYSSTATS_H
+
+#include <linux/types.h>
+#include <linux/taskstats.h>
+#include <linux/cgroupstats.h>
+
+#define SYSSTATS_VERSION	1
+
+/*
+ * Data shared between user space and kernel space
+ * Each member is aligned to a 8 byte boundary.
+ * All values in KB.
+ */
+struct sys_memstats {
+	__u64	version;
+	__u64	memtotal;
+	__u64	vmalloc_total;
+	__u64	reclaimable;
+	__u64	zram_compressed;
+	__u64	swap_used;
+	__u64	swap_total;
+	__u64	unreclaimable;
+	__u64	buffer;
+	__u64	slab_reclaimable;
+	__u64	slab_unreclaimable;
+	__u64	free_cma;
+	__u64	file_mapped;
+	__u64	swapcache;
+	__u64	pagetable;
+	__u64	kernelstack;
+	__u64	shmem;
+	__u64	dma_nr_free_pages;
+	__u64	dma_nr_active_anon;
+	__u64	dma_nr_inactive_anon;
+	__u64	dma_nr_active_file;
+	__u64	dma_nr_inactive_file;
+	__u64	normal_nr_free_pages;
+	__u64	normal_nr_active_anon;
+	__u64	normal_nr_inactive_anon;
+	__u64	normal_nr_active_file;
+	__u64	normal_nr_inactive_file;
+	__u64	movable_nr_free_pages;
+	__u64	movable_nr_active_anon;
+	__u64	movable_nr_inactive_anon;
+	__u64	movable_nr_active_file;
+	__u64	movable_nr_inactive_file;
+	__u64	highmem_nr_free_pages;
+	__u64	highmem_nr_active_anon;
+	__u64	highmem_nr_inactive_anon;
+	__u64	highmem_nr_active_file;
+	__u64	highmem_nr_inactive_file;
+	/* version 1 ends here */
+};
+
+/*
+ * Commands sent from userspace
+ * Not versioned. New commands should only be inserted at the enum's end.
+ */
+
+enum {
+	SYSSTATS_CMD_UNSPEC = __CGROUPSTATS_CMD_MAX,	/* Reserved */
+	SYSSTATS_CMD_GET,		/* user->kernel request/get-response */
+	SYSSTATS_CMD_NEW,		/* kernel->user event */
+};
+
+#define SYSSTATS_CMD_UNSPEC SYSSTATS_CMD_UNSPEC
+#define SYSSTATS_CMD_GET SYSSTATS_CMD_GET
+#define SYSSTATS_CMD_NEW SYSSTATS_CMD_NEW
+
+enum {
+	SYSSTATS_TYPE_UNSPEC = 0,	/* Reserved */
+	SYSSTATS_TYPE_SYSMEM_STATS,	/* contains name + memory stats */
+};
+
+#define SYSSTATS_TYPE_UNSPEC SYSSTATS_TYPE_UNSPEC
+#define SYSSTATS_TYPE_SYSMEM_STATS SYSSTATS_TYPE_SYSMEM_STATS
+
+enum {
+	SYSSTATS_CMD_ATTR_UNSPEC = 0,
+	SYSSTATS_CMD_ATTR_SYSMEM_STATS,
+};
+
+#define SYSSTATS_CMD_ATTR_UNSPEC SYSSTATS_CMD_ATTR_UNSPEC
+#define SYSSTATS_CMD_ATTR_SYSMEM_STATS SYSSTATS_CMD_ATTR_SYSMEM_STATS
+
+#endif /* _LINUX_SYSSTATS_H */
diff --git a/include/uapi/linux/taskstats.h b/include/uapi/linux/taskstats.h
index b7aa7bb..e9c95bd 100644
--- a/include/uapi/linux/taskstats.h
+++ b/include/uapi/linux/taskstats.h
@@ -35,6 +35,7 @@
 
 
 #define TASKSTATS_VERSION	8
+#define TASKSTATS2_VERSION	1
 #define TS_COMM_LEN		32	/* should be >= TASK_COMM_LEN
 					 * in linux/sched.h */
 
@@ -166,6 +167,17 @@ struct taskstats {
 	__u64	freepages_delay_total;
 };
 
+struct taskstats2 {
+	__u16 version;
+	__s16 oom_score;
+	__u32 pid;
+	__u64 anon_rss;	/* KB */
+	__u64 file_rss;	/* KB */
+	__u64 swap_rss;	/* KB */
+	__u64 shmem_rss;	/* KB */
+	__u64 unreclaimable;	/* KB */
+	/* version 1 ends here */
+};
 
 /*
  * Commands sent from userspace
@@ -177,6 +189,7 @@ enum {
 	TASKSTATS_CMD_UNSPEC = 0,	/* Reserved */
 	TASKSTATS_CMD_GET,		/* user->kernel request/get-response */
 	TASKSTATS_CMD_NEW,		/* kernel->user event */
+	TASKSTATS2_CMD_GET,		/* user->kernel request/get-response */
 	__TASKSTATS_CMD_MAX,
 };
 
@@ -190,6 +203,7 @@ enum {
 	TASKSTATS_TYPE_AGGR_PID,	/* contains pid + stats */
 	TASKSTATS_TYPE_AGGR_TGID,	/* contains tgid + stats */
 	TASKSTATS_TYPE_NULL,		/* contains nothing */
+	TASKSTATS_TYPE_FOREACH,		/* contains stats */
 	__TASKSTATS_TYPE_MAX,
 };
 
@@ -201,6 +215,7 @@ enum {
 	TASKSTATS_CMD_ATTR_TGID,
 	TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
 	TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
+	TASKSTATS_CMD_ATTR_FOREACH,
 	__TASKSTATS_CMD_ATTR_MAX,
 };
 
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index dd502a9..31e4e48 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -747,6 +747,9 @@ enum v4l2_mpeg_vidc_extradata {
 	V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY = 29,
 	V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE = 30,
 	V4L2_MPEG_VIDC_EXTRADATA_UBWC_CR_STATS_INFO = 31,
+#define V4L2_MPEG_VIDC_EXTRADATA_ENC_FRAME_QP \
+	V4L2_MPEG_VIDC_EXTRADATA_ENC_FRAME_QP
+	V4L2_MPEG_VIDC_EXTRADATA_ENC_FRAME_QP = 32,
 };
 
 #define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE	\
diff --git a/include/uapi/media/msm_cam_sensor.h b/include/uapi/media/msm_cam_sensor.h
index 9dc8cad..18276f5 100644
--- a/include/uapi/media/msm_cam_sensor.h
+++ b/include/uapi/media/msm_cam_sensor.h
@@ -39,6 +39,8 @@
 
 #define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
 #define MSM_V4L2_PIX_FMT_META10 v4l2_fourcc('M', 'E', '1', '0') /* META10 */
+#define MSM_V4L2_PIX_FMT_META12 v4l2_fourcc('M', 'E', '1', '2') /* META12 */
+
 #define MSM_V4L2_PIX_FMT_SBGGR14 v4l2_fourcc('B', 'G', '1', '4')
 	/* 14  BGBG.. GRGR.. */
 #define MSM_V4L2_PIX_FMT_SGBRG14 v4l2_fourcc('G', 'B', '1', '4')
diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h
index 63abd156..082a83e 100644
--- a/include/uapi/media/msm_camsensor_sdk.h
+++ b/include/uapi/media/msm_camsensor_sdk.h
@@ -52,6 +52,8 @@
 
 #define SENSOR_PROBE_WRITE
 
+#define SECURE_CAMERA
+
 enum msm_sensor_camera_id_t {
 	CAMERA_0,
 	CAMERA_1,
@@ -352,6 +354,7 @@ struct msm_camera_csid_params {
 	unsigned int csi_clk;
 	struct msm_camera_csid_lut_params lut_params;
 	unsigned char csi_3p_sel;
+	unsigned char is_secure;
 };
 
 struct msm_camera_csid_testmode_parms {
diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h
index 48baf45..4b734c9 100644
--- a/include/uapi/media/msmb_isp.h
+++ b/include/uapi/media/msmb_isp.h
@@ -27,10 +27,16 @@
 
 #define VFE_HW_LIMIT 1
 #define DUAL_ISP_SYNC 1
-
+#define ISP_KERNEL_STATE 1
 
 struct msm_vfe_cfg_cmd_list;
 
+struct isp_kstate {
+	uint32_t kernel_sofid;
+	uint32_t drop_reconfig;
+	uint32_t vfeid;
+};
+
 enum ISP_START_PIXEL_PATTERN {
 	ISP_BAYER_RGRGRG,
 	ISP_BAYER_GRGRGR,
diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h
index 5e6fd7f..d28d79d 100644
--- a/include/uapi/sound/compress_params.h
+++ b/include/uapi/sound/compress_params.h
@@ -56,6 +56,9 @@
 
 #define SND_DEC_DDP_MAX_PARAMS 18
 
+/* Maximum PCM channels */
+#define MAX_PCM_DECODE_CHANNELS 32
+
 /* AUDIO CODECS SUPPORTED */
 #define MAX_NUM_CODECS 32
 #define MAX_NUM_CODEC_DESCRIPTORS 32
@@ -76,6 +79,11 @@
 /* Bit-0 - 0 : Disable Timestamp mode */
 #define COMPRESSED_TIMESTAMP_FLAG 0x0001
 
+/* Perf mode flag */
+/* Bit-1 - 1 : Enable perf mode */
+/* Bit-1 - 0 : Disable perf mode */
+#define COMPRESSED_PERF_MODE_FLAG 0x0002
+
 /* Codecs are listed linearly to allow for extensibility */
 #define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
 #define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
@@ -416,6 +424,15 @@ struct snd_dec_aptx {
 	__u32 nap;
 };
 
+/** struct snd_dec_pcm - codec options for PCM format
+ * @num_channels: Number of channels
+ * @ch_map: Channel map for the above corresponding channels
+ */
+struct snd_dec_pcm {
+	__u32 num_channels;
+	__u8 ch_map[MAX_PCM_DECODE_CHANNELS];
+} __attribute__((packed, aligned(4)));
+
 union snd_codec_options {
 	struct snd_enc_wma wma;
 	struct snd_enc_vorbis vorbis;
@@ -429,6 +446,7 @@ union snd_codec_options {
 	struct snd_dec_ape ape;
 	struct snd_dec_aptx aptx_dec;
 	struct snd_dec_thd truehd;
+	struct snd_dec_pcm pcm_dec;
 };
 
 /** struct snd_codec_desc - description of codec capabilities
diff --git a/include/xen/interface/vcpu.h b/include/xen/interface/vcpu.h
index 98188c8..504c716 100644
--- a/include/xen/interface/vcpu.h
+++ b/include/xen/interface/vcpu.h
@@ -178,4 +178,46 @@ DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_info);
 
 /* Send an NMI to the specified VCPU. @extra_arg == NULL. */
 #define VCPUOP_send_nmi             11
+
+/*
+ * Get the physical ID information for a pinned vcpu's underlying physical
+ * processor.  The physical ID informmation is architecture-specific.
+ * On x86: id[31:0]=apic_id, id[63:32]=acpi_id.
+ * This command returns -EINVAL if it is not a valid operation for this VCPU.
+ */
+#define VCPUOP_get_physid           12 /* arg == vcpu_get_physid_t */
+struct vcpu_get_physid {
+	uint64_t phys_id;
+};
+DEFINE_GUEST_HANDLE_STRUCT(vcpu_get_physid);
+#define xen_vcpu_physid_to_x86_apicid(physid) ((uint32_t)(physid))
+#define xen_vcpu_physid_to_x86_acpiid(physid) ((uint32_t)((physid) >> 32))
+
+/*
+ * Register a memory location to get a secondary copy of the vcpu time
+ * parameters.  The master copy still exists as part of the vcpu shared
+ * memory area, and this secondary copy is updated whenever the master copy
+ * is updated (and using the same versioning scheme for synchronisation).
+ *
+ * The intent is that this copy may be mapped (RO) into userspace so
+ * that usermode can compute system time using the time info and the
+ * tsc.  Usermode will see an array of vcpu_time_info structures, one
+ * for each vcpu, and choose the right one by an existing mechanism
+ * which allows it to get the current vcpu number (such as via a
+ * segment limit).  It can then apply the normal algorithm to compute
+ * system time from the tsc.
+ *
+ * @extra_arg == pointer to vcpu_register_time_info_memory_area structure.
+ */
+#define VCPUOP_register_vcpu_time_memory_area   13
+DEFINE_GUEST_HANDLE_STRUCT(vcpu_time_info);
+struct vcpu_register_time_memory_area {
+	union {
+		GUEST_HANDLE(vcpu_time_info) h;
+		struct pvclock_vcpu_time_info *v;
+		uint64_t p;
+	} addr;
+};
+DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_time_memory_area);
+
 #endif /* __XEN_PUBLIC_VCPU_H__ */
diff --git a/init/main.c b/init/main.c
index fa1f183..6d1880f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1008,7 +1008,7 @@ static int __ref kernel_init(void *unused)
 	numa_default_policy();
 
 	rcu_end_inkernel_boot();
-	place_marker("M : Kernel End");
+	place_marker("M - DRIVER Kernel Boot Done");
 
 	if (ramdisk_execute_command) {
 		ret = run_init_process(ramdisk_execute_command);
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 109c32c..21bbfc09 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1692,7 +1692,7 @@ static int parse_cgroup_root_flags(char *data, unsigned int *root_flags)
 
 	*root_flags = 0;
 
-	if (!data)
+	if (!data || *data == '\0')
 		return 0;
 
 	while ((token = strsep(&data, ",")) != NULL) {
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 2982fb7..f41ae56 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -867,6 +867,20 @@ void rebuild_sched_domains(void)
 	mutex_unlock(&cpuset_mutex);
 }
 
+static int update_cpus_allowed(struct cpuset *cs, struct task_struct *p,
+			       const struct cpumask *new_mask)
+{
+	int ret;
+
+	if (cpumask_subset(&p->cpus_requested, cs->cpus_requested)) {
+		ret = set_cpus_allowed_ptr(p, &p->cpus_requested);
+		if (!ret)
+			return ret;
+	}
+
+	return set_cpus_allowed_ptr(p, new_mask);
+}
+
 /**
  * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset.
  * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed
@@ -882,7 +896,7 @@ static void update_tasks_cpumask(struct cpuset *cs)
 
 	css_task_iter_start(&cs->css, 0, &it);
 	while ((task = css_task_iter_next(&it)))
-		set_cpus_allowed_ptr(task, cs->effective_cpus);
+		update_cpus_allowed(cs, task, cs->effective_cpus);
 	css_task_iter_end(&it);
 }
 
@@ -1550,7 +1564,7 @@ static void cpuset_attach(struct cgroup_taskset *tset)
 		 * can_attach beforehand should guarantee that this doesn't
 		 * fail.  TODO: have a better way to handle failure here
 		 */
-		WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
+		WARN_ON_ONCE(update_cpus_allowed(cs, task, cpus_attach));
 
 		cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
 		cpuset_update_task_spread_flag(cs, task);
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 01b97a3c..e10202f 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -360,9 +360,6 @@ void __weak arch_smt_update(void) { }
 
 #ifdef CONFIG_HOTPLUG_SMT
 enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
-EXPORT_SYMBOL_GPL(cpu_smt_control);
-
-static bool cpu_smt_available __read_mostly;
 
 void __init cpu_smt_disable(bool force)
 {
@@ -380,25 +377,11 @@ void __init cpu_smt_disable(bool force)
 
 /*
  * The decision whether SMT is supported can only be done after the full
- * CPU identification. Called from architecture code before non boot CPUs
- * are brought up.
- */
-void __init cpu_smt_check_topology_early(void)
-{
-	if (!topology_smt_supported())
-		cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
-}
-
-/*
- * If SMT was disabled by BIOS, detect it here, after the CPUs have been
- * brought online. This ensures the smt/l1tf sysfs entries are consistent
- * with reality. cpu_smt_available is set to true during the bringup of non
- * boot CPUs when a SMT sibling is detected. Note, this may overwrite
- * cpu_smt_control's previous setting.
+ * CPU identification. Called from architecture code.
  */
 void __init cpu_smt_check_topology(void)
 {
-	if (!cpu_smt_available)
+	if (!topology_smt_supported())
 		cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
 }
 
@@ -411,18 +394,10 @@ early_param("nosmt", smt_cmdline_disable);
 
 static inline bool cpu_smt_allowed(unsigned int cpu)
 {
-	if (topology_is_primary_thread(cpu))
+	if (cpu_smt_control == CPU_SMT_ENABLED)
 		return true;
 
-	/*
-	 * If the CPU is not a 'primary' thread and the booted_once bit is
-	 * set then the processor has SMT support. Store this information
-	 * for the late check of SMT support in cpu_smt_check_topology().
-	 */
-	if (per_cpu(cpuhp_state, cpu).booted_once)
-		cpu_smt_available = true;
-
-	if (cpu_smt_control == CPU_SMT_ENABLED)
+	if (topology_is_primary_thread(cpu))
 		return true;
 
 	/*
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index 65c0f13..94aa9ae 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -535,6 +535,8 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
 				arch_kgdb_ops.correct_hw_break();
 			if (trace_on)
 				tracing_on();
+			kgdb_info[cpu].debuggerinfo = NULL;
+			kgdb_info[cpu].task = NULL;
 			kgdb_info[cpu].exception_state &=
 				~(DCPU_WANT_MASTER | DCPU_IS_SLAVE);
 			kgdb_info[cpu].enter_kgdb--;
@@ -667,6 +669,8 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
 	if (trace_on)
 		tracing_on();
 
+	kgdb_info[cpu].debuggerinfo = NULL;
+	kgdb_info[cpu].task = NULL;
 	kgdb_info[cpu].exception_state &=
 		~(DCPU_WANT_MASTER | DCPU_IS_SLAVE);
 	kgdb_info[cpu].enter_kgdb--;
diff --git a/kernel/debug/kdb/kdb_bt.c b/kernel/debug/kdb/kdb_bt.c
index 7921ae4..7e2379a 100644
--- a/kernel/debug/kdb/kdb_bt.c
+++ b/kernel/debug/kdb/kdb_bt.c
@@ -186,7 +186,16 @@ kdb_bt(int argc, const char **argv)
 		kdb_printf("btc: cpu status: ");
 		kdb_parse("cpu\n");
 		for_each_online_cpu(cpu) {
-			sprintf(buf, "btt 0x%px\n", KDB_TSK(cpu));
+			void *kdb_tsk = KDB_TSK(cpu);
+
+			/* If a CPU failed to round up we could be here */
+			if (!kdb_tsk) {
+				kdb_printf("WARNING: no task for cpu %ld\n",
+					   cpu);
+				continue;
+			}
+
+			sprintf(buf, "btt 0x%px\n", kdb_tsk);
 			kdb_parse(buf);
 			touch_nmi_watchdog();
 		}
diff --git a/kernel/debug/kdb/kdb_debugger.c b/kernel/debug/kdb/kdb_debugger.c
index 15e1a7a..53a0df6 100644
--- a/kernel/debug/kdb/kdb_debugger.c
+++ b/kernel/debug/kdb/kdb_debugger.c
@@ -118,13 +118,6 @@ int kdb_stub(struct kgdb_state *ks)
 	kdb_bp_remove();
 	KDB_STATE_CLEAR(DOING_SS);
 	KDB_STATE_SET(PAGER);
-	/* zero out any offline cpu data */
-	for_each_present_cpu(i) {
-		if (!cpu_online(i)) {
-			kgdb_info[i].debuggerinfo = NULL;
-			kgdb_info[i].task = NULL;
-		}
-	}
 	if (ks->err_code == DIE_OOPS || reason == KDB_REASON_OOPS) {
 		ks->pass_exception = 1;
 		KDB_FLAG_SET(CATASTROPHIC);
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6070380..4337dbb 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4931,6 +4931,11 @@ static void __perf_event_period(struct perf_event *event,
 	}
 }
 
+static int perf_event_check_period(struct perf_event *event, u64 value)
+{
+	return event->pmu->check_period(event, value);
+}
+
 static int perf_event_period(struct perf_event *event, u64 __user *arg)
 {
 	u64 value;
@@ -4947,6 +4952,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
 	if (event->attr.freq && value > sysctl_perf_event_sample_rate)
 		return -EINVAL;
 
+	if (perf_event_check_period(event, value))
+		return -EINVAL;
+
 	event_function_call(event, __perf_event_period, &value);
 
 	return 0;
@@ -9149,6 +9157,11 @@ static int perf_pmu_nop_int(struct pmu *pmu)
 	return 0;
 }
 
+static int perf_event_nop_int(struct perf_event *event, u64 value)
+{
+	return 0;
+}
+
 static DEFINE_PER_CPU(unsigned int, nop_txn_flags);
 
 static void perf_pmu_start_txn(struct pmu *pmu, unsigned int flags)
@@ -9449,6 +9462,9 @@ int perf_pmu_register(struct pmu *pmu, const char *name, int type)
 		pmu->pmu_disable = perf_pmu_nop_void;
 	}
 
+	if (!pmu->check_period)
+		pmu->check_period = perf_event_nop_int;
+
 	if (!pmu->event_idx)
 		pmu->event_idx = perf_event_idx_default;
 
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index c573c73..489dc6b 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -719,6 +719,9 @@ struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags)
 	size = sizeof(struct ring_buffer);
 	size += nr_pages * sizeof(void *);
 
+	if (order_base_2(size) >= PAGE_SHIFT+MAX_ORDER)
+		goto fail;
+
 	rb = kzalloc(size, GFP_KERNEL);
 	if (!rb)
 		goto fail;
diff --git a/kernel/exit.c b/kernel/exit.c
index ac1a814..a5392ec 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -306,7 +306,7 @@ void rcuwait_wake_up(struct rcuwait *w)
 	 *        MB (A)	      MB (B)
 	 *    [L] cond		  [L] tsk
 	 */
-	smp_rmb(); /* (B) */
+	smp_mb(); /* (B) */
 
 	/*
 	 * Avoid using task_rcu_dereference() magic as long as we are careful,
@@ -561,12 +561,14 @@ static struct task_struct *find_alive_thread(struct task_struct *p)
 	return NULL;
 }
 
-static struct task_struct *find_child_reaper(struct task_struct *father)
+static struct task_struct *find_child_reaper(struct task_struct *father,
+						struct list_head *dead)
 	__releases(&tasklist_lock)
 	__acquires(&tasklist_lock)
 {
 	struct pid_namespace *pid_ns = task_active_pid_ns(father);
 	struct task_struct *reaper = pid_ns->child_reaper;
+	struct task_struct *p, *n;
 
 	if (likely(reaper != father))
 		return reaper;
@@ -582,6 +584,12 @@ static struct task_struct *find_child_reaper(struct task_struct *father)
 		panic("Attempted to kill init! exitcode=0x%08x\n",
 			father->signal->group_exit_code ?: father->exit_code);
 	}
+
+	list_for_each_entry_safe(p, n, dead, ptrace_entry) {
+		list_del_init(&p->ptrace_entry);
+		release_task(p);
+	}
+
 	zap_pid_ns_processes(pid_ns);
 	write_lock_irq(&tasklist_lock);
 
@@ -671,7 +679,7 @@ static void forget_original_parent(struct task_struct *father,
 		exit_ptrace(father, dead);
 
 	/* Can drop and reacquire tasklist_lock */
-	reaper = find_child_reaper(father);
+	reaper = find_child_reaper(father, dead);
 	if (list_empty(&father->children))
 		return;
 
diff --git a/kernel/fork.c b/kernel/fork.c
index d9b3c6b..37b23e01 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1686,8 +1686,6 @@ static __latent_entropy struct task_struct *copy_process(
 
 	posix_cpu_timers_init(p);
 
-	p->start_time = ktime_get_ns();
-	p->real_start_time = ktime_get_boot_ns();
 	p->io_context = NULL;
 	p->audit_context = NULL;
 	cgroup_fork(p);
@@ -1852,6 +1850,17 @@ static __latent_entropy struct task_struct *copy_process(
 		goto bad_fork_free_pid;
 
 	/*
+	 * From this point on we must avoid any synchronous user-space
+	 * communication until we take the tasklist-lock. In particular, we do
+	 * not want user-space to be able to predict the process start-time by
+	 * stalling fork(2) after we recorded the start_time but before it is
+	 * visible to the system.
+	 */
+
+	p->start_time = ktime_get_ns();
+	p->real_start_time = ktime_get_boot_ns();
+
+	/*
 	 * Make it visible to the rest of the system, but dont wake it up yet.
 	 * Need tasklist lock for parent etc handling!
 	 */
diff --git a/kernel/futex.c b/kernel/futex.c
index 046cd78..22f83064 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1166,11 +1166,65 @@ static int attach_to_pi_state(u32 __user *uaddr, u32 uval,
 	return ret;
 }
 
+static int handle_exit_race(u32 __user *uaddr, u32 uval,
+			    struct task_struct *tsk)
+{
+	u32 uval2;
+
+	/*
+	 * If PF_EXITPIDONE is not yet set, then try again.
+	 */
+	if (tsk && !(tsk->flags & PF_EXITPIDONE))
+		return -EAGAIN;
+
+	/*
+	 * Reread the user space value to handle the following situation:
+	 *
+	 * CPU0				CPU1
+	 *
+	 * sys_exit()			sys_futex()
+	 *  do_exit()			 futex_lock_pi()
+	 *                                futex_lock_pi_atomic()
+	 *   exit_signals(tsk)		    No waiters:
+	 *    tsk->flags |= PF_EXITING;	    *uaddr == 0x00000PID
+	 *  mm_release(tsk)		    Set waiter bit
+	 *   exit_robust_list(tsk) {	    *uaddr = 0x80000PID;
+	 *      Set owner died		    attach_to_pi_owner() {
+	 *    *uaddr = 0xC0000000;	     tsk = get_task(PID);
+	 *   }				     if (!tsk->flags & PF_EXITING) {
+	 *  ...				       attach();
+	 *  tsk->flags |= PF_EXITPIDONE;     } else {
+	 *				       if (!(tsk->flags & PF_EXITPIDONE))
+	 *				         return -EAGAIN;
+	 *				       return -ESRCH; <--- FAIL
+	 *				     }
+	 *
+	 * Returning ESRCH unconditionally is wrong here because the
+	 * user space value has been changed by the exiting task.
+	 *
+	 * The same logic applies to the case where the exiting task is
+	 * already gone.
+	 */
+	if (get_futex_value_locked(&uval2, uaddr))
+		return -EFAULT;
+
+	/* If the user space value has changed, try again. */
+	if (uval2 != uval)
+		return -EAGAIN;
+
+	/*
+	 * The exiting task did not have a robust list, the robust list was
+	 * corrupted or the user space value in *uaddr is simply bogus.
+	 * Give up and tell user space.
+	 */
+	return -ESRCH;
+}
+
 /*
  * Lookup the task for the TID provided from user space and attach to
  * it after doing proper sanity checks.
  */
-static int attach_to_pi_owner(u32 uval, union futex_key *key,
+static int attach_to_pi_owner(u32 __user *uaddr, u32 uval, union futex_key *key,
 			      struct futex_pi_state **ps)
 {
 	pid_t pid = uval & FUTEX_TID_MASK;
@@ -1180,12 +1234,15 @@ static int attach_to_pi_owner(u32 uval, union futex_key *key,
 	/*
 	 * We are the first waiter - try to look up the real owner and attach
 	 * the new pi_state to it, but bail out when TID = 0 [1]
+	 *
+	 * The !pid check is paranoid. None of the call sites should end up
+	 * with pid == 0, but better safe than sorry. Let the caller retry
 	 */
 	if (!pid)
-		return -ESRCH;
+		return -EAGAIN;
 	p = futex_find_get_task(pid);
 	if (!p)
-		return -ESRCH;
+		return handle_exit_race(uaddr, uval, NULL);
 
 	if (unlikely(p->flags & PF_KTHREAD)) {
 		put_task_struct(p);
@@ -1205,7 +1262,7 @@ static int attach_to_pi_owner(u32 uval, union futex_key *key,
 		 * set, we know that the task has finished the
 		 * cleanup:
 		 */
-		int ret = (p->flags & PF_EXITPIDONE) ? -ESRCH : -EAGAIN;
+		int ret = handle_exit_race(uaddr, uval, p);
 
 		raw_spin_unlock_irq(&p->pi_lock);
 		put_task_struct(p);
@@ -1262,7 +1319,7 @@ static int lookup_pi_state(u32 __user *uaddr, u32 uval,
 	 * We are the first waiter - try to look up the owner based on
 	 * @uval and attach to it.
 	 */
-	return attach_to_pi_owner(uval, key, ps);
+	return attach_to_pi_owner(uaddr, uval, key, ps);
 }
 
 static int lock_pi_update_atomic(u32 __user *uaddr, u32 uval, u32 newval)
@@ -1370,7 +1427,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
 	 * attach to the owner. If that fails, no harm done, we only
 	 * set the FUTEX_WAITERS bit in the user space variable.
 	 */
-	return attach_to_pi_owner(uval, key, ps);
+	return attach_to_pi_owner(uaddr, newval, key, ps);
 }
 
 /**
@@ -1405,11 +1462,7 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
 	if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
 		return;
 
-	/*
-	 * Queue the task for later wakeup for after we've released
-	 * the hb->lock. wake_q_add() grabs reference to p.
-	 */
-	wake_q_add(wake_q, p);
+	get_task_struct(p);
 	__unqueue_futex(q);
 	/*
 	 * The waiting task can free the futex_q as soon as q->lock_ptr = NULL
@@ -1419,6 +1472,13 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
 	 * plist_del in __unqueue_futex().
 	 */
 	smp_store_release(&q->lock_ptr, NULL);
+
+	/*
+	 * Queue the task for later wakeup for after we've released
+	 * the hb->lock. wake_q_add() grabs reference to p.
+	 */
+	wake_q_add(wake_q, p);
+	put_task_struct(p);
 }
 
 /*
@@ -2811,35 +2871,39 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
 	 * and BUG when futex_unlock_pi() interleaves with this.
 	 *
 	 * Therefore acquire wait_lock while holding hb->lock, but drop the
-	 * latter before calling rt_mutex_start_proxy_lock(). This still fully
-	 * serializes against futex_unlock_pi() as that does the exact same
-	 * lock handoff sequence.
+	 * latter before calling __rt_mutex_start_proxy_lock(). This
+	 * interleaves with futex_unlock_pi() -- which does a similar lock
+	 * handoff -- such that the latter can observe the futex_q::pi_state
+	 * before __rt_mutex_start_proxy_lock() is done.
 	 */
 	raw_spin_lock_irq(&q.pi_state->pi_mutex.wait_lock);
 	spin_unlock(q.lock_ptr);
+	/*
+	 * __rt_mutex_start_proxy_lock() unconditionally enqueues the @rt_waiter
+	 * such that futex_unlock_pi() is guaranteed to observe the waiter when
+	 * it sees the futex_q::pi_state.
+	 */
 	ret = __rt_mutex_start_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter, current);
 	raw_spin_unlock_irq(&q.pi_state->pi_mutex.wait_lock);
 
 	if (ret) {
 		if (ret == 1)
 			ret = 0;
-
-		spin_lock(q.lock_ptr);
-		goto no_block;
+		goto cleanup;
 	}
 
-
 	if (unlikely(to))
 		hrtimer_start_expires(&to->timer, HRTIMER_MODE_ABS);
 
 	ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter);
 
+cleanup:
 	spin_lock(q.lock_ptr);
 	/*
-	 * If we failed to acquire the lock (signal/timeout), we must
+	 * If we failed to acquire the lock (deadlock/signal/timeout), we must
 	 * first acquire the hb->lock before removing the lock from the
-	 * rt_mutex waitqueue, such that we can keep the hb and rt_mutex
-	 * wait lists consistent.
+	 * rt_mutex waitqueue, such that we can keep the hb and rt_mutex wait
+	 * lists consistent.
 	 *
 	 * In particular; it is important that futex_unlock_pi() can not
 	 * observe this inconsistency.
@@ -2963,6 +3027,10 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
 		 * there is no point where we hold neither; and therefore
 		 * wake_futex_pi() must observe a state consistent with what we
 		 * observed.
+		 *
+		 * In particular; this forces __rt_mutex_start_proxy() to
+		 * complete such that we're guaranteed to observe the
+		 * rt_waiter. Also see the WARN in wake_futex_pi().
 		 */
 		raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
 		spin_unlock(&hb->lock);
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 254f3c1..381085b 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -42,7 +42,7 @@ int sysctl_hung_task_selective_monitoring = 1;
  * is disabled during the critical section. It also controls the size of
  * the RCU grace period. So it needs to be upper-bound.
  */
-#define HUNG_TASK_BATCHING 1024
+#define HUNG_TASK_LOCK_BREAK (HZ / 10)
 
 /*
  * Zero means infinite timeout - no checking done:
@@ -112,8 +112,11 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
 
 	trace_sched_process_hang(t);
 
-	if (!sysctl_hung_task_warnings && !sysctl_hung_task_panic)
-		return;
+	if (sysctl_hung_task_panic) {
+		console_verbose();
+		hung_task_show_lock = true;
+		hung_task_call_panic = true;
+	}
 
 	/*
 	 * Ok, the task did not get scheduled for more than 2 minutes,
@@ -135,11 +138,6 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
 	}
 
 	touch_nmi_watchdog();
-
-	if (sysctl_hung_task_panic) {
-		hung_task_show_lock = true;
-		hung_task_call_panic = true;
-	}
 }
 
 /*
@@ -173,7 +171,7 @@ static bool rcu_lock_break(struct task_struct *g, struct task_struct *t)
 static void check_hung_uninterruptible_tasks(unsigned long timeout)
 {
 	int max_count = sysctl_hung_task_check_count;
-	int batch_count = HUNG_TASK_BATCHING;
+	unsigned long last_break = jiffies;
 	struct task_struct *g, *t;
 
 	/*
@@ -188,10 +186,10 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
 	for_each_process_thread(g, t) {
 		if (!max_count--)
 			goto unlock;
-		if (!--batch_count) {
-			batch_count = HUNG_TASK_BATCHING;
+		if (time_after(jiffies, last_break + HUNG_TASK_LOCK_BREAK)) {
 			if (!rcu_lock_break(g, t))
 				goto unlock;
+			last_break = jiffies;
 		}
 		/* use "==" to skip the TASK_KILLABLE tasks waiting on NFS */
 		if (t->state == TASK_UNINTERRUPTIBLE)
diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
index a37a3b4..e066554 100644
--- a/kernel/irq/affinity.c
+++ b/kernel/irq/affinity.c
@@ -108,7 +108,7 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 	int affv = nvecs - affd->pre_vectors - affd->post_vectors;
 	int last_affv = affv + affd->pre_vectors;
 	nodemask_t nodemsk = NODE_MASK_NONE;
-	struct cpumask *masks;
+	struct cpumask *masks = NULL;
 	cpumask_var_t nmsk, *node_to_possible_cpumask;
 
 	/*
@@ -121,13 +121,13 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 	if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))
 		return NULL;
 
-	masks = kcalloc(nvecs, sizeof(*masks), GFP_KERNEL);
-	if (!masks)
-		goto out;
-
 	node_to_possible_cpumask = alloc_node_to_possible_cpumask();
 	if (!node_to_possible_cpumask)
-		goto out;
+		goto outcpumsk;
+
+	masks = kcalloc(nvecs, sizeof(*masks), GFP_KERNEL);
+	if (!masks)
+		goto outnodemsk;
 
 	/* Fill out vectors at the beginning that don't need affinity */
 	for (curvec = 0; curvec < affd->pre_vectors; curvec++)
@@ -192,8 +192,9 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 	/* Fill out vectors at the end that don't need affinity */
 	for (; curvec < nvecs; curvec++)
 		cpumask_copy(masks + curvec, irq_default_affinity);
+outnodemsk:
 	free_node_to_possible_cpumask(node_to_possible_cpumask);
-out:
+outcpumsk:
 	free_cpumask_var(nmsk);
 	return masks;
 }
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 4ad35718..71c554a 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1726,12 +1726,33 @@ void rt_mutex_proxy_unlock(struct rt_mutex *lock,
 	rt_mutex_set_owner(lock, NULL);
 }
 
+/**
+ * __rt_mutex_start_proxy_lock() - Start lock acquisition for another task
+ * @lock:		the rt_mutex to take
+ * @waiter:		the pre-initialized rt_mutex_waiter
+ * @task:		the task to prepare
+ *
+ * Starts the rt_mutex acquire; it enqueues the @waiter and does deadlock
+ * detection. It does not wait, see rt_mutex_wait_proxy_lock() for that.
+ *
+ * NOTE: does _NOT_ remove the @waiter on failure; must either call
+ * rt_mutex_wait_proxy_lock() or rt_mutex_cleanup_proxy_lock() after this.
+ *
+ * Returns:
+ *  0 - task blocked on lock
+ *  1 - acquired the lock for task, caller should wake it up
+ * <0 - error
+ *
+ * Special API call for PI-futex support.
+ */
 int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
 			      struct rt_mutex_waiter *waiter,
 			      struct task_struct *task)
 {
 	int ret;
 
+	lockdep_assert_held(&lock->wait_lock);
+
 	if (try_to_take_rt_mutex(lock, task, NULL))
 		return 1;
 
@@ -1749,9 +1770,6 @@ int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
 		ret = 0;
 	}
 
-	if (unlikely(ret))
-		remove_waiter(lock, waiter);
-
 	debug_rt_mutex_print_deadlock(waiter);
 
 	return ret;
@@ -1763,12 +1781,18 @@ int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
  * @waiter:		the pre-initialized rt_mutex_waiter
  * @task:		the task to prepare
  *
+ * Starts the rt_mutex acquire; it enqueues the @waiter and does deadlock
+ * detection. It does not wait, see rt_mutex_wait_proxy_lock() for that.
+ *
+ * NOTE: unlike __rt_mutex_start_proxy_lock this _DOES_ remove the @waiter
+ * on failure.
+ *
  * Returns:
  *  0 - task blocked on lock
  *  1 - acquired the lock for task, caller should wake it up
  * <0 - error
  *
- * Special API call for FUTEX_REQUEUE_PI support.
+ * Special API call for PI-futex support.
  */
 int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
 			      struct rt_mutex_waiter *waiter,
@@ -1778,6 +1802,8 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
 
 	raw_spin_lock_irq(&lock->wait_lock);
 	ret = __rt_mutex_start_proxy_lock(lock, waiter, task);
+	if (unlikely(ret))
+		remove_waiter(lock, waiter);
 	raw_spin_unlock_irq(&lock->wait_lock);
 
 	return ret;
@@ -1845,7 +1871,8 @@ int rt_mutex_wait_proxy_lock(struct rt_mutex *lock,
  * @lock:		the rt_mutex we were woken on
  * @waiter:		the pre-initialized rt_mutex_waiter
  *
- * Attempt to clean up after a failed rt_mutex_wait_proxy_lock().
+ * Attempt to clean up after a failed __rt_mutex_start_proxy_lock() or
+ * rt_mutex_wait_proxy_lock().
  *
  * Unless we acquired the lock; we're still enqueued on the wait-list and can
  * in fact still be granted ownership until we're removed. Therefore we can
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
index 8b41d88..1e01501 100644
--- a/kernel/locking/rwsem-xadd.c
+++ b/kernel/locking/rwsem-xadd.c
@@ -190,15 +190,22 @@ static void __rwsem_mark_wake(struct rw_semaphore *sem,
 		woken++;
 		tsk = waiter->task;
 
-		wake_q_add(wake_q, tsk);
+		get_task_struct(tsk);
 		list_del(&waiter->list);
 		/*
-		 * Ensure that the last operation is setting the reader
+		 * Ensure calling get_task_struct() before setting the reader
 		 * waiter to nil such that rwsem_down_read_failed() cannot
 		 * race with do_exit() by always holding a reference count
 		 * to the task to wakeup.
 		 */
 		smp_store_release(&waiter->task, NULL);
+		/*
+		 * Ensure issuing the wakeup (either by us or someone else)
+		 * after setting the reader waiter to nil.
+		 */
+		wake_q_add(wake_q, tsk);
+		/* wake_q_add() already take the task ref */
+		put_task_struct(tsk);
 	}
 
 	adjustment = woken * RWSEM_ACTIVE_READ_BIAS - adjustment;
diff --git a/kernel/memremap.c b/kernel/memremap.c
index 790ddf3..0d676d6 100644
--- a/kernel/memremap.c
+++ b/kernel/memremap.c
@@ -379,15 +379,12 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
 	is_ram = region_intersects(align_start, align_size,
 		IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
 
-	if (is_ram == REGION_MIXED) {
-		WARN_ONCE(1, "%s attempted on mixed region %pr\n",
-				__func__, res);
+	if (is_ram != REGION_DISJOINT) {
+		WARN_ONCE(1, "%s attempted on %s region %pr\n", __func__,
+				is_ram == REGION_MIXED ? "mixed" : "ram", res);
 		return ERR_PTR(-ENXIO);
 	}
 
-	if (is_ram == REGION_INTERSECTS)
-		return __va(res->start);
-
 	if (!ref)
 		return ERR_PTR(-EINVAL);
 
@@ -482,7 +479,7 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
 	devres_free(page_map);
 	return ERR_PTR(error);
 }
-EXPORT_SYMBOL(devm_memremap_pages);
+EXPORT_SYMBOL_GPL(devm_memremap_pages);
 
 unsigned long vmem_altmap_offset(struct vmem_altmap *altmap)
 {
diff --git a/kernel/module.c b/kernel/module.c
index 6aca518..e0affc2 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1201,8 +1201,10 @@ static ssize_t store_uevent(struct module_attribute *mattr,
 			    struct module_kobject *mk,
 			    const char *buffer, size_t count)
 {
-	kobject_synth_uevent(&mk->kobj, buffer, count);
-	return count;
+	int rc;
+
+	rc = kobject_synth_uevent(&mk->kobj, buffer, count);
+	return rc ? rc : count;
 }
 
 struct module_attribute module_uevent =
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 27ab3cc..12bea110 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -32,6 +32,7 @@
 #include <linux/kthread.h>
 
 #include <asm/switch_to.h>
+#include <linux/msm_rtb.h>
 #include <asm/tlb.h>
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
@@ -2916,7 +2917,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
 	 */
 	rq_unpin_lock(rq, rf);
 	spin_release(&rq->lock.dep_map, 1, _THIS_IP_);
-
+	uncached_logk(LOGK_CTXID, (void *)(u64)next->pid);
 	/* Here we just switch the register state and the stack. */
 	switch_to(prev, next, prev);
 	barrier();
@@ -4889,6 +4890,9 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
 		retval = -EINVAL;
 	}
 
+	if (!retval && !(p->flags & PF_KTHREAD))
+		cpumask_and(&p->cpus_requested, in_mask, cpu_possible_mask);
+
 out_free_new_mask:
 	free_cpumask_var(new_mask);
 out_free_cpus_allowed:
@@ -6318,6 +6322,7 @@ void __init sched_init_smp(void)
 	/* Move init over to a non-isolated CPU */
 	if (set_cpus_allowed_ptr(current, non_isolated_cpus) < 0)
 		BUG();
+	cpumask_copy(&current->cpus_requested, cpu_possible_mask);
 	sched_init_granularity();
 	free_cpumask_var(non_isolated_cpus);
 
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 8b18026..f362c58 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -441,10 +441,9 @@ static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq)
 	}
 }
 
-/* Iterate thr' all leaf cfs_rq's on a runqueue */
-#define for_each_leaf_cfs_rq_safe(rq, cfs_rq, pos)			\
-	list_for_each_entry_safe(cfs_rq, pos, &rq->leaf_cfs_rq_list,	\
-				 leaf_cfs_rq_list)
+/* Iterate through all leaf cfs_rq's on a runqueue: */
+#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+	list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
 
 /* Do the two (enqueued) entities belong to the same group ? */
 static inline struct cfs_rq *
@@ -537,8 +536,8 @@ static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq)
 {
 }
 
-#define for_each_leaf_cfs_rq_safe(rq, cfs_rq, pos)	\
-		for (cfs_rq = &rq->cfs, pos = NULL; cfs_rq; cfs_rq = pos)
+#define for_each_leaf_cfs_rq(rq, cfs_rq)	\
+		for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
 
 static inline struct sched_entity *parent_entity(struct sched_entity *se)
 {
@@ -4397,6 +4396,7 @@ void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b)
 	now = sched_clock_cpu(smp_processor_id());
 	cfs_b->runtime = cfs_b->quota;
 	cfs_b->runtime_expires = now + ktime_to_ns(cfs_b->period);
+	cfs_b->expires_seq++;
 }
 
 static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
@@ -4419,6 +4419,7 @@ static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 	struct task_group *tg = cfs_rq->tg;
 	struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(tg);
 	u64 amount = 0, min_amount, expires;
+	int expires_seq;
 
 	/* note: this is a positive sum as runtime_remaining <= 0 */
 	min_amount = sched_cfs_bandwidth_slice() - cfs_rq->runtime_remaining;
@@ -4435,6 +4436,7 @@ static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 			cfs_b->idle = 0;
 		}
 	}
+	expires_seq = cfs_b->expires_seq;
 	expires = cfs_b->runtime_expires;
 	raw_spin_unlock(&cfs_b->lock);
 
@@ -4444,8 +4446,10 @@ static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 	 * spread between our sched_clock and the one on which runtime was
 	 * issued.
 	 */
-	if ((s64)(expires - cfs_rq->runtime_expires) > 0)
+	if (cfs_rq->expires_seq != expires_seq) {
+		cfs_rq->expires_seq = expires_seq;
 		cfs_rq->runtime_expires = expires;
+	}
 
 	return cfs_rq->runtime_remaining > 0;
 }
@@ -4471,12 +4475,9 @@ static void expire_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 	 * has not truly expired.
 	 *
 	 * Fortunately we can check determine whether this the case by checking
-	 * whether the global deadline has advanced. It is valid to compare
-	 * cfs_b->runtime_expires without any locks since we only care about
-	 * exact equality, so a partial write will still work.
+	 * whether the global deadline(cfs_b->expires_seq) has advanced.
 	 */
-
-	if (cfs_rq->runtime_expires != cfs_b->runtime_expires) {
+	if (cfs_rq->expires_seq == cfs_b->expires_seq) {
 		/* extend local deadline, drift is bounded above by 2 ticks */
 		cfs_rq->runtime_expires += TICK_NSEC;
 	} else {
@@ -6959,6 +6960,7 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p
 
 #ifdef CONFIG_SCHED_SMT
 DEFINE_STATIC_KEY_FALSE(sched_smt_present);
+EXPORT_SYMBOL_GPL(sched_smt_present);
 
 static inline void set_idle_cores(int cpu, int val)
 {
@@ -7273,8 +7275,9 @@ static inline bool task_fits_max(struct task_struct *p, int cpu)
 	if (capacity == max_capacity)
 		return true;
 
-	if (task_boost_policy(p) == SCHED_BOOST_ON_BIG
-			&& is_min_capacity_cpu(cpu))
+	if ((task_boost_policy(p) == SCHED_BOOST_ON_BIG ||
+			schedtune_task_boost(p) > 0) &&
+			is_min_capacity_cpu(cpu))
 		return false;
 
 	return task_fits_capacity(p, capacity, cpu);
@@ -9350,27 +9353,10 @@ static void attach_tasks(struct lb_env *env)
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 
-static inline bool cfs_rq_is_decayed(struct cfs_rq *cfs_rq)
-{
-	if (cfs_rq->load.weight)
-		return false;
-
-	if (cfs_rq->avg.load_sum)
-		return false;
-
-	if (cfs_rq->avg.util_sum)
-		return false;
-
-	if (cfs_rq->runnable_load_sum)
-		return false;
-
-	return true;
-}
-
 static void update_blocked_averages(int cpu)
 {
 	struct rq *rq = cpu_rq(cpu);
-	struct cfs_rq *cfs_rq, *pos;
+	struct cfs_rq *cfs_rq;
 	struct rq_flags rf;
 
 	rq_lock_irqsave(rq, &rf);
@@ -9380,7 +9366,7 @@ static void update_blocked_averages(int cpu)
 	 * Iterates the task_group tree in a bottom up fashion, see
 	 * list_add_leaf_cfs_rq() for details.
 	 */
-	for_each_leaf_cfs_rq_safe(rq, cfs_rq, pos) {
+	for_each_leaf_cfs_rq(rq, cfs_rq) {
 		struct sched_entity *se;
 
 		/* throttled entities do not contribute to load */
@@ -9394,13 +9380,6 @@ static void update_blocked_averages(int cpu)
 		se = cfs_rq->tg->se[cpu];
 		if (se && !skip_blocked_update(se))
 			update_load_avg(se, 0);
-
-		/*
-		 * There can be a lot of idle CPU cgroups.  Don't let fully
-		 * decayed cfs_rqs linger on the list.
-		 */
-		if (cfs_rq_is_decayed(cfs_rq))
-			list_del_leaf_cfs_rq(cfs_rq);
 	}
 	update_rt_rq_load_avg(rq_clock_task(rq), cpu, &rq->rt, 0);
 #ifdef CONFIG_NO_HZ_COMMON
@@ -12586,10 +12565,10 @@ const struct sched_class fair_sched_class = {
 #ifdef CONFIG_SCHED_DEBUG
 void print_cfs_stats(struct seq_file *m, int cpu)
 {
-	struct cfs_rq *cfs_rq, *pos;
+	struct cfs_rq *cfs_rq;
 
 	rcu_read_lock();
-	for_each_leaf_cfs_rq_safe(cpu_rq(cpu), cfs_rq, pos)
+	for_each_leaf_cfs_rq(cpu_rq(cpu), cfs_rq)
 		print_cfs_rq(m, cpu, cfs_rq);
 	rcu_read_unlock();
 }
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 22c4509..f2f44a0 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -350,8 +350,9 @@ struct cfs_bandwidth {
 	u64 quota, runtime;
 	s64 hierarchical_quota;
 	u64 runtime_expires;
+	int expires_seq;
 
-	int idle, period_active;
+	short idle, period_active;
 	struct hrtimer period_timer, slack_timer;
 	struct list_head throttled_cfs_rq;
 
@@ -561,6 +562,7 @@ struct cfs_rq {
 
 #ifdef CONFIG_CFS_BANDWIDTH
 	int runtime_enabled;
+	int expires_seq;
 	u64 runtime_expires;
 	s64 runtime_remaining;
 
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index 0bda756..f57486b 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -3177,13 +3177,19 @@ void walt_irq_work(struct irq_work *irq_work)
 	u64 wc;
 	bool is_migration = false;
 	u64 total_grp_load = 0;
+	int level = 0;
 
 	/* Am I the window rollover work or the migration work? */
 	if (irq_work == &walt_migration_irq_work)
 		is_migration = true;
 
-	for_each_cpu(cpu, cpu_possible_mask)
-		raw_spin_lock(&cpu_rq(cpu)->lock);
+	for_each_cpu(cpu, cpu_possible_mask) {
+		if (level == 0)
+			raw_spin_lock(&cpu_rq(cpu)->lock);
+		else
+			raw_spin_lock_nested(&cpu_rq(cpu)->lock, level);
+		level++;
+	}
 
 	wc = sched_ktime_clock();
 	walt_load_reported_window = atomic64_read(&walt_irq_work_lastq_ws);
diff --git a/kernel/signal.c b/kernel/signal.c
index bd4bc31..5da5b95 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -674,6 +674,48 @@ void signal_wake_up_state(struct task_struct *t, unsigned int state)
 		kick_process(t);
 }
 
+static int dequeue_synchronous_signal(siginfo_t *info)
+{
+	struct task_struct *tsk = current;
+	struct sigpending *pending = &tsk->pending;
+	struct sigqueue *q, *sync = NULL;
+
+	/*
+	 * Might a synchronous signal be in the queue?
+	 */
+	if (!((pending->signal.sig[0] & ~tsk->blocked.sig[0]) & SYNCHRONOUS_MASK))
+		return 0;
+
+	/*
+	 * Return the first synchronous signal in the queue.
+	 */
+	list_for_each_entry(q, &pending->list, list) {
+		/* Synchronous signals have a postive si_code */
+		if ((q->info.si_code > SI_USER) &&
+		    (sigmask(q->info.si_signo) & SYNCHRONOUS_MASK)) {
+			sync = q;
+			goto next;
+		}
+	}
+	return 0;
+next:
+	/*
+	 * Check if there is another siginfo for the same signal.
+	 */
+	list_for_each_entry_continue(q, &pending->list, list) {
+		if (q->info.si_signo == sync->info.si_signo)
+			goto still_pending;
+	}
+
+	sigdelset(&pending->signal, sync->info.si_signo);
+	recalc_sigpending();
+still_pending:
+	list_del_init(&sync->list);
+	copy_siginfo(info, &sync->info);
+	__sigqueue_free(sync);
+	return info->si_signo;
+}
+
 /*
  * Remove signals in mask from the pending set and queue.
  * Returns 1 if any signals were found.
@@ -2230,6 +2272,14 @@ int get_signal(struct ksignal *ksig)
 		goto relock;
 	}
 
+	/* Has this task already been marked for death? */
+	if (signal_group_exit(signal)) {
+		ksig->info.si_signo = signr = SIGKILL;
+		sigdelset(&current->pending.signal, SIGKILL);
+		recalc_sigpending();
+		goto fatal;
+	}
+
 	for (;;) {
 		struct k_sigaction *ka;
 
@@ -2243,7 +2293,15 @@ int get_signal(struct ksignal *ksig)
 			goto relock;
 		}
 
-		signr = dequeue_signal(current, &current->blocked, &ksig->info);
+		/*
+		 * Signals generated by the execution of an instruction
+		 * need to be delivered before any other pending signals
+		 * so that the instruction pointer in the signal stack
+		 * frame points to the faulting instruction.
+		 */
+		signr = dequeue_synchronous_signal(&ksig->info);
+		if (!signr)
+			signr = dequeue_signal(current, &current->blocked, &ksig->info);
 
 		if (!signr)
 			break; /* will return 0 */
@@ -2325,6 +2383,7 @@ int get_signal(struct ksignal *ksig)
 			continue;
 		}
 
+	fatal:
 		spin_unlock_irq(&sighand->siglock);
 
 		/*
diff --git a/kernel/smp.c b/kernel/smp.c
index d710fd3..7672a68 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -616,8 +616,6 @@ void __init smp_init(void)
 		num_nodes, (num_nodes > 1 ? "s" : ""),
 		num_cpus,  (num_cpus  > 1 ? "s" : ""));
 
-	/* Final decision about SMT support */
-	cpu_smt_check_topology();
 	/* Any cleanup work */
 	smp_cpus_done(setup_max_cpus);
 }
diff --git a/kernel/softirq.c b/kernel/softirq.c
index ee4f0e0..dc5da15 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -514,7 +514,9 @@ static __latent_entropy void tasklet_action(struct softirq_action *a)
 				if (!test_and_clear_bit(TASKLET_STATE_SCHED,
 							&t->state))
 					BUG();
+				trace_tasklet_entry(t->func);
 				t->func(t->data);
+				trace_tasklet_exit(t->func);
 				tasklet_unlock(t);
 				continue;
 			}
@@ -550,7 +552,9 @@ static __latent_entropy void tasklet_hi_action(struct softirq_action *a)
 				if (!test_and_clear_bit(TASKLET_STATE_SCHED,
 							&t->state))
 					BUG();
+				trace_tasklet_hi_entry(t->func);
 				t->func(t->data);
+				trace_tasklet_hi_exit(t->func);
 				tasklet_unlock(t);
 				continue;
 			}
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index daf3783..450e5cf 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2924,6 +2924,8 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
 			bool neg;
 
 			left -= proc_skip_spaces(&p);
+			if (!left)
+				break;
 
 			err = proc_get_long(&p, &left, &val, &neg,
 					     proc_wspace_sep,
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 4559e91..609cc53 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -23,7 +23,10 @@
 #include <linux/cpumask.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
+#include <linux/swap.h>
+#include <linux/vmalloc.h>
 #include <linux/cgroupstats.h>
+#include <linux/sysstats.h>
 #include <linux/cgroup.h>
 #include <linux/fs.h>
 #include <linux/file.h>
@@ -31,6 +34,7 @@
 #include <net/genetlink.h>
 #include <linux/atomic.h>
 #include <linux/sched/cputime.h>
+#include <linux/oom.h>
 
 /*
  * Maximum length of a cpumask that can be specified in
@@ -48,7 +52,8 @@ static const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1
 	[TASKSTATS_CMD_ATTR_PID]  = { .type = NLA_U32 },
 	[TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 },
 	[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING },
-	[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },};
+	[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },
+	[TASKSTATS_CMD_ATTR_FOREACH] = { .type = NLA_U32 },};
 
 /*
  * We have to use TASKSTATS_CMD_ATTR_MAX here, it is the maxattr in the family.
@@ -58,6 +63,11 @@ static const struct nla_policy cgroupstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX
 	[CGROUPSTATS_CMD_ATTR_FD] = { .type = NLA_U32 },
 };
 
+static const struct nla_policy
+		sysstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = {
+	[SYSSTATS_CMD_ATTR_SYSMEM_STATS] = { .type = NLA_U32 },
+};
+
 struct listener {
 	struct list_head list;
 	pid_t pid;
@@ -70,6 +80,11 @@ struct listener_list {
 };
 static DEFINE_PER_CPU(struct listener_list, listener_array);
 
+struct tgid_iter {
+	unsigned int tgid;
+	struct task_struct *task;
+};
+
 enum actions {
 	REGISTER,
 	DEREGISTER,
@@ -400,6 +415,142 @@ static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid)
 	return NULL;
 }
 
+#define K(x) ((x) << (PAGE_SHIFT - 10))
+#ifndef CONFIG_NUMA
+static void sysstats_fill_zoneinfo(struct sys_memstats *stats)
+{
+	pg_data_t *pgdat;
+	struct zone *zone;
+	struct zone *node_zones;
+	unsigned long zspages = 0;
+
+	pgdat = NODE_DATA(0);
+	node_zones = pgdat->node_zones;
+
+	for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
+		if (!populated_zone(zone))
+			continue;
+
+		zspages += zone_page_state(zone, NR_ZSPAGES);
+		if (!strcmp(zone->name, "DMA")) {
+			stats->dma_nr_free_pages =
+				K(zone_page_state(zone, NR_FREE_PAGES));
+			stats->dma_nr_active_anon =
+				K(zone_page_state(zone, NR_ZONE_ACTIVE_ANON));
+			stats->dma_nr_inactive_anon =
+				K(zone_page_state(zone, NR_ZONE_INACTIVE_ANON));
+			stats->dma_nr_active_file =
+				K(zone_page_state(zone, NR_ZONE_ACTIVE_FILE));
+			stats->dma_nr_inactive_file =
+				K(zone_page_state(zone, NR_ZONE_INACTIVE_FILE));
+		} else if (!strcmp(zone->name, "Normal")) {
+			stats->normal_nr_free_pages =
+				K(zone_page_state(zone, NR_FREE_PAGES));
+			stats->normal_nr_active_anon =
+				K(zone_page_state(zone, NR_ZONE_ACTIVE_ANON));
+			stats->normal_nr_inactive_anon =
+				K(zone_page_state(zone, NR_ZONE_INACTIVE_ANON));
+			stats->normal_nr_active_file =
+				K(zone_page_state(zone, NR_ZONE_ACTIVE_FILE));
+			stats->normal_nr_inactive_file =
+				K(zone_page_state(zone, NR_ZONE_INACTIVE_FILE));
+		} else if (!strcmp(zone->name, "HighMem")) {
+			stats->highmem_nr_free_pages =
+				K(zone_page_state(zone, NR_FREE_PAGES));
+			stats->highmem_nr_active_anon =
+				K(zone_page_state(zone, NR_ZONE_ACTIVE_ANON));
+			stats->highmem_nr_inactive_anon =
+				K(zone_page_state(zone, NR_ZONE_INACTIVE_ANON));
+			stats->highmem_nr_active_file =
+				K(zone_page_state(zone, NR_ZONE_ACTIVE_FILE));
+			stats->highmem_nr_inactive_file =
+				K(zone_page_state(zone, NR_ZONE_INACTIVE_FILE));
+		} else if (!strcmp(zone->name, "Movable")) {
+			stats->movable_nr_free_pages =
+				K(zone_page_state(zone, NR_FREE_PAGES));
+			stats->movable_nr_active_anon =
+				K(zone_page_state(zone, NR_ZONE_ACTIVE_ANON));
+			stats->movable_nr_inactive_anon =
+				K(zone_page_state(zone, NR_ZONE_INACTIVE_ANON));
+			stats->movable_nr_active_file =
+				K(zone_page_state(zone, NR_ZONE_ACTIVE_FILE));
+			stats->movable_nr_inactive_file =
+				K(zone_page_state(zone, NR_ZONE_INACTIVE_FILE));
+		}
+	}
+	stats->zram_compressed = K(zspages);
+}
+#elif
+static void sysstats_fill_zoneinfo(struct sys_memstats *stats)
+{
+}
+#endif
+
+static void sysstats_build(struct sys_memstats *stats)
+{
+	struct sysinfo i;
+
+	si_meminfo(&i);
+	si_swapinfo(&i);
+
+	stats->version = SYSSTATS_VERSION;
+	stats->memtotal = K(i.totalram);
+	stats->reclaimable =
+		global_node_page_state(NR_INDIRECTLY_RECLAIMABLE_BYTES) >> 10;
+	stats->swap_used = K(i.totalswap - i.freeswap);
+	stats->swap_total = K(i.totalswap);
+	stats->vmalloc_total = K(vmalloc_nr_pages());
+	stats->unreclaimable =
+		K(global_node_page_state(NR_UNRECLAIMABLE_PAGES));
+	stats->buffer = K(i.bufferram);
+	stats->swapcache = K(total_swapcache_pages());
+	stats->slab_reclaimable =
+		K(global_node_page_state(NR_SLAB_RECLAIMABLE));
+	stats->slab_unreclaimable =
+		K(global_node_page_state(NR_SLAB_UNRECLAIMABLE));
+	stats->free_cma = K(global_zone_page_state(NR_FREE_CMA_PAGES));
+	stats->file_mapped = K(global_node_page_state(NR_FILE_MAPPED));
+	stats->kernelstack = global_zone_page_state(NR_KERNEL_STACK_KB);
+	stats->pagetable = K(global_zone_page_state(NR_PAGETABLE));
+	stats->shmem = K(i.sharedram);
+	sysstats_fill_zoneinfo(stats);
+}
+#undef K
+
+static int sysstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+	int rc = 0;
+	struct sk_buff *rep_skb;
+	struct sys_memstats *stats;
+	struct nlattr *na;
+	size_t size;
+
+	size = nla_total_size(sizeof(struct sys_memstats));
+
+	rc = prepare_reply(info, SYSSTATS_CMD_NEW, &rep_skb,
+				size);
+	if (rc < 0)
+		goto err;
+
+	na = nla_reserve(rep_skb, SYSSTATS_TYPE_SYSMEM_STATS,
+				sizeof(struct sys_memstats));
+	if (na == NULL) {
+		nlmsg_free(rep_skb);
+		rc = -EMSGSIZE;
+		goto err;
+	}
+
+	stats = nla_data(na);
+	memset(stats, 0, sizeof(*stats));
+
+	sysstats_build(stats);
+
+	rc = send_reply(rep_skb, info);
+
+err:
+	return rc;
+}
+
 static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
 {
 	int rc = 0;
@@ -493,6 +644,65 @@ static size_t taskstats_packet_size(void)
 	return size;
 }
 
+static int taskstats2_cmd_attr_pid(struct genl_info *info)
+{
+	struct taskstats2 *stats;
+	struct sk_buff *rep_skb;
+	struct nlattr *ret;
+	struct task_struct *tsk;
+	struct task_struct *p;
+	size_t size;
+	u32 pid;
+	int rc;
+
+	size = nla_total_size_64bit(sizeof(struct taskstats2));
+
+	rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size);
+	if (rc < 0)
+		return rc;
+
+	rc = -EINVAL;
+	pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]);
+
+	ret = nla_reserve_64bit(rep_skb, TASKSTATS_TYPE_STATS,
+				sizeof(struct taskstats2), TASKSTATS_TYPE_NULL);
+	if (!ret)
+		goto err;
+
+	stats = nla_data(ret);
+
+	rcu_read_lock();
+	tsk = find_task_by_vpid(pid);
+	if (tsk)
+		get_task_struct(tsk);
+	rcu_read_unlock();
+	if (!tsk) {
+		rc = -ESRCH;
+		goto err;
+	}
+	memset(stats, 0, sizeof(*stats));
+	stats->version = TASKSTATS2_VERSION;
+	stats->pid = task_pid_nr_ns(tsk, task_active_pid_ns(current));
+	p = find_lock_task_mm(tsk);
+	if (p) {
+#define K(x) ((x) << (PAGE_SHIFT - 10))
+		stats->anon_rss = K(get_mm_counter(p->mm, MM_ANONPAGES));
+		stats->file_rss = K(get_mm_counter(p->mm, MM_FILEPAGES));
+		stats->shmem_rss = K(get_mm_counter(p->mm, MM_SHMEMPAGES));
+		stats->swap_rss = K(get_mm_counter(p->mm, MM_SWAPENTS));
+		stats->unreclaimable =
+				K(get_mm_counter(p->mm, MM_UNRECLAIMABLE));
+#undef K
+		task_unlock(p);
+	}
+	put_task_struct(tsk);
+
+	return send_reply(rep_skb, info);
+err:
+	nlmsg_free(rep_skb);
+	return rc;
+}
+
 static int cmd_attr_pid(struct genl_info *info)
 {
 	struct taskstats *stats;
@@ -551,6 +761,114 @@ static int cmd_attr_tgid(struct genl_info *info)
 	return rc;
 }
 
+static struct tgid_iter next_tgid(struct pid_namespace *ns,
+					struct tgid_iter iter)
+{
+	struct pid *pid;
+
+	if (iter.task)
+		put_task_struct(iter.task);
+	rcu_read_lock();
+retry:
+	iter.task = NULL;
+	pid = find_ge_pid(iter.tgid, ns);
+	if (pid) {
+		iter.tgid = pid_nr_ns(pid, ns);
+		iter.task = pid_task(pid, PIDTYPE_PID);
+		if (!iter.task || !has_group_leader_pid(iter.task)) {
+			iter.tgid += 1;
+			goto retry;
+		}
+		get_task_struct(iter.task);
+	}
+	rcu_read_unlock();
+	return iter;
+}
+
+static int taskstats2_foreach(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct pid_namespace *ns = task_active_pid_ns(current);
+	struct tgid_iter iter;
+	void *reply;
+	struct nlattr *attr;
+	struct nlattr *nla;
+	struct taskstats2 *stats;
+	struct task_struct *p;
+	short oom_score;
+	short oom_score_min;
+	short oom_score_max;
+	u32 buf;
+
+	nla = nla_find(nlmsg_attrdata(cb->nlh, GENL_HDRLEN),
+			nlmsg_attrlen(cb->nlh, GENL_HDRLEN),
+			TASKSTATS_TYPE_FOREACH);
+	buf  = nla_get_u32(nla);
+	oom_score_min = (short) (buf & 0xFFFF);
+	oom_score_max = (short) ((buf >> 16) & 0xFFFF);
+
+	iter.tgid = cb->args[0];
+	iter.task = NULL;
+	for (iter = next_tgid(ns, iter); iter.task;
+			iter.tgid += 1, iter = next_tgid(ns, iter)) {
+
+		if (iter.task->flags & PF_KTHREAD)
+			continue;
+
+		oom_score = iter.task->signal->oom_score_adj;
+		if ((oom_score < oom_score_min)
+			|| (oom_score > oom_score_max))
+			continue;
+
+		reply = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
+			cb->nlh->nlmsg_seq, &family, 0, TASKSTATS2_CMD_GET);
+		if (reply == NULL) {
+			put_task_struct(iter.task);
+			break;
+		}
+		attr = nla_reserve(skb, TASKSTATS_TYPE_FOREACH,
+				sizeof(struct taskstats2));
+		if (!attr) {
+			put_task_struct(iter.task);
+			genlmsg_cancel(skb, reply);
+			break;
+		}
+		stats = nla_data(attr);
+		memset(stats, 0, sizeof(struct taskstats2));
+		stats->version = TASKSTATS2_VERSION;
+		rcu_read_lock();
+		stats->pid = task_pid_nr_ns(iter.task,
+						task_active_pid_ns(current));
+		stats->oom_score = iter.task->signal->oom_score_adj;
+		rcu_read_unlock();
+		p = find_lock_task_mm(iter.task);
+		if (p) {
+#define K(x) ((x) << (PAGE_SHIFT - 10))
+			stats->anon_rss =
+				K(get_mm_counter(p->mm, MM_ANONPAGES));
+			stats->file_rss =
+				K(get_mm_counter(p->mm, MM_FILEPAGES));
+			stats->shmem_rss =
+				K(get_mm_counter(p->mm, MM_SHMEMPAGES));
+			stats->swap_rss =
+				K(get_mm_counter(p->mm, MM_SWAPENTS));
+			task_unlock(p);
+#undef K
+		}
+		genlmsg_end(skb, reply);
+	}
+
+	cb->args[0] = iter.tgid;
+	return skb->len;
+}
+
+static int taskstats2_user_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+	if (info->attrs[TASKSTATS_CMD_ATTR_PID])
+		return taskstats2_cmd_attr_pid(info);
+	else
+		return -EINVAL;
+}
+
 static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
 {
 	if (info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK])
@@ -658,10 +976,21 @@ static const struct genl_ops taskstats_ops[] = {
 		.flags		= GENL_ADMIN_PERM,
 	},
 	{
+		.cmd		= TASKSTATS2_CMD_GET,
+		.doit		= taskstats2_user_cmd,
+		.dumpit		= taskstats2_foreach,
+		.policy		= taskstats_cmd_get_policy,
+	},
+	{
 		.cmd		= CGROUPSTATS_CMD_GET,
 		.doit		= cgroupstats_user_cmd,
 		.policy		= cgroupstats_cmd_get_policy,
 	},
+	{
+		.cmd		= SYSSTATS_CMD_GET,
+		.doit		= sysstats_user_cmd,
+		.policy		= sysstats_cmd_get_policy,
+	},
 };
 
 static struct genl_family family __ro_after_init = {
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 2da660d..6e8c230 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -685,6 +685,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 	 * set up the signal and overrun bookkeeping.
 	 */
 	timer->it.cpu.incr = timespec64_to_ns(&new->it_interval);
+	timer->it_interval = ns_to_ktime(timer->it.cpu.incr);
 
 	/*
 	 * This acts as a modification timestamp for the timer,
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 2cafb49..1ce7c40 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -41,7 +41,9 @@
 static struct {
 	seqcount_t		seq;
 	struct timekeeper	timekeeper;
-} tk_core ____cacheline_aligned;
+} tk_core ____cacheline_aligned = {
+	.seq = SEQCNT_ZERO(tk_core.seq),
+};
 
 static DEFINE_RAW_SPINLOCK(timekeeper_lock);
 static struct timekeeper shadow_timekeeper;
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index aa093a9..be04302 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -17,7 +17,7 @@
  * Copyright (C) IBM Corporation, 2010-2012
  * Author:	Srikar Dronamraju <srikar@linux.vnet.ibm.com>
  */
-#define pr_fmt(fmt)	"trace_kprobe: " fmt
+#define pr_fmt(fmt)	"trace_uprobe: " fmt
 
 #include <linux/module.h>
 #include <linux/uaccess.h>
@@ -153,7 +153,14 @@ static void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs,
 
 	ret = strncpy_from_user(dst, src, maxlen);
 	if (ret == maxlen)
-		dst[--ret] = '\0';
+		dst[ret - 1] = '\0';
+	else if (ret >= 0)
+		/*
+		 * Include the terminating null byte. In this case it
+		 * was copied by strncpy_from_user but not accounted
+		 * for in ret.
+		 */
+		ret++;
 
 	if (ret < 0) {	/* Failed to fetch string */
 		((u8 *)get_rloc_data(dest))[0] = '\0';
diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile
index 4add700d..ad523be 100644
--- a/lib/raid6/Makefile
+++ b/lib/raid6/Makefile
@@ -18,6 +18,21 @@
 
 ifeq ($(CONFIG_ALTIVEC),y)
 altivec_flags := -maltivec $(call cc-option,-mabi=altivec)
+
+ifeq ($(cc-name),clang)
+# clang ppc port does not yet support -maltivec when -msoft-float is
+# enabled. A future release of clang will resolve this
+# https://bugs.llvm.org/show_bug.cgi?id=31177
+CFLAGS_REMOVE_altivec1.o  += -msoft-float
+CFLAGS_REMOVE_altivec2.o  += -msoft-float
+CFLAGS_REMOVE_altivec4.o  += -msoft-float
+CFLAGS_REMOVE_altivec8.o  += -msoft-float
+CFLAGS_REMOVE_altivec8.o  += -msoft-float
+CFLAGS_REMOVE_vpermxor1.o += -msoft-float
+CFLAGS_REMOVE_vpermxor2.o += -msoft-float
+CFLAGS_REMOVE_vpermxor4.o += -msoft-float
+CFLAGS_REMOVE_vpermxor8.o += -msoft-float
+endif
 endif
 
 # The GCC option -ffreestanding is required in order to compile code containing
diff --git a/lib/seq_buf.c b/lib/seq_buf.c
index 11f2ae0..6aabb60 100644
--- a/lib/seq_buf.c
+++ b/lib/seq_buf.c
@@ -144,9 +144,13 @@ int seq_buf_puts(struct seq_buf *s, const char *str)
 
 	WARN_ON(s->size == 0);
 
+	/* Add 1 to len for the trailing null byte which must be there */
+	len += 1;
+
 	if (seq_buf_can_fit(s, len)) {
 		memcpy(s->buffer + s->len, str, len);
-		s->len += len;
+		/* Don't count the trailing null byte against the capacity */
+		s->len += len - 1;
 		return 0;
 	}
 	seq_buf_set_overflow(s);
diff --git a/lib/test_debug_virtual.c b/lib/test_debug_virtual.c
index b9cdeec..777b491 100644
--- a/lib/test_debug_virtual.c
+++ b/lib/test_debug_virtual.c
@@ -5,6 +5,7 @@
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/sizes.h>
+#include <linux/io.h>
 
 #include <asm/page.h>
 #ifdef CONFIG_MIPS
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 9386c98..6fa3175 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -684,6 +684,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
 	INIT_RADIX_TREE(&bdi->cgwb_tree, GFP_ATOMIC);
 	bdi->cgwb_congested_tree = RB_ROOT;
 	mutex_init(&bdi->cgwb_release_mutex);
+	init_rwsem(&bdi->wb_switch_rwsem);
 
 	ret = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
 	if (!ret) {
diff --git a/mm/filemap.c b/mm/filemap.c
index e77e15d..ce948e2 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1431,6 +1431,9 @@ EXPORT_SYMBOL(find_lock_entry);
  *   @gfp_mask and added to the page cache and the VM's LRU
  *   list. The page is returned locked and with an increased
  *   refcount. Otherwise, NULL is returned.
+ * - FGP_FOR_MMAP: Similar to FGP_CREAT, only we want to allow the caller to do
+ *   its own locking dance if the page is already in cache, or unlock the page
+ *   before returning if we had to add the page to pagecache.
  *
  * If FGP_LOCK or FGP_CREAT are specified then the function may sleep even
  * if the GFP flags specified for FGP_CREAT are atomic.
@@ -1483,7 +1486,7 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset,
 		if (!page)
 			return NULL;
 
-		if (WARN_ON_ONCE(!(fgp_flags & FGP_LOCK)))
+		if (WARN_ON_ONCE(!(fgp_flags & (FGP_LOCK | FGP_FOR_MMAP))))
 			fgp_flags |= FGP_LOCK;
 
 		/* Init accessed so avoid atomic mark_page_accessed later */
@@ -1497,6 +1500,13 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset,
 			if (err == -EEXIST)
 				goto repeat;
 		}
+
+		/*
+		 * add_to_page_cache_lru lock's the page, and for mmap we expect
+		 * a unlocked page.
+		 */
+		if (fgp_flags & FGP_FOR_MMAP)
+			unlock_page(page);
 	}
 
 	return page;
@@ -2258,62 +2268,92 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
 EXPORT_SYMBOL(generic_file_read_iter);
 
 #ifdef CONFIG_MMU
-/**
- * page_cache_read - adds requested page to the page cache if not already there
- * @file:	file to read
- * @offset:	page index
- * @gfp_mask:	memory allocation flags
- *
- * This adds the requested page to the page cache if it isn't already there,
- * and schedules an I/O to read in its contents from disk.
- */
-static int page_cache_read(struct file *file, pgoff_t offset, gfp_t gfp_mask)
+#define MMAP_LOTSAMISS  (100)
+static struct file *maybe_unlock_mmap_for_io(struct vm_fault *vmf,
+					     struct file *fpin)
 {
-	struct address_space *mapping = file->f_mapping;
-	struct page *page;
-	int ret;
+	int flags = vmf->flags;
+	if (fpin)
+		return fpin;
 
-	do {
-		page = __page_cache_alloc(gfp_mask|__GFP_COLD);
-		if (!page)
-			return -ENOMEM;
-
-		ret = add_to_page_cache_lru(page, mapping, offset, gfp_mask);
-		if (ret == 0)
-			ret = mapping->a_ops->readpage(file, page);
-		else if (ret == -EEXIST)
-			ret = 0; /* losing race to add is OK */
-
-		put_page(page);
-
-	} while (ret == AOP_TRUNCATED_PAGE);
-
-	return ret;
+	/*
+	 * FAULT_FLAG_RETRY_NOWAIT means we don't want to wait on page locks or
+	 * anything, so we only pin the file and drop the mmap_sem if only
+	 * FAULT_FLAG_ALLOW_RETRY is set.
+	 */
+	if ((flags & (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT)) ==
+	    FAULT_FLAG_ALLOW_RETRY) {
+		fpin = get_file(vmf->vma->vm_file);
+		up_read(&vmf->vma->vm_mm->mmap_sem);
+	}
+	return fpin;
 }
 
-#define MMAP_LOTSAMISS  (100)
+/*
+ * lock_page_maybe_drop_mmap - lock the page, possibly dropping the mmap_sem
+ * @vmf - the vm_fault for this fault.
+ * @page - the page to lock.
+ * @fpin - the pointer to the file we may pin (or is already pinned).
+ *
+ * This works similar to lock_page_or_retry in that it can drop the mmap_sem.
+ * It differs in that it actually returns the page locked if it returns 1 and 0
+ * if it couldn't lock the page.  If we did have to drop the mmap_sem then fpin
+ * will point to the pinned file and needs to be fput()'ed at a later point.
+ */
+static int lock_page_maybe_drop_mmap(struct vm_fault *vmf, struct page *page,
+				     struct file **fpin)
+{
+	if (trylock_page(page))
+		return 1;
+
+	if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)
+		return 0;
+
+	*fpin = maybe_unlock_mmap_for_io(vmf, *fpin);
+	if (vmf->flags & FAULT_FLAG_KILLABLE) {
+		if (__lock_page_killable(page)) {
+			/*
+			 * We didn't have the right flags to drop the mmap_sem,
+			 * but all fault_handlers only check for fatal signals
+			 * if we return VM_FAULT_RETRY, so we need to drop the
+			 * mmap_sem here and return 0 if we don't have a fpin.
+			 */
+			if (*fpin == NULL)
+				up_read(&vmf->vma->vm_mm->mmap_sem);
+			return 0;
+		}
+	} else
+		__lock_page(page);
+	return 1;
+}
+
 
 /*
- * Synchronous readahead happens when we don't even find
- * a page in the page cache at all.
+ * Synchronous readahead happens when we don't even find a page in the page
+ * cache at all.  We don't want to perform IO under the mmap sem, so if we have
+ * to drop the mmap sem we return the file that was pinned in order for us to do
+ * that.  If we didn't pin a file then we return NULL.  The file that is
+ * returned needs to be fput()'ed when we're done with it.
  */
-static void do_sync_mmap_readahead(struct vm_area_struct *vma,
-				   struct file_ra_state *ra,
-				   struct file *file,
-				   pgoff_t offset)
+static struct file *do_sync_mmap_readahead(struct vm_fault *vmf)
 {
+	struct file *file = vmf->vma->vm_file;
+	struct file_ra_state *ra = &file->f_ra;
 	struct address_space *mapping = file->f_mapping;
+	struct file *fpin = NULL;
+	pgoff_t offset = vmf->pgoff;
 
 	/* If we don't want any read-ahead, don't bother */
-	if (vma->vm_flags & VM_RAND_READ)
-		return;
+	if (vmf->vma->vm_flags & VM_RAND_READ)
+		return fpin;
 	if (!ra->ra_pages)
-		return;
+		return fpin;
 
-	if (vma->vm_flags & VM_SEQ_READ) {
+	if (vmf->vma->vm_flags & VM_SEQ_READ) {
+		fpin = maybe_unlock_mmap_for_io(vmf, fpin);
 		page_cache_sync_readahead(mapping, ra, file, offset,
 					  ra->ra_pages);
-		return;
+		return fpin;
 	}
 
 	/* Avoid banging the cache line if not needed */
@@ -2325,37 +2365,44 @@ static void do_sync_mmap_readahead(struct vm_area_struct *vma,
 	 * stop bothering with read-ahead. It will only hurt.
 	 */
 	if (ra->mmap_miss > MMAP_LOTSAMISS)
-		return;
+		return fpin;
 
 	/*
 	 * mmap read-around
 	 */
+	fpin = maybe_unlock_mmap_for_io(vmf, fpin);
 	ra->start = max_t(long, 0, offset - ra->ra_pages / 2);
 	ra->size = ra->ra_pages;
 	ra->async_size = ra->ra_pages / 4;
 	ra_submit(ra, mapping, file);
+	return fpin;
 }
 
 /*
  * Asynchronous readahead happens when we find the page and PG_readahead,
- * so we want to possibly extend the readahead further..
+ * so we want to possibly extend the readahead further.  We return the file that
+ * was pinned if we have to drop the mmap_sem in order to do IO.
  */
-static void do_async_mmap_readahead(struct vm_area_struct *vma,
-				    struct file_ra_state *ra,
-				    struct file *file,
-				    struct page *page,
-				    pgoff_t offset)
+static struct file *do_async_mmap_readahead(struct vm_fault *vmf,
+					    struct page *page)
 {
+	struct file *file = vmf->vma->vm_file;
+	struct file_ra_state *ra = &file->f_ra;
 	struct address_space *mapping = file->f_mapping;
+	struct file *fpin = NULL;
+	pgoff_t offset = vmf->pgoff;
 
 	/* If we don't want any read-ahead, don't bother */
-	if (vma->vm_flags & VM_RAND_READ)
-		return;
+	if (vmf->vma->vm_flags & VM_RAND_READ)
+		return fpin;
 	if (ra->mmap_miss > 0)
 		ra->mmap_miss--;
-	if (PageReadahead(page))
+	if (PageReadahead(page)) {
+		fpin = maybe_unlock_mmap_for_io(vmf, fpin);
 		page_cache_async_readahead(mapping, ra, file,
 					   page, offset, ra->ra_pages);
+	}
+	return fpin;
 }
 
 /**
@@ -2385,6 +2432,7 @@ int filemap_fault(struct vm_fault *vmf)
 {
 	int error;
 	struct file *file = vmf->vma->vm_file;
+	struct file *fpin = NULL;
 	struct address_space *mapping = file->f_mapping;
 	struct file_ra_state *ra = &file->f_ra;
 	struct inode *inode = mapping->host;
@@ -2406,23 +2454,26 @@ int filemap_fault(struct vm_fault *vmf)
 		 * We found the page, so try async readahead before
 		 * waiting for the lock.
 		 */
-		do_async_mmap_readahead(vmf->vma, ra, file, page, offset);
+		fpin = do_async_mmap_readahead(vmf, page);
 	} else if (!page) {
 		/* No page in the page cache at all */
-		do_sync_mmap_readahead(vmf->vma, ra, file, offset);
 		count_vm_event(PGMAJFAULT);
 		count_memcg_event_mm(vmf->vma->vm_mm, PGMAJFAULT);
 		ret = VM_FAULT_MAJOR;
+		fpin = do_sync_mmap_readahead(vmf);
 retry_find:
-		page = find_get_page(mapping, offset);
-		if (!page)
-			goto no_cached_page;
+		page = pagecache_get_page(mapping, offset,
+					  FGP_CREAT|FGP_FOR_MMAP,
+					  vmf->gfp_mask);
+		if (!page) {
+			if (fpin)
+				goto out_retry;
+			return VM_FAULT_OOM;
+		}
 	}
 
-	if (!lock_page_or_retry(page, vmf->vma->vm_mm, vmf->flags)) {
-		put_page(page);
-		return ret | VM_FAULT_RETRY;
-	}
+	if (!lock_page_maybe_drop_mmap(vmf, page, &fpin))
+		goto out_retry;
 
 	/* Did it get truncated? */
 	if (unlikely(page->mapping != mapping)) {
@@ -2440,6 +2491,16 @@ int filemap_fault(struct vm_fault *vmf)
 		goto page_not_uptodate;
 
 	/*
+	 * We've made it this far and we had to drop our mmap_sem, now is the
+	 * time to return to the upper layer and have it re-find the vma and
+	 * redo the fault.
+	 */
+	if (fpin) {
+		unlock_page(page);
+		goto out_retry;
+	}
+
+	/*
 	 * Found the page and have a reference on it.
 	 * We must recheck i_size under page lock.
 	 */
@@ -2453,30 +2514,6 @@ int filemap_fault(struct vm_fault *vmf)
 	vmf->page = page;
 	return ret | VM_FAULT_LOCKED;
 
-no_cached_page:
-	/*
-	 * We're only likely to ever get here if MADV_RANDOM is in
-	 * effect.
-	 */
-	error = page_cache_read(file, offset, vmf->gfp_mask);
-
-	/*
-	 * The page we want has now been added to the page cache.
-	 * In the unlikely event that someone removed it in the
-	 * meantime, we'll just come back here and read it again.
-	 */
-	if (error >= 0)
-		goto retry_find;
-
-	/*
-	 * An error return from page_cache_read can result if the
-	 * system is low on memory, or a problem occurs while trying
-	 * to schedule I/O.
-	 */
-	if (error == -ENOMEM)
-		return VM_FAULT_OOM;
-	return VM_FAULT_SIGBUS;
-
 page_not_uptodate:
 	/*
 	 * Umm, take care of errors if the page isn't up-to-date.
@@ -2485,12 +2522,15 @@ int filemap_fault(struct vm_fault *vmf)
 	 * and we need to check for errors.
 	 */
 	ClearPageError(page);
+	fpin = maybe_unlock_mmap_for_io(vmf, fpin);
 	error = mapping->a_ops->readpage(file, page);
 	if (!error) {
 		wait_on_page_locked(page);
 		if (!PageUptodate(page))
 			error = -EIO;
 	}
+	if (fpin)
+		goto out_retry;
 	put_page(page);
 
 	if (!error || error == AOP_TRUNCATED_PAGE)
@@ -2499,6 +2539,18 @@ int filemap_fault(struct vm_fault *vmf)
 	/* Things didn't work out. Return zero to tell the mm layer so. */
 	shrink_readahead_size_eio(file, ra);
 	return VM_FAULT_SIGBUS;
+
+out_retry:
+	/*
+	 * We dropped the mmap_sem, we need to return to the fault handler to
+	 * re-find the vma and come back and find our hopefully still populated
+	 * page.
+	 */
+	if (page)
+		put_page(page);
+	if (fpin)
+		fput(fpin);
+	return ret | VM_FAULT_RETRY;
 }
 EXPORT_SYMBOL(filemap_fault);
 
diff --git a/mm/hmm.c b/mm/hmm.c
index 81ff1db..a5def9f 100644
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -767,7 +767,6 @@ static void hmm_devmem_ref_exit(void *data)
 
 	devmem = container_of(ref, struct hmm_devmem, ref);
 	percpu_ref_exit(ref);
-	devm_remove_action(devmem->device, &hmm_devmem_ref_exit, data);
 }
 
 static void hmm_devmem_ref_kill(void *data)
@@ -778,7 +777,6 @@ static void hmm_devmem_ref_kill(void *data)
 	devmem = container_of(ref, struct hmm_devmem, ref);
 	percpu_ref_kill(ref);
 	wait_for_completion(&devmem->completion);
-	devm_remove_action(devmem->device, &hmm_devmem_ref_kill, data);
 }
 
 static int hmm_devmem_fault(struct vm_area_struct *vma,
@@ -818,7 +816,7 @@ static void hmm_devmem_radix_release(struct resource *resource)
 	mutex_unlock(&hmm_devmem_lock);
 }
 
-static void hmm_devmem_release(struct device *dev, void *data)
+static void hmm_devmem_release(void *data)
 {
 	struct hmm_devmem *devmem = data;
 	struct resource *resource = devmem->resource;
@@ -826,11 +824,6 @@ static void hmm_devmem_release(struct device *dev, void *data)
 	struct zone *zone;
 	struct page *page;
 
-	if (percpu_ref_tryget_live(&devmem->ref)) {
-		dev_WARN(dev, "%s: page mapping is still live!\n", __func__);
-		percpu_ref_put(&devmem->ref);
-	}
-
 	/* pages are dead and unused, undo the arch mapping */
 	start_pfn = (resource->start & ~(PA_SECTION_SIZE - 1)) >> PAGE_SHIFT;
 	npages = ALIGN(resource_size(resource), PA_SECTION_SIZE) >> PAGE_SHIFT;
@@ -961,19 +954,6 @@ static int hmm_devmem_pages_create(struct hmm_devmem *devmem)
 	return ret;
 }
 
-static int hmm_devmem_match(struct device *dev, void *data, void *match_data)
-{
-	struct hmm_devmem *devmem = data;
-
-	return devmem->resource == match_data;
-}
-
-static void hmm_devmem_pages_remove(struct hmm_devmem *devmem)
-{
-	devres_release(devmem->device, &hmm_devmem_release,
-		       &hmm_devmem_match, devmem->resource);
-}
-
 /*
  * hmm_devmem_add() - hotplug ZONE_DEVICE memory for device memory
  *
@@ -1001,8 +981,7 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 
 	static_branch_enable(&device_private_key);
 
-	devmem = devres_alloc_node(&hmm_devmem_release, sizeof(*devmem),
-				   GFP_KERNEL, dev_to_node(device));
+	devmem = devm_kzalloc(device, sizeof(*devmem), GFP_KERNEL);
 	if (!devmem)
 		return ERR_PTR(-ENOMEM);
 
@@ -1016,11 +995,11 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 	ret = percpu_ref_init(&devmem->ref, &hmm_devmem_ref_release,
 			      0, GFP_KERNEL);
 	if (ret)
-		goto error_percpu_ref;
+		return ERR_PTR(ret);
 
-	ret = devm_add_action(device, hmm_devmem_ref_exit, &devmem->ref);
+	ret = devm_add_action_or_reset(device, hmm_devmem_ref_exit, &devmem->ref);
 	if (ret)
-		goto error_devm_add_action;
+		return ERR_PTR(ret);
 
 	size = ALIGN(size, PA_SECTION_SIZE);
 	addr = min((unsigned long)iomem_resource.end,
@@ -1040,16 +1019,12 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 
 		devmem->resource = devm_request_mem_region(device, addr, size,
 							   dev_name(device));
-		if (!devmem->resource) {
-			ret = -ENOMEM;
-			goto error_no_resource;
-		}
+		if (!devmem->resource)
+			return ERR_PTR(-ENOMEM);
 		break;
 	}
-	if (!devmem->resource) {
-		ret = -ERANGE;
-		goto error_no_resource;
-	}
+	if (!devmem->resource)
+		return ERR_PTR(-ERANGE);
 
 	devmem->resource->desc = IORES_DESC_DEVICE_PRIVATE_MEMORY;
 	devmem->pfn_first = devmem->resource->start >> PAGE_SHIFT;
@@ -1058,30 +1033,15 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 
 	ret = hmm_devmem_pages_create(devmem);
 	if (ret)
-		goto error_pages;
-
-	devres_add(device, devmem);
-
-	ret = devm_add_action(device, hmm_devmem_ref_kill, &devmem->ref);
-	if (ret) {
-		hmm_devmem_remove(devmem);
 		return ERR_PTR(ret);
-	}
+
+	ret = devm_add_action_or_reset(device, hmm_devmem_release, devmem);
+	if (ret)
+		return ERR_PTR(ret);
 
 	return devmem;
-
-error_pages:
-	devm_release_mem_region(device, devmem->resource->start,
-				resource_size(devmem->resource));
-error_no_resource:
-error_devm_add_action:
-	hmm_devmem_ref_kill(&devmem->ref);
-	hmm_devmem_ref_exit(&devmem->ref);
-error_percpu_ref:
-	devres_free(devmem);
-	return ERR_PTR(ret);
 }
-EXPORT_SYMBOL(hmm_devmem_add);
+EXPORT_SYMBOL_GPL(hmm_devmem_add);
 
 struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
 					   struct device *device,
@@ -1095,8 +1055,7 @@ struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
 
 	static_branch_enable(&device_private_key);
 
-	devmem = devres_alloc_node(&hmm_devmem_release, sizeof(*devmem),
-				   GFP_KERNEL, dev_to_node(device));
+	devmem = devm_kzalloc(device, sizeof(*devmem), GFP_KERNEL);
 	if (!devmem)
 		return ERR_PTR(-ENOMEM);
 
@@ -1110,12 +1069,12 @@ struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
 	ret = percpu_ref_init(&devmem->ref, &hmm_devmem_ref_release,
 			      0, GFP_KERNEL);
 	if (ret)
-		goto error_percpu_ref;
+		return ERR_PTR(ret);
 
-	ret = devm_add_action(device, hmm_devmem_ref_exit, &devmem->ref);
+	ret = devm_add_action_or_reset(device, hmm_devmem_ref_exit,
+			&devmem->ref);
 	if (ret)
-		goto error_devm_add_action;
-
+		return ERR_PTR(ret);
 
 	devmem->pfn_first = devmem->resource->start >> PAGE_SHIFT;
 	devmem->pfn_last = devmem->pfn_first +
@@ -1123,58 +1082,20 @@ struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
 
 	ret = hmm_devmem_pages_create(devmem);
 	if (ret)
-		goto error_devm_add_action;
-
-	devres_add(device, devmem);
-
-	ret = devm_add_action(device, hmm_devmem_ref_kill, &devmem->ref);
-	if (ret) {
-		hmm_devmem_remove(devmem);
 		return ERR_PTR(ret);
-	}
+
+	ret = devm_add_action_or_reset(device, hmm_devmem_release, devmem);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = devm_add_action_or_reset(device, hmm_devmem_ref_kill,
+			&devmem->ref);
+	if (ret)
+		return ERR_PTR(ret);
 
 	return devmem;
-
-error_devm_add_action:
-	hmm_devmem_ref_kill(&devmem->ref);
-	hmm_devmem_ref_exit(&devmem->ref);
-error_percpu_ref:
-	devres_free(devmem);
-	return ERR_PTR(ret);
 }
-EXPORT_SYMBOL(hmm_devmem_add_resource);
-
-/*
- * hmm_devmem_remove() - remove device memory (kill and free ZONE_DEVICE)
- *
- * @devmem: hmm_devmem struct use to track and manage the ZONE_DEVICE memory
- *
- * This will hot-unplug memory that was hotplugged by hmm_devmem_add on behalf
- * of the device driver. It will free struct page and remove the resource that
- * reserved the physical address range for this device memory.
- */
-void hmm_devmem_remove(struct hmm_devmem *devmem)
-{
-	resource_size_t start, size;
-	struct device *device;
-	bool cdm = false;
-
-	if (!devmem)
-		return;
-
-	device = devmem->device;
-	start = devmem->resource->start;
-	size = resource_size(devmem->resource);
-
-	cdm = devmem->resource->desc == IORES_DESC_DEVICE_PUBLIC_MEMORY;
-	hmm_devmem_ref_kill(&devmem->ref);
-	hmm_devmem_ref_exit(&devmem->ref);
-	hmm_devmem_pages_remove(devmem);
-
-	if (!cdm)
-		devm_release_mem_region(device, start, size);
-}
-EXPORT_SYMBOL(hmm_devmem_remove);
+EXPORT_SYMBOL_GPL(hmm_devmem_add_resource);
 
 /*
  * A device driver that wants to handle multiple devices memory through a
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 42d8fa6..052d41b 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -339,7 +339,8 @@ static void kill_procs(struct list_head *to_kill, int forcekill, int trapno,
 			if (fail || tk->addr_valid == 0) {
 				pr_err("Memory failure: %#lx: forcibly killing %s:%d because of failure to unmap corrupted page\n",
 				       pfn, tk->tsk->comm, tk->tsk->pid);
-				force_sig(SIGKILL, tk->tsk);
+				do_send_sig_info(SIGKILL, SEND_SIG_PRIV,
+						 tk->tsk, PIDTYPE_PID);
 			}
 
 			/*
diff --git a/mm/memory.c b/mm/memory.c
index 9ff21b7..5a20d1c 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3422,6 +3422,29 @@ static int __do_fault(struct vm_fault *vmf)
 	struct vm_area_struct *vma = vmf->vma;
 	int ret;
 
+	/*
+	 * Preallocate pte before we take page_lock because this might lead to
+	 * deadlocks for memcg reclaim which waits for pages under writeback:
+	 *				lock_page(A)
+	 *				SetPageWriteback(A)
+	 *				unlock_page(A)
+	 * lock_page(B)
+	 *				lock_page(B)
+	 * pte_alloc_pne
+	 *   shrink_page_list
+	 *     wait_on_page_writeback(A)
+	 *				SetPageWriteback(B)
+	 *				unlock_page(B)
+	 *				# flush A, B to clear the writeback
+	 */
+	if (pmd_none(*vmf->pmd) && !vmf->prealloc_pte) {
+		vmf->prealloc_pte = pte_alloc_one(vmf->vma->vm_mm,
+						  vmf->address);
+		if (!vmf->prealloc_pte)
+			return VM_FAULT_OOM;
+		smp_wmb(); /* See comment in __pte_alloc() */
+	}
+
 	ret = vma->vm_ops->fault(vmf);
 	if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY |
 			    VM_FAULT_DONE_COW)))
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 1102c65..ad68848 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -36,6 +36,7 @@
 #include <linux/bootmem.h>
 #include <linux/compaction.h>
 #include <linux/device.h>
+#include <linux/rmap.h>
 
 #include <asm/tlbflush.h>
 
@@ -1465,6 +1466,22 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
 			pfn = page_to_pfn(compound_head(page))
 				+ hpage_nr_pages(page) - 1;
 
+		/*
+		 * HWPoison pages have elevated reference counts so the migration would
+		 * fail on them. It also doesn't make any sense to migrate them in the
+		 * first place. Still try to unmap such a page in case it is still mapped
+		 * (e.g. current hwpoison implementation doesn't unmap KSM pages but keep
+		 * the unmap as the catch all safety net).
+		 */
+		if (PageHWPoison(page)) {
+			if (WARN_ON(PageLRU(page)))
+				isolate_lru_page(page);
+			if (page_mapped(page))
+				try_to_unmap(page, TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS,
+					     NULL);
+			continue;
+		}
+
 		if (!get_page_unless_zero(page))
 			continue;
 		/*
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 70d2e31..9061fb0 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1338,7 +1338,7 @@ static int copy_nodes_to_user(unsigned long __user *mask, unsigned long maxnode,
 			      nodemask_t *nodes)
 {
 	unsigned long copy = ALIGN(maxnode-1, 64) / 8;
-	const int nbytes = BITS_TO_LONGS(MAX_NUMNODES) * sizeof(long);
+	unsigned int nbytes = BITS_TO_LONGS(nr_node_ids) * sizeof(long);
 
 	if (copy > nbytes) {
 		if (copy > PAGE_SIZE)
@@ -1499,7 +1499,7 @@ SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
 	int uninitialized_var(pval);
 	nodemask_t nodes;
 
-	if (nmask != NULL && maxnode < MAX_NUMNODES)
+	if (nmask != NULL && maxnode < nr_node_ids)
 		return -EINVAL;
 
 	err = do_get_mempolicy(&pval, &nodes, addr, flags);
@@ -1528,7 +1528,7 @@ COMPAT_SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
 	unsigned long nr_bits, alloc_size;
 	DECLARE_BITMAP(bm, MAX_NUMNODES);
 
-	nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+	nr_bits = min_t(unsigned long, maxnode-1, nr_node_ids);
 	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
 
 	if (nmask)
diff --git a/mm/migrate.c b/mm/migrate.c
index 12d821f..9b5e446 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1106,10 +1106,13 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
 	 * If migration is successful, decrease refcount of the newpage
 	 * which will not free the page because new page owner increased
 	 * refcounter. As well, if it is LRU page, add the page to LRU
-	 * list in here.
+	 * list in here. Use the old state of the isolated source page to
+	 * determine if we migrated a LRU page. newpage was already unlocked
+	 * and possibly modified by its owner - don't rely on the page
+	 * state.
 	 */
 	if (rc == MIGRATEPAGE_SUCCESS) {
-		if (unlikely(__PageMovable(newpage)))
+		if (unlikely(!is_lru))
 			put_page(newpage);
 		else
 			putback_lru_page(newpage);
diff --git a/mm/mmap.c b/mm/mmap.c
index e81d207..4f4a840 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2459,12 +2459,11 @@ int expand_downwards(struct vm_area_struct *vma,
 {
 	struct mm_struct *mm = vma->vm_mm;
 	struct vm_area_struct *prev;
-	int error;
+	int error = 0;
 
 	address &= PAGE_MASK;
-	error = security_mmap_addr(address);
-	if (error)
-		return error;
+	if (address < mmap_min_addr)
+		return -EPERM;
 
 	/* Enforce stack_guard_gap */
 	prev = vma->vm_prev;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index a5d7a8b..9224b97 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -613,8 +613,8 @@ void wake_oom_reaper(struct task_struct *tsk)
 	 */
 	spin_lock(&oom_reaper_lock);
 
-	/* tsk is already queued? */
-	if (tsk == oom_reaper_list || tsk->oom_reaper_list) {
+	/* mm is already queued? */
+	if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags)) {
 		spin_unlock(&oom_reaper_lock);
 		return;
 	}
@@ -861,6 +861,13 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
 	 * still freeing memory.
 	 */
 	read_lock(&tasklist_lock);
+
+	/*
+	 * The task 'p' might have already exited before reaching here. The
+	 * put_task_struct() will free task_struct 'p' while the loop still try
+	 * to access the field of 'p', so, get an extra reference.
+	 */
+	get_task_struct(p);
 	for_each_thread(p, t) {
 		list_for_each_entry(child, &t->children, sibling) {
 			unsigned int child_points;
@@ -880,6 +887,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
 			}
 		}
 	}
+	put_task_struct(p);
 	read_unlock(&tasklist_lock);
 
 	p = find_lock_task_mm(victim);
@@ -1095,6 +1103,9 @@ void pagefault_out_of_memory(void)
 		.order = 0,
 	};
 
+	if (IS_ENABLED(CONFIG_HAVE_LOW_MEMORY_KILLER))
+		return;
+
 	if (mem_cgroup_oom_synchronize(true))
 		return;
 
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 3175ac8..e001de5 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2157,6 +2157,7 @@ int write_cache_pages(struct address_space *mapping,
 {
 	int ret = 0;
 	int done = 0;
+	int error;
 	struct pagevec pvec;
 	int nr_pages;
 	pgoff_t uninitialized_var(writeback_index);
@@ -2253,25 +2254,31 @@ int write_cache_pages(struct address_space *mapping,
 				goto continue_unlock;
 
 			trace_wbc_writepage(wbc, inode_to_bdi(mapping->host));
-			ret = (*writepage)(page, wbc, data);
-			if (unlikely(ret)) {
-				if (ret == AOP_WRITEPAGE_ACTIVATE) {
+			error = (*writepage)(page, wbc, data);
+			if (unlikely(error)) {
+				/*
+				 * Handle errors according to the type of
+				 * writeback. There's no need to continue for
+				 * background writeback. Just push done_index
+				 * past this page so media errors won't choke
+				 * writeout for the entire file. For integrity
+				 * writeback, we must process the entire dirty
+				 * set regardless of errors because the fs may
+				 * still have state to clear for each page. In
+				 * that case we continue processing and return
+				 * the first error.
+				 */
+				if (error == AOP_WRITEPAGE_ACTIVATE) {
 					unlock_page(page);
-					ret = 0;
-				} else {
-					/*
-					 * done_index is set past this page,
-					 * so media errors will not choke
-					 * background writeout for the entire
-					 * file. This has consequences for
-					 * range_cyclic semantics (ie. it may
-					 * not be suitable for data integrity
-					 * writeout).
-					 */
+					error = 0;
+				} else if (wbc->sync_mode != WB_SYNC_ALL) {
+					ret = error;
 					done_index = page->index + 1;
 					done = 1;
 					break;
 				}
+				if (!ret)
+					ret = error;
 			}
 
 			/*
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index dbcdfe1..32355a0 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4118,6 +4118,9 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
 	if (current->flags & PF_MEMALLOC)
 		goto nopage;
 
+	if (fatal_signal_pending(current) && !(gfp_mask & __GFP_NOFAIL))
+		goto nopage;
+
 	/* Try direct reclaim and then allocating */
 	page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags, ac,
 							&did_some_progress);
diff --git a/mm/percpu-km.c b/mm/percpu-km.c
index 0d88d7b..c22d959 100644
--- a/mm/percpu-km.c
+++ b/mm/percpu-km.c
@@ -50,6 +50,7 @@ static struct pcpu_chunk *pcpu_create_chunk(gfp_t gfp)
 	const int nr_pages = pcpu_group_sizes[0] >> PAGE_SHIFT;
 	struct pcpu_chunk *chunk;
 	struct page *pages;
+	unsigned long flags;
 	int i;
 
 	chunk = pcpu_alloc_chunk(gfp);
@@ -68,9 +69,9 @@ static struct pcpu_chunk *pcpu_create_chunk(gfp_t gfp)
 	chunk->data = pages;
 	chunk->base_addr = page_address(pages) - pcpu_group_offsets[0];
 
-	spin_lock_irq(&pcpu_lock);
+	spin_lock_irqsave(&pcpu_lock, flags);
 	pcpu_chunk_populated(chunk, 0, nr_pages, false);
-	spin_unlock_irq(&pcpu_lock);
+	spin_unlock_irqrestore(&pcpu_lock, flags);
 
 	pcpu_stats_chunk_alloc();
 	trace_percpu_create_chunk(chunk->base_addr);
diff --git a/mm/slab.c b/mm/slab.c
index bd8db5cd..b3f9193 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -679,8 +679,10 @@ static struct alien_cache *__alloc_alien_cache(int node, int entries,
 	struct alien_cache *alc = NULL;
 
 	alc = kmalloc_node(memsize, gfp, node);
-	init_arraycache(&alc->ac, entries, batch);
-	spin_lock_init(&alc->lock);
+	if (alc) {
+		init_arraycache(&alc->ac, entries, batch);
+		spin_lock_init(&alc->lock);
+	}
 	return alc;
 }
 
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 31d13e1..f1f8dcc 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2246,7 +2246,8 @@ int try_to_unuse(unsigned int type, bool frontswap,
 		 */
 		if (PageSwapCache(page) &&
 		    likely(page_private(page) == entry.val) &&
-		    !page_swapped(page))
+		    (!PageTransCompound(page) ||
+		     !swap_page_trans_huge_swapped(si, entry)))
 			delete_from_swap_cache(compound_head(page));
 
 		/*
@@ -2857,8 +2858,9 @@ static struct swap_info_struct *alloc_swap_info(void)
 	struct swap_info_struct *p;
 	unsigned int type;
 	int i;
+	int size = sizeof(*p) + nr_node_ids * sizeof(struct plist_node);
 
-	p = kvzalloc(sizeof(*p), GFP_KERNEL);
+	p = kvzalloc(size, GFP_KERNEL);
 	if (!p)
 		return ERR_PTR(-ENOMEM);
 
diff --git a/mm/util.c b/mm/util.c
index 547e04b..842ba5f 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -449,7 +449,7 @@ bool page_mapped(struct page *page)
 		return true;
 	if (PageHuge(page))
 		return false;
-	for (i = 0; i < hpage_nr_pages(page); i++) {
+	for (i = 0; i < (1 << compound_order(page)); i++) {
 		if (atomic_read(&page[i]._mapcount) >= 0)
 			return true;
 	}
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 9ff21a1..ccec6dc 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -340,6 +340,13 @@ static unsigned long cached_align;
 
 static unsigned long vmap_area_pcpu_hole;
 
+static atomic_long_t nr_vmalloc_pages;
+
+unsigned long vmalloc_nr_pages(void)
+{
+	return atomic_long_read(&nr_vmalloc_pages);
+}
+
 static struct vmap_area *__find_vmap_area(unsigned long addr)
 {
 	struct rb_node *n = vmap_area_root.rb_node;
@@ -1539,6 +1546,7 @@ static void __vunmap(const void *addr, int deallocate_pages)
 			BUG_ON(!page);
 			__free_pages(page, 0);
 		}
+		atomic_long_sub(area->nr_pages, &nr_vmalloc_pages);
 
 		kvfree(area->pages);
 	}
@@ -1704,12 +1712,14 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
 		if (unlikely(!page)) {
 			/* Successfully allocated i pages, free them in __vunmap() */
 			area->nr_pages = i;
+			atomic_long_add(area->nr_pages, &nr_vmalloc_pages);
 			goto fail;
 		}
 		area->pages[i] = page;
 		if (gfpflags_allow_blocking(gfp_mask|highmem_mask))
 			cond_resched();
 	}
+	atomic_long_add(area->nr_pages, &nr_vmalloc_pages);
 
 	if (map_vm_area(area, prot, pages))
 		goto fail;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index b7592d3..1c0e98b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -350,16 +350,6 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
 	delta *= 4;
 	do_div(delta, shrinker->seeks);
 
-	/*
-	 * Make sure we apply some minimal pressure on default priority
-	 * even on small cgroups. Stale objects are not only consuming memory
-	 * by themselves, but can also hold a reference to a dying cgroup,
-	 * preventing it from being reclaimed. A dying cgroup with all
-	 * corresponding structures like per-cpu stats and kmem caches
-	 * can be really big, so it may lead to a significant waste of memory.
-	 */
-	delta = max_t(unsigned long long, delta, min(freeable, batch_size));
-
 	total_scan += delta;
 	if (total_scan < 0) {
 		pr_err("shrink_slab: %pF negative objects to delete nr=%ld\n",
@@ -1857,13 +1847,13 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
 		if (stalled)
 			return 0;
 
-		/* wait a bit for the reclaimer. */
-		msleep(100);
-		stalled = true;
-
 		/* We are about to die and free our memory. Return now. */
 		if (fatal_signal_pending(current))
 			return SWAP_CLUSTER_MAX;
+
+		/* wait a bit for the reclaimer. */
+		msleep(100);
+		stalled = true;
 	}
 
 	lru_add_drain();
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 0b8090d..8b88259c 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1091,6 +1091,7 @@ const char * const vmstat_text[] = {
 	"nr_dirtied",
 	"nr_written",
 	"nr_indirectly_reclaimable",
+	"nr_unreclaimable_pages",
 
 	/* enum writeback_stat_item counters */
 	"nr_dirty_threshold",
diff --git a/net/9p/client.c b/net/9p/client.c
index 3ec5a82..ef0f8fe 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -181,6 +181,12 @@ static int parse_opts(char *opts, struct p9_client *clnt)
 				ret = r;
 				continue;
 			}
+			if (option < 4096) {
+				p9_debug(P9_DEBUG_ERROR,
+					 "msize should be at least 4k\n");
+				ret = -EINVAL;
+				continue;
+			}
 			clnt->msize = option;
 			break;
 		case Opt_trans:
@@ -996,10 +1002,18 @@ static int p9_client_version(struct p9_client *c)
 	else if (!strncmp(version, "9P2000", 6))
 		c->proto_version = p9_proto_legacy;
 	else {
+		p9_debug(P9_DEBUG_ERROR,
+			 "server returned an unknown version: %s\n", version);
 		err = -EREMOTEIO;
 		goto error;
 	}
 
+	if (msize < 4096) {
+		p9_debug(P9_DEBUG_ERROR,
+			 "server returned a msize < 4096: %d\n", msize);
+		err = -EREMOTEIO;
+		goto error;
+	}
 	if (msize < c->msize)
 		c->msize = msize;
 
@@ -1064,6 +1078,13 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
 	if (clnt->msize > clnt->trans_mod->maxsize)
 		clnt->msize = clnt->trans_mod->maxsize;
 
+	if (clnt->msize < 4096) {
+		p9_debug(P9_DEBUG_ERROR,
+			 "Please specify a msize of at least 4k\n");
+		err = -EINVAL;
+		goto free_client;
+	}
+
 	err = p9_client_version(clnt);
 	if (err)
 		goto close_trans;
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index 183b1c5..dd526c9 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -114,6 +114,7 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
 	dst = (ax25_address *)(bp + 1);
 	src = (ax25_address *)(bp + 8);
 
+	ax25_route_lock_use();
 	route = ax25_get_route(dst, NULL);
 	if (route) {
 		digipeat = route->digipeat;
@@ -206,9 +207,8 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
 	ax25_queue_xmit(skb, dev);
 
 put:
-	if (route)
-		ax25_put_route(route);
 
+	ax25_route_lock_unuse();
 	return NETDEV_TX_OK;
 }
 
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 0446b89..7f369f1 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -40,7 +40,7 @@
 #include <linux/export.h>
 
 static ax25_route *ax25_route_list;
-static DEFINE_RWLOCK(ax25_route_lock);
+DEFINE_RWLOCK(ax25_route_lock);
 
 void ax25_rt_device_down(struct net_device *dev)
 {
@@ -349,6 +349,7 @@ const struct file_operations ax25_route_fops = {
  *	Find AX.25 route
  *
  *	Only routes with a reference count of zero can be destroyed.
+ *	Must be called with ax25_route_lock read locked.
  */
 ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
 {
@@ -356,7 +357,6 @@ ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
 	ax25_route *ax25_def_rt = NULL;
 	ax25_route *ax25_rt;
 
-	read_lock(&ax25_route_lock);
 	/*
 	 *	Bind to the physical interface we heard them on, or the default
 	 *	route if none is found;
@@ -379,11 +379,6 @@ ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
 	if (ax25_spe_rt != NULL)
 		ax25_rt = ax25_spe_rt;
 
-	if (ax25_rt != NULL)
-		ax25_hold_route(ax25_rt);
-
-	read_unlock(&ax25_route_lock);
-
 	return ax25_rt;
 }
 
@@ -414,9 +409,12 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
 	ax25_route *ax25_rt;
 	int err = 0;
 
-	if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL)
+	ax25_route_lock_use();
+	ax25_rt = ax25_get_route(addr, NULL);
+	if (!ax25_rt) {
+		ax25_route_lock_unuse();
 		return -EHOSTUNREACH;
-
+	}
 	if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) {
 		err = -EHOSTUNREACH;
 		goto put;
@@ -451,8 +449,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
 	}
 
 put:
-	ax25_put_route(ax25_rt);
-
+	ax25_route_lock_unuse();
 	return err;
 }
 
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index e348f76..2e1a084 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -19,7 +19,6 @@
 #include "main.h"
 
 #include <linux/atomic.h>
-#include <linux/bug.h>
 #include <linux/byteorder/generic.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -172,8 +171,10 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
 	parent_dev = __dev_get_by_index((struct net *)parent_net,
 					dev_get_iflink(net_dev));
 	/* if we got a NULL parent_dev there is something broken.. */
-	if (WARN(!parent_dev, "Cannot find parent device"))
+	if (!parent_dev) {
+		pr_err("Cannot find parent device\n");
 		return false;
+	}
 
 	if (batadv_mutual_parents(net_dev, net, parent_dev, parent_net))
 		return false;
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 8cedb5d..7c88342 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -213,10 +213,14 @@ static int batadv_interface_tx(struct sk_buff *skb,
 
 	netif_trans_update(soft_iface);
 	vid = batadv_get_vid(skb, 0);
+
+	skb_reset_mac_header(skb);
 	ethhdr = eth_hdr(skb);
 
 	switch (ntohs(ethhdr->h_proto)) {
 	case ETH_P_8021Q:
+		if (!pskb_may_pull(skb, sizeof(*vhdr)))
+			goto dropped;
 		vhdr = vlan_eth_hdr(skb);
 
 		/* drop batman-in-batman packets to prevent loops */
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 01f211e..363dc85 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -5212,6 +5212,12 @@ static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
 		return true;
 	}
 
+	/* Check if request ended in Command Status - no way to retreive
+	 * any extra parameters in this case.
+	 */
+	if (hdr->evt == HCI_EV_CMD_STATUS)
+		return false;
+
 	if (hdr->evt != HCI_EV_CMD_COMPLETE) {
 		BT_DBG("Last event is not cmd complete (0x%2.2x)", hdr->evt);
 		return false;
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 48fb174..57f69f3 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -35,10 +35,10 @@ static inline int should_deliver(const struct net_bridge_port *p,
 
 int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+	skb_push(skb, ETH_HLEN);
 	if (!is_skb_forwardable(skb->dev, skb))
 		goto drop;
 
-	skb_push(skb, ETH_HLEN);
 	br_drop_fake_rtable(skb);
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL &&
@@ -96,12 +96,11 @@ static void __br_forward(const struct net_bridge_port *to,
 		net = dev_net(indev);
 	} else {
 		if (unlikely(netpoll_tx_running(to->br->dev))) {
-			if (!is_skb_forwardable(skb->dev, skb)) {
+			skb_push(skb, ETH_HLEN);
+			if (!is_skb_forwardable(skb->dev, skb))
 				kfree_skb(skb);
-			} else {
-				skb_push(skb, ETH_HLEN);
+			else
 				br_netpoll_send_skb(to, skb);
-			}
 			return;
 		}
 		br_hook = NF_BR_LOCAL_OUT;
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index a813dfe..8dc5c8d 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1390,14 +1390,7 @@ static void br_multicast_query_received(struct net_bridge *br,
 		return;
 
 	br_multicast_update_query_timer(br, query, max_delay);
-
-	/* Based on RFC4541, section 2.1.1 IGMP Forwarding Rules,
-	 * the arrival port for IGMP Queries where the source address
-	 * is 0.0.0.0 should not be added to router port list.
-	 */
-	if ((saddr->proto == htons(ETH_P_IP) && saddr->u.ip4) ||
-	    saddr->proto == htons(ETH_P_IPV6))
-		br_multicast_mark_router(br, port);
+	br_multicast_mark_router(br, port);
 }
 
 static int br_ip4_multicast_query(struct net_bridge *br,
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 7582f28..3f3859b 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -275,7 +275,7 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
 		struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
 		int ret;
 
-		if (neigh->hh.hh_len) {
+		if ((neigh->nud_state & NUD_CONNECTED) && neigh->hh.hh_len) {
 			neigh_hh_bridge(&neigh->hh, skb);
 			skb->dev = nf_bridge->physindev;
 			ret = br_handle_frame_finish(net, sk, skb);
diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c
index 96c072e..5811208 100644
--- a/net/bridge/br_netfilter_ipv6.c
+++ b/net/bridge/br_netfilter_ipv6.c
@@ -131,6 +131,7 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb)
 					IPSTATS_MIB_INDISCARDS);
 			goto drop;
 		}
+		hdr = ipv6_hdr(skb);
 	}
 	if (hdr->nexthdr == NEXTHDR_HOP && br_nf_check_hbh_len(skb))
 		goto drop;
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 54c7fe6..22e4c15 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1134,14 +1134,16 @@ static int do_replace(struct net *net, const void __user *user,
 	tmp.name[sizeof(tmp.name) - 1] = 0;
 
 	countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
-	newinfo = vmalloc(sizeof(*newinfo) + countersize);
+	newinfo = __vmalloc(sizeof(*newinfo) + countersize, GFP_KERNEL_ACCOUNT,
+			    PAGE_KERNEL);
 	if (!newinfo)
 		return -ENOMEM;
 
 	if (countersize)
 		memset(newinfo->counters, 0, countersize);
 
-	newinfo->entries = vmalloc(tmp.entries_size);
+	newinfo->entries = __vmalloc(tmp.entries_size, GFP_KERNEL_ACCOUNT,
+				     PAGE_KERNEL);
 	if (!newinfo->entries) {
 		ret = -ENOMEM;
 		goto free_newinfo;
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
index eaf05de3..b09ec86 100644
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -230,6 +230,7 @@ static bool reject6_br_csum_ok(struct sk_buff *skb, int hook)
 	    pskb_trim_rcsum(skb, ntohs(ip6h->payload_len) + sizeof(*ip6h)))
 		return false;
 
+	ip6h = ipv6_hdr(skb);
 	thoff = ipv6_skip_exthdr(skb, ((u8*)(ip6h+1) - skb->data), &proto, &fo);
 	if (thoff < 0 || thoff >= skb->len || (fo & htons(~0x7)) != 0)
 		return false;
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 13690334..12d851c 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -67,6 +67,9 @@
  */
 #define MAX_NFRAMES 256
 
+/* limit timers to 400 days for sending/timeouts */
+#define BCM_TIMER_SEC_MAX (400 * 24 * 60 * 60)
+
 /* use of last_frames[index].flags */
 #define RX_RECV    0x40 /* received data for this element */
 #define RX_THR     0x80 /* element not been sent due to throttle feature */
@@ -140,6 +143,22 @@ static inline ktime_t bcm_timeval_to_ktime(struct bcm_timeval tv)
 	return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC);
 }
 
+/* check limitations for timeval provided by user */
+static bool bcm_is_invalid_tv(struct bcm_msg_head *msg_head)
+{
+	if ((msg_head->ival1.tv_sec < 0) ||
+	    (msg_head->ival1.tv_sec > BCM_TIMER_SEC_MAX) ||
+	    (msg_head->ival1.tv_usec < 0) ||
+	    (msg_head->ival1.tv_usec >= USEC_PER_SEC) ||
+	    (msg_head->ival2.tv_sec < 0) ||
+	    (msg_head->ival2.tv_sec > BCM_TIMER_SEC_MAX) ||
+	    (msg_head->ival2.tv_usec < 0) ||
+	    (msg_head->ival2.tv_usec >= USEC_PER_SEC))
+		return true;
+
+	return false;
+}
+
 #define CFSIZ(flags) ((flags & CAN_FD_FRAME) ? CANFD_MTU : CAN_MTU)
 #define OPSIZ sizeof(struct bcm_op)
 #define MHSIZ sizeof(struct bcm_msg_head)
@@ -886,6 +905,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 	if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES)
 		return -EINVAL;
 
+	/* check timeval limitations */
+	if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
+		return -EINVAL;
+
 	/* check the given can_id */
 	op = bcm_find_op(&bo->tx_ops, msg_head, ifindex);
 	if (op) {
@@ -1065,6 +1088,10 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 	     (!(msg_head->can_id & CAN_RTR_FLAG))))
 		return -EINVAL;
 
+	/* check timeval limitations */
+	if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
+		return -EINVAL;
+
 	/* check the given can_id */
 	op = bcm_find_op(&bo->rx_ops, msg_head, ifindex);
 	if (op) {
diff --git a/net/can/gw.c b/net/can/gw.c
index 73a02af..5114b8f 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -416,13 +416,29 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
 	while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx])
 		(*gwj->mod.modfunc[modidx++])(cf, &gwj->mod);
 
-	/* check for checksum updates when the CAN frame has been modified */
+	/* Has the CAN frame been modified? */
 	if (modidx) {
-		if (gwj->mod.csumfunc.crc8)
-			(*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8);
+		/* get available space for the processed CAN frame type */
+		int max_len = nskb->len - offsetof(struct can_frame, data);
 
-		if (gwj->mod.csumfunc.xor)
+		/* dlc may have changed, make sure it fits to the CAN frame */
+		if (cf->can_dlc > max_len)
+			goto out_delete;
+
+		/* check for checksum updates in classic CAN length only */
+		if (gwj->mod.csumfunc.crc8) {
+			if (cf->can_dlc > 8)
+				goto out_delete;
+
+			(*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8);
+		}
+
+		if (gwj->mod.csumfunc.xor) {
+			if (cf->can_dlc > 8)
+				goto out_delete;
+
 			(*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor);
+		}
 	}
 
 	/* clear the skb timestamp if not configured the other way */
@@ -434,6 +450,14 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
 		gwj->dropped_frames++;
 	else
 		gwj->handled_frames++;
+
+	return;
+
+ out_delete:
+	/* delete frame due to misconfiguration */
+	gwj->deleted_frames++;
+	kfree_skb(nskb);
+	return;
 }
 
 static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj)
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index f864807..081a41c 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2057,6 +2057,8 @@ static int process_connect(struct ceph_connection *con)
 	dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
 
 	if (con->auth) {
+		int len = le32_to_cpu(con->in_reply.authorizer_len);
+
 		/*
 		 * Any connection that defines ->get_authorizer()
 		 * should also define ->add_authorizer_challenge() and
@@ -2066,8 +2068,7 @@ static int process_connect(struct ceph_connection *con)
 		 */
 		if (con->in_reply.tag == CEPH_MSGR_TAG_CHALLENGE_AUTHORIZER) {
 			ret = con->ops->add_authorizer_challenge(
-				    con, con->auth->authorizer_reply_buf,
-				    le32_to_cpu(con->in_reply.authorizer_len));
+				    con, con->auth->authorizer_reply_buf, len);
 			if (ret < 0)
 				return ret;
 
@@ -2077,10 +2078,12 @@ static int process_connect(struct ceph_connection *con)
 			return 0;
 		}
 
-		ret = con->ops->verify_authorizer_reply(con);
-		if (ret < 0) {
-			con->error_msg = "bad authorize reply";
-			return ret;
+		if (len) {
+			ret = con->ops->verify_authorizer_reply(con);
+			if (ret < 0) {
+				con->error_msg = "bad authorize reply";
+				return ret;
+			}
 		}
 	}
 
@@ -3210,9 +3213,10 @@ void ceph_con_keepalive(struct ceph_connection *con)
 	dout("con_keepalive %p\n", con);
 	mutex_lock(&con->mutex);
 	clear_standby(con);
+	con_flag_set(con, CON_FLAG_KEEPALIVE_PENDING);
 	mutex_unlock(&con->mutex);
-	if (con_flag_test_and_set(con, CON_FLAG_KEEPALIVE_PENDING) == 0 &&
-	    con_flag_test_and_set(con, CON_FLAG_WRITE_PENDING) == 0)
+
+	if (con_flag_test_and_set(con, CON_FLAG_WRITE_PENDING) == 0)
 		queue_con(con);
 }
 EXPORT_SYMBOL(ceph_con_keepalive);
diff --git a/net/core/dev.c b/net/core/dev.c
index 8ffa7ee..8f3eb0a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4348,6 +4348,10 @@ static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev,
 #endif /* CONFIG_NETFILTER_INGRESS */
 	return 0;
 }
+
+int (*gsb_nw_stack_recv)(struct sk_buff *skb) __rcu __read_mostly;
+EXPORT_SYMBOL(gsb_nw_stack_recv);
+
 int (*embms_tm_multicast_recv)(struct sk_buff *skb) __rcu __read_mostly;
 EXPORT_SYMBOL(embms_tm_multicast_recv);
 
@@ -4363,6 +4367,7 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
 	bool deliver_exact = false;
 	int ret = NET_RX_DROP;
 	__be16 type;
+	int (*gsb_ns_recv)(struct sk_buff *skb);
 	int (*embms_recv)(struct sk_buff *skb);
 	int (*fast_recv)(struct sk_buff *skb, struct packet_type *pt_temp);
 
@@ -4426,6 +4431,14 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
 		embms_recv(skb);
 
 skip_classify:
+	gsb_ns_recv = rcu_dereference(gsb_nw_stack_recv);
+	if (gsb_ns_recv) {
+		if (gsb_ns_recv(skb)) {
+			ret = NET_RX_SUCCESS;
+			goto out;
+		}
+	}
+
 	fast_recv = rcu_dereference(athrs_fast_nat_recv);
 	if (fast_recv) {
 		if (fast_recv(skb, pt_prev)) {
@@ -7310,7 +7323,7 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower,
 	netdev_features_t feature;
 	int feature_bit;
 
-	for_each_netdev_feature(&upper_disables, feature_bit) {
+	for_each_netdev_feature(upper_disables, feature_bit) {
 		feature = __NETIF_F_BIT(feature_bit);
 		if (!(upper->wanted_features & feature)
 		    && (features & feature)) {
@@ -7330,7 +7343,7 @@ static void netdev_sync_lower_features(struct net_device *upper,
 	netdev_features_t feature;
 	int feature_bit;
 
-	for_each_netdev_feature(&upper_disables, feature_bit) {
+	for_each_netdev_feature(upper_disables, feature_bit) {
 		feature = __NETIF_F_BIT(feature_bit);
 		if (!(features & feature) && (lower->features & feature)) {
 			netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n",
@@ -7810,6 +7823,9 @@ int init_dummy_netdev(struct net_device *dev)
 	set_bit(__LINK_STATE_PRESENT, &dev->state);
 	set_bit(__LINK_STATE_START, &dev->state);
 
+	/* napi_busy_loop stats accounting wants this */
+	dev_net_set(dev, &init_net);
+
 	/* Note : We dont allocate pcpu_refcnt for dummy devices,
 	 * because users of this 'device' dont need to change
 	 * its refcount.
diff --git a/net/core/filter.c b/net/core/filter.c
index d5158a1..41ede90 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -1714,18 +1714,19 @@ static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
 static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev,
 				 u32 flags)
 {
-	/* skb->mac_len is not set on normal egress */
-	unsigned int mlen = skb->network_header - skb->mac_header;
+	unsigned int mlen = skb_network_offset(skb);
 
-	__skb_pull(skb, mlen);
+	if (mlen) {
+		__skb_pull(skb, mlen);
 
-	/* At ingress, the mac header has already been pulled once.
-	 * At egress, skb_pospull_rcsum has to be done in case that
-	 * the skb is originated from ingress (i.e. a forwarded skb)
-	 * to ensure that rcsum starts at net header.
-	 */
-	if (!skb_at_tc_ingress(skb))
-		skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
+		/* At ingress, the mac header has already been pulled once.
+		 * At egress, skb_pospull_rcsum has to be done in case that
+		 * the skb is originated from ingress (i.e. a forwarded skb)
+		 * to ensure that rcsum starts at net header.
+		 */
+		if (!skb_at_tc_ingress(skb))
+			skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
+	}
 	skb_pop_mac_header(skb);
 	skb_reset_mac_len(skb);
 	return flags & BPF_F_INGRESS ?
@@ -3101,7 +3102,10 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
 			sk->sk_rcvlowat = val ? : 1;
 			break;
 		case SO_MARK:
-			sk->sk_mark = val;
+			if (sk->sk_mark != val) {
+				sk->sk_mark = val;
+				sk_dst_reset(sk);
+			}
 			break;
 		default:
 			ret = -EINVAL;
@@ -3127,7 +3131,7 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
 			/* Only some options are supported */
 			switch (optname) {
 			case TCP_BPF_IW:
-				if (val <= 0 || tp->data_segs_out > 0)
+				if (val <= 0 || tp->data_segs_out > tp->syn_data)
 					ret = -EINVAL;
 				else
 					tp->snd_cwnd = val;
diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
index 832d696..65313c7 100644
--- a/net/core/lwt_bpf.c
+++ b/net/core/lwt_bpf.c
@@ -65,6 +65,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
 				     lwt->name ? : "<unknown>");
 			ret = BPF_OK;
 		} else {
+			skb_reset_mac_header(skb);
 			ret = skb_do_redirect(skb);
 			if (ret == 0)
 				ret = BPF_REDIRECT;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 06256bf..3bd8874 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1322,9 +1322,10 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
 						 lladdr || !dev->addr_len);
 	if (neigh) {
 		if (neigh_probe_enable) {
-			if (!(neigh->nud_state == NUD_REACHABLE)) {
+			if (neigh->nud_state != NUD_REACHABLE &&
+			    neigh->nud_state != NUD_PERMANENT) {
 				neigh_update(neigh, lladdr, NUD_STALE,
-					     NEIGH_UPDATE_F_OVERRIDE, 0);
+				NEIGH_UPDATE_F_OVERRIDE, 0);
 				write_lock(&neigh->lock);
 				neigh_probe(neigh);
 				neigh_update_notify(neigh, 0);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 7add15f..56ac81e 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -353,6 +353,8 @@ static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
  */
 void *netdev_alloc_frag(unsigned int fragsz)
 {
+	fragsz = SKB_DATA_ALIGN(fragsz);
+
 	return __netdev_alloc_frag(fragsz, GFP_ATOMIC | __GFP_COLD);
 }
 EXPORT_SYMBOL(netdev_alloc_frag);
@@ -366,6 +368,8 @@ static void *__napi_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
 
 void *napi_alloc_frag(unsigned int fragsz)
 {
+	fragsz = SKB_DATA_ALIGN(fragsz);
+
 	return __napi_alloc_frag(fragsz, GFP_ATOMIC | __GFP_COLD);
 }
 EXPORT_SYMBOL(napi_alloc_frag);
@@ -4936,6 +4940,45 @@ unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
 EXPORT_SYMBOL_GPL(skb_gso_transport_seglen);
 
 /**
+ * skb_gso_size_check - check the skb size, considering GSO_BY_FRAGS
+ *
+ * There are a couple of instances where we have a GSO skb, and we
+ * want to determine what size it would be after it is segmented.
+ *
+ * We might want to check:
+ * -    L3+L4+payload size (e.g. IP forwarding)
+ * - L2+L3+L4+payload size (e.g. sanity check before passing to driver)
+ *
+ * This is a helper to do that correctly considering GSO_BY_FRAGS.
+ *
+ * @seg_len: The segmented length (from skb_gso_*_seglen). In the
+ *           GSO_BY_FRAGS case this will be [header sizes + GSO_BY_FRAGS].
+ *
+ * @max_len: The maximum permissible length.
+ *
+ * Returns true if the segmented length <= max length.
+ */
+static inline bool skb_gso_size_check(const struct sk_buff *skb,
+				      unsigned int seg_len,
+				      unsigned int max_len) {
+	const struct skb_shared_info *shinfo = skb_shinfo(skb);
+	const struct sk_buff *iter;
+
+	if (shinfo->gso_size != GSO_BY_FRAGS)
+		return seg_len <= max_len;
+
+	/* Undo this so we can re-use header sizes */
+	seg_len -= GSO_BY_FRAGS;
+
+	skb_walk_frags(skb, iter) {
+		if (seg_len + skb_headlen(iter) > max_len)
+			return false;
+	}
+
+	return true;
+}
+
+/**
  * skb_gso_validate_mtu - Return in case such skb fits a given MTU
  *
  * @skb: GSO skb
@@ -4946,27 +4989,25 @@ EXPORT_SYMBOL_GPL(skb_gso_transport_seglen);
  */
 bool skb_gso_validate_mtu(const struct sk_buff *skb, unsigned int mtu)
 {
-	const struct skb_shared_info *shinfo = skb_shinfo(skb);
-	const struct sk_buff *iter;
-	unsigned int hlen;
-
-	hlen = skb_gso_network_seglen(skb);
-
-	if (shinfo->gso_size != GSO_BY_FRAGS)
-		return hlen <= mtu;
-
-	/* Undo this so we can re-use header sizes */
-	hlen -= GSO_BY_FRAGS;
-
-	skb_walk_frags(skb, iter) {
-		if (hlen + skb_headlen(iter) > mtu)
-			return false;
-	}
-
-	return true;
+	return skb_gso_size_check(skb, skb_gso_network_seglen(skb), mtu);
 }
 EXPORT_SYMBOL_GPL(skb_gso_validate_mtu);
 
+/**
+ * skb_gso_validate_mac_len - Will a split GSO skb fit in a given length?
+ *
+ * @skb: GSO skb
+ * @len: length to validate against
+ *
+ * skb_gso_validate_mac_len validates if a given skb will fit a wanted
+ * length once split, including L2, L3 and L4 headers and the payload.
+ */
+bool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len)
+{
+	return skb_gso_size_check(skb, skb_gso_mac_seglen(skb), len);
+}
+EXPORT_SYMBOL_GPL(skb_gso_validate_mac_len);
+
 static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
 {
 	int mac_len;
@@ -5160,7 +5201,6 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
 	unsigned long chunk;
 	struct sk_buff *skb;
 	struct page *page;
-	gfp_t gfp_head;
 	int i;
 
 	*errcode = -EMSGSIZE;
@@ -5170,12 +5210,8 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
 	if (npages > MAX_SKB_FRAGS)
 		return NULL;
 
-	gfp_head = gfp_mask;
-	if (gfp_head & __GFP_DIRECT_RECLAIM)
-		gfp_head |= __GFP_RETRY_MAYFAIL;
-
 	*errcode = -ENOBUFS;
-	skb = alloc_skb(header_len, gfp_head);
+	skb = alloc_skb(header_len, gfp_mask);
 	if (!skb)
 		return NULL;
 
diff --git a/net/core/sock.c b/net/core/sock.c
index 779fc33..e807bb4 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -735,6 +735,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
 		break;
 	case SO_DONTROUTE:
 		sock_valbool_flag(sk, SOCK_LOCALROUTE, valbool);
+		sk_dst_reset(sk);
 		break;
 	case SO_BROADCAST:
 		sock_valbool_flag(sk, SOCK_BROADCAST, valbool);
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index 6eb837a..baaaeb2 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -202,7 +202,7 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
 static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
 					   u8 pkt, u8 opt, u8 *val, u8 len)
 {
-	if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)
+	if (!ccid || !ccid->ccid_ops->ccid_hc_tx_parse_options)
 		return 0;
 	return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
 }
@@ -214,7 +214,7 @@ static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
 static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
 					   u8 pkt, u8 opt, u8 *val, u8 len)
 {
-	if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)
+	if (!ccid || !ccid->ccid_ops->ccid_hc_rx_parse_options)
 		return 0;
 	return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
 }
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 242e74b..b14d530 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -156,10 +156,14 @@ static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
 	struct dsa_slave_priv *p = netdev_priv(dev);
 	struct net_device *master = dsa_master_netdev(p);
 
-	if (change & IFF_ALLMULTI)
-		dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1);
-	if (change & IFF_PROMISC)
-		dev_set_promiscuity(master, dev->flags & IFF_PROMISC ? 1 : -1);
+	if (dev->flags & IFF_UP) {
+		if (change & IFF_ALLMULTI)
+			dev_set_allmulti(master,
+					 dev->flags & IFF_ALLMULTI ? 1 : -1);
+		if (change & IFF_PROMISC)
+			dev_set_promiscuity(master,
+					    dev->flags & IFF_PROMISC ? 1 : -1);
+	}
 }
 
 static void dsa_slave_set_rx_mode(struct net_device *dev)
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 1b3f860..b5317b2 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -193,7 +193,7 @@ static void fib_flush(struct net *net)
 		struct fib_table *tb;
 
 		hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
-			flushed += fib_table_flush(net, tb);
+			flushed += fib_table_flush(net, tb, false);
 	}
 
 	if (flushed)
@@ -1299,7 +1299,7 @@ static void ip_fib_net_exit(struct net *net)
 
 		hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) {
 			hlist_del(&tb->tb_hlist);
-			fib_table_flush(net, tb);
+			fib_table_flush(net, tb, true);
 			fib_free_table(tb);
 		}
 	}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index c636650..bb847d2 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1836,7 +1836,7 @@ void fib_table_flush_external(struct fib_table *tb)
 }
 
 /* Caller must hold RTNL. */
-int fib_table_flush(struct net *net, struct fib_table *tb)
+int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
 {
 	struct trie *t = (struct trie *)tb->tb_data;
 	struct key_vector *pn = t->kv;
@@ -1884,8 +1884,17 @@ int fib_table_flush(struct net *net, struct fib_table *tb)
 		hlist_for_each_entry_safe(fa, tmp, &n->leaf, fa_list) {
 			struct fib_info *fi = fa->fa_info;
 
-			if (!fi || !(fi->fib_flags & RTNH_F_DEAD) ||
-			    tb->tb_id != fa->tb_id) {
+			if (!fi || tb->tb_id != fa->tb_id ||
+			    (!(fi->fib_flags & RTNH_F_DEAD) &&
+			     !fib_props[fa->fa_type].error)) {
+				slen = fa->fa_slen;
+				continue;
+			}
+
+			/* Do not flush error routes if network namespace is
+			 * not being dismantled
+			 */
+			if (!flush_all && fib_props[fa->fa_type].error) {
 				slen = fa->fa_slen;
 				continue;
 			}
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 857ec3d..33edccf 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -109,6 +109,7 @@ static size_t inet_sk_attr_size(struct sock *sk,
 		+ nla_total_size(1) /* INET_DIAG_TOS */
 		+ nla_total_size(1) /* INET_DIAG_TCLASS */
 		+ nla_total_size(4) /* INET_DIAG_MARK */
+		+ nla_total_size(4) /* INET_DIAG_CLASS_ID */
 		+ nla_total_size(sizeof(struct inet_diag_meminfo))
 		+ nla_total_size(sizeof(struct inet_diag_msg))
 		+ nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
@@ -288,12 +289,19 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 			goto errout;
 	}
 
-	if (ext & (1 << (INET_DIAG_CLASS_ID - 1))) {
+	if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) ||
+	    ext & (1 << (INET_DIAG_TCLASS - 1))) {
 		u32 classid = 0;
 
 #ifdef CONFIG_SOCK_CGROUP_DATA
 		classid = sock_cgroup_classid(&sk->sk_cgrp_data);
 #endif
+		/* Fallback to socket priority if class id isn't set.
+		 * Classful qdiscs use it as direct reference to class.
+		 * For cgroup2 classid is always zero.
+		 */
+		if (!classid)
+			classid = sk->sk_priority;
 
 		if (nla_put_u32(skb, INET_DIAG_CLASS_ID, classid))
 			goto errout;
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index b2ca4aa..1d2fb4a 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -90,7 +90,7 @@ static void inet_frags_free_cb(void *ptr, void *arg)
 
 void inet_frags_exit_net(struct netns_frags *nf)
 {
-	nf->low_thresh = 0; /* prevent creation of new frags */
+	nf->high_thresh = 0; /* prevent creation of new frags */
 
 	rhashtable_free_and_destroy(&nf->rhashtable, inet_frags_free_cb, NULL);
 }
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 64007ce..f9cef27 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -215,6 +215,7 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
 			atomic_set(&p->rid, 0);
 			p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
 			p->rate_tokens = 0;
+			p->n_redirects = 0;
 			/* 60*HZ is arbitrary, but chosen enough high so that the first
 			 * calculation of tokens is at its maximum.
 			 */
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index f8bbd69..d95b32af 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -425,6 +425,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 	 * fragment.
 	 */
 
+	err = -EINVAL;
 	/* Find out where to put this fragment.  */
 	prev_tail = qp->q.fragments_tail;
 	if (!prev_tail)
@@ -501,7 +502,6 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 
 discard_qp:
 	inet_frag_kill(&qp->q);
-	err = -EINVAL;
 	__IP_INC_STATS(net, IPSTATS_MIB_REASM_OVERLAPS);
 err:
 	kfree_skb(skb);
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 09e6d25..880ef55 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -480,6 +480,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 		goto drop;
 	}
 
+	iph = ip_hdr(skb);
 	skb->transport_header = skb->network_header + iph->ihl*4;
 
 	/* Remove any debris in the socket control block */
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 4ef92eb..d1081ea 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -146,19 +146,17 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 
 static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
 {
+	__be16 _ports[2], *ports;
 	struct sockaddr_in sin;
-	__be16 *ports;
-	int end;
-
-	end = skb_transport_offset(skb) + 4;
-	if (end > 0 && !pskb_may_pull(skb, end))
-		return;
 
 	/* All current transport protocols have the port numbers in the
 	 * first four bytes of the transport header and this function is
 	 * written with this assumption in mind.
 	 */
-	ports = (__be16 *)skb_transport_header(skb);
+	ports = skb_header_pointer(skb, skb_transport_offset(skb),
+				   sizeof(_ports), &_ports);
+	if (!ports)
+		return;
 
 	sin.sin_family = AF_INET;
 	sin.sin_addr.s_addr = ip_hdr(skb)->daddr;
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index cc7c9d6..45f2148 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -492,7 +492,8 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
 			if (IS_ERR(config))
 				return PTR_ERR(config);
 		}
-	}
+	} else if (memcmp(&config->clustermac, &cipinfo->clustermac, ETH_ALEN))
+		return -EINVAL;
 
 	ret = nf_ct_netns_get(par->net, par->family);
 	if (ret < 0) {
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 7afa8d2..cb30f4e 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -904,13 +904,15 @@ void ip_rt_send_redirect(struct sk_buff *skb)
 	/* No redirected packets during ip_rt_redirect_silence;
 	 * reset the algorithm.
 	 */
-	if (time_after(jiffies, peer->rate_last + ip_rt_redirect_silence))
+	if (time_after(jiffies, peer->rate_last + ip_rt_redirect_silence)) {
 		peer->rate_tokens = 0;
+		peer->n_redirects = 0;
+	}
 
 	/* Too many ignored redirects; do not send anything
 	 * set dst.rate_last to the last seen redirected packet.
 	 */
-	if (peer->rate_tokens >= ip_rt_redirect_number) {
+	if (peer->n_redirects >= ip_rt_redirect_number) {
 		peer->rate_last = jiffies;
 		goto out_put_peer;
 	}
@@ -927,6 +929,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
 		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw);
 		peer->rate_last = jiffies;
 		++peer->rate_tokens;
+		++peer->n_redirects;
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 		if (log_martians &&
 		    peer->rate_tokens == ip_rt_redirect_number)
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index e773886..e8f3b74 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1184,7 +1184,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
 	flags = msg->msg_flags;
 
 	if (flags & MSG_ZEROCOPY && size && sock_flag(sk, SOCK_ZEROCOPY)) {
-		if (sk->sk_state != TCP_ESTABLISHED) {
+		if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
 			err = -EINVAL;
 			goto out_err;
 		}
@@ -2309,7 +2309,7 @@ static inline bool tcp_need_reset(int state)
 {
 	return (1 << state) &
 	       (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_FIN_WAIT1 |
-		TCPF_FIN_WAIT2 | TCPF_SYN_RECV);
+		TCPF_FIN_WAIT2 | TCPF_SYN_RECV | TCPF_SYN_SENT);
 }
 
 int tcp_disconnect(struct sock *sk, int flags)
@@ -2336,8 +2336,7 @@ int tcp_disconnect(struct sock *sk, int flags)
 		 */
 		tcp_send_active_reset(sk, gfp_any());
 		sk->sk_err = ECONNRESET;
-	} else if (old_state == TCP_SYN_SENT)
-		sk->sk_err = ECONNRESET;
+	}
 
 	tcp_clear_xmit_timers(sk);
 	__skb_queue_purge(&sk->sk_receive_queue);
@@ -2356,7 +2355,6 @@ int tcp_disconnect(struct sock *sk, int flags)
 	tp->write_seq += tp->max_window + 2;
 	if (tp->write_seq == 0)
 		tp->write_seq = 1;
-	icsk->icsk_backoff = 0;
 	tp->snd_cwnd = 2;
 	icsk->icsk_probes_out = 0;
 	tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index fe4daf6..8d5096f 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -475,14 +475,15 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
 		if (sock_owned_by_user(sk))
 			break;
 
+		skb = tcp_write_queue_head(sk);
+		if (WARN_ON_ONCE(!skb))
+			break;
+
 		icsk->icsk_backoff--;
 		icsk->icsk_rto = tp->srtt_us ? __tcp_set_rto(tp) :
 					       TCP_TIMEOUT_INIT;
 		icsk->icsk_rto = inet_csk_rto_backoff(icsk, TCP_RTO_MAX);
 
-		skb = tcp_write_queue_head(sk);
-		BUG_ON(!skb);
-
 		tcp_mstamp_refresh(tp);
 		delta_us = (u32)(tp->tcp_mstamp - skb->skb_mstamp);
 		remaining = icsk->icsk_rto -
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 61c7784..862cf69 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1128,7 +1128,8 @@ check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
 	list_for_each_entry(ifa, &idev->addr_list, if_list) {
 		if (ifa == ifp)
 			continue;
-		if (!ipv6_prefix_equal(&ifa->addr, &ifp->addr,
+		if (ifa->prefix_len != ifp->prefix_len ||
+		    !ipv6_prefix_equal(&ifa->addr, &ifp->addr,
 				       ifp->prefix_len))
 			continue;
 		if (ifa->flags & (IFA_F_PERMANENT | IFA_F_NOPREFIXROUTE))
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e9fa881..70b392d 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -333,6 +333,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
 	/* Check if the address belongs to the host. */
 	if (addr_type == IPV6_ADDR_MAPPED) {
+		struct net_device *dev = NULL;
 		int chk_addr_ret;
 
 		/* Binding to v4-mapped address on a v6-only socket
@@ -343,9 +344,20 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 			goto out;
 		}
 
+		rcu_read_lock();
+		if (sk->sk_bound_dev_if) {
+			dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
+			if (!dev) {
+				err = -ENODEV;
+				goto out_unlock;
+			}
+		}
+
 		/* Reproduce AF_INET checks to make the bindings consistent */
 		v4addr = addr->sin6_addr.s6_addr32[3];
-		chk_addr_ret = inet_addr_type(net, v4addr);
+		chk_addr_ret = inet_addr_type_dev_table(net, dev, v4addr);
+		rcu_read_unlock();
+
 		if (!net->ipv4.sysctl_ip_nonlocal_bind &&
 		    !(inet->freebind || inet->transparent) &&
 		    v4addr != htonl(INADDR_ANY) &&
@@ -374,6 +386,9 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 					err = -EINVAL;
 					goto out_unlock;
 				}
+			}
+
+			if (sk->sk_bound_dev_if) {
 				dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
 				if (!dev) {
 					err = -ENODEV;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index b17210f..fa4f183 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -349,6 +349,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info)
 	skb_reset_network_header(skb);
 	iph = ipv6_hdr(skb);
 	iph->daddr = fl6->daddr;
+	ip6_flow_hdr(iph, 0, 0);
 
 	serr = SKB_EXT_ERR(skb);
 	serr->ee.ee_errno = err;
@@ -708,17 +709,15 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
 	}
 	if (np->rxopt.bits.rxorigdstaddr) {
 		struct sockaddr_in6 sin6;
-		__be16 *ports;
-		int end;
+		__be16 _ports[2], *ports;
 
-		end = skb_transport_offset(skb) + 4;
-		if (end <= 0 || pskb_may_pull(skb, end)) {
+		ports = skb_header_pointer(skb, skb_transport_offset(skb),
+					   sizeof(_ports), &_ports);
+		if (ports) {
 			/* All current transport protocols have the port numbers in the
 			 * first four bytes of the transport header and this function is
 			 * written with this assumption in mind.
 			 */
-			ports = (__be16 *)skb_transport_header(skb);
-
 			sin6.sin6_family = AF_INET6;
 			sin6.sin6_addr = ipv6_hdr(skb)->daddr;
 			sin6.sin6_port = ports[1];
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 1f8b1a4..a776fbc 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -24,9 +24,11 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
 	struct sock *sk = sk_to_full_sk(skb->sk);
 	unsigned int hh_len;
 	struct dst_entry *dst;
+	int strict = (ipv6_addr_type(&iph->daddr) &
+		      (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
 	struct flowi6 fl6 = {
 		.flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if :
-			rt6_need_strict(&iph->daddr) ? skb_dst(skb)->dev->ifindex : 0,
+			strict ? skb_dst(skb)->dev->ifindex : 0,
 		.flowi6_mark = skb->mark,
 		.flowi6_uid = sock_net_uid(net, sk),
 		.daddr = iph->daddr,
diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
index c814077..fdeb90d 100644
--- a/net/ipv6/seg6.c
+++ b/net/ipv6/seg6.c
@@ -220,9 +220,7 @@ static int seg6_genl_get_tunsrc(struct sk_buff *skb, struct genl_info *info)
 	rcu_read_unlock();
 
 	genlmsg_end(msg, hdr);
-	genlmsg_reply(msg, info);
-
-	return 0;
+	return genlmsg_reply(msg, info);
 
 nla_put_failure:
 	rcu_read_unlock();
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index cf9342b..de4c982 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -126,6 +126,8 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
 	} else {
 		ip6_flow_hdr(hdr, 0, 0);
 		hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb));
+
+		memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
 	}
 
 	hdr->nexthdr = NEXTHDR_ROUTING;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 5d00a38..2e55f98 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -540,7 +540,8 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
 	}
 
 	err = 0;
-	if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
+	if (__in6_dev_get(skb->dev) &&
+	    !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
 		goto out;
 
 	if (t->parms.iph.daddr == 0)
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 4e438bc..c28e3ea 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -144,6 +144,9 @@ static u32 __xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr)
 		index = __xfrm6_tunnel_spi_check(net, spi);
 		if (index >= 0)
 			goto alloc_spi;
+
+		if (spi == XFRM6_TUNNEL_SPI_MAX)
+			break;
 	}
 	for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tn->spi; spi++) {
 		index = __xfrm6_tunnel_spi_check(net, spi);
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 33ea389..e494f04 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -83,8 +83,7 @@
 #define L2TP_SLFLAG_S	   0x40000000
 #define L2TP_SL_SEQ_MASK   0x00ffffff
 
-#define L2TP_HDR_SIZE_SEQ		10
-#define L2TP_HDR_SIZE_NOSEQ		6
+#define L2TP_HDR_SIZE_MAX		14
 
 /* Default trace flags */
 #define L2TP_DEFAULT_DEBUG_FLAGS	0
@@ -759,11 +758,9 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
 				 "%s: recv data ns=%u, session nr=%u\n",
 				 session->name, ns, session->nr);
 		}
+		ptr += 4;
 	}
 
-	/* Advance past L2-specific header, if present */
-	ptr += session->l2specific_len;
-
 	if (L2TP_SKB_CB(skb)->has_seq) {
 		/* Received a packet with sequence numbers. If we're the LNS,
 		 * check if we sre sending sequence numbers and if not,
@@ -907,7 +904,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
 	__skb_pull(skb, sizeof(struct udphdr));
 
 	/* Short packet? */
-	if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) {
+	if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) {
 		l2tp_info(tunnel, L2TP_MSG_DATA,
 			  "%s: recv short packet (len=%d)\n",
 			  tunnel->name, skb->len);
@@ -986,6 +983,10 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
 		goto error;
 	}
 
+	if (tunnel->version == L2TP_HDR_VER_3 &&
+	    l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+		goto error;
+
 	l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, payload_hook);
 	l2tp_session_dec_refcount(session);
 
@@ -1085,21 +1086,20 @@ static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf)
 		memcpy(bufp, &session->cookie[0], session->cookie_len);
 		bufp += session->cookie_len;
 	}
-	if (session->l2specific_len) {
-		if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
-			u32 l2h = 0;
-			if (session->send_seq) {
-				l2h = 0x40000000 | session->ns;
-				session->ns++;
-				session->ns &= 0xffffff;
-				l2tp_dbg(session, L2TP_MSG_SEQ,
-					 "%s: updated ns to %u\n",
-					 session->name, session->ns);
-			}
+	if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
+		u32 l2h = 0;
 
-			*((__be32 *) bufp) = htonl(l2h);
+		if (session->send_seq) {
+			l2h = 0x40000000 | session->ns;
+			session->ns++;
+			session->ns &= 0xffffff;
+			l2tp_dbg(session, L2TP_MSG_SEQ,
+				 "%s: updated ns to %u\n",
+				 session->name, session->ns);
 		}
-		bufp += session->l2specific_len;
+
+		*((__be32 *)bufp) = htonl(l2h);
+		bufp += 4;
 	}
 
 	return bufp - optr;
@@ -1765,7 +1765,7 @@ int l2tp_session_delete(struct l2tp_session *session)
 EXPORT_SYMBOL_GPL(l2tp_session_delete);
 
 /* We come here whenever a session's send_seq, cookie_len or
- * l2specific_len parameters are set.
+ * l2specific_type parameters are set.
  */
 void l2tp_session_set_header_len(struct l2tp_session *session, int version)
 {
@@ -1774,7 +1774,8 @@ void l2tp_session_set_header_len(struct l2tp_session *session, int version)
 		if (session->send_seq)
 			session->hdr_len += 4;
 	} else {
-		session->hdr_len = 4 + session->cookie_len + session->l2specific_len;
+		session->hdr_len = 4 + session->cookie_len;
+		session->hdr_len += l2tp_get_l2specific_len(session);
 		if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP)
 			session->hdr_len += 4;
 	}
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 0a58c07..62598ee 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -320,6 +320,37 @@ do {									\
 #define l2tp_session_dec_refcount(s) l2tp_session_dec_refcount_1(s)
 #endif
 
+static inline int l2tp_get_l2specific_len(struct l2tp_session *session)
+{
+	switch (session->l2specific_type) {
+	case L2TP_L2SPECTYPE_DEFAULT:
+		return 4;
+	case L2TP_L2SPECTYPE_NONE:
+	default:
+		return 0;
+	}
+}
+
+static inline int l2tp_v3_ensure_opt_in_linear(struct l2tp_session *session, struct sk_buff *skb,
+					       unsigned char **ptr, unsigned char **optr)
+{
+	int opt_len = session->peer_cookie_len + l2tp_get_l2specific_len(session);
+
+	if (opt_len > 0) {
+		int off = *ptr - *optr;
+
+		if (!pskb_may_pull(skb, off + opt_len))
+			return -1;
+
+		if (skb->data != *optr) {
+			*optr = skb->data;
+			*ptr = skb->data + off;
+		}
+	}
+
+	return 0;
+}
+
 #define l2tp_printk(ptr, type, func, fmt, ...)				\
 do {									\
 	if (((ptr)->debug) & (type))					\
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index e4280b6..f7880be 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -165,6 +165,9 @@ static int l2tp_ip_recv(struct sk_buff *skb)
 		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
 	}
 
+	if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+		goto discard_sess;
+
 	l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, tunnel->recv_payload_hook);
 	l2tp_session_dec_refcount(session);
 
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 8bcaa97..3c77507 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -178,6 +178,9 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
 		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
 	}
 
+	if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+		goto discard_sess;
+
 	l2tp_recv_common(session, skb, ptr, optr, 0, skb->len,
 			 tunnel->recv_payload_hook);
 	l2tp_session_dec_refcount(session);
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 8bef35a..0da10aa 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -180,6 +180,12 @@ static int pppol2tp_recv_payload_hook(struct sk_buff *skb)
 	if ((skb->data[0] == PPP_ALLSTATIONS) && (skb->data[1] == PPP_UI))
 		skb_pull(skb, 2);
 
+	if (skb->len >= 1 && skb->data[0] & 1)
+		*(u8 *)skb_push(skb, 1) = 0;
+
+	if (skb->len < 2)
+		return 1;
+
 	return 0;
 }
 
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6355833..150dd21 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -884,6 +884,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 		      BSS_CHANGED_P2P_PS |
 		      BSS_CHANGED_TXPOWER;
 	int err;
+	int prev_beacon_int;
 
 	old = sdata_dereference(sdata->u.ap.beacon, sdata);
 	if (old)
@@ -906,6 +907,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 
 	sdata->needed_rx_chains = sdata->local->rx_chains;
 
+	prev_beacon_int = sdata->vif.bss_conf.beacon_int;
 	sdata->vif.bss_conf.beacon_int = params->beacon_interval;
 
 	mutex_lock(&local->mtx);
@@ -914,8 +916,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	if (!err)
 		ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
 	mutex_unlock(&local->mtx);
-	if (err)
+	if (err) {
+		sdata->vif.bss_conf.beacon_int = prev_beacon_int;
 		return err;
+	}
 
 	/*
 	 * Apply control port protocol, this allows us to
@@ -1462,6 +1466,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 	if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
 		sta->sta.tdls = true;
 
+	if (sta->sta.tdls && sdata->vif.type == NL80211_IFTYPE_STATION &&
+	    !sdata->u.mgd.associated)
+		return -EINVAL;
+
 	err = sta_apply_parameters(local, sta, params);
 	if (err) {
 		sta_info_free(local, sta);
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 97269ca..1ce06886 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -448,17 +448,15 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
 
 	} while (unlikely(ret == -EEXIST && !mpath));
 
-	if (ret && ret != -EEXIST)
-		return ERR_PTR(ret);
-
-	/* At this point either new_mpath was added, or we found a
-	 * matching entry already in the table; in the latter case
-	 * free the unnecessary new entry.
-	 */
-	if (ret == -EEXIST) {
+	if (ret) {
 		kfree(new_mpath);
+
+		if (ret != -EEXIST)
+			return ERR_PTR(ret);
+
 		new_mpath = mpath;
 	}
+
 	sdata->u.mesh.mesh_paths_generation++;
 	return new_mpath;
 }
@@ -488,6 +486,9 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
 					    &new_mpath->rhash,
 					    mesh_rht_params);
 
+	if (ret)
+		kfree(new_mpath);
+
 	sdata->u.mesh.mpp_paths_generation++;
 	return ret;
 }
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9e19ddb..1512e54 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -141,6 +141,9 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
 	/* allocate extra bitmaps */
 	if (status->chains)
 		len += 4 * hweight8(status->chains);
+	/* vendor presence bitmap */
+	if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)
+		len += 4;
 
 	if (ieee80211_have_rx_timestamp(status)) {
 		len = ALIGN(len, 8);
@@ -182,8 +185,6 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
 	if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
 		struct ieee80211_vendor_radiotap *rtap = (void *)skb->data;
 
-		/* vendor presence bitmap */
-		len += 4;
 		/* alignment for fixed 6-byte vendor data header */
 		len = ALIGN(len, 2);
 		/* vendor data header */
@@ -205,7 +206,7 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
 		struct ieee80211_hdr_3addr hdr;
 		u8 category;
 		u8 action_code;
-	} __packed action;
+	} __packed __aligned(2) action;
 
 	if (!sdata)
 		return;
@@ -2532,7 +2533,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 	skb_set_queue_mapping(skb, q);
 
 	if (!--mesh_hdr->ttl) {
-		IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
+		if (!is_multicast_ether_addr(hdr->addr1))
+			IEEE80211_IFSTA_MESH_CTR_INC(ifmsh,
+						     dropped_frames_ttl);
 		goto out;
 	}
 
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 3591227..b18466c 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -545,6 +545,11 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
 	}
 
 	ieee80211_led_tx(local);
+
+	if (skb_has_frag_list(skb)) {
+		kfree_skb_list(skb_shinfo(skb)->frag_list);
+		skb_shinfo(skb)->frag_list = NULL;
+	}
 }
 
 /*
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 6b9bf9c..305a465 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1856,9 +1856,16 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
 				int head_need, bool may_encrypt)
 {
 	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_hdr *hdr;
+	bool enc_tailroom;
 	int tail_need = 0;
 
-	if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) {
+	hdr = (struct ieee80211_hdr *) skb->data;
+	enc_tailroom = may_encrypt &&
+		       (sdata->crypto_tx_tailroom_needed_cnt ||
+			ieee80211_is_mgmt(hdr->frame_control));
+
+	if (enc_tailroom) {
 		tail_need = IEEE80211_ENCRYPT_TAILROOM;
 		tail_need -= skb_tailroom(skb);
 		tail_need = max_t(int, tail_need, 0);
@@ -1866,8 +1873,7 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
 
 	if (skb_cloned(skb) &&
 	    (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
-	     !skb_clone_writable(skb, ETH_HLEN) ||
-	     (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt)))
+	     !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
 		I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
 	else if (head_need || tail_need)
 		I802_DEBUG_INC(local->tx_expand_skb_head);
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index 75d52ae..e563921 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -542,8 +542,8 @@ list_set_list(const struct ip_set *set,
 		ret = -EMSGSIZE;
 	} else {
 		cb->args[IPSET_CB_ARG0] = i;
+		ipset_nest_end(skb, atd);
 	}
-	ipset_nest_end(skb, atd);
 out:
 	rcu_read_unlock();
 	return ret;
diff --git a/net/netfilter/nf_conntrack_seqadj.c b/net/netfilter/nf_conntrack_seqadj.c
index a975efd..9da3034 100644
--- a/net/netfilter/nf_conntrack_seqadj.c
+++ b/net/netfilter/nf_conntrack_seqadj.c
@@ -115,12 +115,12 @@ static void nf_ct_sack_block_adjust(struct sk_buff *skb,
 /* TCP SACK sequence number adjustment */
 static unsigned int nf_ct_sack_adjust(struct sk_buff *skb,
 				      unsigned int protoff,
-				      struct tcphdr *tcph,
 				      struct nf_conn *ct,
 				      enum ip_conntrack_info ctinfo)
 {
-	unsigned int dir, optoff, optend;
+	struct tcphdr *tcph = (void *)skb->data + protoff;
 	struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
+	unsigned int dir, optoff, optend;
 
 	optoff = protoff + sizeof(struct tcphdr);
 	optend = protoff + tcph->doff * 4;
@@ -128,6 +128,7 @@ static unsigned int nf_ct_sack_adjust(struct sk_buff *skb,
 	if (!skb_make_writable(skb, optend))
 		return 0;
 
+	tcph = (void *)skb->data + protoff;
 	dir = CTINFO2DIR(ctinfo);
 
 	while (optoff < optend) {
@@ -207,7 +208,7 @@ int nf_ct_seq_adjust(struct sk_buff *skb,
 		 ntohl(newack));
 	tcph->ack_seq = newack;
 
-	res = nf_ct_sack_adjust(skb, protoff, tcph, ct, ctinfo);
+	res = nf_ct_sack_adjust(skb, protoff, ct, ctinfo);
 out:
 	spin_unlock_bh(&ct->lock);
 
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index af8345f..ed0ea64b 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -97,7 +97,8 @@ int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family)
 	dst = skb_dst(skb);
 	if (dst->xfrm)
 		dst = ((struct xfrm_dst *)dst)->route;
-	dst_hold(dst);
+	if (!dst_hold_safe(dst))
+		return -EHOSTUNREACH;
 
 	dst = xfrm_lookup(net, dst, &fl, skb->sk, 0);
 	if (IS_ERR(dst))
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 623ec29..c445d57 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -304,6 +304,9 @@ static int nft_delrule_by_chain(struct nft_ctx *ctx)
 	int err;
 
 	list_for_each_entry(rule, &ctx->chain->rules, list) {
+		if (!nft_is_active_next(ctx->net, rule))
+			continue;
+
 		err = nft_delrule(ctx, rule);
 		if (err < 0)
 			return err;
@@ -4046,6 +4049,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
 err5:
 	kfree(trans);
 err4:
+	if (obj)
+		obj->use--;
 	kfree(elem.priv);
 err3:
 	if (nla[NFTA_SET_ELEM_DATA] != NULL)
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 7533c2fd..7344ec7 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -277,6 +277,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
 	struct xt_target *target = expr->ops->data;
 	void *info = nft_expr_priv(expr);
+	struct module *me = target->me;
 	struct xt_tgdtor_param par;
 
 	par.net = ctx->net;
@@ -287,7 +288,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 		par.target->destroy(&par);
 
 	if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops)))
-		module_put(target->me);
+		module_put(me);
 }
 
 static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
index 94d05806..f0ecaec 100644
--- a/net/netrom/nr_timer.c
+++ b/net/netrom/nr_timer.c
@@ -53,21 +53,21 @@ void nr_start_t1timer(struct sock *sk)
 {
 	struct nr_sock *nr = nr_sk(sk);
 
-	mod_timer(&nr->t1timer, jiffies + nr->t1);
+	sk_reset_timer(sk, &nr->t1timer, jiffies + nr->t1);
 }
 
 void nr_start_t2timer(struct sock *sk)
 {
 	struct nr_sock *nr = nr_sk(sk);
 
-	mod_timer(&nr->t2timer, jiffies + nr->t2);
+	sk_reset_timer(sk, &nr->t2timer, jiffies + nr->t2);
 }
 
 void nr_start_t4timer(struct sock *sk)
 {
 	struct nr_sock *nr = nr_sk(sk);
 
-	mod_timer(&nr->t4timer, jiffies + nr->t4);
+	sk_reset_timer(sk, &nr->t4timer, jiffies + nr->t4);
 }
 
 void nr_start_idletimer(struct sock *sk)
@@ -75,37 +75,37 @@ void nr_start_idletimer(struct sock *sk)
 	struct nr_sock *nr = nr_sk(sk);
 
 	if (nr->idle > 0)
-		mod_timer(&nr->idletimer, jiffies + nr->idle);
+		sk_reset_timer(sk, &nr->idletimer, jiffies + nr->idle);
 }
 
 void nr_start_heartbeat(struct sock *sk)
 {
-	mod_timer(&sk->sk_timer, jiffies + 5 * HZ);
+	sk_reset_timer(sk, &sk->sk_timer, jiffies + 5 * HZ);
 }
 
 void nr_stop_t1timer(struct sock *sk)
 {
-	del_timer(&nr_sk(sk)->t1timer);
+	sk_stop_timer(sk, &nr_sk(sk)->t1timer);
 }
 
 void nr_stop_t2timer(struct sock *sk)
 {
-	del_timer(&nr_sk(sk)->t2timer);
+	sk_stop_timer(sk, &nr_sk(sk)->t2timer);
 }
 
 void nr_stop_t4timer(struct sock *sk)
 {
-	del_timer(&nr_sk(sk)->t4timer);
+	sk_stop_timer(sk, &nr_sk(sk)->t4timer);
 }
 
 void nr_stop_idletimer(struct sock *sk)
 {
-	del_timer(&nr_sk(sk)->idletimer);
+	sk_stop_timer(sk, &nr_sk(sk)->idletimer);
 }
 
 void nr_stop_heartbeat(struct sock *sk)
 {
-	del_timer(&sk->sk_timer);
+	sk_stop_timer(sk, &sk->sk_timer);
 }
 
 int nr_t1timer_running(struct sock *sk)
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index f70e9cb..e687b89 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -459,7 +459,7 @@ static int __parse_flow_nlattrs(const struct nlattr *attr,
 			return -EINVAL;
 		}
 
-		if (!nz || !is_all_zero(nla_data(nla), expected_len)) {
+		if (!nz || !is_all_zero(nla_data(nla), nla_len(nla))) {
 			attrs |= 1 << type;
 			a[type] = nla;
 		}
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 91a323f..73d16a1 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2666,7 +2666,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 		addr	= saddr->sll_halen ? saddr->sll_addr : NULL;
 		dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
 		if (addr && dev && saddr->sll_halen < dev->addr_len)
-			goto out;
+			goto out_put;
 	}
 
 	err = -ENXIO;
@@ -2866,7 +2866,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 		addr	= saddr->sll_halen ? saddr->sll_addr : NULL;
 		dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
 		if (addr && dev && saddr->sll_halen < dev->addr_len)
-			goto out;
+			goto out_unlock;
 	}
 
 	err = -ENXIO;
@@ -3942,7 +3942,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 			len = sizeof(int);
 		if (len < sizeof(int))
 			return -EINVAL;
-		if (copy_from_user(&val, optval, len))
+		if (copy_from_user(&val, optval, sizeof(val)))
 			return -EFAULT;
 		switch (val) {
 		case TPACKET_V1:
@@ -4313,7 +4313,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 		rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
 		if (unlikely(rb->frames_per_block == 0))
 			goto out;
-		if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+		if (unlikely(rb->frames_per_block > UINT_MAX / req->tp_block_nr))
 			goto out;
 		if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
 					req->tp_frame_nr))
diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index 35e84bb..67003d3 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015, Sony Mobile Communications Inc.
- * Copyright (c) 2013, 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -506,8 +506,10 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
 	size_t len = skb->len;
 	int rc = -ENODEV;
 
-	if (!atomic_read(&node->hello_sent) && type != QRTR_TYPE_HELLO)
+	if (!atomic_read(&node->hello_sent) && type != QRTR_TYPE_HELLO) {
+		kfree_skb(skb);
 		return rc;
+	}
 
 	/* If sk is null, this is a forwarded packet and should not wait */
 	if (!skb->sk) {
@@ -527,14 +529,12 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
 	hdr->type = cpu_to_le32(type);
 	hdr->src_node_id = cpu_to_le32(from->sq_node);
 	hdr->src_port_id = cpu_to_le32(from->sq_port);
-	if (to->sq_port == QRTR_PORT_CTRL) {
+	if (to->sq_node == QRTR_NODE_BCAST)
 		hdr->dst_node_id = cpu_to_le32(node->nid);
-		hdr->dst_port_id = cpu_to_le32(QRTR_NODE_BCAST);
-	} else {
+	else
 		hdr->dst_node_id = cpu_to_le32(to->sq_node);
-		hdr->dst_port_id = cpu_to_le32(to->sq_port);
-	}
 
+	hdr->dst_port_id = cpu_to_le32(to->sq_port);
 	hdr->size = cpu_to_le32(len);
 	hdr->confirm_rx = !!confirm_rx;
 
diff --git a/net/rds/bind.c b/net/rds/bind.c
index 48257d3..4f1427c 100644
--- a/net/rds/bind.c
+++ b/net/rds/bind.c
@@ -62,10 +62,10 @@ struct rds_sock *rds_find_bound(__be32 addr, __be16 port)
 
 	rcu_read_lock();
 	rs = rhashtable_lookup(&bind_hash_table, &key, ht_parms);
-	if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD))
-		rds_sock_addref(rs);
-	else
+	if (rs && (sock_flag(rds_rs_to_sk(rs), SOCK_DEAD) ||
+		   !refcount_inc_not_zero(&rds_rs_to_sk(rs)->sk_refcnt)))
 		rs = NULL;
+
 	rcu_read_unlock();
 
 	rdsdebug("returning rs %p for %pI4:%u\n", rs, &addr,
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 452bbb3..2741abe 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -848,6 +848,7 @@ void rose_link_device_down(struct net_device *dev)
 
 /*
  *	Route a frame to an appropriate AX.25 connection.
+ *	A NULL ax25_cb indicates an internally generated frame.
  */
 int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 {
@@ -865,6 +866,10 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 
 	if (skb->len < ROSE_MIN_LEN)
 		return res;
+
+	if (!ax25)
+		return rose_loopback_queue(skb, NULL);
+
 	frametype = skb->data[2];
 	lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
 	if (frametype == ROSE_CALL_REQUEST &&
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index abcf480..b74cde2 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -588,6 +588,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 	}
 error_no_call:
 	release_sock(&rx->sk);
+error_trace:
 	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, 0, 0, 0, ret);
 	return ret;
 
@@ -596,7 +597,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 wait_error:
 	finish_wait(sk_sleep(&rx->sk), &wait);
 	call = NULL;
-	goto error_no_call;
+	goto error_trace;
 }
 
 /**
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 04a7079..32819d1 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -318,7 +318,6 @@ EXPORT_SYMBOL(tcf_block_put);
 int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 		 struct tcf_result *res, bool compat_mode)
 {
-	__be16 protocol = tc_skb_protocol(skb);
 #ifdef CONFIG_NET_CLS_ACT
 	const int max_reclassify_loop = 4;
 	const struct tcf_proto *orig_tp = tp;
@@ -328,6 +327,7 @@ int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 reclassify:
 #endif
 	for (; tp; tp = rcu_dereference_bh(tp->next)) {
+		__be16 protocol = tc_skb_protocol(skb);
 		int err;
 
 		if (tp->protocol != protocol &&
@@ -359,7 +359,6 @@ int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 	}
 
 	tp = first_tp;
-	protocol = tc_skb_protocol(skb);
 	goto reclassify;
 #endif
 }
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index b36ecb5..107cc76 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -142,16 +142,6 @@ static u64 psched_ns_t2l(const struct psched_ratecfg *r,
 	return len;
 }
 
-/*
- * Return length of individual segments of a gso packet,
- * including all headers (MAC, IP, TCP/UDP)
- */
-static unsigned int skb_gso_mac_seglen(const struct sk_buff *skb)
-{
-	unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
-	return hdr_len + skb_gso_transport_seglen(skb);
-}
-
 /* GSO packet is too big, segment it so that tbf can transmit
  * each segment in time
  */
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 8002a72..7eb06fa 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -97,11 +97,9 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
 
 	switch (ev) {
 	case NETDEV_UP:
-		addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+		addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
 		if (addr) {
 			addr->a.v6.sin6_family = AF_INET6;
-			addr->a.v6.sin6_port = 0;
-			addr->a.v6.sin6_flowinfo = 0;
 			addr->a.v6.sin6_addr = ifa->addr;
 			addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
 			addr->valid = 1;
@@ -415,7 +413,6 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
 		addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
 		if (addr) {
 			addr->a.v6.sin6_family = AF_INET6;
-			addr->a.v6.sin6_port = 0;
 			addr->a.v6.sin6_addr = ifp->addr;
 			addr->a.v6.sin6_scope_id = dev->ifindex;
 			addr->valid = 1;
diff --git a/net/sctp/offload.c b/net/sctp/offload.c
index 35bc710..055e1ab 100644
--- a/net/sctp/offload.c
+++ b/net/sctp/offload.c
@@ -36,6 +36,7 @@ static __le32 sctp_gso_make_checksum(struct sk_buff *skb)
 {
 	skb->ip_summed = CHECKSUM_NONE;
 	skb->csum_not_inet = 0;
+	gso_reset_checksum(skb, ~0);
 	return sctp_compute_cksum(skb, skb_transport_offset(skb));
 }
 
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index df22a9c..cbb04d6 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -151,7 +151,6 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
 		addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
 		if (addr) {
 			addr->a.v4.sin_family = AF_INET;
-			addr->a.v4.sin_port = 0;
 			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
 			addr->valid = 1;
 			INIT_LIST_HEAD(&addr->list);
@@ -782,10 +781,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 
 	switch (ev) {
 	case NETDEV_UP:
-		addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+		addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
 		if (addr) {
 			addr->a.v4.sin_family = AF_INET;
-			addr->a.v4.sin_port = 0;
 			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
 			addr->valid = 1;
 			spin_lock_bh(&net->sctp.local_addr_lock);
diff --git a/net/sctp/sctp_diag.c b/net/sctp/sctp_diag.c
index a72a7d9..75274a6 100644
--- a/net/sctp/sctp_diag.c
+++ b/net/sctp/sctp_diag.c
@@ -225,6 +225,7 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc)
 		+ nla_total_size(1) /* INET_DIAG_TOS */
 		+ nla_total_size(1) /* INET_DIAG_TCLASS */
 		+ nla_total_size(4) /* INET_DIAG_MARK */
+		+ nla_total_size(4) /* INET_DIAG_CLASS_ID */
 		+ nla_total_size(addrlen * asoc->peer.transport_count)
 		+ nla_total_size(addrlen * addrcnt)
 		+ nla_total_size(sizeof(struct inet_diag_meminfo))
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 6127353..71534bd 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -360,9 +360,9 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 	struct sctp_strreset_outreq *outreq = param.v;
 	struct sctp_stream *stream = &asoc->stream;
 	__u32 result = SCTP_STRRESET_DENIED;
-	__u16 i, nums, flags = 0;
 	__be16 *str_p = NULL;
 	__u32 request_seq;
+	__u16 i, nums;
 
 	request_seq = ntohl(outreq->request_seq);
 
@@ -390,6 +390,15 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 	if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
 		goto out;
 
+	nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
+	str_p = outreq->list_of_streams;
+	for (i = 0; i < nums; i++) {
+		if (ntohs(str_p[i]) >= stream->incnt) {
+			result = SCTP_STRRESET_ERR_WRONG_SSN;
+			goto out;
+		}
+	}
+
 	if (asoc->strreset_chunk) {
 		if (!sctp_chunk_lookup_strreset_param(
 				asoc, outreq->response_seq,
@@ -412,32 +421,19 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 			sctp_chunk_put(asoc->strreset_chunk);
 			asoc->strreset_chunk = NULL;
 		}
-
-		flags = SCTP_STREAM_RESET_INCOMING_SSN;
 	}
 
-	nums = (ntohs(param.p->length) - sizeof(*outreq)) / 2;
-	if (nums) {
-		str_p = outreq->list_of_streams;
-		for (i = 0; i < nums; i++) {
-			if (ntohs(str_p[i]) >= stream->incnt) {
-				result = SCTP_STRRESET_ERR_WRONG_SSN;
-				goto out;
-			}
-		}
-
+	if (nums)
 		for (i = 0; i < nums; i++)
 			stream->in[ntohs(str_p[i])].ssn = 0;
-	} else {
+	else
 		for (i = 0; i < stream->incnt; i++)
 			stream->in[i].ssn = 0;
-	}
 
 	result = SCTP_STRRESET_PERFORMED;
 
 	*evp = sctp_ulpevent_make_stream_reset_event(asoc,
-		flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p,
-		GFP_ATOMIC);
+		SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
 
 out:
 	sctp_update_strreset_result(asoc, result);
@@ -507,9 +503,6 @@ struct sctp_chunk *sctp_process_strreset_inreq(
 
 	result = SCTP_STRRESET_PERFORMED;
 
-	*evp = sctp_ulpevent_make_stream_reset_event(asoc,
-		SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
-
 out:
 	sctp_update_strreset_result(asoc, result);
 err:
@@ -642,6 +635,16 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
 	if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
 		goto out;
 
+	in = ntohs(addstrm->number_of_streams);
+	incnt = stream->incnt + in;
+	if (!in || incnt > SCTP_MAX_STREAM)
+		goto out;
+
+	streamin = krealloc(stream->in, incnt * sizeof(*streamin),
+			    GFP_ATOMIC);
+	if (!streamin)
+		goto out;
+
 	if (asoc->strreset_chunk) {
 		if (!sctp_chunk_lookup_strreset_param(
 			asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
@@ -665,16 +668,6 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
 		}
 	}
 
-	in = ntohs(addstrm->number_of_streams);
-	incnt = stream->incnt + in;
-	if (!in || incnt > SCTP_MAX_STREAM)
-		goto out;
-
-	streamin = krealloc(stream->in, incnt * sizeof(*streamin),
-			    GFP_ATOMIC);
-	if (!streamin)
-		goto out;
-
 	memset(streamin + stream->incnt, 0, in * sizeof(*streamin));
 	stream->in = streamin;
 	stream->incnt = incnt;
@@ -750,9 +743,6 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
 
 	result = SCTP_STRRESET_PERFORMED;
 
-	*evp = sctp_ulpevent_make_stream_change_event(asoc,
-		0, 0, ntohs(addstrm->number_of_streams), GFP_ATOMIC);
-
 out:
 	sctp_update_strreset_result(asoc, result);
 err:
@@ -805,10 +795,10 @@ struct sctp_chunk *sctp_process_strreset_resp(
 				for (i = 0; i < stream->outcnt; i++)
 					stream->out[i].ssn = 0;
 			}
-
-			flags = SCTP_STREAM_RESET_OUTGOING_SSN;
 		}
 
+		flags |= SCTP_STREAM_RESET_OUTGOING_SSN;
+
 		for (i = 0; i < stream->outcnt; i++)
 			stream->out[i].state = SCTP_STREAM_OPEN;
 
@@ -826,6 +816,8 @@ struct sctp_chunk *sctp_process_strreset_resp(
 		str_p = inreq->list_of_streams;
 		nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) / 2;
 
+		flags |= SCTP_STREAM_RESET_INCOMING_SSN;
+
 		*evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
 			nums, str_p, GFP_ATOMIC);
 	} else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) {
diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
index c8b9082..2d2ed67 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
@@ -44,7 +44,7 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
 		      unsigned char *cksum, unsigned char *buf)
 {
 	struct crypto_skcipher *cipher;
-	unsigned char plain[8];
+	unsigned char *plain;
 	s32 code;
 
 	dprintk("RPC:       %s:\n", __func__);
@@ -53,6 +53,10 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
 	if (IS_ERR(cipher))
 		return PTR_ERR(cipher);
 
+	plain = kmalloc(8, GFP_NOFS);
+	if (!plain)
+		return -ENOMEM;
+
 	plain[0] = (unsigned char) ((seqnum >> 24) & 0xff);
 	plain[1] = (unsigned char) ((seqnum >> 16) & 0xff);
 	plain[2] = (unsigned char) ((seqnum >> 8) & 0xff);
@@ -69,6 +73,7 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
 	code = krb5_encrypt(cipher, cksum, plain, buf, 8);
 out:
 	crypto_free_skcipher(cipher);
+	kfree(plain);
 	return code;
 }
 s32
@@ -78,12 +83,17 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
 		u32 seqnum,
 		unsigned char *cksum, unsigned char *buf)
 {
-	unsigned char plain[8];
+	unsigned char *plain;
+	s32 code;
 
 	if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
 		return krb5_make_rc4_seq_num(kctx, direction, seqnum,
 					     cksum, buf);
 
+	plain = kmalloc(8, GFP_NOFS);
+	if (!plain)
+		return -ENOMEM;
+
 	plain[0] = (unsigned char) (seqnum & 0xff);
 	plain[1] = (unsigned char) ((seqnum >> 8) & 0xff);
 	plain[2] = (unsigned char) ((seqnum >> 16) & 0xff);
@@ -94,7 +104,9 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
 	plain[6] = direction;
 	plain[7] = direction;
 
-	return krb5_encrypt(key, cksum, plain, buf, 8);
+	code = krb5_encrypt(key, cksum, plain, buf, 8);
+	kfree(plain);
+	return code;
 }
 
 static s32
@@ -102,7 +114,7 @@ krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum,
 		     unsigned char *buf, int *direction, s32 *seqnum)
 {
 	struct crypto_skcipher *cipher;
-	unsigned char plain[8];
+	unsigned char *plain;
 	s32 code;
 
 	dprintk("RPC:       %s:\n", __func__);
@@ -115,20 +127,28 @@ krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum,
 	if (code)
 		goto out;
 
+	plain = kmalloc(8, GFP_NOFS);
+	if (!plain) {
+		code = -ENOMEM;
+		goto out;
+	}
+
 	code = krb5_decrypt(cipher, cksum, buf, plain, 8);
 	if (code)
-		goto out;
+		goto out_plain;
 
 	if ((plain[4] != plain[5]) || (plain[4] != plain[6])
 				   || (plain[4] != plain[7])) {
 		code = (s32)KG_BAD_SEQ;
-		goto out;
+		goto out_plain;
 	}
 
 	*direction = plain[4];
 
 	*seqnum = ((plain[0] << 24) | (plain[1] << 16) |
 					(plain[2] << 8) | (plain[3]));
+out_plain:
+	kfree(plain);
 out:
 	crypto_free_skcipher(cipher);
 	return code;
@@ -141,26 +161,33 @@ krb5_get_seq_num(struct krb5_ctx *kctx,
 	       int *direction, u32 *seqnum)
 {
 	s32 code;
-	unsigned char plain[8];
 	struct crypto_skcipher *key = kctx->seq;
+	unsigned char *plain;
 
 	dprintk("RPC:       krb5_get_seq_num:\n");
 
 	if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
 		return krb5_get_rc4_seq_num(kctx, cksum, buf,
 					    direction, seqnum);
+	plain = kmalloc(8, GFP_NOFS);
+	if (!plain)
+		return -ENOMEM;
 
 	if ((code = krb5_decrypt(key, cksum, buf, plain, 8)))
-		return code;
+		goto out;
 
 	if ((plain[4] != plain[5]) || (plain[4] != plain[6]) ||
-	    (plain[4] != plain[7]))
-		return (s32)KG_BAD_SEQ;
+	    (plain[4] != plain[7])) {
+		code = (s32)KG_BAD_SEQ;
+		goto out;
+	}
 
 	*direction = plain[4];
 
 	*seqnum = ((plain[0]) |
 		   (plain[1] << 8) | (plain[2] << 16) | (plain[3] << 24));
 
-	return 0;
+out:
+	kfree(plain);
+	return code;
 }
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index f41ffb2..cc08cb1 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1120,7 +1120,7 @@ static int svcauth_gss_legacy_init(struct svc_rqst *rqstp,
 	struct kvec *resv = &rqstp->rq_res.head[0];
 	struct rsi *rsip, rsikey;
 	int ret;
-	struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
+	struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
 
 	memset(&rsikey, 0, sizeof(rsikey));
 	ret = gss_read_verf(gc, argv, authp,
@@ -1231,7 +1231,7 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
 	uint64_t handle;
 	int status;
 	int ret;
-	struct net *net = rqstp->rq_xprt->xpt_net;
+	struct net *net = SVC_NET(rqstp);
 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
 	memset(&ud, 0, sizeof(ud));
@@ -1422,7 +1422,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 	__be32		*rpcstart;
 	__be32		*reject_stat = resv->iov_base + resv->iov_len;
 	int		ret;
-	struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
+	struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
 
 	dprintk("RPC:       svcauth_gss: argv->iov_len = %zd\n",
 			argv->iov_len);
@@ -1710,7 +1710,7 @@ svcauth_gss_release(struct svc_rqst *rqstp)
 	struct rpc_gss_wire_cred *gc = &gsd->clcred;
 	struct xdr_buf *resbuf = &rqstp->rq_res;
 	int stat = -EINVAL;
-	struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
+	struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
 
 	if (gc->gc_proc != RPC_GSS_PROC_DATA)
 		goto out;
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 79d55d9..f2cf4ed 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -54,6 +54,11 @@ static void cache_init(struct cache_head *h, struct cache_detail *detail)
 	h->last_refresh = now;
 }
 
+static void cache_fresh_locked(struct cache_head *head, time_t expiry,
+				struct cache_detail *detail);
+static void cache_fresh_unlocked(struct cache_head *head,
+				struct cache_detail *detail);
+
 struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
 				       struct cache_head *key, int hash)
 {
@@ -95,6 +100,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
 			if (cache_is_expired(detail, tmp)) {
 				hlist_del_init(&tmp->cache_list);
 				detail->entries --;
+				cache_fresh_locked(tmp, 0, detail);
 				freeme = tmp;
 				break;
 			}
@@ -110,8 +116,10 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
 	cache_get(new);
 	write_unlock(&detail->hash_lock);
 
-	if (freeme)
+	if (freeme) {
+		cache_fresh_unlocked(freeme, detail);
 		cache_put(freeme, detail);
+	}
 	return new;
 }
 EXPORT_SYMBOL_GPL(sunrpc_cache_lookup);
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index ea0676f..da21efa 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -771,6 +771,12 @@ void rpcb_getport_async(struct rpc_task *task)
 	case RPCBVERS_3:
 		map->r_netid = xprt->address_strings[RPC_DISPLAY_NETID];
 		map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC);
+		if (!map->r_addr) {
+			status = -ENOMEM;
+			dprintk("RPC: %5u %s: no memory available\n",
+				task->tk_pid, __func__);
+			goto bailout_free_args;
+		}
 		map->r_owner = "";
 		break;
 	case RPCBVERS_2:
@@ -793,6 +799,8 @@ void rpcb_getport_async(struct rpc_task *task)
 	rpc_put_task(child);
 	return;
 
+bailout_free_args:
+	kfree(map);
 bailout_release_client:
 	rpc_release_client(rpcb_clnt);
 bailout_nofree:
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index e5e4e18..4eb470a 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1144,6 +1144,8 @@ void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
 static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {}
 #endif
 
+extern void svc_tcp_prep_reply_hdr(struct svc_rqst *);
+
 /*
  * Common routine for processing the RPC request.
  */
@@ -1172,7 +1174,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
 	clear_bit(RQ_DROPME, &rqstp->rq_flags);
 
 	/* Setup reply header */
-	rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp);
+	if (rqstp->rq_prot == IPPROTO_TCP)
+		svc_tcp_prep_reply_hdr(rqstp);
 
 	svc_putu32(resv, rqstp->rq_xid);
 
@@ -1244,7 +1247,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
 	 * for lower versions. RPC_PROG_MISMATCH seems to be the closest
 	 * fit.
 	 */
-	if (versp->vs_need_cong_ctrl &&
+	if (versp->vs_need_cong_ctrl && rqstp->rq_xprt &&
 	    !test_bit(XPT_CONG_CTRL, &rqstp->rq_xprt->xpt_flags))
 		goto err_bad_vers;
 
@@ -1335,7 +1338,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
 	return 0;
 
  close:
-	if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags))
+	if (rqstp->rq_xprt && test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags))
 		svc_close_xprt(rqstp->rq_xprt);
 	dprintk("svc: svc_process close\n");
 	return 0;
@@ -1462,10 +1465,10 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
 	dprintk("svc: %s(%p)\n", __func__, req);
 
 	/* Build the svc_rqst used by the common processing routine */
-	rqstp->rq_xprt = serv->sv_bc_xprt;
 	rqstp->rq_xid = req->rq_xid;
 	rqstp->rq_prot = req->rq_xprt->prot;
 	rqstp->rq_server = serv;
+	rqstp->rq_bc_net = req->rq_xprt->xprt_net;
 
 	rqstp->rq_addrlen = sizeof(req->rq_xprt->addr);
 	memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index ea7b5a3..7e5f849 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -510,10 +510,11 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool)
  */
 void svc_reserve(struct svc_rqst *rqstp, int space)
 {
+	struct svc_xprt *xprt = rqstp->rq_xprt;
+
 	space += rqstp->rq_res.head[0].iov_len;
 
-	if (space < rqstp->rq_reserved) {
-		struct svc_xprt *xprt = rqstp->rq_xprt;
+	if (xprt && space < rqstp->rq_reserved) {
 		atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved);
 		rqstp->rq_reserved = space;
 
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index c83df30..d6771f3 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1207,7 +1207,7 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp)
 /*
  * Setup response header. TCP has a 4B record length field.
  */
-static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
+void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
 {
 	struct kvec *resv = &rqstp->rq_res.head[0];
 
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 30192abf..05a58cc 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -2223,8 +2223,8 @@ static void xs_udp_setup_socket(struct work_struct *work)
 	trace_rpc_socket_connect(xprt, sock, 0);
 	status = 0;
 out:
-	xprt_unlock_connect(xprt, transport);
 	xprt_clear_connecting(xprt);
+	xprt_unlock_connect(xprt, transport);
 	xprt_wake_pending_tasks(xprt, status);
 }
 
@@ -2451,8 +2451,8 @@ static void xs_tcp_setup_socket(struct work_struct *work)
 	}
 	status = -EAGAIN;
 out:
-	xprt_unlock_connect(xprt, transport);
 	xprt_clear_connecting(xprt);
+	xprt_unlock_connect(xprt, transport);
 	xprt_wake_pending_tasks(xprt, status);
 }
 
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index e48f0b2..73895da 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -87,6 +87,11 @@ static int tipc_skb_tailroom(struct sk_buff *skb)
 	return limit;
 }
 
+static inline int TLV_GET_DATA_LEN(struct tlv_desc *tlv)
+{
+	return TLV_GET_LEN(tlv) - TLV_SPACE(0);
+}
+
 static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len)
 {
 	struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb);
@@ -166,6 +171,11 @@ static struct sk_buff *tipc_get_err_tlv(char *str)
 	return buf;
 }
 
+static inline bool string_is_valid(char *s, int len)
+{
+	return memchr(s, '\0', len) ? true : false;
+}
+
 static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
 				   struct tipc_nl_compat_msg *msg,
 				   struct sk_buff *arg)
@@ -370,6 +380,7 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
 	struct nlattr *prop;
 	struct nlattr *bearer;
 	struct tipc_bearer_config *b;
+	int len;
 
 	b = (struct tipc_bearer_config *)TLV_DATA(msg->req);
 
@@ -377,6 +388,10 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
 	if (!bearer)
 		return -EMSGSIZE;
 
+	len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
+	if (!string_is_valid(b->name, len))
+		return -EINVAL;
+
 	if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, b->name))
 		return -EMSGSIZE;
 
@@ -402,6 +417,7 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
 {
 	char *name;
 	struct nlattr *bearer;
+	int len;
 
 	name = (char *)TLV_DATA(msg->req);
 
@@ -409,6 +425,10 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
 	if (!bearer)
 		return -EMSGSIZE;
 
+	len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
+	if (!string_is_valid(name, len))
+		return -EINVAL;
+
 	if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, name))
 		return -EMSGSIZE;
 
@@ -469,6 +489,7 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
 	struct nlattr *prop[TIPC_NLA_PROP_MAX + 1];
 	struct nlattr *stats[TIPC_NLA_STATS_MAX + 1];
 	int err;
+	int len;
 
 	if (!attrs[TIPC_NLA_LINK])
 		return -EINVAL;
@@ -495,6 +516,11 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
 		return err;
 
 	name = (char *)TLV_DATA(msg->req);
+
+	len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+	if (!string_is_valid(name, len))
+		return -EINVAL;
+
 	if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0)
 		return 0;
 
@@ -635,6 +661,7 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
 	struct nlattr *prop;
 	struct nlattr *media;
 	struct tipc_link_config *lc;
+	int len;
 
 	lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
@@ -642,6 +669,10 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
 	if (!media)
 		return -EMSGSIZE;
 
+	len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
+	if (!string_is_valid(lc->name, len))
+		return -EINVAL;
+
 	if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name))
 		return -EMSGSIZE;
 
@@ -662,6 +693,7 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
 	struct nlattr *prop;
 	struct nlattr *bearer;
 	struct tipc_link_config *lc;
+	int len;
 
 	lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
@@ -669,6 +701,10 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
 	if (!bearer)
 		return -EMSGSIZE;
 
+	len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
+	if (!string_is_valid(lc->name, len))
+		return -EINVAL;
+
 	if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name))
 		return -EMSGSIZE;
 
@@ -717,9 +753,14 @@ static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd,
 	struct tipc_link_config *lc;
 	struct tipc_bearer *bearer;
 	struct tipc_media *media;
+	int len;
 
 	lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
+	len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+	if (!string_is_valid(lc->name, len))
+		return -EINVAL;
+
 	media = tipc_media_find(lc->name);
 	if (media) {
 		cmd->doit = &tipc_nl_media_set;
@@ -741,6 +782,7 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
 {
 	char *name;
 	struct nlattr *link;
+	int len;
 
 	name = (char *)TLV_DATA(msg->req);
 
@@ -748,6 +790,10 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
 	if (!link)
 		return -EMSGSIZE;
 
+	len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+	if (!string_is_valid(name, len))
+		return -EINVAL;
+
 	if (nla_put_string(skb, TIPC_NLA_LINK_NAME, name))
 		return -EMSGSIZE;
 
@@ -769,6 +815,8 @@ static int tipc_nl_compat_name_table_dump_header(struct tipc_nl_compat_msg *msg)
 	};
 
 	ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req);
+	if (TLV_GET_DATA_LEN(msg->req) < sizeof(struct tipc_name_table_query))
+		return -EINVAL;
 
 	depth = ntohl(ntq->depth);
 
@@ -1192,7 +1240,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
 	}
 
 	len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
-	if (len && !TLV_OK(msg.req, len)) {
+	if (!len || !TLV_OK(msg.req, len)) {
 		msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
 		err = -EOPNOTSUPP;
 		goto send;
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index bf7c516..ad3f47a 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -1648,6 +1648,10 @@ static void vmci_transport_cleanup(struct work_struct *work)
 
 static void vmci_transport_destruct(struct vsock_sock *vsk)
 {
+	/* transport can be NULL if we hit a failure at init() time */
+	if (!vmci_trans(vsk))
+		return;
+
 	/* Ensure that the detach callback doesn't use the sk/vsk
 	 * we are about to destruct.
 	 */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3cb2dd9..4cfd76f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4068,6 +4068,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 
 	nl80211_calculate_ap_params(&params);
 
+	if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
+		params.flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
+
 	wdev_lock(wdev);
 	err = rdev_start_ap(rdev, dev, &params);
 	if (!err) {
@@ -12491,7 +12494,9 @@ static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
 	if (!rdev->ops->external_auth)
 		return -EOPNOTSUPP;
 
-	if (!info->attrs[NL80211_ATTR_SSID])
+	if (!info->attrs[NL80211_ATTR_SSID] &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
 		return -EINVAL;
 
 	if (!info->attrs[NL80211_ATTR_BSSID])
@@ -12502,18 +12507,24 @@ static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
 
 	memset(&params, 0, sizeof(params));
 
-	params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
-	if (params.ssid.ssid_len == 0 ||
-	    params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN)
-		return -EINVAL;
-	memcpy(params.ssid.ssid, nla_data(info->attrs[NL80211_ATTR_SSID]),
-	       params.ssid.ssid_len);
+	if (info->attrs[NL80211_ATTR_SSID]) {
+		params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
+		if (params.ssid.ssid_len == 0 ||
+		    params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN)
+			return -EINVAL;
+		memcpy(params.ssid.ssid,
+		       nla_data(info->attrs[NL80211_ATTR_SSID]),
+		       params.ssid.ssid_len);
+	}
 
 	memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
 	       ETH_ALEN);
 
 	params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
 
+	if (info->attrs[NL80211_ATTR_PMKID])
+		params.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
+
 	return rdev_external_auth(rdev, dev, &params);
 }
 
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index c8dad6af..744db13 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -764,7 +764,7 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd)
  * definitions (the "2.4 GHz band", the "5 GHz band" and the "60GHz band"),
  * however it is safe for now to assume that a frequency rule should not be
  * part of a frequency's band if the start freq or end freq are off by more
- * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 10 GHz for the
+ * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 20 GHz for the
  * 60 GHz band.
  * This resolution can be lowered and should be considered as we add
  * regulatory rule support for other "bands".
@@ -779,7 +779,7 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
 	 * with the Channel starting frequency above 45 GHz.
 	 */
 	u32 limit = freq_khz > 45 * ONE_GHZ_IN_KHZ ?
-			10 * ONE_GHZ_IN_KHZ : 2 * ONE_GHZ_IN_KHZ;
+			20 * ONE_GHZ_IN_KHZ : 2 * ONE_GHZ_IN_KHZ;
 	if (abs(freq_khz - freq_range->start_freq_khz) <= limit)
 		return true;
 	if (abs(freq_khz - freq_range->end_freq_khz) <= limit)
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index ac09593..47f6005 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -352,17 +352,15 @@ static unsigned int x25_new_lci(struct x25_neigh *nb)
 	unsigned int lci = 1;
 	struct sock *sk;
 
-	read_lock_bh(&x25_list_lock);
-
-	while ((sk = __x25_find_socket(lci, nb)) != NULL) {
+	while ((sk = x25_find_socket(lci, nb)) != NULL) {
 		sock_put(sk);
 		if (++lci == 4096) {
 			lci = 0;
 			break;
 		}
+		cond_resched();
 	}
 
-	read_unlock_bh(&x25_list_lock);
 	return lci;
 }
 
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 8e75319..06dec32 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -341,6 +341,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 
 		skb->sp->xvec[skb->sp->len++] = x;
 
+		skb_dst_force(skb);
+		if (!skb_dst(skb)) {
+			XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR);
+			goto drop;
+		}
+
 lock:
 		spin_lock(&x->lock);
 
@@ -380,7 +386,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 		XFRM_SKB_CB(skb)->seq.input.low = seq;
 		XFRM_SKB_CB(skb)->seq.input.hi = seq_hi;
 
-		skb_dst_force(skb);
 		dev_hold(skb->dev);
 
 		if (crypto_done)
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index c47660f..b226b23 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -103,6 +103,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
 		skb_dst_force(skb);
 		if (!skb_dst(skb)) {
 			XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR);
+			err = -EHOSTUNREACH;
 			goto error_nolock;
 		}
 
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 6c4ec69..0cd2bdf 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -789,7 +789,7 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
 {
 	spin_lock_bh(&net->xfrm.xfrm_state_lock);
 	si->sadcnt = net->xfrm.state_num;
-	si->sadhcnt = net->xfrm.state_hmask;
+	si->sadhcnt = net->xfrm.state_hmask + 1;
 	si->sadhmcnt = xfrm_state_hashmax;
 	spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 }
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 4e83197..9ff9255 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1445,10 +1445,15 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
 		if (!ut[i].family)
 			ut[i].family = family;
 
-		if ((ut[i].mode == XFRM_MODE_TRANSPORT) &&
-		    (ut[i].family != prev_family))
-			return -EINVAL;
-
+		switch (ut[i].mode) {
+		case XFRM_MODE_TUNNEL:
+		case XFRM_MODE_BEET:
+			break;
+		default:
+			if (ut[i].family != prev_family)
+				return -EINVAL;
+			break;
+		}
 		if (ut[i].mode >= XFRM_MODE_MAX)
 			return -EINVAL;
 
diff --git a/samples/mei/mei-amt-version.c b/samples/mei/mei-amt-version.c
index 57d0d87..bb99889 100644
--- a/samples/mei/mei-amt-version.c
+++ b/samples/mei/mei-amt-version.c
@@ -117,7 +117,7 @@ static bool mei_init(struct mei *me, const uuid_le *guid,
 
 	me->verbose = verbose;
 
-	me->fd = open("/dev/mei", O_RDWR);
+	me->fd = open("/dev/mei0", O_RDWR);
 	if (me->fd == -1) {
 		mei_err(me, "Cannot establish a handle to the Intel MEI driver\n");
 		goto err;
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index d8fec68..6c380a9 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -273,7 +273,7 @@
 sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
 	"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
 	"$(if $(CONFIG_64BIT),64,32)" \
-	"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
+	"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)" \
 	"$(LD)" "$(NM)" "$(RM)" "$(MV)" \
 	"$(if $(part-of-module),1,0)" "$(@)";
 
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 2e879e7..0888e60 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -472,6 +472,7 @@
 
 our $signature_tags = qr{(?xi:
 	Signed-off-by:|
+	Co-developed-by:|
 	Acked-by:|
 	Tested-by:|
 	Reviewed-by:|
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index cb99380..16dc157 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -46,8 +46,8 @@
 	$xs	= "[0-9a-f ]";	# hex character or space
 	$funcre = qr/^$x* <(.*)>:$/;
 	if ($arch eq 'aarch64') {
-		#ffffffc0006325cc:       a9bb7bfd        stp     x29, x30, [sp,#-80]!
-		$re = qr/^.*stp.*sp,\#-([0-9]{1,8})\]\!/o;
+		#ffffffc0006325cc:       a9bb7bfd        stp     x29, x30, [sp, #-80]!
+		$re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o;
 	} elsif ($arch eq 'arm') {
 		#c0008ffc:	e24dd064	sub	sp, sp, #100	; 0x64
 		$re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o;
diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh
index 64220e3..98a7d63 100755
--- a/scripts/decode_stacktrace.sh
+++ b/scripts/decode_stacktrace.sh
@@ -78,7 +78,7 @@
 	fi
 
 	# Strip out the base of the path
-	code=${code//$basepath/""}
+	code=${code//^$basepath/""}
 
 	# In the case of inlines, move everything to same line
 	code=${code//$'\n'/' '}
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index afa0b44..3d1d6fb 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -51,7 +51,7 @@
     line = line.rstrip('\n')
     m = warning_re.match(line)
     if m and m.group(2) not in allowed_warnings:
-        print "error, forbidden warning:", m.group(2)
+        print >> sys.stderr, "error, forbidden warning:", m.group(2)
 
         # If there is a warning, remove any object if it exists.
         if ofile:
@@ -76,17 +76,17 @@
     try:
         proc = subprocess.Popen(args, stderr=subprocess.PIPE)
         for line in proc.stderr:
-            print line,
+            print >> sys.stderr, line,
             interpret_warning(line)
 
         result = proc.wait()
     except OSError as e:
         result = e.errno
         if result == errno.ENOENT:
-            print args[0] + ':',e.strerror
-            print 'Is your PATH set correctly?'
+            print >> sys.stderr, args[0] + ':',e.strerror
+            print >> sys.stderr, 'Is your PATH set correctly?'
         else:
-            print ' '.join(args), str(e)
+            print >> sys.stderr, ' '.join(args), str(e)
 
     return result
 
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index 086d272..0aebd75 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -41,7 +41,7 @@
 
     def invoke(self, arg, from_tty):
         # linux_banner should contain a newline
-        gdb.write(gdb.parse_and_eval("linux_banner").string())
+        gdb.write(gdb.parse_and_eval("(char *)linux_banner").string())
 
 LxVersion()
 
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 9ee9bf7..1dd24c5 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -221,6 +221,7 @@ static int symbol_valid(struct sym_entry *s)
 
 	static char *special_prefixes[] = {
 		"__crc_",		/* modversions */
+		"__efistub_",		/* arm64 EFI stub namespace */
 		NULL };
 
 	static char *special_suffixes[] = {
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
index c410d25..0c78001 100644
--- a/scripts/kconfig/zconf.l
+++ b/scripts/kconfig/zconf.l
@@ -71,7 +71,7 @@
 {
 	fprintf(stderr,
 	        "%s:%d:warning: ignoring unsupported character '%c'\n",
-	        zconf_curname(), zconf_lineno(), chr);
+	        current_file->name, yylineno, chr);
 }
 %}
 
@@ -191,6 +191,8 @@
 	}
 	<<EOF>>	{
 		BEGIN(INITIAL);
+		yylval.string = text;
+		return T_WORD_QUOTE;
 	}
 }
 
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 957f604..e36a673 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1215,6 +1215,30 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
 	return 1;
 }
 
+static inline int is_arm_mapping_symbol(const char *str)
+{
+	return str[0] == '$' && strchr("axtd", str[1])
+	       && (str[2] == '\0' || str[2] == '.');
+}
+
+/*
+ * If there's no name there, ignore it; likewise, ignore it if it's
+ * one of the magic symbols emitted used by current ARM tools.
+ *
+ * Otherwise if find_symbols_between() returns those symbols, they'll
+ * fail the whitelist tests and cause lots of false alarms ... fixable
+ * only by merging __exit and __init sections into __text, bloating
+ * the kernel (which is especially evil on embedded platforms).
+ */
+static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
+{
+	const char *name = elf->strtab + sym->st_name;
+
+	if (!name || !strlen(name))
+		return 0;
+	return !is_arm_mapping_symbol(name);
+}
+
 /**
  * Find symbol based on relocation record info.
  * In some cases the symbol supplied is a valid symbol so
@@ -1240,6 +1264,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
 			continue;
 		if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
 			continue;
+		if (!is_valid_name(elf, sym))
+			continue;
 		if (sym->st_value == addr)
 			return sym;
 		/* Find a symbol nearby - addr are maybe negative */
@@ -1258,30 +1284,6 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
 		return NULL;
 }
 
-static inline int is_arm_mapping_symbol(const char *str)
-{
-	return str[0] == '$' && strchr("axtd", str[1])
-	       && (str[2] == '\0' || str[2] == '.');
-}
-
-/*
- * If there's no name there, ignore it; likewise, ignore it if it's
- * one of the magic symbols emitted used by current ARM tools.
- *
- * Otherwise if find_symbols_between() returns those symbols, they'll
- * fail the whitelist tests and cause lots of false alarms ... fixable
- * only by merging __exit and __init sections into __text, bloating
- * the kernel (which is especially evil on embedded platforms).
- */
-static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
-{
-	const char *name = elf->strtab + sym->st_name;
-
-	if (!name || !strlen(name))
-		return 0;
-	return !is_arm_mapping_symbol(name);
-}
-
 /*
  * Find symbols before or equal addr and after addr - in the section sec.
  * If we find two symbols with equal offset prefer one with a valid name.
@@ -2168,7 +2170,7 @@ static void add_intree_flag(struct buffer *b, int is_intree)
 /* Cannot check for assembler */
 static void add_retpoline(struct buffer *b)
 {
-	buf_printf(b, "\n#ifdef RETPOLINE\n");
+	buf_printf(b, "\n#ifdef CONFIG_RETPOLINE\n");
 	buf_printf(b, "MODULE_INFO(retpoline, \"Y\");\n");
 	buf_printf(b, "#endif\n");
 }
diff --git a/security/keys/key.c b/security/keys/key.c
index 83bf4b4..87172f9 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -265,8 +265,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
 
 		spin_lock(&user->lock);
 		if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
-			if (user->qnkeys + 1 >= maxkeys ||
-			    user->qnbytes + quotalen >= maxbytes ||
+			if (user->qnkeys + 1 > maxkeys ||
+			    user->qnbytes + quotalen > maxbytes ||
 			    user->qnbytes + quotalen < user->qnbytes)
 				goto no_quota;
 		}
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 36f842e..359b9cb 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -661,9 +661,6 @@ static bool search_nested_keyrings(struct key *keyring,
 	BUG_ON((ctx->flags & STATE_CHECKS) == 0 ||
 	       (ctx->flags & STATE_CHECKS) == STATE_CHECKS);
 
-	if (ctx->index_key.description)
-		ctx->index_key.desc_len = strlen(ctx->index_key.description);
-
 	/* Check to see if this top-level keyring is what we are looking for
 	 * and whether it is valid or not.
 	 */
@@ -921,6 +918,7 @@ key_ref_t keyring_search(key_ref_t keyring,
 	struct keyring_search_context ctx = {
 		.index_key.type		= type,
 		.index_key.description	= description,
+		.index_key.desc_len	= strlen(description),
 		.cred			= current_cred(),
 		.match_data.cmp		= key_default_cmp,
 		.match_data.raw_data	= description,
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 6d1fcbb..0ee9a36 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -188,8 +188,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
 	int rc;
 
 	struct keyring_search_context ctx = {
-		.index_key.type		= key->type,
-		.index_key.description	= key->description,
+		.index_key		= key->index_key,
 		.cred			= m->file->f_cred,
 		.match_data.cmp		= lookup_user_key_possessed,
 		.match_data.raw_data	= key,
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 7dc7413..c707fdb 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -545,6 +545,7 @@ struct key *request_key_and_link(struct key_type *type,
 	struct keyring_search_context ctx = {
 		.index_key.type		= type,
 		.index_key.description	= description,
+		.index_key.desc_len	= strlen(description),
 		.cred			= current_cred(),
 		.match_data.cmp		= key_default_cmp,
 		.match_data.raw_data	= description,
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 424e1d9..6797843 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -246,7 +246,7 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
 	struct key *authkey;
 	key_ref_t authkey_ref;
 
-	sprintf(description, "%x", target_id);
+	ctx.index_key.desc_len = sprintf(description, "%x", target_id);
 
 	authkey_ref = search_process_keyrings(&ctx);
 
diff --git a/security/security.c b/security/security.c
index 01d0416..be7cbdc 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1003,6 +1003,13 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
 
 void security_cred_free(struct cred *cred)
 {
+	/*
+	 * There is a failure case in prepare_creds() that
+	 * may result in a call here with ->security being NULL.
+	 */
+	if (unlikely(cred->security == NULL))
+		return;
+
 	call_void_hook(cred_free, cred);
 }
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index dd9ca3b..db5c663 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2837,7 +2837,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
 		return rc;
 
 	/* Allow all mounts performed by the kernel */
-	if (flags & MS_KERNMOUNT)
+	if (flags & (MS_KERNMOUNT | MS_SUBMOUNT))
 		return 0;
 
 	ad.type = LSM_AUDIT_DATA_DENTRY;
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 6688ac5..524068d 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -730,7 +730,8 @@ static int sens_destroy(void *key, void *datum, void *p)
 	kfree(key);
 	if (datum) {
 		levdatum = datum;
-		ebitmap_destroy(&levdatum->level->cat);
+		if (levdatum->level)
+			ebitmap_destroy(&levdatum->level->cat);
 		kfree(levdatum->level);
 	}
 	kfree(datum);
@@ -2107,6 +2108,7 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
 {
 	int i, j, rc;
 	u32 nel, len;
+	__be64 prefixbuf[1];
 	__le32 buf[3];
 	struct ocontext *l, *c;
 	u32 nodebuf[8];
@@ -2216,21 +2218,30 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
 					goto out;
 				break;
 			}
-			case OCON_IBPKEY:
-				rc = next_entry(nodebuf, fp, sizeof(u32) * 4);
+			case OCON_IBPKEY: {
+				u32 pkey_lo, pkey_hi;
+
+				rc = next_entry(prefixbuf, fp, sizeof(u64));
 				if (rc)
 					goto out;
 
-				c->u.ibpkey.subnet_prefix = be64_to_cpu(*((__be64 *)nodebuf));
+				/* we need to have subnet_prefix in CPU order */
+				c->u.ibpkey.subnet_prefix = be64_to_cpu(prefixbuf[0]);
 
-				if (nodebuf[2] > 0xffff ||
-				    nodebuf[3] > 0xffff) {
+				rc = next_entry(buf, fp, sizeof(u32) * 2);
+				if (rc)
+					goto out;
+
+				pkey_lo = le32_to_cpu(buf[0]);
+				pkey_hi = le32_to_cpu(buf[1]);
+
+				if (pkey_lo > U16_MAX || pkey_hi > U16_MAX) {
 					rc = -EINVAL;
 					goto out;
 				}
 
-				c->u.ibpkey.low_pkey = le32_to_cpu(nodebuf[2]);
-				c->u.ibpkey.high_pkey = le32_to_cpu(nodebuf[3]);
+				c->u.ibpkey.low_pkey  = pkey_lo;
+				c->u.ibpkey.high_pkey = pkey_hi;
 
 				rc = context_read_and_validate(&c->context[0],
 							       p,
@@ -2238,7 +2249,10 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
 				if (rc)
 					goto out;
 				break;
-			case OCON_IBENDPORT:
+			}
+			case OCON_IBENDPORT: {
+				u32 port;
+
 				rc = next_entry(buf, fp, sizeof(u32) * 2);
 				if (rc)
 					goto out;
@@ -2248,12 +2262,13 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
 				if (rc)
 					goto out;
 
-				if (buf[1] > 0xff || buf[1] == 0) {
+				port = le32_to_cpu(buf[1]);
+				if (port > U8_MAX || port == 0) {
 					rc = -EINVAL;
 					goto out;
 				}
 
-				c->u.ibendport.port = le32_to_cpu(buf[1]);
+				c->u.ibendport.port = port;
 
 				rc = context_read_and_validate(&c->context[0],
 							       p,
@@ -2261,7 +2276,8 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
 				if (rc)
 					goto out;
 				break;
-			}
+			} /* end case */
+			} /* end switch */
 		}
 	}
 	rc = 0;
@@ -3104,6 +3120,7 @@ static int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
 {
 	unsigned int i, j, rc;
 	size_t nel, len;
+	__be64 prefixbuf[1];
 	__le32 buf[3];
 	u32 nodebuf[8];
 	struct ocontext *c;
@@ -3191,12 +3208,17 @@ static int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
 					return rc;
 				break;
 			case OCON_IBPKEY:
-				*((__be64 *)nodebuf) = cpu_to_be64(c->u.ibpkey.subnet_prefix);
+				/* subnet_prefix is in CPU order */
+				prefixbuf[0] = cpu_to_be64(c->u.ibpkey.subnet_prefix);
 
-				nodebuf[2] = cpu_to_le32(c->u.ibpkey.low_pkey);
-				nodebuf[3] = cpu_to_le32(c->u.ibpkey.high_pkey);
+				rc = put_entry(prefixbuf, sizeof(u64), 1, fp);
+				if (rc)
+					return rc;
 
-				rc = put_entry(nodebuf, sizeof(u32), 4, fp);
+				buf[0] = cpu_to_le32(c->u.ibpkey.low_pkey);
+				buf[1] = cpu_to_le32(c->u.ibpkey.high_pkey);
+
+				rc = put_entry(buf, sizeof(u32), 2, fp);
 				if (rc)
 					return rc;
 				rc = context_write(p, &c->context[0], fp);
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index c8fd5c1..0d5ce71 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4356,6 +4356,12 @@ static int smack_key_permission(key_ref_t key_ref,
 	int request = 0;
 	int rc;
 
+	/*
+	 * Validate requested permissions
+	 */
+	if (perm & ~KEY_NEED_ALL)
+		return -EINVAL;
+
 	keyp = key_ref_to_ptr(key_ref);
 	if (keyp == NULL)
 		return -EINVAL;
@@ -4375,10 +4381,10 @@ static int smack_key_permission(key_ref_t key_ref,
 	ad.a.u.key_struct.key = keyp->serial;
 	ad.a.u.key_struct.key_desc = keyp->description;
 #endif
-	if (perm & KEY_NEED_READ)
-		request = MAY_READ;
+	if (perm & (KEY_NEED_READ | KEY_NEED_SEARCH | KEY_NEED_VIEW))
+		request |= MAY_READ;
 	if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR))
-		request = MAY_WRITE;
+		request |= MAY_WRITE;
 	rc = smk_access(tkp, keyp->security, request, &ad);
 	rc = smk_bu_note("key access", tkp, keyp->security, request, rc);
 	return rc;
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index 8298e09..7d5541c 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -373,7 +373,9 @@ static int yama_ptrace_access_check(struct task_struct *child,
 			break;
 		case YAMA_SCOPE_RELATIONAL:
 			rcu_read_lock();
-			if (!task_is_descendant(current, child) &&
+			if (!pid_alive(child))
+				rc = -EPERM;
+			if (!rc && !task_is_descendant(current, child) &&
 			    !ptracer_exception_found(current, child) &&
 			    !ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
 				rc = -EPERM;
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index add1f8d..31ea168 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -532,7 +532,8 @@ static int snd_compress_check_input(struct snd_compr_params *params)
 {
 	/* first let's check the buffer parameter's */
 	if (params->buffer.fragment_size == 0 ||
-	    params->buffer.fragments > U32_MAX / params->buffer.fragment_size)
+	    params->buffer.fragments > U32_MAX / params->buffer.fragment_size ||
+	    params->buffer.fragments == 0)
 		return -EINVAL;
 
 	/* now codec parameters */
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index 529d9f4..0cb65d0 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -41,6 +41,7 @@
 	   * Mackie(Loud) U.420/U.420d
 	   * TASCAM FireOne
 	   * Stanton Controllers & Systems 1 Deck/Mixer
+	   * APOGEE duet FireWire
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-oxfw.
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c
index 9367635..de4af8a 100644
--- a/sound/firewire/bebob/bebob.c
+++ b/sound/firewire/bebob/bebob.c
@@ -434,7 +434,7 @@ static const struct ieee1394_device_id bebob_id_table[] = {
 	/* Apogee Electronics, DA/AD/DD-16X (X-FireWire card) */
 	SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00010048, &spec_normal),
 	/* Apogee Electronics, Ensemble */
-	SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00001eee, &spec_normal),
+	SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x01eeee, &spec_normal),
 	/* ESI, Quatafire610 */
 	SND_BEBOB_DEV_ENTRY(VEN_ESI, 0x00010064, &spec_normal),
 	/* AcousticReality, eARMasterOne */
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c
index a315d5b6..1554dc9 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -20,6 +20,7 @@
 #define VENDOR_LACIE		0x00d04b
 #define VENDOR_TASCAM		0x00022e
 #define OUI_STANTON		0x001260
+#define OUI_APOGEE		0x0003db
 
 #define MODEL_SATELLITE		0x00200f
 
@@ -442,6 +443,13 @@ static const struct ieee1394_device_id oxfw_id_table[] = {
 		.vendor_id	= OUI_STANTON,
 		.model_id	= 0x002000,
 	},
+	// APOGEE, duet FireWire
+	{
+		.match_flags	= IEEE1394_MATCH_VENDOR_ID |
+				  IEEE1394_MATCH_MODEL_ID,
+		.vendor_id	= OUI_APOGEE,
+		.model_id	= 0x01dddd,
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(ieee1394, oxfw_id_table);
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index aa61615..f03bbd0 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -900,6 +900,9 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
 	struct dsp_spos_instance * ins = chip->dsp_spos_instance;
 	int i;
 
+	if (!ins)
+		return 0;
+
 	snd_info_free_entry(ins->proc_sym_info_entry);
 	ins->proc_sym_info_entry = NULL;
 
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
index d361bb7..8db1890 100644
--- a/sound/pci/hda/hda_bind.c
+++ b/sound/pci/hda/hda_bind.c
@@ -109,7 +109,8 @@ static int hda_codec_driver_probe(struct device *dev)
 	err = snd_hda_codec_build_controls(codec);
 	if (err < 0)
 		goto error_module;
-	if (codec->card->registered) {
+	/* only register after the bus probe finished; otherwise it's racy */
+	if (!codec->bus->bus_probing && codec->card->registered) {
 		err = snd_card_register(codec->card);
 		if (err < 0)
 			goto error_module;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 681c360..3812238 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -68,6 +68,7 @@ struct hda_bus {
 	unsigned int response_reset:1;	/* controller was reset */
 	unsigned int in_reset:1;	/* during reset operation */
 	unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
+	unsigned int bus_probing :1;	/* during probing process */
 
 	int primary_dig_out_type;	/* primary digital out PCM type */
 	unsigned int mixer_assigned;	/* codec addr for mixer name */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d8e80b6..afa591c 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2236,6 +2236,7 @@ static int azx_probe_continue(struct azx *chip)
 	int val;
 	int err;
 
+	to_hda_bus(bus)->bus_probing = 1;
 	hda->probe_continued = 1;
 
 	/* bind with i915 if needed */
@@ -2341,6 +2342,7 @@ static int azx_probe_continue(struct azx *chip)
 	if (err < 0)
 		hda->init_failed = 1;
 	complete_all(&hda->probe_wait);
+	to_hda_bus(bus)->bus_probing = 0;
 	return err;
 }
 
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 0a225dc..d14516f 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -962,6 +962,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
 	SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK),
 	SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK),
 	SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK),
+	SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
 	SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
 	SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
 	SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
@@ -969,6 +970,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
 	SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO),
 	SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO),
 	SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
+	SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
 	SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 31c91e0..972fd95 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -118,6 +118,7 @@ struct alc_spec {
 	int codec_variant;	/* flag for other variants */
 	unsigned int has_alc5505_dsp:1;
 	unsigned int no_depop_delay:1;
+	unsigned int done_hp_init:1;
 
 	/* for PLL fix */
 	hda_nid_t pll_nid;
@@ -3213,6 +3214,48 @@ static void alc_default_shutup(struct hda_codec *codec)
 	snd_hda_shutup_pins(codec);
 }
 
+static void alc294_hp_init(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+	int i, val;
+
+	if (!hp_pin)
+		return;
+
+	snd_hda_codec_write(codec, hp_pin, 0,
+			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+
+	msleep(100);
+
+	snd_hda_codec_write(codec, hp_pin, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+
+	alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
+	alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
+
+	/* Wait for depop procedure finish  */
+	val = alc_read_coefex_idx(codec, 0x58, 0x01);
+	for (i = 0; i < 20 && val & 0x0080; i++) {
+		msleep(50);
+		val = alc_read_coefex_idx(codec, 0x58, 0x01);
+	}
+	/* Set HP depop to auto mode */
+	alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
+	msleep(50);
+}
+
+static void alc294_init(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	if (!spec->done_hp_init) {
+		alc294_hp_init(codec);
+		spec->done_hp_init = true;
+	}
+	alc_default_init(codec);
+}
+
 static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
 			     unsigned int val)
 {
@@ -4005,6 +4048,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
 	case 0x10ec0225:
 	case 0x10ec0295:
 	case 0x10ec0299:
+		alc_process_coef_fw(codec, alc225_pre_hsmode);
 		alc_process_coef_fw(codec, coef0225);
 		break;
 	case 0x10ec0867:
@@ -5252,6 +5296,13 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec,
 	spec->gen.preferred_dacs = preferred_pairs;
 }
 
+static void alc_fixup_disable_mic_vref(struct hda_codec *codec,
+				  const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_PRE_PROBE)
+		snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
+}
+
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
@@ -5361,6 +5412,7 @@ enum {
 	ALC293_FIXUP_LENOVO_SPK_NOISE,
 	ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
 	ALC255_FIXUP_DELL_SPK_NOISE,
+	ALC225_FIXUP_DISABLE_MIC_VREF,
 	ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
 	ALC295_FIXUP_DISABLE_DAC3,
 	ALC280_FIXUP_HP_HEADSET_MIC,
@@ -6062,6 +6114,12 @@ static const struct hda_fixup alc269_fixups[] = {
 		.chained = true,
 		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
 	},
+	[ALC225_FIXUP_DISABLE_MIC_VREF] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc_fixup_disable_mic_vref,
+		.chained = true,
+		.chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
+	},
 	[ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = {
 		.type = HDA_FIXUP_VERBS,
 		.v.verbs = (const struct hda_verb[]) {
@@ -6071,7 +6129,7 @@ static const struct hda_fixup alc269_fixups[] = {
 			{}
 		},
 		.chained = true,
-		.chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
+		.chain_id = ALC225_FIXUP_DISABLE_MIC_VREF
 	},
 	[ALC280_FIXUP_HP_HEADSET_MIC] = {
 		.type = HDA_FIXUP_FUNC,
@@ -6311,6 +6369,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
 	SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
 	SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB),
+	SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
 	SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -6965,37 +7024,6 @@ static void alc269_fill_coef(struct hda_codec *codec)
 	alc_update_coef_idx(codec, 0x4, 0, 1<<11);
 }
 
-static void alc294_hp_init(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
-	int i, val;
-
-	if (!hp_pin)
-		return;
-
-	snd_hda_codec_write(codec, hp_pin, 0,
-			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
-	msleep(100);
-
-	snd_hda_codec_write(codec, hp_pin, 0,
-			    AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
-	alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
-	alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
-
-	/* Wait for depop procedure finish  */
-	val = alc_read_coefex_idx(codec, 0x58, 0x01);
-	for (i = 0; i < 20 && val & 0x0080; i++) {
-		msleep(50);
-		val = alc_read_coefex_idx(codec, 0x58, 0x01);
-	}
-	/* Set HP depop to auto mode */
-	alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
-	msleep(50);
-}
-
 /*
  */
 static int patch_alc269(struct hda_codec *codec)
@@ -7132,7 +7160,7 @@ static int patch_alc269(struct hda_codec *codec)
 		spec->codec_variant = ALC269_TYPE_ALC294;
 		spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */
 		alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */
-		alc294_hp_init(codec);
+		spec->init_hook = alc294_init;
 		break;
 	case 0x10ec0300:
 		spec->codec_variant = ALC269_TYPE_ALC300;
@@ -7144,7 +7172,7 @@ static int patch_alc269(struct hda_codec *codec)
 		spec->codec_variant = ALC269_TYPE_ALC700;
 		spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
 		alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */
-		alc294_hp_init(codec);
+		spec->init_hook = alc294_init;
 		break;
 
 	}
diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c
index 8f92e5c..cd048df 100644
--- a/sound/soc/codecs/rt274.c
+++ b/sound/soc/codecs/rt274.c
@@ -1128,8 +1128,11 @@ static int rt274_i2c_probe(struct i2c_client *i2c,
 		return ret;
 	}
 
-	regmap_read(rt274->regmap,
+	ret = regmap_read(rt274->regmap,
 		RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
+	if (ret)
+		return ret;
+
 	if (val != RT274_VENDOR_ID) {
 		dev_err(&i2c->dev,
 			"Device with ID register %#x is not rt274\n", val);
diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c
index 12f2ecf..662afc5 100644
--- a/sound/soc/codecs/rt5514-spi.c
+++ b/sound/soc/codecs/rt5514-spi.c
@@ -265,6 +265,8 @@ static int rt5514_spi_pcm_probe(struct snd_soc_platform *platform)
 
 	rt5514_dsp = devm_kzalloc(platform->dev, sizeof(*rt5514_dsp),
 			GFP_KERNEL);
+	if (!rt5514_dsp)
+		return -ENOMEM;
 
 	rt5514_dsp->dev = &rt5514_spi->dev;
 	mutex_init(&rt5514_dsp->dma_lock);
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 37f9b62..4087dee 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -221,7 +221,7 @@
 
 config SND_SOC_EUKREA_TLV320
 	tristate "Eukrea TLV320"
-	depends on ARCH_MXC && I2C
+	depends on ARCH_MXC && !ARM64 && I2C
 	select SND_SOC_TLV320AIC23_I2C
 	select SND_SOC_IMX_AUDMUX
 	select SND_SOC_IMX_SSI
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index 392d5eef..99e07b0 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -86,49 +86,49 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
 	if (!buf)
 		return -ENOMEM;
 
-	ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
+	ret = scnprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
 		       pdcr, ptcr);
 
 	if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
-		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 				"TxFS output from %s, ",
 				audmux_port_string((ptcr >> 27) & 0x7));
 	else
-		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 				"TxFS input, ");
 
 	if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR)
-		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 				"TxClk output from %s",
 				audmux_port_string((ptcr >> 22) & 0x7));
 	else
-		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 				"TxClk input");
 
-	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+	ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
 
 	if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) {
-		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 				"Port is symmetric");
 	} else {
 		if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR)
-			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 					"RxFS output from %s, ",
 					audmux_port_string((ptcr >> 17) & 0x7));
 		else
-			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 					"RxFS input, ");
 
 		if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR)
-			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 					"RxClk output from %s",
 					audmux_port_string((ptcr >> 12) & 0x7));
 		else
-			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 					"RxClk input");
 	}
 
-	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+	ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 			"\nData received from %s\n",
 			audmux_port_string((pdcr >> 13) & 0x7));
 
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 43e7fdd..4558c8b 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -399,7 +399,13 @@ static int sst_media_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params,
 				struct snd_soc_dai *dai)
 {
-	snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+	int ret;
+
+	ret =
+		snd_pcm_lib_malloc_pages(substream,
+				params_buffer_bytes(params));
+	if (ret)
+		return ret;
 	memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
 	return 0;
 }
diff --git a/sound/soc/intel/atom/sst/sst_loader.c b/sound/soc/intel/atom/sst/sst_loader.c
index 3391714..054b1d5 100644
--- a/sound/soc/intel/atom/sst/sst_loader.c
+++ b/sound/soc/intel/atom/sst/sst_loader.c
@@ -354,14 +354,14 @@ static int sst_request_fw(struct intel_sst_drv *sst)
 	const struct firmware *fw;
 
 	retval = request_firmware(&fw, sst->firmware_name, sst->dev);
-	if (fw == NULL) {
-		dev_err(sst->dev, "fw is returning as null\n");
-		return -EINVAL;
-	}
 	if (retval) {
 		dev_err(sst->dev, "request fw failed %d\n", retval);
 		return retval;
 	}
+	if (fw == NULL) {
+		dev_err(sst->dev, "fw is returning as null\n");
+		return -EINVAL;
+	}
 	mutex_lock(&sst->sst_lock);
 	retval = sst_cache_and_parse_fw(sst, fw);
 	mutex_unlock(&sst->sst_lock);
diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c
index 6dcbbce..88c26ab 100644
--- a/sound/soc/intel/boards/broadwell.c
+++ b/sound/soc/intel/boards/broadwell.c
@@ -191,7 +191,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
 		.stream_name = "Loopback",
 		.cpu_dai_name = "Loopback Pin",
 		.platform_name = "haswell-pcm-audio",
-		.dynamic = 0,
+		.dynamic = 1,
 		.codec_name = "snd-soc-dummy",
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c
index 5e1ea03..8158409 100644
--- a/sound/soc/intel/boards/haswell.c
+++ b/sound/soc/intel/boards/haswell.c
@@ -145,7 +145,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = {
 		.stream_name = "Loopback",
 		.cpu_dai_name = "Loopback Pin",
 		.platform_name = "haswell-pcm-audio",
-		.dynamic = 0,
+		.dynamic = 1,
 		.codec_name = "snd-soc-dummy",
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 6799980..f9835bc 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2026,19 +2026,19 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
 		out = is_connected_output_ep(w, NULL, NULL);
 	}
 
-	ret = snprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
+	ret = scnprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
 		       w->name, w->power ? "On" : "Off",
 		       w->force ? " (forced)" : "", in, out);
 
 	if (w->reg >= 0)
-		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 				" - R%d(0x%x) mask 0x%x",
 				w->reg, w->reg, w->mask << w->shift);
 
-	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+	ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
 
 	if (w->sname)
-		ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
+		ret += scnprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
 				w->sname,
 				w->active ? "active" : "inactive");
 
@@ -2051,7 +2051,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
 			if (!p->connect)
 				continue;
 
-			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
 					" %s  \"%s\" \"%s\"\n",
 					(rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out",
 					p->name ? p->name : "static",
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index ff8848c..45b3102 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -2142,7 +2142,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
 				char *name)
 {
 	struct uac_processing_unit_descriptor *desc = raw_desc;
-	int num_ins = desc->bNrInPins;
+	int num_ins;
 	struct usb_mixer_elem_info *cval;
 	struct snd_kcontrol *kctl;
 	int i, err, nameid, type, len;
@@ -2157,7 +2157,13 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
 		0, NULL, default_value_info
 	};
 
-	if (desc->bLength < 13 || desc->bLength < 13 + num_ins ||
+	if (desc->bLength < 13) {
+		usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
+		return -EINVAL;
+	}
+
+	num_ins = desc->bNrInPins;
+	if (desc->bLength < 13 + num_ins ||
 	    desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) {
 		usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
 		return -EINVAL;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index f97f309..0bce936 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -376,6 +376,9 @@ static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
 	return 0;
 }
 
+/* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
+ * applies. Returns 1 if a quirk was found.
+ */
 static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 					 struct usb_device *dev,
 					 struct usb_interface_descriptor *altsd,
@@ -454,7 +457,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 
 	subs->data_endpoint->sync_master = subs->sync_endpoint;
 
-	return 0;
+	return 1;
 }
 
 static int set_sync_endpoint(struct snd_usb_substream *subs,
@@ -493,6 +496,10 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 	if (err < 0)
 		return err;
 
+	/* endpoint set by quirk */
+	if (err > 0)
+		return 0;
+
 	if (altsd->bNumEndpoints < 2)
 		return 0;
 
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 15cbe25..d32727c 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3321,6 +3321,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
 					}
 				}
 			},
+			{
+				.ifnum = -1
+			},
 		}
 	}
 },
diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c
index 64e403e..f629a1f 100644
--- a/sound/usb/usb_audio_qmi_svc.c
+++ b/sound/usb/usb_audio_qmi_svc.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
@@ -1229,13 +1229,13 @@ static void uaudio_qmi_bye_cb(struct qmi_handle *handle, unsigned int node)
 {
 	struct uaudio_qmi_svc *svc = uaudio_svc;
 
-	uaudio_dbg("node:\n", node);
 	if (svc->uaudio_svc_hdl != handle) {
 		uaudio_err("handle mismatch\n");
 		return;
 	}
 
 	if (svc->client_connected && svc->client_sq.sq_node == node) {
+		uaudio_dbg("node:\n", node);
 		queue_work(svc->uaudio_wq, &svc->qmi_disconnect_work);
 		svc->client_sq.sq_node = 0;
 		svc->client_sq.sq_port = 0;
@@ -1249,7 +1249,6 @@ static void uaudio_qmi_svc_disconnect_cb(struct qmi_handle *handle,
 {
 	struct uaudio_qmi_svc *svc = uaudio_svc;
 
-	uaudio_dbg("client node:%x port:%x\n", node, port);
 	if (svc->uaudio_svc_hdl != handle) {
 		uaudio_err("handle mismatch\n");
 		return;
@@ -1257,6 +1256,7 @@ static void uaudio_qmi_svc_disconnect_cb(struct qmi_handle *handle,
 
 	if (svc->client_connected && svc->client_sq.sq_node == node &&
 			svc->client_sq.sq_port == port) {
+		uaudio_dbg("client node:%x port:%x\n", node, port);
 		queue_work(svc->uaudio_wq, &svc->qmi_disconnect_work);
 		svc->client_sq.sq_node = 0;
 		svc->client_sq.sq_port = 0;
diff --git a/tools/cgroup/Makefile b/tools/cgroup/Makefile
index 860fa15..ffca068 100644
--- a/tools/cgroup/Makefile
+++ b/tools/cgroup/Makefile
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for cgroup tools
 
-CC = $(CROSS_COMPILE)gcc
 CFLAGS = -Wall -Wextra
 
 all: cgroup_event_listener
diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile
index 805a2c0..240eda0 100644
--- a/tools/gpio/Makefile
+++ b/tools/gpio/Makefile
@@ -12,8 +12,6 @@
 # (this improves performance and avoids hard-to-debug behaviour);
 MAKEFLAGS += -r
 
-CC = $(CROSS_COMPILE)gcc
-LD = $(CROSS_COMPILE)ld
 CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
 
 ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon
diff --git a/tools/hv/Makefile b/tools/hv/Makefile
index 3150381..68c2d7b 100644
--- a/tools/hv/Makefile
+++ b/tools/hv/Makefile
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for Hyper-V tools
 
-CC = $(CROSS_COMPILE)gcc
 WARNINGS = -Wall -Wextra
 CFLAGS = $(WARNINGS) -g $(shell getconf LFS_CFLAGS)
 
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 3965186..62c9a50 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -1172,6 +1172,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
 	FILE *file;
 	char cmd[PATH_MAX];
 	char *mac_addr;
+	int str_len;
 
 	/*
 	 * Set the configuration for the specified interface with
@@ -1295,8 +1296,18 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
 	 * invoke the external script to do its magic.
 	 */
 
-	snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s",
-		 "hv_set_ifconfig", if_file);
+	str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s",
+			   "hv_set_ifconfig", if_file);
+	/*
+	 * This is a little overcautious, but it's necessary to suppress some
+	 * false warnings from gcc 8.0.1.
+	 */
+	if (str_len <= 0 || (unsigned int)str_len >= sizeof(cmd)) {
+		syslog(LOG_ERR, "Cmd '%s' (len=%d) may be too long",
+		       cmd, str_len);
+		return HV_E_FAIL;
+	}
+
 	if (system(cmd)) {
 		syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s",
 				cmd, errno, strerror(errno));
diff --git a/tools/iio/Makefile b/tools/iio/Makefile
index a08e7a4..332ed2f6 100644
--- a/tools/iio/Makefile
+++ b/tools/iio/Makefile
@@ -12,8 +12,6 @@
 # (this improves performance and avoids hard-to-debug behaviour);
 MAKEFLAGS += -r
 
-CC = $(CROSS_COMPILE)gcc
-LD = $(CROSS_COMPILE)ld
 CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
 
 ALL_TARGETS := iio_event_monitor lsiio iio_generic_buffer
diff --git a/tools/laptop/freefall/Makefile b/tools/laptop/freefall/Makefile
index 5f758c4..b572d94 100644
--- a/tools/laptop/freefall/Makefile
+++ b/tools/laptop/freefall/Makefile
@@ -2,7 +2,6 @@
 PREFIX ?= /usr
 SBINDIR ?= sbin
 INSTALL ?= install
-CC = $(CROSS_COMPILE)gcc
 
 TARGET = freefall
 
diff --git a/tools/leds/Makefile b/tools/leds/Makefile
index c379af0..7b6bed1 100644
--- a/tools/leds/Makefile
+++ b/tools/leds/Makefile
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for LEDs tools
 
-CC = $(CROSS_COMPILE)gcc
 CFLAGS = -Wall -Wextra -g -I../../include/uapi
 
 all: uledmon led_hw_brightness_mon
diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile
index 95563b8..ed61fb3 100644
--- a/tools/lib/subcmd/Makefile
+++ b/tools/lib/subcmd/Makefile
@@ -36,8 +36,6 @@
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 
 CFLAGS += -I$(srctree)/tools/include/
-CFLAGS += -I$(srctree)/include/uapi
-CFLAGS += -I$(srctree)/include
 
 SUBCMD_IN := $(OUTPUT)libsubcmd-in.o
 
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 2a858ea..349ea51 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -144,12 +144,6 @@
     $(eval $(1) = $(2)))
 endef
 
-# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
-$(call allow-override,CC,$(CROSS_COMPILE)gcc)
-$(call allow-override,AR,$(CROSS_COMPILE)ar)
-$(call allow-override,LD,$(CROSS_COMPILE)ld)
-$(call allow-override,CXX,$(CROSS_COMPILE)g++)
-
 LD += $(EXTRA_LDFLAGS)
 
 HOSTCC  ?= gcc
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index db0ba8c..ba8ecaf 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -524,10 +524,21 @@ static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu,
 				    struct perf_evsel *evsel)
 {
 	int err;
+	char c;
 
 	if (!evsel)
 		return 0;
 
+	/*
+	 * If supported, force pass-through config term (pt=1) even if user
+	 * sets pt=0, which avoids senseless kernel errors.
+	 */
+	if (perf_pmu__scan_file(intel_pt_pmu, "format/pt", "%c", &c) == 1 &&
+	    !(evsel->attr.config & 1)) {
+		pr_warning("pt=0 doesn't make sense, forcing pt=1\n");
+		evsel->attr.config |= 1;
+	}
+
 	err = intel_pt_val_config_term(intel_pt_pmu, "caps/cycle_thresholds",
 				       "cyc_thresh", "caps/psb_cyc",
 				       evsel->attr.config);
diff --git a/tools/perf/arch/x86/util/kvm-stat.c b/tools/perf/arch/x86/util/kvm-stat.c
index b32409a..081353d 100644
--- a/tools/perf/arch/x86/util/kvm-stat.c
+++ b/tools/perf/arch/x86/util/kvm-stat.c
@@ -156,7 +156,7 @@ int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)
 	if (strstr(cpuid, "Intel")) {
 		kvm->exit_reasons = vmx_exit_reasons;
 		kvm->exit_reasons_isa = "VMX";
-	} else if (strstr(cpuid, "AMD")) {
+	} else if (strstr(cpuid, "AMD") || strstr(cpuid, "Hygon")) {
 		kvm->exit_reasons = svm_exit_reasons;
 		kvm->exit_reasons_isa = "SVM";
 	} else
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py
index ff9b60b..44090a9 100644
--- a/tools/perf/tests/attr.py
+++ b/tools/perf/tests/attr.py
@@ -116,7 +116,7 @@
             if not self.has_key(t) or not other.has_key(t):
                 continue
             if not data_equal(self[t], other[t]):
-		log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
+                log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
 
 # Test file description needs to have following sections:
 # [config]
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index 31e0b1d..3794066 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -23,7 +23,7 @@
 freq=1
 inherit_stat=0
 enable_on_exec=1
-task=0
+task=1
 watermark=0
 precise_ip=0|1|2|3
 mmap_data=0
diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group
index 6e7961f..618ba1c 100644
--- a/tools/perf/tests/attr/test-record-group
+++ b/tools/perf/tests/attr/test-record-group
@@ -17,5 +17,6 @@
 read_format=4
 mmap=0
 comm=0
+task=0
 enable_on_exec=0
 disabled=0
diff --git a/tools/perf/tests/attr/test-record-group-sampling b/tools/perf/tests/attr/test-record-group-sampling
index ef59afd..f906b79 100644
--- a/tools/perf/tests/attr/test-record-group-sampling
+++ b/tools/perf/tests/attr/test-record-group-sampling
@@ -23,7 +23,7 @@
 
 # PERF_FORMAT_ID | PERF_FORMAT_GROUP
 read_format=12
-
+task=0
 mmap=0
 comm=0
 enable_on_exec=0
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1
index 87a222d..48e8bd1 100644
--- a/tools/perf/tests/attr/test-record-group1
+++ b/tools/perf/tests/attr/test-record-group1
@@ -18,5 +18,6 @@
 read_format=4
 mmap=0
 comm=0
+task=0
 enable_on_exec=0
 disabled=0
diff --git a/tools/perf/tests/attr/test-stat-C0 b/tools/perf/tests/attr/test-stat-C0
index 67717fe..a2c76d1 100644
--- a/tools/perf/tests/attr/test-stat-C0
+++ b/tools/perf/tests/attr/test-stat-C0
@@ -7,3 +7,4 @@
 # events are disabled by default when attached to cpu
 disabled=1
 enable_on_exec=0
+optional=1
diff --git a/tools/perf/tests/attr/test-stat-basic b/tools/perf/tests/attr/test-stat-basic
index 74e1788..69867d0 100644
--- a/tools/perf/tests/attr/test-stat-basic
+++ b/tools/perf/tests/attr/test-stat-basic
@@ -4,3 +4,4 @@
 ret     = 1
 
 [event:base-stat]
+optional=1
diff --git a/tools/perf/tests/attr/test-stat-default b/tools/perf/tests/attr/test-stat-default
index e911dbd..d9e99b3 100644
--- a/tools/perf/tests/attr/test-stat-default
+++ b/tools/perf/tests/attr/test-stat-default
@@ -32,6 +32,7 @@
 fd=5
 type=0
 config=0
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
 [event6:base-stat]
@@ -52,15 +53,18 @@
 fd=8
 type=0
 config=1
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
 [event9:base-stat]
 fd=9
 type=0
 config=4
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
 [event10:base-stat]
 fd=10
 type=0
 config=5
+optional=1
diff --git a/tools/perf/tests/attr/test-stat-detailed-1 b/tools/perf/tests/attr/test-stat-detailed-1
index b39270a..8b04a05 100644
--- a/tools/perf/tests/attr/test-stat-detailed-1
+++ b/tools/perf/tests/attr/test-stat-detailed-1
@@ -33,6 +33,7 @@
 fd=5
 type=0
 config=0
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
 [event6:base-stat]
@@ -53,18 +54,21 @@
 fd=8
 type=0
 config=1
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
 [event9:base-stat]
 fd=9
 type=0
 config=4
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
 [event10:base-stat]
 fd=10
 type=0
 config=5
+optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
@@ -74,6 +78,7 @@
 fd=11
 type=3
 config=0
+optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
@@ -83,6 +88,7 @@
 fd=12
 type=3
 config=65536
+optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
@@ -92,6 +98,7 @@
 fd=13
 type=3
 config=2
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
@@ -101,3 +108,4 @@
 fd=14
 type=3
 config=65538
+optional=1
diff --git a/tools/perf/tests/attr/test-stat-detailed-2 b/tools/perf/tests/attr/test-stat-detailed-2
index 45f8e6e..4fca9f1 100644
--- a/tools/perf/tests/attr/test-stat-detailed-2
+++ b/tools/perf/tests/attr/test-stat-detailed-2
@@ -33,6 +33,7 @@
 fd=5
 type=0
 config=0
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
 [event6:base-stat]
@@ -53,18 +54,21 @@
 fd=8
 type=0
 config=1
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
 [event9:base-stat]
 fd=9
 type=0
 config=4
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
 [event10:base-stat]
 fd=10
 type=0
 config=5
+optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
@@ -74,6 +78,7 @@
 fd=11
 type=3
 config=0
+optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
@@ -83,6 +88,7 @@
 fd=12
 type=3
 config=65536
+optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
@@ -92,6 +98,7 @@
 fd=13
 type=3
 config=2
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
@@ -101,6 +108,7 @@
 fd=14
 type=3
 config=65538
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_L1I                <<  0  |
@@ -120,6 +128,7 @@
 fd=16
 type=3
 config=65537
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_DTLB               <<  0  |
@@ -129,6 +138,7 @@
 fd=17
 type=3
 config=3
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_DTLB               <<  0  |
@@ -138,6 +148,7 @@
 fd=18
 type=3
 config=65539
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_ITLB               <<  0  |
@@ -147,6 +158,7 @@
 fd=19
 type=3
 config=4
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_ITLB               <<  0  |
@@ -156,3 +168,4 @@
 fd=20
 type=3
 config=65540
+optional=1
diff --git a/tools/perf/tests/attr/test-stat-detailed-3 b/tools/perf/tests/attr/test-stat-detailed-3
index 30ae0fb..4bb58e1 100644
--- a/tools/perf/tests/attr/test-stat-detailed-3
+++ b/tools/perf/tests/attr/test-stat-detailed-3
@@ -33,6 +33,7 @@
 fd=5
 type=0
 config=0
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
 [event6:base-stat]
@@ -53,18 +54,21 @@
 fd=8
 type=0
 config=1
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
 [event9:base-stat]
 fd=9
 type=0
 config=4
+optional=1
 
 # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
 [event10:base-stat]
 fd=10
 type=0
 config=5
+optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
@@ -74,6 +78,7 @@
 fd=11
 type=3
 config=0
+optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
@@ -83,6 +88,7 @@
 fd=12
 type=3
 config=65536
+optional=1
 
 # PERF_TYPE_HW_CACHE /
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
@@ -92,6 +98,7 @@
 fd=13
 type=3
 config=2
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_LL                 <<  0  |
@@ -101,6 +108,7 @@
 fd=14
 type=3
 config=65538
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_L1I                <<  0  |
@@ -120,6 +128,7 @@
 fd=16
 type=3
 config=65537
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_DTLB               <<  0  |
@@ -129,6 +138,7 @@
 fd=17
 type=3
 config=3
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_DTLB               <<  0  |
@@ -138,6 +148,7 @@
 fd=18
 type=3
 config=65539
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_ITLB               <<  0  |
@@ -147,6 +158,7 @@
 fd=19
 type=3
 config=4
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_ITLB               <<  0  |
@@ -156,6 +168,7 @@
 fd=20
 type=3
 config=65540
+optional=1
 
 # PERF_TYPE_HW_CACHE,
 #  PERF_COUNT_HW_CACHE_L1D                <<  0  |
diff --git a/tools/perf/tests/attr/test-stat-group b/tools/perf/tests/attr/test-stat-group
index fdc1596..e15d694 100644
--- a/tools/perf/tests/attr/test-stat-group
+++ b/tools/perf/tests/attr/test-stat-group
@@ -6,6 +6,7 @@
 [event-1:base-stat]
 fd=1
 group_fd=-1
+read_format=3|15
 
 [event-2:base-stat]
 fd=2
@@ -13,3 +14,4 @@
 config=1
 disabled=0
 enable_on_exec=0
+read_format=3|15
diff --git a/tools/perf/tests/attr/test-stat-group1 b/tools/perf/tests/attr/test-stat-group1
index 2a1f86e..1746751 100644
--- a/tools/perf/tests/attr/test-stat-group1
+++ b/tools/perf/tests/attr/test-stat-group1
@@ -6,6 +6,7 @@
 [event-1:base-stat]
 fd=1
 group_fd=-1
+read_format=3|15
 
 [event-2:base-stat]
 fd=2
@@ -13,3 +14,4 @@
 config=1
 disabled=0
 enable_on_exec=0
+read_format=3|15
diff --git a/tools/perf/tests/attr/test-stat-no-inherit b/tools/perf/tests/attr/test-stat-no-inherit
index d54b2a1e..924fbb9 100644
--- a/tools/perf/tests/attr/test-stat-no-inherit
+++ b/tools/perf/tests/attr/test-stat-no-inherit
@@ -5,3 +5,4 @@
 
 [event:base-stat]
 inherit=0
+optional=1
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index 699561f..67bcbf8 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -17,7 +17,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
 		return -1;
 	}
 
-	is_signed = !!(field->flags | FIELD_IS_SIGNED);
+	is_signed = !!(field->flags & FIELD_IS_SIGNED);
 	if (should_be_signed && !is_signed) {
 		pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
 			 evsel->name, name, is_signed, should_be_signed);
diff --git a/tools/perf/tests/shell/lib/probe_vfs_getname.sh b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
index 30a950c..068d463 100644
--- a/tools/perf/tests/shell/lib/probe_vfs_getname.sh
+++ b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
@@ -13,7 +13,8 @@
 	local verbose=$1
 	if [ $had_vfs_getname -eq 1 ] ; then
 		line=$(perf probe -L getname_flags 2>&1 | egrep 'result.*=.*filename;' | sed -r 's/[[:space:]]+([[:digit:]]+)[[:space:]]+result->uptr.*/\1/')
-		perf probe $verbose "vfs_getname=getname_flags:${line} pathname=result->name:string"
+		perf probe -q       "vfs_getname=getname_flags:${line} pathname=result->name:string" || \
+		perf probe $verbose "vfs_getname=getname_flags:${line} pathname=filename:string"
 	fi
 }
 
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1ceb332..696f265 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3132,7 +3132,7 @@ perf_event__synthesize_event_update_unit(struct perf_tool *tool,
 	if (ev == NULL)
 		return -ENOMEM;
 
-	strncpy(ev->data, evsel->unit, size);
+	strlcpy(ev->data, evsel->unit, size + 1);
 	err = process(tool, (union perf_event *)ev, NULL, NULL);
 	free(ev);
 	return err;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 53f6204..d0b92d3 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -2300,7 +2300,7 @@ void print_symbol_events(const char *event_glob, unsigned type,
 		if (!name_only && strlen(syms->alias))
 			snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
 		else
-			strncpy(name, syms->symbol, MAX_NAME_LEN);
+			strlcpy(name, syms->symbol, MAX_NAME_LEN);
 
 		evt_list[evt_i] = strdup(name);
 		if (evt_list[evt_i] == NULL)
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index cdf8d83..6ab9230 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -424,7 +424,7 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target,
 
 	if (target && build_id_cache__cached(target)) {
 		/* This is a cached buildid */
-		strncpy(sbuildid, target, SBUILD_ID_SIZE);
+		strlcpy(sbuildid, target, SBUILD_ID_SIZE);
 		dir_name = build_id_cache__linkname(sbuildid, NULL, 0);
 		goto found;
 	}
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 1cbada2..f735ee0 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -334,7 +334,7 @@ static char *cpu_model(void)
 	if (file) {
 		while (fgets(buf, 255, file)) {
 			if (strstr(buf, "model name")) {
-				strncpy(cpu_m, &buf[13], 255);
+				strlcpy(cpu_m, &buf[13], 255);
 				break;
 			}
 		}
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 1e9c974..f1fe5ac 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -44,13 +44,13 @@ static int __report_module(struct addr_location *al, u64 ip,
 		Dwarf_Addr s;
 
 		dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL);
-		if (s != al->map->start)
+		if (s != al->map->start - al->map->pgoff)
 			mod = 0;
 	}
 
 	if (!mod)
 		mod = dwfl_report_elf(ui->dwfl, dso->short_name,
-				      dso->long_name, -1, al->map->start,
+				      (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start - al->map->pgoff,
 				      false);
 
 	return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
diff --git a/tools/power/acpi/Makefile.config b/tools/power/acpi/Makefile.config
index a1883bb..f304be7 100644
--- a/tools/power/acpi/Makefile.config
+++ b/tools/power/acpi/Makefile.config
@@ -56,9 +56,7 @@
 # to compile vs uClibc, that can be done here as well.
 CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc-
 CROSS_COMPILE ?= $(CROSS)
-CC = $(CROSS_COMPILE)gcc
-LD = $(CROSS_COMPILE)gcc
-STRIP = $(CROSS_COMPILE)strip
+LD = $(CC)
 HOSTCC = gcc
 
 # check if compiler option is supported
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 5f3f1f4..71dc7ef 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -42,6 +42,24 @@
 
 CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?)
 
+# Makefiles suck: This macro sets a default value of $(2) for the
+# variable named by $(1), unless the variable has been set by
+# environment or command line. This is necessary for CC and AR
+# because make sets default values, so the simpler ?= approach
+# won't work as expected.
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting various cross-compile vars or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
+$(call allow-override,CXX,$(CROSS_COMPILE)g++)
+$(call allow-override,STRIP,$(CROSS_COMPILE)strip)
+
 ifeq ($(CC_NO_CLANG), 1)
 EXTRA_WARNINGS += -Wstrict-aliasing=3
 endif
diff --git a/tools/spi/Makefile b/tools/spi/Makefile
index 90615e1..815d155 100644
--- a/tools/spi/Makefile
+++ b/tools/spi/Makefile
@@ -11,8 +11,6 @@
 # (this improves performance and avoids hard-to-debug behaviour);
 MAKEFLAGS += -r
 
-CC = $(CROSS_COMPILE)gcc
-LD = $(CROSS_COMPILE)ld
 CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
 
 ALL_TARGETS := spidev_test spidev_fdx
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index e1f75a1..f2a00b0 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -114,7 +114,7 @@ void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res,
 		return nfit_res->buf + offset - nfit_res->res.start;
 	return devm_memremap_pages(dev, res, ref, altmap);
 }
-EXPORT_SYMBOL(__wrap_devm_memremap_pages);
+EXPORT_SYMBOL_GPL(__wrap_devm_memremap_pages);
 
 pfn_t __wrap_phys_to_pfn_t(phys_addr_t addr, unsigned long flags)
 {
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index 11ee25c..1903fb4 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -43,10 +43,10 @@ static struct {
 	struct iphdr iph;
 	struct tcphdr tcp;
 } __packed pkt_v4 = {
-	.eth.h_proto = bpf_htons(ETH_P_IP),
+	.eth.h_proto = __bpf_constant_htons(ETH_P_IP),
 	.iph.ihl = 5,
 	.iph.protocol = 6,
-	.iph.tot_len = bpf_htons(MAGIC_BYTES),
+	.iph.tot_len = __bpf_constant_htons(MAGIC_BYTES),
 	.tcp.urg_ptr = 123,
 };
 
@@ -56,9 +56,9 @@ static struct {
 	struct ipv6hdr iph;
 	struct tcphdr tcp;
 } __packed pkt_v6 = {
-	.eth.h_proto = bpf_htons(ETH_P_IPV6),
+	.eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
 	.iph.nexthdr = 6,
-	.iph.payload_len = bpf_htons(MAGIC_BYTES),
+	.iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
 	.tcp.urg_ptr = 123,
 };
 
diff --git a/tools/testing/selftests/gpio/gpio-mockup-chardev.c b/tools/testing/selftests/gpio/gpio-mockup-chardev.c
index 667e916..6ceeeed 100644
--- a/tools/testing/selftests/gpio/gpio-mockup-chardev.c
+++ b/tools/testing/selftests/gpio/gpio-mockup-chardev.c
@@ -37,7 +37,7 @@ static int get_debugfs(char **path)
 	struct libmnt_table *tb;
 	struct libmnt_iter *itr = NULL;
 	struct libmnt_fs *fs;
-	int found = 0;
+	int found = 0, ret;
 
 	cxt = mnt_new_context();
 	if (!cxt)
@@ -58,8 +58,11 @@ static int get_debugfs(char **path)
 			break;
 		}
 	}
-	if (found)
-		asprintf(path, "%s/gpio", mnt_fs_get_target(fs));
+	if (found) {
+		ret = asprintf(path, "%s/gpio", mnt_fs_get_target(fs));
+		if (ret < 0)
+			err(EXIT_FAILURE, "failed to format string");
+	}
 
 	mnt_free_iter(itr);
 	mnt_free_context(cxt);
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h
index e81bd28..8f32d69 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -330,7 +330,7 @@
  * ASSERT_EQ(expected, measured): expected == measured
  */
 #define ASSERT_EQ(expected, seen) \
-	__EXPECT(expected, seen, ==, 1)
+	__EXPECT(expected, #expected, seen, #seen, ==, 1)
 
 /**
  * ASSERT_NE(expected, seen)
@@ -341,7 +341,7 @@
  * ASSERT_NE(expected, measured): expected != measured
  */
 #define ASSERT_NE(expected, seen) \
-	__EXPECT(expected, seen, !=, 1)
+	__EXPECT(expected, #expected, seen, #seen, !=, 1)
 
 /**
  * ASSERT_LT(expected, seen)
@@ -352,7 +352,7 @@
  * ASSERT_LT(expected, measured): expected < measured
  */
 #define ASSERT_LT(expected, seen) \
-	__EXPECT(expected, seen, <, 1)
+	__EXPECT(expected, #expected, seen, #seen, <, 1)
 
 /**
  * ASSERT_LE(expected, seen)
@@ -363,7 +363,7 @@
  * ASSERT_LE(expected, measured): expected <= measured
  */
 #define ASSERT_LE(expected, seen) \
-	__EXPECT(expected, seen, <=, 1)
+	__EXPECT(expected, #expected, seen, #seen, <=, 1)
 
 /**
  * ASSERT_GT(expected, seen)
@@ -374,7 +374,7 @@
  * ASSERT_GT(expected, measured): expected > measured
  */
 #define ASSERT_GT(expected, seen) \
-	__EXPECT(expected, seen, >, 1)
+	__EXPECT(expected, #expected, seen, #seen, >, 1)
 
 /**
  * ASSERT_GE(expected, seen)
@@ -385,7 +385,7 @@
  * ASSERT_GE(expected, measured): expected >= measured
  */
 #define ASSERT_GE(expected, seen) \
-	__EXPECT(expected, seen, >=, 1)
+	__EXPECT(expected, #expected, seen, #seen, >=, 1)
 
 /**
  * ASSERT_NULL(seen)
@@ -395,7 +395,7 @@
  * ASSERT_NULL(measured): NULL == measured
  */
 #define ASSERT_NULL(seen) \
-	__EXPECT(NULL, seen, ==, 1)
+	__EXPECT(NULL, "NULL", seen, #seen, ==, 1)
 
 /**
  * ASSERT_TRUE(seen)
@@ -405,7 +405,7 @@
  * ASSERT_TRUE(measured): measured != 0
  */
 #define ASSERT_TRUE(seen) \
-	ASSERT_NE(0, seen)
+	__EXPECT(0, "0", seen, #seen, !=, 1)
 
 /**
  * ASSERT_FALSE(seen)
@@ -415,7 +415,7 @@
  * ASSERT_FALSE(measured): measured == 0
  */
 #define ASSERT_FALSE(seen) \
-	ASSERT_EQ(0, seen)
+	__EXPECT(0, "0", seen, #seen, ==, 1)
 
 /**
  * ASSERT_STREQ(expected, seen)
@@ -448,7 +448,7 @@
  * EXPECT_EQ(expected, measured): expected == measured
  */
 #define EXPECT_EQ(expected, seen) \
-	__EXPECT(expected, seen, ==, 0)
+	__EXPECT(expected, #expected, seen, #seen, ==, 0)
 
 /**
  * EXPECT_NE(expected, seen)
@@ -459,7 +459,7 @@
  * EXPECT_NE(expected, measured): expected != measured
  */
 #define EXPECT_NE(expected, seen) \
-	__EXPECT(expected, seen, !=, 0)
+	__EXPECT(expected, #expected, seen, #seen, !=, 0)
 
 /**
  * EXPECT_LT(expected, seen)
@@ -470,7 +470,7 @@
  * EXPECT_LT(expected, measured): expected < measured
  */
 #define EXPECT_LT(expected, seen) \
-	__EXPECT(expected, seen, <, 0)
+	__EXPECT(expected, #expected, seen, #seen, <, 0)
 
 /**
  * EXPECT_LE(expected, seen)
@@ -481,7 +481,7 @@
  * EXPECT_LE(expected, measured): expected <= measured
  */
 #define EXPECT_LE(expected, seen) \
-	__EXPECT(expected, seen, <=, 0)
+	__EXPECT(expected, #expected, seen, #seen, <=, 0)
 
 /**
  * EXPECT_GT(expected, seen)
@@ -492,7 +492,7 @@
  * EXPECT_GT(expected, measured): expected > measured
  */
 #define EXPECT_GT(expected, seen) \
-	__EXPECT(expected, seen, >, 0)
+	__EXPECT(expected, #expected, seen, #seen, >, 0)
 
 /**
  * EXPECT_GE(expected, seen)
@@ -503,7 +503,7 @@
  * EXPECT_GE(expected, measured): expected >= measured
  */
 #define EXPECT_GE(expected, seen) \
-	__EXPECT(expected, seen, >=, 0)
+	__EXPECT(expected, #expected, seen, #seen, >=, 0)
 
 /**
  * EXPECT_NULL(seen)
@@ -513,7 +513,7 @@
  * EXPECT_NULL(measured): NULL == measured
  */
 #define EXPECT_NULL(seen) \
-	__EXPECT(NULL, seen, ==, 0)
+	__EXPECT(NULL, "NULL", seen, #seen, ==, 0)
 
 /**
  * EXPECT_TRUE(seen)
@@ -523,7 +523,7 @@
  * EXPECT_TRUE(measured): 0 != measured
  */
 #define EXPECT_TRUE(seen) \
-	EXPECT_NE(0, seen)
+	__EXPECT(0, "0", seen, #seen, !=, 0)
 
 /**
  * EXPECT_FALSE(seen)
@@ -533,7 +533,7 @@
  * EXPECT_FALSE(measured): 0 == measured
  */
 #define EXPECT_FALSE(seen) \
-	EXPECT_EQ(0, seen)
+	__EXPECT(0, "0", seen, #seen, ==, 0)
 
 /**
  * EXPECT_STREQ(expected, seen)
@@ -573,7 +573,7 @@
 	if (_metadata->passed && _metadata->step < 255) \
 		_metadata->step++;
 
-#define __EXPECT(_expected, _seen, _t, _assert) do { \
+#define __EXPECT(_expected, _expected_str, _seen, _seen_str, _t, _assert) do { \
 	/* Avoid multiple evaluation of the cases */ \
 	__typeof__(_expected) __exp = (_expected); \
 	__typeof__(_seen) __seen = (_seen); \
@@ -582,8 +582,8 @@
 		unsigned long long __exp_print = (uintptr_t)__exp; \
 		unsigned long long __seen_print = (uintptr_t)__seen; \
 		__TH_LOG("Expected %s (%llu) %s %s (%llu)", \
-			 #_expected, __exp_print, #_t, \
-			 #_seen, __seen_print); \
+			 _expected_str, __exp_print, #_t, \
+			 _seen_str, __seen_print); \
 		_metadata->passed = 0; \
 		/* Ensure the optional handler is triggered */ \
 		_metadata->trigger = 1; \
diff --git a/tools/testing/selftests/seccomp/Makefile b/tools/testing/selftests/seccomp/Makefile
index fce7f4c..1760b3e 100644
--- a/tools/testing/selftests/seccomp/Makefile
+++ b/tools/testing/selftests/seccomp/Makefile
@@ -9,7 +9,7 @@
 CFLAGS += -Wl,-no-as-needed -Wall
 
 seccomp_bpf: seccomp_bpf.c ../kselftest_harness.h
-	$(CC) $(CFLAGS) $(LDFLAGS) -lpthread $< -o $@
+	$(CC) $(CFLAGS) $(LDFLAGS) $< -lpthread -o $@
 
 TEST_PROGS += $(BINARIES)
 EXTRA_CLEAN := $(BINARIES)
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index e350cf3..ba15baa 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -145,15 +145,6 @@ struct seccomp_data {
 #define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
 #endif
 
-#ifndef PTRACE_SECCOMP_GET_METADATA
-#define PTRACE_SECCOMP_GET_METADATA	0x420d
-
-struct seccomp_metadata {
-	__u64 filter_off;       /* Input: which filter */
-	__u64 flags;             /* Output: filter's flags */
-};
-#endif
-
 #ifndef seccomp
 int seccomp(unsigned int op, unsigned int flags, void *args)
 {
@@ -1563,7 +1554,16 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 #ifdef SYSCALL_NUM_RET_SHARE_REG
 # define EXPECT_SYSCALL_RETURN(val, action)	EXPECT_EQ(-1, action)
 #else
-# define EXPECT_SYSCALL_RETURN(val, action)	EXPECT_EQ(val, action)
+# define EXPECT_SYSCALL_RETURN(val, action)		\
+	do {						\
+		errno = 0;				\
+		if (val < 0) {				\
+			EXPECT_EQ(-1, action);		\
+			EXPECT_EQ(-(val), errno);	\
+		} else {				\
+			EXPECT_EQ(val, action);		\
+		}					\
+	} while (0)
 #endif
 
 /* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
@@ -1602,7 +1602,7 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
 
 /* Architecture-specific syscall changing routine. */
 void change_syscall(struct __test_metadata *_metadata,
-		    pid_t tracee, int syscall)
+		    pid_t tracee, int syscall, int result)
 {
 	int ret;
 	ARCH_REGS regs;
@@ -1661,7 +1661,7 @@ void change_syscall(struct __test_metadata *_metadata,
 #ifdef SYSCALL_NUM_RET_SHARE_REG
 		TH_LOG("Can't modify syscall return on this architecture");
 #else
-		regs.SYSCALL_RET = EPERM;
+		regs.SYSCALL_RET = result;
 #endif
 
 #ifdef HAVE_GETREGS
@@ -1689,14 +1689,19 @@ void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
 	case 0x1002:
 		/* change getpid to getppid. */
 		EXPECT_EQ(__NR_getpid, get_syscall(_metadata, tracee));
-		change_syscall(_metadata, tracee, __NR_getppid);
+		change_syscall(_metadata, tracee, __NR_getppid, 0);
 		break;
 	case 0x1003:
-		/* skip gettid. */
+		/* skip gettid with valid return code. */
 		EXPECT_EQ(__NR_gettid, get_syscall(_metadata, tracee));
-		change_syscall(_metadata, tracee, -1);
+		change_syscall(_metadata, tracee, -1, 45000);
 		break;
 	case 0x1004:
+		/* skip openat with error. */
+		EXPECT_EQ(__NR_openat, get_syscall(_metadata, tracee));
+		change_syscall(_metadata, tracee, -1, -ESRCH);
+		break;
+	case 0x1005:
 		/* do nothing (allow getppid) */
 		EXPECT_EQ(__NR_getppid, get_syscall(_metadata, tracee));
 		break;
@@ -1729,9 +1734,11 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
 	nr = get_syscall(_metadata, tracee);
 
 	if (nr == __NR_getpid)
-		change_syscall(_metadata, tracee, __NR_getppid);
+		change_syscall(_metadata, tracee, __NR_getppid, 0);
+	if (nr == __NR_gettid)
+		change_syscall(_metadata, tracee, -1, 45000);
 	if (nr == __NR_openat)
-		change_syscall(_metadata, tracee, -1);
+		change_syscall(_metadata, tracee, -1, -ESRCH);
 }
 
 FIXTURE_DATA(TRACE_syscall) {
@@ -1748,8 +1755,10 @@ FIXTURE_SETUP(TRACE_syscall)
 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1002),
 		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_gettid, 0, 1),
 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1003),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_openat, 0, 1),
 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1004),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1005),
 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
 	};
 
@@ -1797,15 +1806,26 @@ TEST_F(TRACE_syscall, ptrace_syscall_redirected)
 	EXPECT_NE(self->mypid, syscall(__NR_getpid));
 }
 
-TEST_F(TRACE_syscall, ptrace_syscall_dropped)
+TEST_F(TRACE_syscall, ptrace_syscall_errno)
 {
 	/* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
 	teardown_trace_fixture(_metadata, self->tracer);
 	self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
 					   true);
 
-	/* Tracer should skip the open syscall, resulting in EPERM. */
-	EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_openat));
+	/* Tracer should skip the open syscall, resulting in ESRCH. */
+	EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
+}
+
+TEST_F(TRACE_syscall, ptrace_syscall_faked)
+{
+	/* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
+	teardown_trace_fixture(_metadata, self->tracer);
+	self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
+					   true);
+
+	/* Tracer should skip the gettid syscall, resulting fake pid. */
+	EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
 }
 
 TEST_F(TRACE_syscall, syscall_allowed)
@@ -1838,7 +1858,21 @@ TEST_F(TRACE_syscall, syscall_redirected)
 	EXPECT_NE(self->mypid, syscall(__NR_getpid));
 }
 
-TEST_F(TRACE_syscall, syscall_dropped)
+TEST_F(TRACE_syscall, syscall_errno)
+{
+	long ret;
+
+	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	/* openat has been skipped and an errno return. */
+	EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
+}
+
+TEST_F(TRACE_syscall, syscall_faked)
 {
 	long ret;
 
@@ -1849,8 +1883,7 @@ TEST_F(TRACE_syscall, syscall_dropped)
 	ASSERT_EQ(0, ret);
 
 	/* gettid has been skipped and an altered return value stored. */
-	EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_gettid));
-	EXPECT_NE(self->mytid, syscall(__NR_gettid));
+	EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
 }
 
 TEST_F(TRACE_syscall, skip_after_RET_TRACE)
@@ -2870,58 +2903,6 @@ TEST(get_action_avail)
 	EXPECT_EQ(errno, EOPNOTSUPP);
 }
 
-TEST(get_metadata)
-{
-	pid_t pid;
-	int pipefd[2];
-	char buf;
-	struct seccomp_metadata md;
-
-	ASSERT_EQ(0, pipe(pipefd));
-
-	pid = fork();
-	ASSERT_GE(pid, 0);
-	if (pid == 0) {
-		struct sock_filter filter[] = {
-			BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-		};
-		struct sock_fprog prog = {
-			.len = (unsigned short)ARRAY_SIZE(filter),
-			.filter = filter,
-		};
-
-		/* one with log, one without */
-		ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER,
-				     SECCOMP_FILTER_FLAG_LOG, &prog));
-		ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog));
-
-		ASSERT_EQ(0, close(pipefd[0]));
-		ASSERT_EQ(1, write(pipefd[1], "1", 1));
-		ASSERT_EQ(0, close(pipefd[1]));
-
-		while (1)
-			sleep(100);
-	}
-
-	ASSERT_EQ(0, close(pipefd[1]));
-	ASSERT_EQ(1, read(pipefd[0], &buf, 1));
-
-	ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid));
-	ASSERT_EQ(pid, waitpid(pid, NULL, 0));
-
-	md.filter_off = 0;
-	ASSERT_EQ(sizeof(md), ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md));
-	EXPECT_EQ(md.flags, SECCOMP_FILTER_FLAG_LOG);
-	EXPECT_EQ(md.filter_off, 0);
-
-	md.filter_off = 1;
-	ASSERT_EQ(sizeof(md), ptrace(PTRACE_SECCOMP_GET_METADATA, pid, sizeof(md), &md));
-	EXPECT_EQ(md.flags, 0);
-	EXPECT_EQ(md.filter_off, 1);
-
-	ASSERT_EQ(0, kill(pid, SIGKILL));
-}
-
 /*
  * TODO:
  * - add microbenchmarks
diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c
index 460b4bd..5d546dc 100644
--- a/tools/testing/selftests/x86/protection_keys.c
+++ b/tools/testing/selftests/x86/protection_keys.c
@@ -1133,6 +1133,21 @@ void test_pkey_syscalls_bad_args(int *ptr, u16 pkey)
 	pkey_assert(err);
 }
 
+void become_child(void)
+{
+	pid_t forkret;
+
+	forkret = fork();
+	pkey_assert(forkret >= 0);
+	dprintf3("[%d] fork() ret: %d\n", getpid(), forkret);
+
+	if (!forkret) {
+		/* in the child */
+		return;
+	}
+	exit(0);
+}
+
 /* Assumes that all pkeys other than 'pkey' are unallocated */
 void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
 {
@@ -1141,7 +1156,7 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
 	int nr_allocated_pkeys = 0;
 	int i;
 
-	for (i = 0; i < NR_PKEYS*2; i++) {
+	for (i = 0; i < NR_PKEYS*3; i++) {
 		int new_pkey;
 		dprintf1("%s() alloc loop: %d\n", __func__, i);
 		new_pkey = alloc_pkey();
@@ -1152,21 +1167,27 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
 		if ((new_pkey == -1) && (errno == ENOSPC)) {
 			dprintf2("%s() failed to allocate pkey after %d tries\n",
 				__func__, nr_allocated_pkeys);
-			break;
+		} else {
+			/*
+			 * Ensure the number of successes never
+			 * exceeds the number of keys supported
+			 * in the hardware.
+			 */
+			pkey_assert(nr_allocated_pkeys < NR_PKEYS);
+			allocated_pkeys[nr_allocated_pkeys++] = new_pkey;
 		}
-		pkey_assert(nr_allocated_pkeys < NR_PKEYS);
-		allocated_pkeys[nr_allocated_pkeys++] = new_pkey;
+
+		/*
+		 * Make sure that allocation state is properly
+		 * preserved across fork().
+		 */
+		if (i == NR_PKEYS*2)
+			become_child();
 	}
 
 	dprintf3("%s()::%d\n", __func__, __LINE__);
 
 	/*
-	 * ensure it did not reach the end of the loop without
-	 * failure:
-	 */
-	pkey_assert(i < NR_PKEYS*2);
-
-	/*
 	 * There are 16 pkeys supported in hardware.  Three are
 	 * allocated by the time we get here:
 	 *   1. The default key (0)
diff --git a/tools/usb/Makefile b/tools/usb/Makefile
index 4e65060..01d758d 100644
--- a/tools/usb/Makefile
+++ b/tools/usb/Makefile
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for USB tools
 
-CC = $(CROSS_COMPILE)gcc
 PTHREAD_LIBS = -lpthread
 WARNINGS = -Wall -Wextra
 CFLAGS = $(WARNINGS) -g -I../include
diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h
index 395521a..268ce23 100644
--- a/tools/virtio/linux/kernel.h
+++ b/tools/virtio/linux/kernel.h
@@ -23,6 +23,10 @@
 #define PAGE_MASK (~(PAGE_SIZE-1))
 #define PAGE_ALIGN(x) ((x + PAGE_SIZE - 1) & PAGE_MASK)
 
+/* generic data direction definitions */
+#define READ                    0
+#define WRITE                   1
+
 typedef unsigned long long phys_addr_t;
 typedef unsigned long long dma_addr_t;
 typedef size_t __kernel_size_t;
diff --git a/tools/vm/Makefile b/tools/vm/Makefile
index be320b9..20f6cf0 100644
--- a/tools/vm/Makefile
+++ b/tools/vm/Makefile
@@ -6,7 +6,6 @@
 LIB_DIR = ../lib/api
 LIBS = $(LIB_DIR)/libapi.a
 
-CC = $(CROSS_COMPILE)gcc
 CFLAGS = -Wall -Wextra -I../lib/
 LDFLAGS = $(LIBS)
 
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index ed42b8c..32aa88c 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -61,7 +61,7 @@ static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu);
 static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
 static u32 kvm_next_vmid;
 static unsigned int kvm_vmid_bits __read_mostly;
-static DEFINE_RWLOCK(kvm_vmid_lock);
+static DEFINE_SPINLOCK(kvm_vmid_lock);
 
 static bool vgic_present;
 
@@ -447,7 +447,9 @@ void force_vm_exit(const cpumask_t *mask)
  */
 static bool need_new_vmid_gen(struct kvm *kvm)
 {
-	return unlikely(kvm->arch.vmid_gen != atomic64_read(&kvm_vmid_gen));
+	u64 current_vmid_gen = atomic64_read(&kvm_vmid_gen);
+	smp_rmb(); /* Orders read of kvm_vmid_gen and kvm->arch.vmid */
+	return unlikely(READ_ONCE(kvm->arch.vmid_gen) != current_vmid_gen);
 }
 
 /**
@@ -462,16 +464,11 @@ static void update_vttbr(struct kvm *kvm)
 {
 	phys_addr_t pgd_phys;
 	u64 vmid;
-	bool new_gen;
 
-	read_lock(&kvm_vmid_lock);
-	new_gen = need_new_vmid_gen(kvm);
-	read_unlock(&kvm_vmid_lock);
-
-	if (!new_gen)
+	if (!need_new_vmid_gen(kvm))
 		return;
 
-	write_lock(&kvm_vmid_lock);
+	spin_lock(&kvm_vmid_lock);
 
 	/*
 	 * We need to re-check the vmid_gen here to ensure that if another vcpu
@@ -479,7 +476,7 @@ static void update_vttbr(struct kvm *kvm)
 	 * use the same vmid.
 	 */
 	if (!need_new_vmid_gen(kvm)) {
-		write_unlock(&kvm_vmid_lock);
+		spin_unlock(&kvm_vmid_lock);
 		return;
 	}
 
@@ -502,7 +499,6 @@ static void update_vttbr(struct kvm *kvm)
 		kvm_call_hyp(__kvm_flush_vm_context);
 	}
 
-	kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen);
 	kvm->arch.vmid = kvm_next_vmid;
 	kvm_next_vmid++;
 	kvm_next_vmid &= (1 << kvm_vmid_bits) - 1;
@@ -513,7 +509,10 @@ static void update_vttbr(struct kvm *kvm)
 	vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits);
 	kvm->arch.vttbr = pgd_phys | vmid;
 
-	write_unlock(&kvm_vmid_lock);
+	smp_wmb();
+	WRITE_ONCE(kvm->arch.vmid_gen, atomic64_read(&kvm_vmid_gen));
+
+	spin_unlock(&kvm_vmid_lock);
 }
 
 static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/mmio.c b/virt/kvm/arm/mmio.c
index dac7ceb1..08443a1 100644
--- a/virt/kvm/arm/mmio.c
+++ b/virt/kvm/arm/mmio.c
@@ -117,6 +117,12 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data);
 	}
 
+	/*
+	 * The MMIO instruction is emulated and should not be re-executed
+	 * in the guest.
+	 */
+	kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+
 	return 0;
 }
 
@@ -144,11 +150,6 @@ static int decode_hsr(struct kvm_vcpu *vcpu, bool *is_write, int *len)
 	vcpu->arch.mmio_decode.sign_extend = sign_extend;
 	vcpu->arch.mmio_decode.rt = rt;
 
-	/*
-	 * The MMIO instruction is emulated and should not be re-executed
-	 * in the guest.
-	 */
-	kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
 	return 0;
 }
 
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 4f35f0d..9b79818 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1962,7 +1962,8 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 EXPORT_SYMBOL_GPL(kvm_gfn_to_hva_cache_init);
 
 int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
-			   void *data, int offset, unsigned long len)
+				  void *data, unsigned int offset,
+				  unsigned long len)
 {
 	struct kvm_memslots *slots = kvm_memslots(kvm);
 	int r;
@@ -2911,8 +2912,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
 	if (ops->init)
 		ops->init(dev);
 
+	kvm_get_kvm(kvm);
 	ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
 	if (ret < 0) {
+		kvm_put_kvm(kvm);
 		mutex_lock(&kvm->lock);
 		list_del(&dev->vm_node);
 		mutex_unlock(&kvm->lock);
@@ -2920,7 +2923,6 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
 		return ret;
 	}
 
-	kvm_get_kvm(kvm);
 	cd->fd = ret;
 	return 0;
 }