Merge "msm: kgsl: Update GPU HARD RESET processing" into msm-4.9
diff --git a/Documentation/devicetree/bindings/arm/msm/board-id.txt b/Documentation/devicetree/bindings/arm/msm/board-id.txt
new file mode 100644
index 0000000..e07a1c9
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/board-id.txt
@@ -0,0 +1,64 @@
+* BOARD-ID
+
+The qcom,board-id entry specifies the MSM platform and subtype revision.
+It can optionally be an array of these to indicate multiple hardware that use
+the same device tree.  It is expected that the bootloader will use this
+information at boot-up to decide which device tree to use when given multiple
+device trees, some of which may not be compatible with the actual hardware.  It
+is the bootloader's responsibility to pass the correct device tree to the kernel.
+
+Legacy format:
+
+It is expected that the qcom,board-id entry be at the top level of the device
+tree structure.  The format of the entry is:
+
+   qcom,board-id = <platform_id, subtype_id> [, <p2, s2> ...]
+
+where platform_id and subtype_id are the numeric values for the platform and
+subtype of the current hardware.
+
+The "subtype_id" cell is a 32-bit integer whose bit values are defined as follows:
+    bits 31-20 = Reserved bits
+    bits 19-16 = Boot Device Type.
+		 MSM:
+		     0: default (eMMC)
+		     2: EMMC_SDC1
+		     4: BOOT_UFS
+		 MDM:
+		     0: default (NAND)
+		     3: EMMC_SDC1
+    bits 15-8  = DDR Size. For devices with DDR Size as 512MB the value is 0x1, default value as 0x0
+    bits 7-0   = Platform Subtype
+
+In the event that a given device tree is applicable to all hardware versions
+matching a given Platform Type / Subtype ID, the major/minior platform version
+fields in the board_id property shall both be specified as 0xff.
+
+Modern format:
+The cell layout of the qcom,board-id property is as follows:
+
+   qcom,board-id = <board_id, reserved>
+
+where board_id is a 32-bit integer whose bit values are defined as follows:
+    bits 31-24 = Platform Subtype ID
+    bits 23-16 = Platform Version (Major)
+    bits 15-8  = Platform Version (Minor)
+    bits  7-0  = Platform Type ID
+
+and the 'reserved' cell is a 32-bit integer whose bit values are defined as follows:
+    bits 31-13 = Reserved Bits
+    bits 12-11 = Panel Detection. 00 - limit to HD, 01 - limit to 720p,
+		 10 - limit to qHD, 11 - limit to FWVGA
+    bits 10-8  = DDR Size. For devices with DDR Size as 512MB the value is 0x1,
+		 default value as 0x0
+    bits 7-0   = Platform Subtype
+
+In the event that a given device tree is applicable to all hardware versions
+matching a given Platform Type / Subtype ID, the major/minior platform version
+fields in the board_id property shall both be specified as 0xff.
+
+Example:
+   qcom,board-id = <15 0>;
+   qcom,board-id = <0x01040708, 0>;
+   qcom,board-id = <0x01ffff08, 0>;
+   qcom,board-id = <8, 0x100>;
diff --git a/Documentation/devicetree/bindings/arm/msm/msm-id.txt b/Documentation/devicetree/bindings/arm/msm/msm-id.txt
new file mode 100644
index 0000000..c243154
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/msm-id.txt
@@ -0,0 +1,33 @@
+* MSM-ID
+
+The qcom,msm-id entry specifies the MSM chipset, platform, hardware revision
+and optional manufactured foundry.  It can optionally be an array of these to
+indicate multiple hardware that use the same device tree.  It is expected that
+the bootloader will use this information at boot-up to decide which device tree
+to use when given multiple device trees, some of which may not be compatible
+with the actual hardware.  It is the bootloader's responsibility to pass the
+correct device tree to the kernel.
+
+Format:
+
+It is expected that the qcom,msm-id entry be at the top level of the device
+tree structure.  The format can take one of the two forms below:
+
+   qcom,msm-id = <chipset_foundry_id, platform_id, rev_id> [, <c2, p2, r2> ...]
+   qcom,msm-id = <chipset_foundry_id, rev_id> [, <c2, r2> ...]
+
+If the second format is used one must also define the board-id.
+
+The "chipset_foundry_id" consists of three fields as below:
+
+   bits 0-15  = The unique MSM chipset id.
+   bits 16-23 = The optional foundry id. If bootloader doesn't find a device
+		tree which has exact matching foundry-id with hardware it
+		chooses the device tree with foundry-id = 0.
+   bits 24-31 = Reserved.
+
+Example:
+   qcom,msm-id = <0x1007e 15 0>;
+
+   qcom,board-id= <15 2>;
+   qcom,msm-id = <0x1007e 0>;
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_memory_dump.txt b/Documentation/devicetree/bindings/arm/msm/msm_memory_dump.txt
new file mode 100644
index 0000000..a415c8f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/msm_memory_dump.txt
@@ -0,0 +1,31 @@
+Qualcomm Technologies Inc. memory dump driver
+
+QTI memory dump driver allows various client subsystems to register and allocate respective
+dump regions. At the time of deadlocks or cpu hangs these dump regions
+are captured to give a snapshot of the system at the time of the crash.
+
+Required properties:
+
+-compatible: "qcom,mem-dump"
+-memory-region: phandle to the CMA region. The size of the CMA region
+		should be greater than sum of size of all child nodes
+		to account for padding.
+
+If any child nodes exist the following property are required:
+
+-qcom,dump-size: The size of memory that needs to be allocated for the
+		 particular node.
+-qcom,dump-id: The ID within the data dump table where this entry needs
+	       to be added.
+
+Example:
+
+	mem_dump {
+		compatible = "qcom,mem-dump";
+		memory-region = <&dump_mem>;
+
+		rpmh_dump {
+			qcom,dump-size = <0x2000000>;
+			qcom,dump-id = <0xEC>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dp.txt b/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
new file mode 100644
index 0000000..790da12
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
@@ -0,0 +1,146 @@
+Qualcomm Technologies, Inc.
+sde-dp is the master Display Port device which supports DP host controllers that are compatible with VESA Display Port interface specification.
+DP Controller: Required properties:
+- compatible:           Should be "qcom,dp-display".
+- reg:                  Base address and length of DP hardware's memory mapped regions.
+- reg-names:            A list of strings that name the list of regs. "dp_ctrl" - DP controller memory region.
+			"dp_phy" - DP PHY memory region.
+			"dp_ln_tx0" - USB3 DP PHY combo TX-0 lane memory region.
+			"dp_ln_tx1" - USB3 DP PHY combo TX-1 lane memory region.
+			"dp_mmss_cc" - Display Clock Control memory region.
+			"qfprom_physical" - QFPROM Phys memory region.
+			"dp_pll" - USB3 DP combo PLL memory region.
+			"hdcp_physical" - DP HDCP memory region.
+- cell-index:           Specifies the controller instance.
+- clocks:               Clocks required for Display Port operation.
+- clock-names:          Names of the clocks corresponding to handles. Following clocks are required:
+			"core_aux_clk", "core_usb_ref_clk_src","core_usb_ref_clk", "core_usb_cfg_ahb_clk",
+			"core_usb_pipe_clk", "ctrl_link_clk", "ctrl_link_iface_clk", "ctrl_crypto_clk",
+			"ctrl_pixel_clk", "pixel_clk_rcg", "pixel_parent".
+- gdsc-supply:		phandle to gdsc regulator node.
+- vdda-1p2-supply:		phandle to vdda 1.2V regulator node.
+- vdda-0p9-supply:		phandle to vdda 0.9V regulator node.
+- interrupt-parent	phandle to the interrupt parent device node.
+- interrupts:		The interrupt signal from the DSI block.
+- qcom,aux-en-gpio:			Specifies the aux-channel enable gpio.
+- qcom,aux-sel-gpio:		Specifies the aux-channel select gpio.
+- qcom,usbplug-cc-gpio:		Specifies the usbplug orientation gpio.
+- qcom,aux-cfg-settings:	An array that specifies the DP AUX configuration settings.
+- qcom,max-pclk-frequency-khz:	An integer specifying the max. pixel clock in KHz supported by Display Port.
+- qcom,dp-usbpd-detection:	Phandle for the PMI regulator node for USB PHY PD detection.
+- qcom,<type>-supply-entries:		A node that lists the elements of the supply used by the a particular "type" of DSI module. The module "types"
+					can be "core", "ctrl", and "phy". Within the same type,
+					there can be more than one instance of this binding,
+					in which case the entry would be appended with the
+					supply entry index.
+					e.g. qcom,ctrl-supply-entry@0
+					-- qcom,supply-name: name of the supply (vdd/vdda/vddio)
+					-- qcom,supply-min-voltage: minimum voltage level (uV)
+					-- 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-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
+					-- qcom,supply-post-off-sleep: time to sleep (ms) after turning off
+- pinctrl-names:	List of names to assign mdss pin states defined in pinctrl device node
+					Refer to pinctrl-bindings.txt
+- pinctrl-<0..n>:	Lists phandles each pointing to the pin configuration node within a pin
+					controller. These pin configurations are installed in the pinctrl
+					device node. Refer to pinctrl-bindings.txt
+
+Example:
+	sde_dp: qcom,dp_display@0{
+		cell-index = <0>;
+		compatible = "qcom,dp-display";
+
+		gdsc-supply = <&mdss_core_gdsc>;
+		vdda-1p2-supply = <&pm8998_l26>;
+		vdda-0p9-supply = <&pm8998_l1>;
+
+		reg =	<0xae90000 0xa84>,
+			<0x88eaa00 0x200>,
+			<0x88ea200 0x200>,
+			<0x88ea600 0x200>,
+			<0xaf02000 0x1a0>,
+			<0x780000 0x621c>,
+			<0x88ea030 0x10>,
+			<0x88e8000 0x621c>,
+			<0x0aee1000 0x034>;
+		reg-names = "dp_ctrl", "dp_phy", "dp_ln_tx0", "dp_ln_tx1",
+			"dp_mmss_cc", "qfprom_physical", "dp_pll",
+			"usb3_dp_com", "hdcp_physical";
+
+		interrupt-parent = <&mdss_mdp>;
+		interrupts = <12 0>;
+
+		clocks =  <&clock_dispcc DISP_CC_MDSS_DP_AUX_CLK>,
+			 <&clock_rpmh RPMH_CXO_CLK>,
+			 <&clock_gcc GCC_USB3_PRIM_CLKREF_CLK>,
+			 <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+			 <&clock_gcc GCC_USB3_PRIM_PHY_PIPE_CLK>,
+			 <&clock_dispcc DISP_CC_MDSS_DP_LINK_CLK>,
+			 <&clock_dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
+			 <&clock_dispcc DISP_CC_MDSS_DP_CRYPTO_CLK>,
+			 <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK>,
+			 <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>,
+			 <&mdss_dp_pll DP_VCO_DIVIDED_CLK_SRC_MUX>;
+		clock-names = "core_aux_clk", "core_usb_ref_clk_src",
+			"core_usb_ref_clk", "core_usb_cfg_ahb_clk",
+			"core_usb_pipe_clk", "ctrl_link_clk",
+			"ctrl_link_iface_clk", "ctrl_crypto_clk",
+			"ctrl_pixel_clk", "pixel_clk_rcg", "pixel_parent";
+
+		qcom,dp-usbpd-detection = <&pmi8998_pdphy>;
+
+		qcom,aux-cfg-settings = [00 13 04 00 0a 26 0a 03 bb 03];
+		qcom,max-pclk-frequency-khz = <593470>;
+		pinctrl-names = "mdss_dp_active", "mdss_dp_sleep";
+		pinctrl-0 = <&sde_dp_aux_active &sde_dp_usbplug_cc_active>;
+		pinctrl-1 = <&sde_dp_aux_suspend &sde_dp_usbplug_cc_suspend>;
+		qcom,aux-en-gpio = <&tlmm 43 0>;
+		qcom,aux-sel-gpio = <&tlmm 51 0>;
+		qcom,usbplug-cc-gpio = <&tlmm 38 0>;
+		qcom,core-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,core-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "gdsc";
+				qcom,supply-min-voltage = <0>;
+				qcom,supply-max-voltage = <0>;
+				qcom,supply-enable-load = <0>;
+				qcom,supply-disable-load = <0>;
+			};
+		};
+
+		qcom,ctrl-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,ctrl-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "vdda-1p2";
+				qcom,supply-min-voltage = <1200000>;
+				qcom,supply-max-voltage = <1200000>;
+				qcom,supply-enable-load = <21800>;
+				qcom,supply-disable-load = <4>;
+			};
+		};
+
+		qcom,phy-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,phy-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "vdda-0p9";
+				qcom,supply-min-voltage = <880000>;
+				qcom,supply-max-voltage = <880000>;
+				qcom,supply-enable-load = <36000>;
+				qcom,supply-disable-load = <32>;
+			};
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
new file mode 100644
index 0000000..8598d0c
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
@@ -0,0 +1,63 @@
+QTI PDC interrupt controller
+
+PDC is QTI's platform parent interrupt controller that serves as wakeup source.
+
+Newer QTI SOCs are replacing MPM (MSM sleep Power Manager) with PDC (Power
+Domain Controller) to manage subsystem wakeups and resources during sleep.
+This driver marks the wakeup interrupts in APSS PDC such that it monitors the
+interrupts when the system is asleep, wakes up the APSS when one of these
+interrupts occur and replays it to the subsystem interrupt controller after it
+becomes operational.
+
+Earlier MPM architecture used arch-extension of GIC interrupt
+controller to mark enabled wake-up interrupts and monitor these when the
+system goes to sleep. Since the arch-extensions are no-longer available
+on newer kernel versions, this driver is implemented as hierarchical irq
+domain.  GIC is parent interrupt controller at the highest level.
+Platform interrupt controller PDC is next in hierarchy, followed by others.
+This driver only configures the interrupts, does not handle them.
+
+PDC interrupt configuration involves programming of 2 set of registers:
+IRQ_ENABLE_BANK    - Enable the irq
+IRQ_i_CFG          - Configure the interrupt i
+
+Properties:
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: Should contain "qcom,pdc-<target>"
+
+- reg:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: Specifies the base physical address for PDC hardware
+			block for DRV2.
+
+- interrupt-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: Specifies the number of cells needed to encode an interrupt source.
+			Value must be 3.
+			The encoding of these cells are same as described in
+			Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
+
+- interrupt-parent:
+	Usage: required
+	Value type: <phandle>
+	Definition: Specifies the interrupt parent necessary for hierarchical domain to operate.
+
+- interrupt-controller:
+	Usage: required
+	Value type: <bool>
+	Definition: Identifies the node as an interrupt controller.
+
+Example:
+
+pdcgic: interrupt-controller@0xb220000{
+	compatible = "qcom,pdc-sdm845";
+	reg = <0xb220000 0x30000>;
+	#interrupt-cells = <3>;
+	interrupt-parent = <&intc>;
+	interrupt-controller;
+};
diff --git a/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt b/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt
index 0295e1b..937ccb9 100644
--- a/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt
@@ -81,6 +81,32 @@
 				limits.
 - qcom,mdss-rot-vbif-qos-setting: This array is used to program vbif qos remapper register
 				  priority for rotator clients.
+- qcom,mdss-rot-cdp-setting:	Integer array of size two, to indicate client driven
+				prefetch is available or not. Index 0 represents
+				if CDP is enabled for read and index 1, if CDP
+				is enabled for write operation.
+- qcom,mdss-rot-qos-lut		A 4 cell property with the format of <rd_lut_0,
+				rd_lut_1, wr_lut_0, wr_lut_1> indicating the qos
+				lut settings for the rotator sspp and writeback
+				client.
+- qcom,mdss-rot-danger-lut	A two cell property with the format of <rd_lut,
+				wr_lut> indicating the danger lut settings for
+				the rotator sspp and writeback client.
+- qcom,mdss-rot-safe-lut	A two cell property with the format of <rd_lut,
+				wr_lut> indicating the safe lut settings for the
+				rotator sspp and writeback client.
+- qcom,mdss-inline-rot-qos-lut:	A 4 cell property with the format of <rd_lut_0,
+				rd_lut_1, wr_lut_0, wr_lut_1> indicating the qos
+				lut settings for the inline rotator sspp and
+				writeback client.
+- qcom,mdss-inline-rot-danger-lut: A two cell property with the format of
+				<rd_lut, wr_lut> indicating the danger lut
+				settings for the inline rotator sspp and
+				writeback client.
+- qcom,mdss-inline-rot-safe-lut: A two cell property with the format of
+				<rd_lut, wr_lut> indicating the safe lut
+				settings for the inline rotator sspp and
+				writeback client.
 - qcom,mdss-rot-mode:		This is integer value indicates operation mode
 				of the rotator device
 - qcom,mdss-sbuf-headroom:	This integer value indicates stream buffer headroom in lines.
@@ -146,9 +172,19 @@
 		/* VBIF QoS remapper settings*/
 		qcom,mdss-rot-vbif-qos-setting = <1 1 1 1>;
 
+		com,mdss-rot-cdp-setting = <1 1>;
+
 		qcom,mdss-default-ot-rd-limit = <8>;
 		qcom,mdss-default-ot-wr-limit = <16>;
 
+		qcom,mdss-rot-qos-lut = <0x0 0x0 0x0 0x0>;
+		qcom,mdss-rot-danger-lut = <0x0 0x0>;
+		qcom,mdss-rot-safe-lut = <0x0000ffff 0x0>;
+
+		qcom,mdss-inline-rot-qos-lut = <0x0 0x0 0x00112233 0x44556677>;
+		qcom,mdss-inline-rot-danger-lut = <0x0 0x0000ffff>;
+		qcom,mdss-inline-rot-safe-lut = <0x0 0x0000ff00>;
+
 		qcom,mdss-sbuf-headroom = <20>;
 		cache-slice-names = "rotator";
 		cache-slices = <&llcc 4>;
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc-vmem.txt b/Documentation/devicetree/bindings/media/video/msm-vidc-vmem.txt
deleted file mode 100644
index 84a8765..0000000
--- a/Documentation/devicetree/bindings/media/video/msm-vidc-vmem.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-* Qualcomm Technologies Inc MSM VIDC VMEM
-
-Required properties:
-- compatible : "qcom,msm-vmem".
-- interrupts : Contains the interrupt that maps to the VMEM module.
-- reg : A set of 2 start address and size pairs that describe the hardware
-register address space and mappable memory address space.
-- reg-names : Strings that describe the pairs in "reg".  The register address
-space should be called "reg-base" and the memory space should be called "mem-base".
-- clocks : A set of clocks that correspond to the AHB and MAXI clocks that the
-hardware uses.
-- clock-names : A string that describes the "clocks" property.  The AHB clock
-should be named "ahb" and the MAXI clock should be named "maxi".
-- qcom,bank-size : The size of each memory bank, in bytes.
-- vdd-supply: phandle to a regulator that is considered to be the footswitch for vmem.
-- qcom,msm-bus,(name|num-cases,num-paths,vectors-KBps) - Bus to be voted for prior to
-  issuing any IO transactions to vmem.  Refer to Documentation/devicetree/bindings/arm/\
-  msm/msm_bus_adhoc.txt for further details.
-
-Example:
-
-qcom,vmem@880000 {
-	compatible = "qcom,msm-vmem";
-	interrupts = <0 429 0>;
-	reg = <0x880000 0x800>,
-	    <0x6800000 0x100000>;
-	reg-names = "reg-base", "mem-base";
-
-	vdd-supply = <&gdsc_mmagic_video>;
-	clocks = <&clock_mmss clk_vmem_ahb_clk>,
-	       <&clock_mmss clk_vmem_maxi_clk>;
-	clock-names = "ahb", "maxi";
-
-	qcom,bank-size = <131072>;
-
-	qcom,msm-bus,name = "vmem";
-	qcom,msm-bus,num-cases = <2>;
-	qcom,msm-bus,num-paths = <1>;
-	qcom,msm-bus,vectors-KBps =
-	        <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_VMEM_CFG   0   0>,
-	        <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_VMEM_CFG 500 800>;
-};
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index bdc0eba..53f419c 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -104,6 +104,9 @@
   memory, performance etc.
 - qcom,debug-timeout = A bool indicating that FW errors such as SYS_ERROR,
   SESSION_ERROR and timeouts will be treated as Fatal.
+- cache-slice-names = An array of supported cache slice names by llcc
+- cache-slices = An array of supported cache slice ids corresponding
+  to cache-slice-names by llcc
 
 [Second level nodes]
 Context Banks
@@ -149,7 +152,7 @@
 Optional properties:
 - qcom,bus-governor : governor to use when scaling bus, generally any commonly
   found devfreq governor might be used.  In addition to those governors, the
-  custom Venus governors, "msm-vidc-ddr" or "msm-vidc-vmem" are also
+  custom Venus governors, "msm-vidc-ddr" or "msm-vidc-llcc" are also
   acceptable values.
   In the absence of this property the "performance" governor is used.
 - qcom,bus-rage-kbps : an array of two items (<min max>) that indicate the
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt
index 5529e308..92ef23c 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt
@@ -22,8 +22,7 @@
   Definition: String which indicates the charging mode. Can be one of the
 	      following:
               Standalone/Parallel Master	- "qcom,smb138x-charger"
-	      smb138x Parallel Slave		- "qcom,smb138x-parallel-slave"
-	      smb1355 Parallel Slave		- "qcom,smb1355-parallel-slave",
+	      Parallel Slave			- "qcom,smb138x-parallel-slave"
 
 - qcom,pmic-revid
   Usage:      required
@@ -36,8 +35,7 @@
   Usage:      optional
   Value type: <u32>
   Definition: Specifies parallel charging mode. If not specified, MID-MID
-	      option is selected by default. Note that smb1355 can only
-	      run in MID-MID configuration.
+	      option is selected by default.
 
 - qcom,suspend-input
   Usage:      optional
@@ -127,7 +125,7 @@
 =======
 
 smb138x_charger: qcom,smb138x-charger {
-	compatible = "qcom,smb138x-charger";
+	compatible = "qcom,qpnp-smb138x-charger";
 	#address-cells = <1>;
 	#size-cells = <1>;
 
diff --git a/Documentation/devicetree/bindings/qbt1000/qbt1000.txt b/Documentation/devicetree/bindings/qbt1000/qbt1000.txt
new file mode 100644
index 0000000..c9861e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/qbt1000/qbt1000.txt
@@ -0,0 +1,54 @@
+Qualcomm Technologies, Inc. QBT1000 Specific Bindings
+
+QBT is a fingerprint sensor ASIC capable of performing fingerprint image scans
+and detecting finger presence on the sensor using programmable firmware.
+
+=======================
+Required Node Structure
+=======================
+
+- compatible
+  Usage:      required
+  Value type: <string>
+  Definition: "qcom,qbt1000".
+
+- clock-names
+  Usage:      required
+  Value type: <stringlist>
+  Definition: List of clock names that need to be voted on/off.
+
+- clocks
+  Usage:      required
+  Value type: <prop_encoded-array>
+  Definition: Property pair that represents the clock controller and the clock
+		id. This in combination with the clock-name is used to obtain
+		the handle for the clock that needs to be voted on/off.
+
+- clock-frequency
+  Usage:      required
+  Value type: <u32>
+  Definition: Frequency of clock in Hz.
+
+- qcom,ipc-gpio
+  Usage:      required
+  Value type: <phandle>
+  Definition: phandle for GPIO to be used for IPC.
+
+- qcom,finger-detect-gpio
+  Usage:      required
+  Value type: <phandle>
+  Definition: phandle for GPIO to be used for finger detect.
+
+=======
+Example
+=======
+
+qcom,qbt1000 {
+	compatible = "qcom,qbt1000";
+	clock-names = "core", "iface";
+	clocks = <&clock_gcc clk_gcc_blsp2_qup6_spi_apps_clk>,
+		<&clock_gcc clk_gcc_blsp2_ahb_clk>;
+	clock-frequency = <15000000>;
+	qcom,ipc-gpio = <&tlmm 121 0>;
+	qcom,finger-detect-gpio = <&pmcobalt_gpios 2 0>;
+};
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index 5d0499c..803df6f 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -59,6 +59,8 @@
  - qcom,poll-cfg-gdscr:	Poll the CFG register of the GDSC to determine if the
 			GDSC is enabled/disabled. This flag should not be set
 			in conjunction with "hw-ctrl-addr".
+ - qcom,toggle-sw-collapse-in-disable: If set, SW_COLLAPSE bit is toggled
+			in disable call.
 
 Example:
 	gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/Makefile b/Makefile
index f47cd95..b9aba93 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 9
-SUBLEVEL = 28
+SUBLEVEL = 29
 EXTRAVERSION =
 NAME = Roaring Lionus
 
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index c2b1315..a08d7a9 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -208,9 +208,10 @@
 
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
-	int ret = 1;
+	struct kvm *kvm = vcpu->kvm;
 	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
 	unsigned long val;
+	int ret = 1;
 
 	switch (psci_fn) {
 	case PSCI_0_2_FN_PSCI_VERSION:
@@ -230,7 +231,9 @@
 		break;
 	case PSCI_0_2_FN_CPU_ON:
 	case PSCI_0_2_FN64_CPU_ON:
+		mutex_lock(&kvm->lock);
 		val = kvm_psci_vcpu_on(vcpu);
+		mutex_unlock(&kvm->lock);
 		break;
 	case PSCI_0_2_FN_AFFINITY_INFO:
 	case PSCI_0_2_FN64_AFFINITY_INFO:
@@ -279,6 +282,7 @@
 
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
+	struct kvm *kvm = vcpu->kvm;
 	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
 	unsigned long val;
 
@@ -288,7 +292,9 @@
 		val = PSCI_RET_SUCCESS;
 		break;
 	case KVM_PSCI_FN_CPU_ON:
+		mutex_lock(&kvm->lock);
 		val = kvm_psci_vcpu_on(vcpu);
+		mutex_unlock(&kvm->lock);
 		break;
 	default:
 		val = PSCI_RET_NOT_SUPPORTED;
diff --git a/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
index 84a6a84..2194a42 100644
--- a/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
@@ -217,6 +217,7 @@
 		sw-reset = <&gpu_gx_sw_reset>;
 		qcom,reset-aon-logic;
 		qcom,poll-cfg-gdscr;
+		qcom,toggle-sw-collapse-in-disable;
 		status = "disabled";
 	};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
index f6493ac..97573ea 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
@@ -767,6 +767,15 @@
 					    <&tpdm_lpass_out_funnel_lpass>;
 				};
 			};
+
+			port@2 {
+				reg = <1>;
+				funnel_lpass_in_audio_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+					    <&audio_etm0_out_funnel_lpass>;
+				};
+			};
 		};
 	};
 
@@ -1387,25 +1396,61 @@
 		};
 	};
 
-	cti_ddr0: cti@69e1000 {
+	cti0_ddr0: cti@69e1000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x69e1000 0x1000>;
 		reg-names = "cti-base";
 
-		coresight-name = "coresight-cti-ddr0";
+		coresight-name = "coresight-cti0-ddr0";
 
 		clocks = <&clock_aop QDSS_CLK>;
 		clock-names = "apb_pclk";
 	};
 
-	cti_ddr1: cti@69e4000 {
+	cti0_ddr1: cti@69e4000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x69e4000 0x1000>;
 		reg-names = "cti-base";
 
-		coresight-name = "coresight-cti-ddr1";
+		coresight-name = "coresight-cti0-ddr1";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti1_ddr1: cti@69e5000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x69e5000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti1-ddr1";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti0_dlmm: cti@6c09000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6c09000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti0-dlmm";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti1_dlmm: cti@6c0a000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6c0a000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti1-dlmm";
 
 		clocks = <&clock_aop QDSS_CLK>;
 		clock-names = "apb_pclk";
@@ -1731,7 +1776,7 @@
 		compatible = "qcom,coresight-remote-etm";
 
 		coresight-name = "coresight-turing-etm0";
-		qcom,inst-id = <1>;
+		qcom,inst-id = <13>;
 
 		port{
 			turing_etm0_out_funnel_turing: endpoint {
@@ -1770,6 +1815,19 @@
 		};
 	};
 
+	audio_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+
+		coresight-name = "coresight-audio-etm0";
+		qcom,inst-id = <5>;
+
+		port {
+			audio_etm0_out_funnel_lpass: endpoint {
+				remote-endpoint = <&funnel_lpass_in_audio_etm0>;
+			};
+		};
+	};
+
 	funnel_apss_merg: funnel@7810000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b908>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
index 59b3396..1744574 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
@@ -2667,11 +2667,11 @@
 
 		trigout_a: trigout_a {
 			mux {
-				pins = "gpio62", "gpio51";
+				pins = "gpio90";
 				function = "qdss_cti";
 			};
 			config {
-				pins = "gpio62", "gpio51";
+				pins = "gpio90";
 				drive-strength = <2>;
 				bias-disable;
 			};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
index 9056569..0aaac6f 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
@@ -14,6 +14,27 @@
 #include <dt-bindings/gpio/gpio.h>
 
 /{
+	bluetooth: bt_wcn3990 {
+		compatible = "qca,wcn3990";
+		qca,bt-vdd-io-supply = <&pm8998_s3>;
+		qca,bt-vdd-xtal-supply = <&pm8998_s5>;
+		qca,bt-vdd-core-supply = <&pm8998_l7>;
+		qca,bt-vdd-pa-supply = <&pm8998_l17>;
+		qca,bt-vdd-ldo-supply = <&pm8998_l25>;
+
+		qca,bt-vdd-io-voltage-level = <1352000 1352000>;
+		qca,bt-vdd-xtal-voltage-level = <2040000 2040000>;
+		qca,bt-vdd-core-voltage-level = <1800000 1800000>;
+		qca,bt-vdd-pa-voltage-level = <1304000 1304000>;
+		qca,bt-vdd-ldo-voltage-level = <3312000 3312000>;
+
+		qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */
+		qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */
+		qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */
+		qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */
+		qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */
+	};
+
 	qrd_batterydata: qcom,battery-data {
 		qcom,batt-id-range-pct = <15>;
 		#include "fg-gen3-batterydata-itech-3000mah.dtsi"
@@ -142,6 +163,7 @@
 	qcom,panel-mode-gpio = <&tlmm 52 0>;
 	qcom,platform-te-gpio = <&tlmm 10 0>;
 	qcom,platform-reset-gpio = <&tlmm 6 0>;
+	qcom,mdss-dsi-panel-orientation = "180";
 };
 
 &dsi_sharp_4k_dsc_video_display {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
index 79ac3b1..19b8744 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
@@ -36,7 +36,7 @@
 			reg = <0x3500 0x100>;
 			regulator-name = "pm8998_s12";
 			regulator-min-microvolt = <568000>;
-			regulator-max-microvolt = <1056000>;
+			regulator-max-microvolt = <1136000>;
 			qcom,enable-time = <500>;
 			regulator-always-on;
 		};
@@ -114,9 +114,9 @@
 				regulator-max-microvolt = <19>;
 
 				qcom,cpr-fuse-corners = <4>;
-				qcom,cpr-fuse-combos = <16>;
-				qcom,cpr-speed-bins = <2>;
-				qcom,cpr-speed-bin-corners = <19 19>;
+				qcom,cpr-fuse-combos = <24>;
+				qcom,cpr-speed-bins = <3>;
+				qcom,cpr-speed-bin-corners = <19 19 19>;
 				qcom,cpr-corners = <19>;
 
 				qcom,cpr-corner-fmax-map = <6 12 17 19>;
@@ -137,6 +137,11 @@
 					<568000  568000  568000  568000  568000
 					 568000  568000  568000  568000  584000
 					 584000  584000  632000  632000  632000
+					 632000  672000  712000  712000>,
+					/* Speed bin 2 */
+					<568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  584000
+					 584000  584000  632000  632000  632000
 					 632000  672000  712000  712000>;
 
 				qcom,cpr-floor-to-ceiling-max-range =
@@ -146,13 +151,30 @@
 					 32000  32000  40000  40000>;
 
 				qcom,corner-frequencies =
+					/* Speed bin 0 */
 					<300000000  422400000  499200000
 					 576000000  652800000  748800000
 					 825600000  902400000  979200000
 					1056000000 1132800000 1209600000
 					1286400000 1363200000 1440000000
 					1516800000 1593600000 1651200000
-					1708800000>;
+					1708800000>,
+					/* Speed bin 1 */
+					<300000000  422400000  499200000
+					 576000000  652800000  748800000
+					 825600000  902400000  979200000
+					1056000000 1132800000 1209600000
+					1286400000 1363200000 1440000000
+					1516800000 1593600000 1651200000
+					1708800000>,
+					/* Speed bin 2 */
+					<300000000  422400000  499200000
+					 576000000  652800000  748800000
+					 825600000  902400000  979200000
+					1056000000 1132800000 1209600000
+					1286400000 1363200000 1440000000
+					1516800000 1593600000 1670400000
+					1747200000>;
 
 				qcom,cpr-ro-scaling-factor =
 					<2594 2795 2576 2761 2469 2673 2198
@@ -185,6 +207,8 @@
 					/* Speed bin 0 */
 					<0 1 1 1 1 1 1 1>,
 					/* Speed bin 1 */
+					<0 1 1 1 1 1 1 1>,
+					/* Speed bin 2 */
 					<0 1 1 1 1 1 1 1>;
 				qcom,allow-aging-open-loop-voltage-adjustment =
 					<1>;
@@ -201,20 +225,41 @@
 			apc0_l3_vreg: regulator {
 				regulator-name = "apc0_l3_corner";
 				regulator-min-microvolt = <1>;
-				regulator-max-microvolt = <11>;
+				regulator-max-microvolt = <13>;
 
 				qcom,cpr-fuse-corners = <4>;
-				qcom,cpr-fuse-combos = <16>;
-				qcom,cpr-speed-bins = <2>;
-				qcom,cpr-speed-bin-corners = <11 11>;
-				qcom,cpr-corners = <11>;
+				qcom,cpr-fuse-combos = <24>;
+				qcom,cpr-speed-bins = <3>;
+				qcom,cpr-speed-bin-corners = <11 11 13>;
+				qcom,cpr-corners =
+					/* Speed bin 0 */
+					<11 11 11 11 11 11 11 11>,
+					/* Speed bin 1 */
+					<11 11 11 11 11 11 11 11>,
+					/* Speed bin 2 */
+					<13 13 13 13 13 13 13 13>;
 
-				qcom,cpr-corner-fmax-map = <4 7 9 11>;
+				qcom,cpr-corner-fmax-map =
+					/* Speed bin 0 */
+					<4 7 9 11>,
+					/* Speed bin 1 */
+					<4 7 9 11>,
+					/* Speed bin 2 */
+					<4 7 9 13>;
 
 				qcom,cpr-voltage-ceiling =
+					/* Speed bin 0 */
 					<872000  872000  872000  872000  872000
 					 872000  872000  872000  928000  996000
-					 996000>;
+					 996000>,
+					/* Speed bin 1 */
+					<872000  872000  872000  872000  872000
+					 872000  872000  872000  928000  996000
+					 996000>,
+					/* Speed bin 2 */
+					<872000  872000  872000  872000  872000
+					 872000  872000  872000  928000  996000
+					 996000  996000  996000>;
 
 				qcom,cpr-voltage-floor =
 					/* Speed bin 0 */
@@ -224,18 +269,43 @@
 					/* Speed bin 1 */
 					<568000  568000  568000  568000  568000
 					 584000  584000  632000  672000  712000
-					 712000>;
+					 712000>,
+					/* Speed bin 2 */
+					<568000  568000  568000  568000  568000
+					 584000  584000  632000  672000  712000
+					 712000  712000  712000>;
 
 				qcom,cpr-floor-to-ceiling-max-range =
+					/* Speed bin 0 */
 					<32000  32000  32000  32000  32000
 					 32000  32000  32000  32000  40000
-					 40000>;
+					 40000>,
+					/* Speed bin 1 */
+					<32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  40000
+					 40000>,
+					/* Speed bin 2 */
+					<32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  40000
+					 40000  40000  40000>;
 
 				qcom,corner-frequencies =
+					/* Speed bin 0 */
 					<300000000  422400000  499200000
 					 576000000  652800000  729600000
 					 806400000  883200000  960000000
-					1036800000 1094400000>;
+					1036800000 1094400000>,
+					/* Speed bin 1 */
+					<300000000  422400000  499200000
+					 576000000  652800000  729600000
+					 806400000  883200000  960000000
+					1036800000 1094400000>,
+					/* Speed bin 2 */
+					<300000000  422400000  499200000
+					 576000000  652800000  729600000
+					 806400000  883200000  960000000
+					1036800000 1113600000 1209600000
+					1305600000>;
 
 				qcom,cpr-ro-scaling-factor =
 					<2857 3056 2828 2952 2699 2796 2447
@@ -262,12 +332,14 @@
 				qcom,cpr-scaled-open-loop-voltage-as-ceiling;
 
 				qcom,cpr-aging-max-voltage-adjustment = <15000>;
-				qcom,cpr-aging-ref-corner = <11>;
+				qcom,cpr-aging-ref-corner = <11 11 13>;
 				qcom,cpr-aging-ro-scaling-factor = <1620>;
 				qcom,allow-aging-voltage-adjustment =
 					/* Speed bin 0 */
 					<0 1 1 1 1 1 1 1>,
 					/* Speed bin 1 */
+					<0 1 1 1 1 1 1 1>,
+					/* Speed bin 2 */
 					<0 1 1 1 1 1 1 1>;
 				qcom,allow-aging-open-loop-voltage-adjustment =
 					<1>;
@@ -320,7 +392,7 @@
 		qcom,cpr-panic-reg-name-list =
 			"APSS_GOLD_CPRH_STATUS_0", "GOLD_SAW4_PMIC_STS";
 
-		qcom,cpr-aging-ref-voltage = <1056000>;
+		qcom,cpr-aging-ref-voltage = <1136000>;
 		vdd-supply = <&pm8998_s12>;
 
 		thread@0 {
@@ -333,23 +405,27 @@
 			apc1_perfcl_vreg: regulator {
 				regulator-name = "apc1_perfcl_corner";
 				regulator-min-microvolt = <1>;
-				regulator-max-microvolt = <26>;
+				regulator-max-microvolt = <27>;
 
 				qcom,cpr-fuse-corners = <3>;
-				qcom,cpr-fuse-combos = <16>;
-				qcom,cpr-speed-bins = <2>;
-				qcom,cpr-speed-bin-corners = <22 24>;
+				qcom,cpr-fuse-combos = <24>;
+				qcom,cpr-speed-bins = <3>;
+				qcom,cpr-speed-bin-corners = <22 24 25>;
 				qcom,cpr-corners =
 					/* Speed bin 0 */
 					<22 22 22 22 22 22 22 22>,
 					/* Speed bin 1 */
-					<24 24 24 24 24 24 24 24>;
+					<24 24 24 24 24 24 24 24>,
+					/* Speed bin 2 */
+					<25 25 25 25 25 25 25 25>;
 
 				qcom,cpr-corner-fmax-map =
 					/* Speed bin 0 */
 					<10 17 22>,
 					/* Speed bin 1 */
-					<10 17 24>;
+					<10 17 24>,
+					/* Speed bin 2 */
+					<10 17 25>;
 
 				qcom,cpr-voltage-ceiling =
 					/* Speed bin 0 */
@@ -357,13 +433,20 @@
 					 828000  828000  828000  828000  828000
 					 828000  828000  828000  828000  828000
 					 828000  828000  884000  952000  952000
-					1056000 1056000>,
+					1136000 1136000>,
 					/* Speed bin 1 */
 					<828000  828000  828000  828000  828000
 					 828000  828000  828000  828000  828000
 					 828000  828000  828000  828000  828000
 					 828000  828000  884000  952000  952000
-					1056000 1056000 1056000 1056000>;
+					1136000 1136000 1136000 1136000>,
+					/* Speed bin 2 */
+					<828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  828000  884000  952000  952000
+					1136000 1136000 1136000 1136000
+					1136000>;
 
 				qcom,cpr-voltage-floor =
 					/* Speed bin 0 */
@@ -377,7 +460,14 @@
 					 568000  568000  568000  568000  568000
 					 584000  584000  632000  632000  632000
 					 632000  632000  672000  712000  712000
-					 772000  772000  772000  772000>;
+					 772000  772000  772000  772000>,
+					/* Speed bin 2 */
+					<568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 584000  584000  632000  632000  632000
+					 632000  632000  672000  712000  712000
+					 772000  772000  772000  772000
+					 772000>;
 
 				qcom,cpr-floor-to-ceiling-max-range =
 					/* Speed bin 0 */
@@ -391,7 +481,13 @@
 					 32000  32000  32000  32000  32000
 					 32000  32000  32000  32000  32000
 					 32000  32000  40000  40000  40000
-					 40000  40000  40000  40000>;
+					 40000  40000  40000  40000>,
+					/* Speed bin 2 */
+					<32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  40000  40000  40000
+					 40000  40000  40000  40000  40000>;
 
 				qcom,corner-frequencies =
 					/* Speed bin 0 */
@@ -411,7 +507,17 @@
 					1267200000 1344000000 1420800000
 					1497600000 1574400000 1651200000
 					1728000000 1804800000 1881600000
-					1958400000 2035200000 2092800000>;
+					1958400000 2035200000 2092800000>,
+					/* Speed bin 2 */
+					<300000000  422400000  499200000
+					 576000000  652800000  729600000
+					 806400000  883200000  960000000
+					1036800000 1113600000 1190400000
+					1267200000 1344000000 1420800000
+					1497600000 1574400000 1651200000
+					1728000000 1804800000 1881600000
+					1958400000 2035200000 2112000000
+					2208000000>;
 
 				qcom,cpr-ro-scaling-factor =
 					<2857 3056 2828 2952 2699 2796 2447
@@ -425,22 +531,76 @@
 					 2003 1675>;
 
 				qcom,cpr-open-loop-voltage-fuse-adjustment =
-					<100000 100000 100000>;
+					/* Speed bin 0 */
+					<100000 100000 100000>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					/* Speed bin 1 */
+					<100000 100000 100000>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					/* Speed bin 2 */
+					<100000 100000 100000>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>;
 
 				qcom,cpr-closed-loop-voltage-fuse-adjustment =
-					<100000 100000 100000>;
+					/* Speed bin 0 */
+					<100000 100000 100000>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					/* Speed bin 1 */
+					<100000 100000 100000>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					/* Speed bin 2 */
+					<100000 100000 100000>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>,
+					<     0      0      0>;
 
 				qcom,allow-voltage-interpolation;
 				qcom,allow-quotient-interpolation;
 				qcom,cpr-scaled-open-loop-voltage-as-ceiling;
 
 				qcom,cpr-aging-max-voltage-adjustment = <15000>;
-				qcom,cpr-aging-ref-corner = <22 24>;
+				qcom,cpr-aging-ref-corner = <22 24 25>;
 				qcom,cpr-aging-ro-scaling-factor = <1700>;
 				qcom,allow-aging-voltage-adjustment =
 					/* Speed bin 0 */
 					<0 1 1 1 1 1 1 1>,
 					/* Speed bin 1 */
+					<0 1 1 1 1 1 1 1>,
+					/* Speed bin 2 */
 					<0 1 1 1 1 1 1 1>;
 				qcom,allow-aging-open-loop-voltage-adjustment =
 					<1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index df2e0c7..e92bfd9 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -14,9 +14,11 @@
 	mdss_mdp: qcom,mdss_mdp@ae00000 {
 		compatible = "qcom,sde-kms";
 		reg = <0x0ae00000 0x81d40>,
-		      <0x0aeb0000 0x2008>;
+		      <0x0aeb0000 0x2008>,
+		      <0x0aeac000 0xf0>;
 		reg-names = "mdp_phys",
-			"vbif_phys";
+			"vbif_phys",
+			"regdma_phys";
 
 		clocks =
 			<&clock_gcc GCC_DISP_AHB_CLK>,
@@ -56,7 +58,7 @@
 		qcom,sde-mixer-size = <0x320>;
 
 		qcom,sde-dspp-off = <0x55000 0x57000 0x59000 0x5b000>;
-		qcom,sde-dspp-size = <0x4>;
+		qcom,sde-dspp-size = <0x17e0>;
 
 		qcom,sde-wb-off = <0x66000>;
 		qcom,sde-wb-size = <0x2c8>;
@@ -97,6 +99,8 @@
 					1 5 9 13>;
 		qcom,sde-sspp-excl-rect = <1 1 1 1
 						1 1 1 1>;
+		qcom,sde-sspp-smart-dma-priority = <5 6 7 8 1 2 3 4>;
+		qcom,sde-smart-dma-rev = "smart_dma_v2";
 
 		qcom,sde-mixer-pair-mask = <2 1 6 0 0 3>;
 
@@ -126,6 +130,8 @@
 		qcom,sde-max-bw-high-kbps = <9600000>;
 		qcom,sde-dram-channels = <2>;
 		qcom,sde-num-nrt-paths = <0>;
+		qcom,sde-dspp-ad-version = <0x00040000>;
+		qcom,sde-dspp-ad-off = <0x28000 0x27000>;
 
 		qcom,sde-vbif-off = <0>;
 		qcom,sde-vbif-size = <0x1040>;
@@ -133,12 +139,22 @@
 
 		qcom,sde-inline-rotator = <&mdss_rotator 0>;
 
+		qcom,sde-reg-dma-off = <0>;
+		qcom,sde-reg-dma-version = <0x1>;
+		qcom,sde-reg-dma-trigger-off = <0x119c>;
+
 		qcom,sde-sspp-vig-blocks {
 			qcom,sde-vig-csc-off = <0x1a00>;
 			qcom,sde-vig-qseed-off = <0xa00>;
 			qcom,sde-vig-qseed-size = <0xa0>;
 		};
 
+		qcom,sde-dspp-blocks {
+			qcom,sde-dspp-vlut = <0xa00 0x00010008>;
+			qcom,sde-dspp-gamut = <0x1000 0x00040000>;
+			qcom,sde-dspp-gc = <0x17c0 0x00010008>;
+		};
+
 		qcom,platform-supply-entries {
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index dddd241..c806627 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -69,11 +69,14 @@
 			};
 			L1_I_0: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
 			};
 			L1_D_0: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
+			};
+			L1_TLB_0: l1-tlb {
+				qcom,dump-size = <0x3000>;
 			};
 		};
 
@@ -97,11 +100,14 @@
 			};
 			L1_I_100: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
 			};
 			L1_D_100: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
+			};
+			L1_TLB_100: l1-tlb {
+				qcom,dump-size = <0x3000>;
 			};
 		};
 
@@ -125,11 +131,14 @@
 			};
 			L1_I_200: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
 			};
 			L1_D_200: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
+			};
+			L1_TLB_200: l1-tlb {
+				qcom,dump-size = <0x3000>;
 			};
 		};
 
@@ -153,11 +162,14 @@
 			};
 			L1_I_300: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
 			};
 			L1_D_300: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x9000>;
+				qcom,dump-size = <0xa000>;
+			};
+			L1_TLB_300: l1-tlb {
+				qcom,dump-size = <0x3000>;
 			};
 		};
 
@@ -181,11 +193,14 @@
 			};
 			L1_I_400: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
 			};
 			L1_D_400: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
+			};
+			L1_TLB_400: l1-tlb {
+				qcom,dump-size = <0x3c000>;
 			};
 		};
 
@@ -209,11 +224,14 @@
 			};
 			L1_I_500: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
 			};
 			L1_D_500: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
+			};
+			L1_TLB_500: l1-tlb {
+				qcom,dump-size = <0x3c000>;
 			};
 		};
 
@@ -237,11 +255,14 @@
 			};
 			L1_I_600: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
 			};
 			L1_D_600: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
+			};
+			L1_TLB_600: l1-tlb {
+				qcom,dump-size = <0x3c000>;
 			};
 		};
 
@@ -265,11 +286,14 @@
 			};
 			L1_I_700: l1-icache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
 			};
 			L1_D_700: l1-dcache {
 				compatible = "arm,arch-cache";
-				qcom,dump-size = <0x12000>;
+				qcom,dump-size = <0x14000>;
+			};
+			L1_TLB_700: l1-tlb {
+				qcom,dump-size = <0x3c000>;
 			};
 		};
 
@@ -363,7 +387,7 @@
 			       1024 1131 /* 1958400 */
 			>;
 			idle-cost-data = <
-				520 500 480 460
+				100 80 60 40
 			>;
 		};
 		CLUSTER_COST_0: cluster-cost0 {
@@ -428,6 +452,13 @@
 
 	soc: soc { };
 
+	vendor: vendor {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0 0xffffffff>;
+		compatible = "simple-bus";
+	};
+
 	reserved-memory {
 		#address-cells = <2>;
 		#size-cells = <2>;
@@ -536,6 +567,12 @@
 			size = <0 0x5c00000>;
 		};
 
+		dump_mem: mem_dump_region {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0 0x2400000>;
+		};
+
 		/* global autoconfigured region for contiguous allocations */
 		linux,cma {
 			compatible = "shared-dma-pool";
@@ -980,6 +1017,35 @@
 		interrupts = <1 5 4>;
 	};
 
+	mincpubw: qcom,mincpubw {
+		compatible = "qcom,devbw";
+		governor = "powersave";
+		qcom,src-dst-ports = <1 512>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			<  762 /*  200 MHz */ >,
+			< 1144 /*  300 MHz */ >,
+			< 1720 /*  451 MHz */ >,
+			< 2086 /*  547 MHz */ >,
+			< 2597 /*  681 MHz */ >,
+			< 2929 /*  768 MHz */ >,
+			< 3879 /* 1017 MHz */ >,
+			< 4943 /* 1296 MHz */ >,
+			< 5931 /* 1555 MHz */ >,
+			< 6881 /* 1804 MHz */ >;
+	};
+
+	devfreq-cpufreq {
+		mincpubw-cpufreq {
+			target-dev = <&mincpubw>;
+			cpu-to-dev-map-0 =
+				< 1708800  762 >;
+			cpu-to-dev-map-4 =
+				< 2035200  762 >,
+				< 2092800 2597 >;
+		};
+	};
+
 	clock_rpmh: qcom,rpmhclk {
 		compatible = "qcom,rpmh-clk-sdm845";
 		#clock-cells = <1>;
@@ -1652,7 +1718,7 @@
 	qcom,ssc@5c00000 {
 		compatible = "qcom,pil-tz-generic";
 		reg = <0x5c00000 0x4000>;
-		interrupts = <0 377 1>;
+		interrupts = <0 494 1>;
 
 		vdd_cx-supply = <&pm8998_l27_level>;
 		vdd_px-supply = <&pm8998_lvs2>;
@@ -2036,6 +2102,38 @@
 			qcom,dump-node = <&LLCC_4>;
 			qcom,dump-id = <0x124>;
 		};
+		qcom,l1_tlb_dump0 {
+			qcom,dump-node = <&L1_TLB_0>;
+			qcom,dump-id = <0x20>;
+		};
+		qcom,l1_tlb_dump100 {
+			qcom,dump-node = <&L1_TLB_100>;
+			qcom,dump-id = <0x21>;
+		};
+		qcom,l1_tlb_dump200 {
+			qcom,dump-node = <&L1_TLB_200>;
+			qcom,dump-id = <0x22>;
+		};
+		qcom,l1_tlb_dump300 {
+			qcom,dump-node = <&L1_TLB_300>;
+			qcom,dump-id = <0x23>;
+		};
+		qcom,l1_tlb_dump400 {
+			qcom,dump-node = <&L1_TLB_400>;
+			qcom,dump-id = <0x24>;
+		};
+		qcom,l1_tlb_dump500 {
+			qcom,dump-node = <&L1_TLB_500>;
+			qcom,dump-id = <0x25>;
+		};
+		qcom,l1_tlb_dump600 {
+			qcom,dump-node = <&L1_TLB_600>;
+			qcom,dump-id = <0x26>;
+		};
+		qcom,l1_tlb_dump700 {
+			qcom,dump-node = <&L1_TLB_700>;
+			qcom,dump-id = <0x27>;
+		};
 	};
 
 	kryo3xx-erp {
@@ -2423,6 +2521,14 @@
 		qcom,pipe-attr-ee;
 	};
 
+	qcom,qbt1000 {
+		compatible = "qcom,qbt1000";
+		clock-names = "core", "iface";
+		clock-frequency = <25000000>;
+		qcom,ipc-gpio = <&tlmm 121 0>;
+		qcom,finger-detect-gpio = <&pm8998_gpios 5 0>;
+	};
+
 	qcom_seecom: qseecom@86d00000 {
 		compatible = "qcom,qseecom";
 		reg = <0x86d00000 0x2200000>;
@@ -2797,7 +2903,7 @@
 			thermal-sensors = <&tsens0 0>;
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2811,7 +2917,7 @@
 			thermal-sensors = <&tsens0 1>;
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2825,7 +2931,7 @@
 			thermal-sensors = <&tsens0 2>;
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2839,7 +2945,7 @@
 			thermal-sensors = <&tsens0 3>;
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2853,7 +2959,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2867,7 +2973,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2881,7 +2987,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2895,7 +3001,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2909,7 +3015,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2923,7 +3029,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2937,7 +3043,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2951,7 +3057,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2965,7 +3071,7 @@
 			thermal-sensors = <&tsens0 12>;
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2979,7 +3085,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -2993,7 +3099,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3009,7 +3115,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3023,7 +3129,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3037,7 +3143,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3051,7 +3157,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3065,7 +3171,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3079,7 +3185,7 @@
 			thermal-governor = "user_space";
 			trips {
 				active-config0 {
-					temperature = <65000>;
+					temperature = <125000>;
 					hysteresis = <1000>;
 					type = "passive";
 				};
@@ -3811,6 +3917,73 @@
 		interrupt-names = "tsens-upper-lower", "tsens-critical";
 		#thermal-sensor-cells = <1>;
 	};
+
+	mem_dump {
+		compatible = "qcom,mem-dump";
+		memory-region = <&dump_mem>;
+
+		rpmh_dump {
+			qcom,dump-size = <0x2000000>;
+			qcom,dump-id = <0xec>;
+		};
+
+		rpm_sw_dump {
+			qcom,dump-size = <0x28000>;
+			qcom,dump-id = <0xea>;
+		};
+
+		pmic_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xe4>;
+		};
+
+		tmc_etf_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xf0>;
+		};
+
+		tmc_etf_swao_dump {
+			qcom,dump-size = <0x8400>;
+			qcom,dump-id = <0xf1>;
+		};
+
+		misc_data_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0xe8>;
+		};
+	};
+
+	gpi_dma0: qcom,gpi-dma@0x800000 {
+		#dma-cells = <6>;
+		compatible = "qcom,gpi-dma";
+		reg = <0x800000 0x60000>;
+		reg-names = "gpi-top";
+		interrupts = <0 244 0>, <0 245 0>, <0 246 0>, <0 247 0>,
+			     <0 248 0>, <0 249 0>, <0 250 0>, <0 251 0>,
+			     <0 252 0>, <0 253 0>, <0 254 0>, <0 255 0>,
+			     <0 256 0>;
+		qcom,max-num-gpii = <13>;
+		qcom,gpii-mask = <0xfa>;
+		qcom,ev-factor = <2>;
+		iommus = <&apps_smmu 0x0016 0x0>;
+		status = "ok";
+	};
+
+	gpi_dma1: qcom,gpi-dma@0xa00000 {
+		#dma-cells = <6>;
+		compatible = "qcom,gpi-dma";
+		reg = <0xa00000 0x60000>;
+		reg-names = "gpi-top";
+		interrupts = <0 279 0>, <0 280 0>, <0 281 0>, <0 282 0>,
+			     <0 283 0>, <0 284 0>, <0 293 0>, <0 294 0>,
+			     <0 295 0>, <0 296 0>, <0 297 0>, <0 298 0>,
+			     <0 299 0>;
+		qcom,max-num-gpii = <13>;
+		qcom,gpii-mask = <0xfa>;
+		qcom,ev-factor = <2>;
+		iommus = <&apps_smmu 0x06d6 0x0>;
+		status = "ok";
+	};
 };
 
 &clock_cpucc {
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 10b44f8..12b1f09 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -491,6 +491,7 @@
 CONFIG_MSM_AVTIMER=y
 CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_PM=y
+CONFIG_MSM_QBT1000=y
 CONFIG_APSS_CORE_EA=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
@@ -546,6 +547,7 @@
 CONFIG_CORESIGHT_DUMMY=y
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
 CONFIG_CRYPTO_XCBC=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 737f47f..23b1215 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -513,6 +513,7 @@
 CONFIG_MSM_AVTIMER=y
 CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_PM=y
+CONFIG_MSM_QBT1000=y
 CONFIG_APSS_CORE_EA=y
 CONFIG_QCOM_DCC_V2=y
 CONFIG_QTI_RPM_STATS_LOG=y
@@ -619,6 +620,7 @@
 CONFIG_CORESIGHT_DUMMY=y
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
 CONFIG_CRYPTO_XCBC=y
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index f5ea0ba..fe39e68 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -240,6 +240,12 @@
 	return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE;
 }
 
+static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
+{
+	u32 esr = kvm_vcpu_get_hsr(vcpu);
+	return (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT;
+}
+
 static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
 {
 	return vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index da845fd..fe8f94a 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -277,12 +277,10 @@
 	}
 	if (!user_mode(regs))
 		show_extra_register_data(regs, 64);
-	printk("\n");
 }
 
 void show_regs(struct pt_regs * regs)
 {
-	printk("\n");
 	__show_regs(regs);
 }
 
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 87e7e66..7cee552 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1573,8 +1573,8 @@
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	int Rt = (hsr >> 5) & 0xf;
-	int Rt2 = (hsr >> 10) & 0xf;
+	int Rt = kvm_vcpu_sys_get_rt(vcpu);
+	int Rt2 = (hsr >> 10) & 0x1f;
 
 	params.is_aarch32 = true;
 	params.is_32bit = false;
@@ -1625,7 +1625,7 @@
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	int Rt  = (hsr >> 5) & 0xf;
+	int Rt  = kvm_vcpu_sys_get_rt(vcpu);
 
 	params.is_aarch32 = true;
 	params.is_32bit = true;
@@ -1740,7 +1740,7 @@
 {
 	struct sys_reg_params params;
 	unsigned long esr = kvm_vcpu_get_hsr(vcpu);
-	int Rt = (esr >> 5) & 0x1f;
+	int Rt = kvm_vcpu_sys_get_rt(vcpu);
 	int ret;
 
 	trace_kvm_handle_sys_reg(esr);
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 837bbab..75088c00 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -943,6 +943,8 @@
 	.sync_single_for_device = __iommu_sync_single_for_device,
 	.sync_sg_for_cpu = __iommu_sync_sg_for_cpu,
 	.sync_sg_for_device = __iommu_sync_sg_for_device,
+	.map_resource = iommu_dma_map_resource,
+	.unmap_resource = iommu_dma_unmap_resource,
 	.dma_supported = iommu_dma_supported,
 	.mapping_error = iommu_dma_mapping_error,
 };
@@ -1847,6 +1849,45 @@
 		__dma_page_cpu_to_dev(page, offset, size, dir);
 }
 
+static dma_addr_t arm_iommu_dma_map_resource(
+			struct device *dev, phys_addr_t phys_addr,
+			size_t size, enum dma_data_direction dir,
+			unsigned long attrs)
+{
+	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+	size_t offset = phys_addr & ~PAGE_MASK;
+	size_t len = PAGE_ALIGN(size + offset);
+	dma_addr_t dma_addr;
+	int prot;
+
+	dma_addr = __alloc_iova(mapping, len);
+	if (dma_addr == DMA_ERROR_CODE)
+		return dma_addr;
+
+	prot = __dma_direction_to_prot(dir);
+	prot |= IOMMU_MMIO;
+
+	if (iommu_map(mapping->domain, dma_addr, phys_addr - offset,
+			len, prot)) {
+		__free_iova(mapping, dma_addr, len);
+		return DMA_ERROR_CODE;
+	}
+	return dma_addr + offset;
+}
+
+static void arm_iommu_dma_unmap_resource(
+			struct device *dev, dma_addr_t addr,
+			size_t size, enum dma_data_direction dir,
+			unsigned long attrs)
+{
+	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+	size_t offset = addr & ~PAGE_MASK;
+	size_t len = PAGE_ALIGN(size + offset);
+
+	iommu_unmap(mapping->domain, addr - offset, len);
+	__free_iova(mapping, addr - offset, len);
+}
+
 static int arm_iommu_mapping_error(struct device *dev,
 				   dma_addr_t dma_addr)
 {
@@ -1869,6 +1910,9 @@
 	.sync_sg_for_cpu	= arm_iommu_sync_sg_for_cpu,
 	.sync_sg_for_device	= arm_iommu_sync_sg_for_device,
 
+	.map_resource		= arm_iommu_dma_map_resource,
+	.unmap_resource		= arm_iommu_dma_unmap_resource,
+
 	.set_dma_mask		= arm_dma_set_mask,
 	.mapping_error		= arm_iommu_mapping_error,
 };
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 34d2c59..7362267 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -561,6 +561,7 @@
 static struct pstore_info nvram_pstore_info = {
 	.owner = THIS_MODULE,
 	.name = "nvram",
+	.flags = PSTORE_FLAGS_DMESG,
 	.open = nvram_pstore_open,
 	.read = nvram_pstore_read,
 	.write = nvram_pstore_write,
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index e5612f3..d7ac721 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -16,7 +16,7 @@
 #ifndef BOOT_BOOT_H
 #define BOOT_BOOT_H
 
-#define STACK_SIZE	512	/* Minimum number of bytes for stack */
+#define STACK_SIZE	1024	/* Minimum number of bytes for stack */
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
index 0a535ce..8b902b6 100644
--- a/arch/x86/events/intel/rapl.c
+++ b/arch/x86/events/intel/rapl.c
@@ -759,7 +759,7 @@
 
 	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_CORE,   hsw_rapl_init),
 	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_GT3E,   hsw_rapl_init),
-	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X,	  hsw_rapl_init),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X,	  hsx_rapl_init),
 	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsw_rapl_init),
 
 	X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_rapl_init),
diff --git a/arch/x86/include/asm/pmem.h b/arch/x86/include/asm/pmem.h
index 529bb4a..e290437 100644
--- a/arch/x86/include/asm/pmem.h
+++ b/arch/x86/include/asm/pmem.h
@@ -103,7 +103,7 @@
 
 		if (bytes < 8) {
 			if (!IS_ALIGNED(dest, 4) || (bytes != 4))
-				arch_wb_cache_pmem(addr, 1);
+				arch_wb_cache_pmem(addr, bytes);
 		} else {
 			if (!IS_ALIGNED(dest, 8)) {
 				dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e5bc139..43c1528 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3051,6 +3051,12 @@
 	    (events->exception.nr > 31 || events->exception.nr == NMI_VECTOR))
 		return -EINVAL;
 
+	/* INITs are latched while in SMM */
+	if (events->flags & KVM_VCPUEVENT_VALID_SMM &&
+	    (events->smi.smm || events->smi.pending) &&
+	    vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED)
+		return -EINVAL;
+
 	process_nmi(vcpu);
 	vcpu->arch.exception.pending = events->exception.injected;
 	vcpu->arch.exception.nr = events->exception.nr;
@@ -7162,6 +7168,12 @@
 	    mp_state->mp_state != KVM_MP_STATE_RUNNABLE)
 		return -EINVAL;
 
+	/* INITs are latched while in SMM */
+	if ((is_smm(vcpu) || vcpu->arch.smi_pending) &&
+	    (mp_state->mp_state == KVM_MP_STATE_SIPI_RECEIVED ||
+	     mp_state->mp_state == KVM_MP_STATE_INIT_RECEIVED))
+		return -EINVAL;
+
 	if (mp_state->mp_state == KVM_MP_STATE_SIPI_RECEIVED) {
 		vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
 		set_bit(KVM_APIC_SIPI, &vcpu->arch.apic->pending_events);
diff --git a/arch/x86/um/ptrace_64.c b/arch/x86/um/ptrace_64.c
index e30202b..7c16017 100644
--- a/arch/x86/um/ptrace_64.c
+++ b/arch/x86/um/ptrace_64.c
@@ -125,7 +125,7 @@
 	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
 		(addr <= offsetof(struct user, u_debugreg[7]))) {
 		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
+		addr = addr >> 3;
 		if ((addr == 4) || (addr == 5))
 			return -EIO;
 		child->thread.arch.debugregs[addr] = data;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 7d5afdb..418f1b8 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2028,7 +2028,8 @@
 
 /*
  * Translate a virtual address to a physical one without relying on mapped
- * page tables.
+ * page tables. Don't rely on big pages being aligned in (guest) physical
+ * space!
  */
 static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr)
 {
@@ -2049,7 +2050,7 @@
 						       sizeof(pud)));
 	if (!pud_present(pud))
 		return 0;
-	pa = pud_pfn(pud) << PAGE_SHIFT;
+	pa = pud_val(pud) & PTE_PFN_MASK;
 	if (pud_large(pud))
 		return pa + (vaddr & ~PUD_MASK);
 
@@ -2057,7 +2058,7 @@
 						       sizeof(pmd)));
 	if (!pmd_present(pmd))
 		return 0;
-	pa = pmd_pfn(pmd) << PAGE_SHIFT;
+	pa = pmd_val(pmd) & PTE_PFN_MASK;
 	if (pmd_large(pmd))
 		return pa + (vaddr & ~PMD_MASK);
 
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index 319f2e4..478f572 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -412,7 +412,8 @@
 
 	bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE |
 		template->flags;
-	bi->interval_exp = ilog2(queue_logical_block_size(disk->queue));
+	bi->interval_exp = template->interval_exp ? :
+		ilog2(queue_logical_block_size(disk->queue));
 	bi->profile = template->profile ? template->profile : &nop_profile;
 	bi->tuple_size = template->tuple_size;
 	bi->tag_size = template->tag_size;
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index fde8d88..6c11537 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -44,6 +44,11 @@
 	char iv[];
 };
 
+struct aead_tfm {
+	struct crypto_aead *aead;
+	bool has_key;
+};
+
 struct aead_ctx {
 	struct aead_sg_list tsgl;
 	struct aead_async_rsgl first_rsgl;
@@ -732,24 +737,146 @@
 	.poll		=	aead_poll,
 };
 
+static int aead_check_key(struct socket *sock)
+{
+	int err = 0;
+	struct sock *psk;
+	struct alg_sock *pask;
+	struct aead_tfm *tfm;
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+
+	lock_sock(sk);
+	if (ask->refcnt)
+		goto unlock_child;
+
+	psk = ask->parent;
+	pask = alg_sk(ask->parent);
+	tfm = pask->private;
+
+	err = -ENOKEY;
+	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
+	if (!tfm->has_key)
+		goto unlock;
+
+	if (!pask->refcnt++)
+		sock_hold(psk);
+
+	ask->refcnt = 1;
+	sock_put(psk);
+
+	err = 0;
+
+unlock:
+	release_sock(psk);
+unlock_child:
+	release_sock(sk);
+
+	return err;
+}
+
+static int aead_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
+				  size_t size)
+{
+	int err;
+
+	err = aead_check_key(sock);
+	if (err)
+		return err;
+
+	return aead_sendmsg(sock, msg, size);
+}
+
+static ssize_t aead_sendpage_nokey(struct socket *sock, struct page *page,
+				       int offset, size_t size, int flags)
+{
+	int err;
+
+	err = aead_check_key(sock);
+	if (err)
+		return err;
+
+	return aead_sendpage(sock, page, offset, size, flags);
+}
+
+static int aead_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
+				  size_t ignored, int flags)
+{
+	int err;
+
+	err = aead_check_key(sock);
+	if (err)
+		return err;
+
+	return aead_recvmsg(sock, msg, ignored, flags);
+}
+
+static struct proto_ops algif_aead_ops_nokey = {
+	.family		=	PF_ALG,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.bind		=	sock_no_bind,
+	.accept		=	sock_no_accept,
+	.setsockopt	=	sock_no_setsockopt,
+
+	.release	=	af_alg_release,
+	.sendmsg	=	aead_sendmsg_nokey,
+	.sendpage	=	aead_sendpage_nokey,
+	.recvmsg	=	aead_recvmsg_nokey,
+	.poll		=	aead_poll,
+};
+
 static void *aead_bind(const char *name, u32 type, u32 mask)
 {
-	return crypto_alloc_aead(name, type, mask);
+	struct aead_tfm *tfm;
+	struct crypto_aead *aead;
+
+	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+	if (!tfm)
+		return ERR_PTR(-ENOMEM);
+
+	aead = crypto_alloc_aead(name, type, mask);
+	if (IS_ERR(aead)) {
+		kfree(tfm);
+		return ERR_CAST(aead);
+	}
+
+	tfm->aead = aead;
+
+	return tfm;
 }
 
 static void aead_release(void *private)
 {
-	crypto_free_aead(private);
+	struct aead_tfm *tfm = private;
+
+	crypto_free_aead(tfm->aead);
+	kfree(tfm);
 }
 
 static int aead_setauthsize(void *private, unsigned int authsize)
 {
-	return crypto_aead_setauthsize(private, authsize);
+	struct aead_tfm *tfm = private;
+
+	return crypto_aead_setauthsize(tfm->aead, authsize);
 }
 
 static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
 {
-	return crypto_aead_setkey(private, key, keylen);
+	struct aead_tfm *tfm = private;
+	int err;
+
+	err = crypto_aead_setkey(tfm->aead, key, keylen);
+	tfm->has_key = !err;
+
+	return err;
 }
 
 static void aead_sock_destruct(struct sock *sk)
@@ -766,12 +893,14 @@
 	af_alg_release_parent(sk);
 }
 
-static int aead_accept_parent(void *private, struct sock *sk)
+static int aead_accept_parent_nokey(void *private, struct sock *sk)
 {
 	struct aead_ctx *ctx;
 	struct alg_sock *ask = alg_sk(sk);
-	unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(private);
-	unsigned int ivlen = crypto_aead_ivsize(private);
+	struct aead_tfm *tfm = private;
+	struct crypto_aead *aead = tfm->aead;
+	unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(aead);
+	unsigned int ivlen = crypto_aead_ivsize(aead);
 
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 	if (!ctx)
@@ -798,7 +927,7 @@
 
 	ask->private = ctx;
 
-	aead_request_set_tfm(&ctx->aead_req, private);
+	aead_request_set_tfm(&ctx->aead_req, aead);
 	aead_request_set_callback(&ctx->aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				  af_alg_complete, &ctx->completion);
 
@@ -807,13 +936,25 @@
 	return 0;
 }
 
+static int aead_accept_parent(void *private, struct sock *sk)
+{
+	struct aead_tfm *tfm = private;
+
+	if (!tfm->has_key)
+		return -ENOKEY;
+
+	return aead_accept_parent_nokey(private, sk);
+}
+
 static const struct af_alg_type algif_type_aead = {
 	.bind		=	aead_bind,
 	.release	=	aead_release,
 	.setkey		=	aead_setkey,
 	.setauthsize	=	aead_setauthsize,
 	.accept		=	aead_accept_parent,
+	.accept_nokey	=	aead_accept_parent_nokey,
 	.ops		=	&algif_aead_ops,
+	.ops_nokey	=	&algif_aead_ops_nokey,
 	.name		=	"aead",
 	.owner		=	THIS_MODULE
 };
diff --git a/drivers/Makefile b/drivers/Makefile
index 413dff9..990f63c 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -103,6 +103,7 @@
 obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_PCI)		+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/
+obj-$(CONFIG_OF)		+= usb/
 obj-$(CONFIG_SERIO)		+= input/serio/
 obj-$(CONFIG_GAMEPORT)		+= input/gameport/
 obj-$(CONFIG_INPUT)		+= input/
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 8f6c23c..deed580 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -287,6 +287,9 @@
 
 	hu->priv = bcm;
 
+	if (!hu->tty->dev)
+		goto out;
+
 	mutex_lock(&bcm_device_lock);
 	list_for_each(p, &bcm_device_list) {
 		struct bcm_device *dev = list_entry(p, struct bcm_device, list);
@@ -307,7 +310,7 @@
 	}
 
 	mutex_unlock(&bcm_device_lock);
-
+out:
 	return 0;
 }
 
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index 9e27128..7330638 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -307,6 +307,9 @@
 	struct list_head *p;
 	int err = -ENODEV;
 
+	if (!hu->tty->dev)
+		return err;
+
 	mutex_lock(&intel_device_list_lock);
 
 	list_for_each(p, &intel_device_list) {
@@ -379,6 +382,9 @@
 	struct intel_data *intel = container_of(work, struct intel_data,
 						busy_work);
 
+	if (!intel->hu->tty->dev)
+		return;
+
 	/* Link is busy, delay the suspend */
 	mutex_lock(&intel_device_list_lock);
 	list_for_each(p, &intel_device_list) {
@@ -889,6 +895,8 @@
 	list_for_each(p, &intel_device_list) {
 		struct intel_device *dev = list_entry(p, struct intel_device,
 						      list);
+		if (!hu->tty->dev)
+			break;
 		if (hu->tty->dev->parent == dev->pdev->dev.parent) {
 			if (device_may_wakeup(&dev->pdev->dev)) {
 				set_bit(STATE_LPM_ENABLED, &intel->flags);
@@ -1056,6 +1064,9 @@
 
 	BT_DBG("hu %p skb %p", hu, skb);
 
+	if (!hu->tty->dev)
+		goto out_enqueue;
+
 	/* Be sure our controller is resumed and potential LPM transaction
 	 * completed before enqueuing any packet.
 	 */
@@ -1072,7 +1083,7 @@
 		}
 	}
 	mutex_unlock(&intel_device_list_lock);
-
+out_enqueue:
 	skb_queue_tail(&intel->txq, skb);
 
 	return 0;
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index ee847d9f..3f2ce31 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -2470,7 +2470,7 @@
 			int srcVM[1] = {VMID_HLOS};
 			int destVM[4] = {VMID_HLOS, VMID_MSS_MSA, VMID_SSC_Q6,
 						VMID_ADSP_Q6};
-			int destVMperm[4] = {PERM_READ | PERM_WRITE,
+			int destVMperm[4] = {PERM_READ | PERM_WRITE | PERM_EXEC,
 				PERM_READ | PERM_WRITE | PERM_EXEC,
 				PERM_READ | PERM_WRITE | PERM_EXEC,
 				PERM_READ | PERM_WRITE | PERM_EXEC,
diff --git a/drivers/char/diag/diagfwd_glink.h b/drivers/char/diag/diagfwd_glink.h
index bad4629..73f2fe8 100644
--- a/drivers/char/diag/diagfwd_glink.h
+++ b/drivers/char/diag/diagfwd_glink.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 5673fff..6958b5c 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -892,6 +892,7 @@
 		 * for details on the intricacies of this.
 		 */
 		int left;
+		unsigned char *data_to_send;
 
 		ssif_inc_stat(ssif_info, sent_messages_parts);
 
@@ -900,6 +901,7 @@
 			left = 32;
 		/* Length byte. */
 		ssif_info->multi_data[ssif_info->multi_pos] = left;
+		data_to_send = ssif_info->multi_data + ssif_info->multi_pos;
 		ssif_info->multi_pos += left;
 		if (left < 32)
 			/*
@@ -913,7 +915,7 @@
 		rv = ssif_i2c_send(ssif_info, msg_written_handler,
 				  I2C_SMBUS_WRITE,
 				  SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE,
-				  ssif_info->multi_data + ssif_info->multi_pos,
+				  data_to_send,
 				  I2C_SMBUS_BLOCK_DATA);
 		if (rv < 0) {
 			/* request failed, just return the error. */
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index d15d1bb..fd3617b 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -59,7 +59,6 @@
 
 #define FABIA_USER_CTL_LO	0xc
 #define FABIA_USER_CTL_HI	0x10
-#define FABIA_CAL_L_VAL		0x8
 #define FABIA_FRAC_VAL		0x38
 #define FABIA_OPMODE		0x2c
 #define FABIA_PLL_STANDBY	0x0
@@ -463,12 +462,9 @@
 {
 	u32 val, mask;
 
-	if (config->l) {
+	if (config->l)
 		regmap_write(regmap, pll->offset + PLL_L_VAL,
 						config->l);
-		regmap_write(regmap, pll->offset + FABIA_CAL_L_VAL,
-						config->l);
-	}
 
 	if (config->frac)
 		regmap_write(regmap, pll->offset + FABIA_FRAC_VAL,
@@ -627,12 +623,6 @@
 	}
 
 	regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
-	/*
-	 * pll_cal_l_val is set to pll_l_val on MOST targets. Set it
-	 * explicitly here for PLL out-of-reset calibration to work
-	 * without a glitch on ALL of them.
-	 */
-	regmap_write(pll->clkr.regmap, off + FABIA_CAL_L_VAL, l);
 	regmap_write(pll->clkr.regmap, off + FABIA_FRAC_VAL, a);
 
 	/* Latch the PLL input */
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 3a38d37..7f56fb6 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -174,6 +174,7 @@
 	struct clk_regmap	clkr;
 	u8			flags;
 #define FORCE_ENABLE_RCG	BIT(0)
+#define DFS_ENABLE_RCG		BIT(1)
 };
 
 #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
@@ -187,4 +188,6 @@
 extern const struct clk_ops clk_gfx3d_ops;
 extern const struct clk_ops clk_dp_ops;
 
+extern int clk_rcg2_get_dfs_clock_rate(struct clk_rcg2 *clk,
+				struct device *dev, u8 rcg_flags);
 #endif
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 3d101ac..6bdea53 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -18,6 +18,7 @@
 #include <linux/export.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/regmap.h>
 #include <linux/rational.h>
 #include <linux/math64.h>
@@ -50,6 +51,14 @@
 #define N_REG			0xc
 #define D_REG			0x10
 
+/* Dynamic Frequency Scaling */
+#define MAX_PERF_LEVEL		16
+#define SE_CMD_DFSR_OFFSET	0x14
+#define SE_CMD_DFS_EN		BIT(0)
+#define SE_PERF_DFSR(level)	(0x1c + 0x4 * (level))
+#define SE_PERF_M_DFSR(level)	(0x5c + 0x4 * (level))
+#define SE_PERF_N_DFSR(level)	(0x9c + 0x4 * (level))
+
 static struct freq_tbl cxo_f = {
 	.freq = 19200000,
 	.src = 0,
@@ -127,6 +136,9 @@
 	int ret;
 	u32 cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
 
+	if (rcg->flags & DFS_ENABLE_RCG)
+		return 0;
+
 	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
 				 CFG_SRC_SEL_MASK, cfg);
 	if (ret)
@@ -236,6 +248,9 @@
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask;
 
+	if (rcg->flags & DFS_ENABLE_RCG)
+		return rcg->current_freq;
+
 	if (rcg->enable_safe_config && !clk_hw_is_prepared(hw)) {
 		if (!rcg->current_freq)
 			rcg->current_freq = cxo_f.freq;
@@ -333,6 +348,9 @@
 	struct clk_hw *hw = &rcg->clkr.hw;
 	int ret, index = qcom_find_src_index(hw, rcg->parent_map, f->src);
 
+	if (rcg->flags & DFS_ENABLE_RCG)
+		return -EPERM;
+
 	if (index < 0)
 		return index;
 
@@ -461,7 +479,7 @@
 	}
 
 	ret = clk_rcg2_configure(rcg, f);
-	if (ret)
+	if (ret && ret != -EPERM)
 		return ret;
 
 	if (rcg->flags & FORCE_ENABLE_RCG) {
@@ -1170,3 +1188,167 @@
 	.list_registers = clk_rcg2_list_registers,
 };
 EXPORT_SYMBOL_GPL(clk_gfx3d_ops);
+
+/* Common APIs to be used for DFS based RCGR */
+static u8 clk_parent_index_pre_div_and_mode(struct clk_hw *hw, u32 offset,
+		u32 *mode, u32 *pre_div)
+{
+	struct clk_rcg2 *rcg;
+	int num_parents = clk_hw_get_num_parents(hw);
+	u32 cfg, mask;
+	int i, ret;
+
+	if (!hw)
+		return -EINVAL;
+
+	rcg = to_clk_rcg2(hw);
+
+	ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + offset, &cfg);
+	if (ret)
+		goto err;
+
+	mask = BIT(rcg->hid_width) - 1;
+	*pre_div = cfg & mask ? (cfg & mask) : 1;
+
+	*mode = cfg & CFG_MODE_MASK;
+	*mode >>= CFG_MODE_SHIFT;
+
+	cfg &= CFG_SRC_SEL_MASK;
+	cfg >>= CFG_SRC_SEL_SHIFT;
+
+	for (i = 0; i < num_parents; i++)
+		if (cfg == rcg->parent_map[i].cfg)
+			return i;
+err:
+	pr_debug("%s: Clock %s has invalid parent, using default.\n",
+		 __func__, clk_hw_get_name(hw));
+	return 0;
+}
+
+static int calculate_m_and_n(struct clk_hw *hw, u32 m_offset, u32 n_offset,
+		u32 mode, u32 *m, u32 *n)
+{
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	u32 val, mask;
+	int ret = 0;
+
+	if (!hw)
+		return -EINVAL;
+
+	*m = *n = 0;
+
+	if (mode) {
+		/* Calculate M & N values */
+		mask = BIT(rcg->mnd_width) - 1;
+		ret =  regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + m_offset,
+					&val);
+		if (ret) {
+			pr_err("Failed to read M offset register\n");
+			goto err;
+		}
+
+		val &= mask;
+		*m  = val;
+
+		ret =  regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + n_offset,
+					&val);
+		if (ret) {
+			pr_err("Failed to read N offset register\n");
+			goto err;
+		}
+
+		/* val ~(N-M) */
+		val = ~val;
+		val &= mask;
+		val += *m;
+		*n = val;
+	}
+err:
+	return ret;
+}
+
+int clk_rcg2_get_dfs_clock_rate(struct clk_rcg2 *clk, struct device *dev,
+						u8 rcg_flags)
+{
+	int i, j, index, ret = 0;
+	unsigned long calc_freq, prate;
+	u32 val, pre_div = 0, mode = 0, m = 0, n = 0;
+	struct freq_tbl *dfs_freq_tbl;
+	struct clk_hw *phw;
+
+	if (!clk)
+		return -EINVAL;
+
+	/* Check for DFS_EN */
+	ret = regmap_read(clk->clkr.regmap, clk->cmd_rcgr + SE_CMD_DFSR_OFFSET,
+						&val);
+	if (ret) {
+		dev_err(dev, "Failed to read DFS enable register\n");
+		return -EINVAL;
+	}
+
+	if (!(val & SE_CMD_DFS_EN))
+		return ret;
+
+	dfs_freq_tbl = devm_kzalloc(dev, MAX_PERF_LEVEL *
+				sizeof(struct freq_tbl), GFP_KERNEL);
+	if (!dfs_freq_tbl)
+		return -ENOMEM;
+
+	/* Populate the Perf Level */
+	for (i = 0; i < MAX_PERF_LEVEL; i++) {
+		/* Get parent index and mode */
+		index = clk_parent_index_pre_div_and_mode(&clk->clkr.hw,
+							SE_PERF_DFSR(i), &mode,
+							&pre_div);
+		if (index < 0) {
+			pr_err("Failed to get parent index & mode %d\n", index);
+			return index;
+		}
+
+		/* clock pre_div */
+		dfs_freq_tbl[i].pre_div = pre_div;
+
+		/* Fill the parent src */
+		dfs_freq_tbl[i].src = clk->parent_map[index].src;
+
+		/* Get the parent clock and parent rate */
+		phw = clk_hw_get_parent_by_index(&clk->clkr.hw, index);
+		prate = clk_hw_get_rate(phw);
+
+		ret = calculate_m_and_n(&clk->clkr.hw, SE_PERF_M_DFSR(i),
+					SE_PERF_N_DFSR(i), mode, &m, &n);
+		if (ret)
+			goto err;
+
+		dfs_freq_tbl[i].m = m;
+		dfs_freq_tbl[i].n = n;
+
+		/* calculate the final frequency */
+		calc_freq = calc_rate(prate, dfs_freq_tbl[i].m,
+						dfs_freq_tbl[i].n, mode,
+						dfs_freq_tbl[i].pre_div);
+
+		/* Check for duplicate frequencies */
+		for (j = 0; j  < i; j++) {
+			if (dfs_freq_tbl[j].freq == calc_freq)
+				goto done;
+		}
+
+		dfs_freq_tbl[i].freq = calc_freq;
+	}
+done:
+	j = i;
+
+	for (i = 0; i < j; i++)
+		pr_debug("Index[%d]\tfreq_table.freq %ld\tfreq_table.src %d\t"
+		"freq_table.pre_div %d\tfreq_table.m %d\tfreq_table.n %d\t"
+		"RCG flags %x\n", i, dfs_freq_tbl[i].freq, dfs_freq_tbl[i].src,
+				dfs_freq_tbl[i].pre_div, dfs_freq_tbl[i].m,
+				dfs_freq_tbl[i].n, rcg_flags);
+
+	clk->flags |= rcg_flags;
+	clk->freq_tbl = dfs_freq_tbl;
+err:
+	return ret;
+}
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index fffcbaf..b2ff04a 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 2017, 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
@@ -275,4 +275,26 @@
 }
 EXPORT_SYMBOL_GPL(qcom_cc_probe);
 
+int qcom_cc_register_rcg_dfs(struct platform_device *pdev,
+			 const struct qcom_cc_dfs_desc *desc)
+{
+	struct clk_dfs *clks = desc->clks;
+	size_t num_clks = desc->num_clks;
+	int i, ret = 0;
+
+	for (i = 0; i < num_clks; i++) {
+		ret = clk_rcg2_get_dfs_clock_rate(clks[i].rcg, &pdev->dev,
+						clks[i].rcg_flags);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed calculating DFS frequencies for %s\n",
+				clk_hw_get_name(&(clks[i].rcg)->clkr.hw));
+			break;
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(qcom_cc_register_rcg_dfs);
+
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index e728dec..5e26763 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -14,6 +14,7 @@
 #define __QCOM_CLK_COMMON_H__
 
 #include <linux/reset-controller.h>
+#include "clk-rcg.h"
 
 struct platform_device;
 struct regmap_config;
@@ -40,6 +41,16 @@
 	unsigned long rrate;
 };
 
+struct clk_dfs {
+	struct clk_rcg2 *rcg;
+	u8 rcg_flags;
+};
+
+struct qcom_cc_dfs_desc {
+	struct clk_dfs *clks;
+	size_t num_clks;
+};
+
 extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
 					     unsigned long rate);
 extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
@@ -56,6 +67,10 @@
 				struct regmap *regmap);
 extern int qcom_cc_probe(struct platform_device *pdev,
 			 const struct qcom_cc_desc *desc);
+
+extern int qcom_cc_register_rcg_dfs(struct platform_device *pdev,
+			 const struct qcom_cc_dfs_desc *desc);
+
 extern struct clk_ops clk_dummy_ops;
 
 #define BM(msb, lsb)	(((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c
index 228f716..2742ab3 100644
--- a/drivers/clk/qcom/gcc-sdm845.c
+++ b/drivers/clk/qcom/gcc-sdm845.c
@@ -245,28 +245,6 @@
 	},
 };
 
-static struct clk_alpha_pll gpll1 = {
-	.offset = 0x1000,
-	.vco_table = fabia_vco,
-	.num_vco = ARRAY_SIZE(fabia_vco),
-	.type = FABIA_PLL,
-	.clkr = {
-		.enable_reg = 0x52000,
-		.enable_mask = BIT(1),
-		.hw.init = &(struct clk_init_data){
-			.name = "gpll1",
-			.parent_names = (const char *[]){ "bi_tcxo" },
-			.num_parents = 1,
-			.ops = &clk_fabia_fixed_pll_ops,
-			VDD_CX_FMAX_MAP4(
-				MIN, 615000000,
-				LOW, 1066000000,
-				LOW_L1, 1600000000,
-				NOMINAL, 2000000000),
-		},
-	},
-};
-
 static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = {
 	F(19200000, P_BI_TCXO, 1, 0, 0),
 	{ }
@@ -314,6 +292,7 @@
 };
 
 static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = {
+	F(19200000, P_BI_TCXO, 1, 0, 0),
 	F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
 	F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
 	F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
@@ -448,6 +427,7 @@
 };
 
 static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = {
+	F(9600000, P_BI_TCXO, 2, 0, 0),
 	F(19200000, P_BI_TCXO, 1, 0, 0),
 	F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0),
 	{ }
@@ -808,6 +788,7 @@
 
 static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
 	F(400000, P_BI_TCXO, 12, 1, 4),
+	F(9600000, P_BI_TCXO, 2, 0, 0),
 	F(19200000, P_BI_TCXO, 1, 0, 0),
 	F(25000000, P_GPLL0_OUT_MAIN, 12, 1, 2),
 	F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0),
@@ -839,6 +820,7 @@
 
 static const struct freq_tbl ftbl_gcc_sdcc4_apps_clk_src[] = {
 	F(400000, P_BI_TCXO, 12, 1, 4),
+	F(9600000, P_BI_TCXO, 2, 0, 0),
 	F(19200000, P_BI_TCXO, 1, 0, 0),
 	F(25000000, P_GPLL0_OUT_MAIN, 12, 1, 2),
 	F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0),
@@ -889,12 +871,20 @@
 	},
 };
 
+static const struct freq_tbl ftbl_gcc_ufs_card_axi_clk_src[] = {
+	F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
+	F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+	F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
+	F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
+	{ }
+};
+
 static struct clk_rcg2 gcc_ufs_card_axi_clk_src = {
 	.cmd_rcgr = 0x7501c,
 	.mnd_width = 8,
 	.hid_width = 5,
 	.parent_map = gcc_parent_map_0,
-	.freq_tbl = ftbl_gcc_gp1_clk_src,
+	.freq_tbl = ftbl_gcc_ufs_card_axi_clk_src,
 	.flags = FORCE_ENABLE_RCG,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_ufs_card_axi_clk_src",
@@ -1102,6 +1092,7 @@
 };
 
 static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = {
+	F(19200000, P_BI_TCXO, 1, 0, 0),
 	F(20000000, P_GPLL0_OUT_EVEN, 15, 0, 0),
 	F(40000000, P_GPLL0_OUT_EVEN, 7.5, 0, 0),
 	F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0),
@@ -3476,7 +3467,6 @@
 	[GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr,
 	[GPLL0] = &gpll0.clkr,
 	[GPLL0_OUT_EVEN] = &gpll0_out_even.clkr,
-	[GPLL1] = &gpll1.clkr,
 };
 
 static const struct qcom_reset_map gcc_sdm845_resets[] = {
@@ -3509,6 +3499,31 @@
 	[GCC_PCIE_1_PHY_BCR] = { 0x8e01c },
 };
 
+/* List of RCG clocks and corresponding flags requested for DFS Mode */
+static struct clk_dfs gcc_dfs_clocks[] = {
+	{ &gcc_qupv3_wrap0_s0_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap0_s1_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap0_s2_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap0_s3_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap0_s4_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap0_s5_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap0_s6_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap0_s7_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap1_s0_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap1_s1_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap1_s2_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap1_s3_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap1_s4_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap1_s5_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap1_s6_clk_src, DFS_ENABLE_RCG },
+	{ &gcc_qupv3_wrap1_s7_clk_src, DFS_ENABLE_RCG },
+};
+
+static const struct qcom_cc_dfs_desc gcc_sdm845_dfs_desc = {
+	.clks = gcc_dfs_clocks,
+	.num_clks = ARRAY_SIZE(gcc_dfs_clocks),
+};
+
 static const struct regmap_config gcc_sdm845_regmap_config = {
 	.reg_bits	= 32,
 	.reg_stride	= 4,
@@ -3599,10 +3614,10 @@
 	clk_prepare_enable(gcc_camera_ahb_clk.clkr.hw.clk);
 	clk_prepare_enable(gcc_video_ahb_clk.clkr.hw.clk);
 
-	/*
-	 * TODO:
-	 * 1. QUPv3 support
-	 */
+	/* DFS clock registration */
+	ret = qcom_cc_register_rcg_dfs(pdev, &gcc_sdm845_dfs_desc);
+	if (ret)
+		dev_err(&pdev->dev, "Failed to register with DFS!\n");
 
 	dev_info(&pdev->dev, "Registered GCC clocks\n");
 	return ret;
diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c
index 3bb7c04..90c76e6 100644
--- a/drivers/clk/qcom/gdsc-regulator.c
+++ b/drivers/clk/qcom/gdsc-regulator.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -54,6 +54,9 @@
 /* Timeout Delay */
 #define TIMEOUT_US		100
 
+/* TOGGLE SW COLLAPSE */
+#define TOGGLE_SW_COLLAPSE_IN_DISABLE	BIT(0)
+
 struct gdsc {
 	struct regulator_dev	*rdev;
 	struct regulator_desc	rdesc;
@@ -79,6 +82,7 @@
 	int			reset_count;
 	int			root_clk_idx;
 	u32			gds_timeout;
+	u32			flags;
 };
 
 enum gdscr_status {
@@ -378,6 +382,13 @@
 		regval |= SW_COLLAPSE_MASK;
 		regmap_write(sc->regmap, REG_OFFSET, regval);
 
+		if (sc->flags & TOGGLE_SW_COLLAPSE_IN_DISABLE) {
+			regval &= ~SW_COLLAPSE_MASK;
+			regmap_write(sc->regmap, REG_OFFSET, regval);
+			regval |= SW_COLLAPSE_MASK;
+			regmap_write(sc->regmap, REG_OFFSET, regval);
+		}
+
 		/* Wait for 8 XO cycles before polling the status bit. */
 		mb();
 		udelay(1);
@@ -522,7 +533,7 @@
 	struct resource *res;
 	struct gdsc *sc;
 	uint32_t regval, clk_dis_wait_val = 0;
-	bool retain_mem, retain_periph, support_hw_trigger;
+	bool retain_mem, retain_periph, support_hw_trigger, prop_val;
 	int i, ret;
 	u32 timeout;
 
@@ -613,6 +624,11 @@
 	sc->force_root_en = of_property_read_bool(pdev->dev.of_node,
 						"qcom,force-enable-root-clk");
 
+	prop_val = of_property_read_bool(pdev->dev.of_node,
+						"qcom,toggle-sw-collapse-in-disable");
+	if (prop_val)
+		sc->flags |= TOGGLE_SW_COLLAPSE_IN_DISABLE;
+
 	for (i = 0; i < sc->clock_count; i++) {
 		const char *clock_name;
 
diff --git a/drivers/clk/qcom/gpucc-sdm845.c b/drivers/clk/qcom/gpucc-sdm845.c
index ae9d509..a5548e0 100644
--- a/drivers/clk/qcom/gpucc-sdm845.c
+++ b/drivers/clk/qcom/gpucc-sdm845.c
@@ -105,20 +105,6 @@
 	"core_bi_pll_test_se",
 };
 
-static const struct parent_map gpu_cc_parent_map_2[] = {
-	{ P_BI_TCXO, 0 },
-	{ P_GPLL0_OUT_MAIN, 5 },
-	{ P_GPLL0_OUT_MAIN_DIV, 6 },
-	{ P_CORE_BI_PLL_TEST_SE, 7 },
-};
-
-static const char * const gpu_cc_parent_names_2[] = {
-	"bi_tcxo",
-	"gcc_gpu_gpll0_clk_src",
-	"gcc_gpu_gpll0_div_clk_src",
-	"core_bi_pll_test_se",
-};
-
 static struct pll_vco fabia_vco[] = {
 	{ 250000000, 2000000000, 0 },
 	{ 125000000, 1000000000, 1 },
@@ -232,29 +218,6 @@
 	},
 };
 
-static const struct freq_tbl ftbl_gpu_cc_rbcpr_clk_src[] = {
-	F(19200000, P_BI_TCXO, 1, 0, 0),
-	{ }
-};
-
-static struct clk_rcg2 gpu_cc_rbcpr_clk_src = {
-	.cmd_rcgr = 0x10b0,
-	.mnd_width = 0,
-	.hid_width = 5,
-	.parent_map = gpu_cc_parent_map_2,
-	.freq_tbl = ftbl_gpu_cc_rbcpr_clk_src,
-	.clkr.hw.init = &(struct clk_init_data){
-		.name = "gpu_cc_rbcpr_clk_src",
-		.parent_names = gpu_cc_parent_names_2,
-		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
-		.ops = &clk_rcg2_ops,
-		VDD_CX_FMAX_MAP2(
-			MIN, 19200000,
-			NOMINAL, 50000000),
-	},
-};
-
 static struct clk_branch gpu_cc_acd_ahb_clk = {
 	.halt_reg = 0x1168,
 	.halt_check = BRANCH_HALT,
@@ -488,37 +451,6 @@
 	},
 };
 
-static struct clk_branch gpu_cc_rbcpr_ahb_clk = {
-	.halt_reg = 0x10f4,
-	.halt_check = BRANCH_HALT,
-	.clkr = {
-		.enable_reg = 0x10f4,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "gpu_cc_rbcpr_ahb_clk",
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
-static struct clk_branch gpu_cc_rbcpr_clk = {
-	.halt_reg = 0x10f0,
-	.halt_check = BRANCH_HALT,
-	.clkr = {
-		.enable_reg = 0x10f0,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "gpu_cc_rbcpr_clk",
-			.parent_names = (const char *[]){
-				"gpu_cc_rbcpr_clk_src",
-			},
-			.num_parents = 1,
-			.flags = CLK_SET_RATE_PARENT,
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_regmap *gpu_cc_sdm845_clocks[] = {
 	[GPU_CC_ACD_AHB_CLK] = &gpu_cc_acd_ahb_clk.clkr,
 	[GPU_CC_ACD_CXO_CLK] = &gpu_cc_acd_cxo_clk.clkr,
@@ -536,9 +468,6 @@
 	[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
 	[GPU_CC_GX_VSENSE_CLK] = &gpu_cc_gx_vsense_clk.clkr,
 	[GPU_CC_PLL_TEST_CLK] = &gpu_cc_pll_test_clk.clkr,
-	[GPU_CC_RBCPR_AHB_CLK] = &gpu_cc_rbcpr_ahb_clk.clkr,
-	[GPU_CC_RBCPR_CLK] = &gpu_cc_rbcpr_clk.clkr,
-	[GPU_CC_RBCPR_CLK_SRC] = &gpu_cc_rbcpr_clk_src.clkr,
 };
 
 static struct clk_regmap *gpu_cc_gfx_sdm845_clocks[] = {
@@ -554,7 +483,6 @@
 	[GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x10a0 },
 	[GPUCC_GPU_CC_GMU_BCR] = { 0x111c },
 	[GPUCC_GPU_CC_GX_BCR] = { 0x1008 },
-	[GPUCC_GPU_CC_RBCPR_BCR] = { 0x10ac },
 	[GPUCC_GPU_CC_SPDM_BCR] = { 0x1110 },
 	[GPUCC_GPU_CC_XO_BCR] = { 0x1000 },
 };
diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c
index 8d2dbac..e68966b 100644
--- a/drivers/crypto/ccp/ccp-dev-v3.c
+++ b/drivers/crypto/ccp/ccp-dev-v3.c
@@ -315,17 +315,73 @@
 	return ccp_do_cmd(op, cr, ARRAY_SIZE(cr));
 }
 
+static void ccp_disable_queue_interrupts(struct ccp_device *ccp)
+{
+	iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG);
+}
+
+static void ccp_enable_queue_interrupts(struct ccp_device *ccp)
+{
+	iowrite32(ccp->qim, ccp->io_regs + IRQ_MASK_REG);
+}
+
+static void ccp_irq_bh(unsigned long data)
+{
+	struct ccp_device *ccp = (struct ccp_device *)data;
+	struct ccp_cmd_queue *cmd_q;
+	u32 q_int, status;
+	unsigned int i;
+
+	status = ioread32(ccp->io_regs + IRQ_STATUS_REG);
+
+	for (i = 0; i < ccp->cmd_q_count; i++) {
+		cmd_q = &ccp->cmd_q[i];
+
+		q_int = status & (cmd_q->int_ok | cmd_q->int_err);
+		if (q_int) {
+			cmd_q->int_status = status;
+			cmd_q->q_status = ioread32(cmd_q->reg_status);
+			cmd_q->q_int_status = ioread32(cmd_q->reg_int_status);
+
+			/* On error, only save the first error value */
+			if ((q_int & cmd_q->int_err) && !cmd_q->cmd_error)
+				cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status);
+
+			cmd_q->int_rcvd = 1;
+
+			/* Acknowledge the interrupt and wake the kthread */
+			iowrite32(q_int, ccp->io_regs + IRQ_STATUS_REG);
+			wake_up_interruptible(&cmd_q->int_queue);
+		}
+	}
+	ccp_enable_queue_interrupts(ccp);
+}
+
+static irqreturn_t ccp_irq_handler(int irq, void *data)
+{
+	struct device *dev = data;
+	struct ccp_device *ccp = dev_get_drvdata(dev);
+
+	ccp_disable_queue_interrupts(ccp);
+	if (ccp->use_tasklet)
+		tasklet_schedule(&ccp->irq_tasklet);
+	else
+		ccp_irq_bh((unsigned long)ccp);
+
+	return IRQ_HANDLED;
+}
+
 static int ccp_init(struct ccp_device *ccp)
 {
 	struct device *dev = ccp->dev;
 	struct ccp_cmd_queue *cmd_q;
 	struct dma_pool *dma_pool;
 	char dma_pool_name[MAX_DMAPOOL_NAME_LEN];
-	unsigned int qmr, qim, i;
+	unsigned int qmr, i;
 	int ret;
 
 	/* Find available queues */
-	qim = 0;
+	ccp->qim = 0;
 	qmr = ioread32(ccp->io_regs + Q_MASK_REG);
 	for (i = 0; i < MAX_HW_QUEUES; i++) {
 		if (!(qmr & (1 << i)))
@@ -370,7 +426,7 @@
 		init_waitqueue_head(&cmd_q->int_queue);
 
 		/* Build queue interrupt mask (two interrupts per queue) */
-		qim |= cmd_q->int_ok | cmd_q->int_err;
+		ccp->qim |= cmd_q->int_ok | cmd_q->int_err;
 
 #ifdef CONFIG_ARM64
 		/* For arm64 set the recommended queue cache settings */
@@ -388,14 +444,14 @@
 	dev_notice(dev, "%u command queues available\n", ccp->cmd_q_count);
 
 	/* Disable and clear interrupts until ready */
-	iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG);
+	ccp_disable_queue_interrupts(ccp);
 	for (i = 0; i < ccp->cmd_q_count; i++) {
 		cmd_q = &ccp->cmd_q[i];
 
 		ioread32(cmd_q->reg_int_status);
 		ioread32(cmd_q->reg_status);
 	}
-	iowrite32(qim, ccp->io_regs + IRQ_STATUS_REG);
+	iowrite32(ccp->qim, ccp->io_regs + IRQ_STATUS_REG);
 
 	/* Request an irq */
 	ret = ccp->get_irq(ccp);
@@ -408,6 +464,11 @@
 	init_waitqueue_head(&ccp->sb_queue);
 	init_waitqueue_head(&ccp->suspend_queue);
 
+	/* Initialize the ISR tasklet? */
+	if (ccp->use_tasklet)
+		tasklet_init(&ccp->irq_tasklet, ccp_irq_bh,
+			     (unsigned long)ccp);
+
 	dev_dbg(dev, "Starting threads...\n");
 	/* Create a kthread for each queue */
 	for (i = 0; i < ccp->cmd_q_count; i++) {
@@ -430,7 +491,7 @@
 
 	dev_dbg(dev, "Enabling interrupts...\n");
 	/* Enable interrupts */
-	iowrite32(qim, ccp->io_regs + IRQ_MASK_REG);
+	ccp_enable_queue_interrupts(ccp);
 
 	dev_dbg(dev, "Registering device...\n");
 	ccp_add_device(ccp);
@@ -467,7 +528,7 @@
 {
 	struct ccp_cmd_queue *cmd_q;
 	struct ccp_cmd *cmd;
-	unsigned int qim, i;
+	unsigned int i;
 
 	/* Unregister the DMA engine */
 	ccp_dmaengine_unregister(ccp);
@@ -478,22 +539,15 @@
 	/* Remove this device from the list of available units */
 	ccp_del_device(ccp);
 
-	/* Build queue interrupt mask (two interrupt masks per queue) */
-	qim = 0;
-	for (i = 0; i < ccp->cmd_q_count; i++) {
-		cmd_q = &ccp->cmd_q[i];
-		qim |= cmd_q->int_ok | cmd_q->int_err;
-	}
-
 	/* Disable and clear interrupts */
-	iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG);
+	ccp_disable_queue_interrupts(ccp);
 	for (i = 0; i < ccp->cmd_q_count; i++) {
 		cmd_q = &ccp->cmd_q[i];
 
 		ioread32(cmd_q->reg_int_status);
 		ioread32(cmd_q->reg_status);
 	}
-	iowrite32(qim, ccp->io_regs + IRQ_STATUS_REG);
+	iowrite32(ccp->qim, ccp->io_regs + IRQ_STATUS_REG);
 
 	/* Stop the queue kthreads */
 	for (i = 0; i < ccp->cmd_q_count; i++)
@@ -520,40 +574,6 @@
 	}
 }
 
-static irqreturn_t ccp_irq_handler(int irq, void *data)
-{
-	struct device *dev = data;
-	struct ccp_device *ccp = dev_get_drvdata(dev);
-	struct ccp_cmd_queue *cmd_q;
-	u32 q_int, status;
-	unsigned int i;
-
-	status = ioread32(ccp->io_regs + IRQ_STATUS_REG);
-
-	for (i = 0; i < ccp->cmd_q_count; i++) {
-		cmd_q = &ccp->cmd_q[i];
-
-		q_int = status & (cmd_q->int_ok | cmd_q->int_err);
-		if (q_int) {
-			cmd_q->int_status = status;
-			cmd_q->q_status = ioread32(cmd_q->reg_status);
-			cmd_q->q_int_status = ioread32(cmd_q->reg_int_status);
-
-			/* On error, only save the first error value */
-			if ((q_int & cmd_q->int_err) && !cmd_q->cmd_error)
-				cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status);
-
-			cmd_q->int_rcvd = 1;
-
-			/* Acknowledge the interrupt and wake the kthread */
-			iowrite32(q_int, ccp->io_regs + IRQ_STATUS_REG);
-			wake_up_interruptible(&cmd_q->int_queue);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
 static const struct ccp_actions ccp3_actions = {
 	.aes = ccp_perform_aes,
 	.xts_aes = ccp_perform_xts_aes,
diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c
index a388bf2..2c0ce5f 100644
--- a/drivers/crypto/ccp/ccp-dev-v5.c
+++ b/drivers/crypto/ccp/ccp-dev-v5.c
@@ -644,6 +644,65 @@
 	return rc;
 }
 
+static void ccp5_disable_queue_interrupts(struct ccp_device *ccp)
+{
+	unsigned int i;
+
+	for (i = 0; i < ccp->cmd_q_count; i++)
+		iowrite32(0x0, ccp->cmd_q[i].reg_int_enable);
+}
+
+static void ccp5_enable_queue_interrupts(struct ccp_device *ccp)
+{
+	unsigned int i;
+
+	for (i = 0; i < ccp->cmd_q_count; i++)
+		iowrite32(SUPPORTED_INTERRUPTS, ccp->cmd_q[i].reg_int_enable);
+}
+
+static void ccp5_irq_bh(unsigned long data)
+{
+	struct ccp_device *ccp = (struct ccp_device *)data;
+	u32 status;
+	unsigned int i;
+
+	for (i = 0; i < ccp->cmd_q_count; i++) {
+		struct ccp_cmd_queue *cmd_q = &ccp->cmd_q[i];
+
+		status = ioread32(cmd_q->reg_interrupt_status);
+
+		if (status) {
+			cmd_q->int_status = status;
+			cmd_q->q_status = ioread32(cmd_q->reg_status);
+			cmd_q->q_int_status = ioread32(cmd_q->reg_int_status);
+
+			/* On error, only save the first error value */
+			if ((status & INT_ERROR) && !cmd_q->cmd_error)
+				cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status);
+
+			cmd_q->int_rcvd = 1;
+
+			/* Acknowledge the interrupt and wake the kthread */
+			iowrite32(status, cmd_q->reg_interrupt_status);
+			wake_up_interruptible(&cmd_q->int_queue);
+		}
+	}
+	ccp5_enable_queue_interrupts(ccp);
+}
+
+static irqreturn_t ccp5_irq_handler(int irq, void *data)
+{
+	struct device *dev = data;
+	struct ccp_device *ccp = dev_get_drvdata(dev);
+
+	ccp5_disable_queue_interrupts(ccp);
+	if (ccp->use_tasklet)
+		tasklet_schedule(&ccp->irq_tasklet);
+	else
+		ccp5_irq_bh((unsigned long)ccp);
+	return IRQ_HANDLED;
+}
+
 static int ccp5_init(struct ccp_device *ccp)
 {
 	struct device *dev = ccp->dev;
@@ -728,19 +787,18 @@
 	dev_notice(dev, "%u command queues available\n", ccp->cmd_q_count);
 
 	/* Turn off the queues and disable interrupts until ready */
+	ccp5_disable_queue_interrupts(ccp);
 	for (i = 0; i < ccp->cmd_q_count; i++) {
 		cmd_q = &ccp->cmd_q[i];
 
 		cmd_q->qcontrol = 0; /* Start with nothing */
 		iowrite32(cmd_q->qcontrol, cmd_q->reg_control);
 
-		/* Disable the interrupts */
-		iowrite32(0x00, cmd_q->reg_int_enable);
 		ioread32(cmd_q->reg_int_status);
 		ioread32(cmd_q->reg_status);
 
-		/* Clear the interrupts */
-		iowrite32(ALL_INTERRUPTS, cmd_q->reg_interrupt_status);
+		/* Clear the interrupt status */
+		iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_interrupt_status);
 	}
 
 	dev_dbg(dev, "Requesting an IRQ...\n");
@@ -750,6 +808,10 @@
 		dev_err(dev, "unable to allocate an IRQ\n");
 		goto e_pool;
 	}
+	/* Initialize the ISR tasklet */
+	if (ccp->use_tasklet)
+		tasklet_init(&ccp->irq_tasklet, ccp5_irq_bh,
+			     (unsigned long)ccp);
 
 	/* Initialize the queue used to suspend */
 	init_waitqueue_head(&ccp->suspend_queue);
@@ -821,11 +883,7 @@
 	}
 
 	dev_dbg(dev, "Enabling interrupts...\n");
-	/* Enable interrupts */
-	for (i = 0; i < ccp->cmd_q_count; i++) {
-		cmd_q = &ccp->cmd_q[i];
-		iowrite32(ALL_INTERRUPTS, cmd_q->reg_int_enable);
-	}
+	ccp5_enable_queue_interrupts(ccp);
 
 	dev_dbg(dev, "Registering device...\n");
 	/* Put this on the unit list to make it available */
@@ -877,17 +935,15 @@
 	ccp_del_device(ccp);
 
 	/* Disable and clear interrupts */
+	ccp5_disable_queue_interrupts(ccp);
 	for (i = 0; i < ccp->cmd_q_count; i++) {
 		cmd_q = &ccp->cmd_q[i];
 
 		/* Turn off the run bit */
 		iowrite32(cmd_q->qcontrol & ~CMD5_Q_RUN, cmd_q->reg_control);
 
-		/* Disable the interrupts */
-		iowrite32(ALL_INTERRUPTS, cmd_q->reg_interrupt_status);
-
 		/* Clear the interrupt status */
-		iowrite32(0x00, cmd_q->reg_int_enable);
+		iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_interrupt_status);
 		ioread32(cmd_q->reg_int_status);
 		ioread32(cmd_q->reg_status);
 	}
@@ -920,38 +976,6 @@
 	}
 }
 
-static irqreturn_t ccp5_irq_handler(int irq, void *data)
-{
-	struct device *dev = data;
-	struct ccp_device *ccp = dev_get_drvdata(dev);
-	u32 status;
-	unsigned int i;
-
-	for (i = 0; i < ccp->cmd_q_count; i++) {
-		struct ccp_cmd_queue *cmd_q = &ccp->cmd_q[i];
-
-		status = ioread32(cmd_q->reg_interrupt_status);
-
-		if (status) {
-			cmd_q->int_status = status;
-			cmd_q->q_status = ioread32(cmd_q->reg_status);
-			cmd_q->q_int_status = ioread32(cmd_q->reg_int_status);
-
-			/* On error, only save the first error value */
-			if ((status & INT_ERROR) && !cmd_q->cmd_error)
-				cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status);
-
-			cmd_q->int_rcvd = 1;
-
-			/* Acknowledge the interrupt and wake the kthread */
-			iowrite32(ALL_INTERRUPTS, cmd_q->reg_interrupt_status);
-			wake_up_interruptible(&cmd_q->int_queue);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
 static void ccp5_config(struct ccp_device *ccp)
 {
 	/* Public side */
diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
index 340aef1..8ac7ae1 100644
--- a/drivers/crypto/ccp/ccp-dev.h
+++ b/drivers/crypto/ccp/ccp-dev.h
@@ -109,9 +109,8 @@
 #define INT_COMPLETION			0x1
 #define INT_ERROR			0x2
 #define INT_QUEUE_STOPPED		0x4
-#define ALL_INTERRUPTS			(INT_COMPLETION| \
-					 INT_ERROR| \
-					 INT_QUEUE_STOPPED)
+#define	INT_EMPTY_QUEUE			0x8
+#define SUPPORTED_INTERRUPTS		(INT_COMPLETION | INT_ERROR)
 
 #define LSB_REGION_WIDTH		5
 #define MAX_LSB_CNT			8
@@ -333,7 +332,10 @@
 	void *dev_specific;
 	int (*get_irq)(struct ccp_device *ccp);
 	void (*free_irq)(struct ccp_device *ccp);
+	unsigned int qim;
 	unsigned int irq;
+	bool use_tasklet;
+	struct tasklet_struct irq_tasklet;
 
 	/* I/O area used for device communication. The register mapping
 	 * starts at an offset into the mapped bar.
diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c
index 28a9996..e880d4cf4 100644
--- a/drivers/crypto/ccp/ccp-pci.c
+++ b/drivers/crypto/ccp/ccp-pci.c
@@ -69,6 +69,7 @@
 			goto e_irq;
 		}
 	}
+	ccp->use_tasklet = true;
 
 	return 0;
 
@@ -100,6 +101,7 @@
 		dev_notice(dev, "unable to allocate MSI IRQ (%d)\n", ret);
 		goto e_msi;
 	}
+	ccp->use_tasklet = true;
 
 	return 0;
 
diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c
index 1932248..586f954 100644
--- a/drivers/dax/dax.c
+++ b/drivers/dax/dax.c
@@ -553,13 +553,10 @@
 	kfree(dax_dev);
 }
 
-static void unregister_dax_dev(void *dev)
+static void kill_dax_dev(struct dax_dev *dax_dev)
 {
-	struct dax_dev *dax_dev = to_dax_dev(dev);
 	struct cdev *cdev = &dax_dev->cdev;
 
-	dev_dbg(dev, "%s\n", __func__);
-
 	/*
 	 * Note, rcu is not protecting the liveness of dax_dev, rcu is
 	 * ensuring that any fault handlers that might have seen
@@ -571,6 +568,15 @@
 	synchronize_srcu(&dax_srcu);
 	unmap_mapping_range(dax_dev->inode->i_mapping, 0, 0, 1);
 	cdev_del(cdev);
+}
+
+static void unregister_dax_dev(void *dev)
+{
+	struct dax_dev *dax_dev = to_dax_dev(dev);
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	kill_dax_dev(dax_dev);
 	device_unregister(dev);
 }
 
@@ -647,6 +653,7 @@
 	dev_set_name(dev, "dax%d.%d", dax_region->id, dax_dev->id);
 	rc = device_add(dev);
 	if (rc) {
+		kill_dax_dev(dax_dev);
 		put_device(dev);
 		return ERR_PTR(rc);
 	}
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
new file mode 100644
index 0000000..30f477e
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__
+
+#include <linux/delay.h>
+
+#include "dp_aux.h"
+
+#define DP_AUX_ENUM_STR(x)		#x
+
+struct aux_buf {
+	u8 *start;      /* buffer start addr */
+	u8 *end;	/* buffer end addr */
+	u8 *data;       /* data pou32er */
+	u32 size;       /* size of buffer */
+	u32 len;	/* dara length */
+	u8 trans_num;   /* transaction number */
+	enum aux_tx_mode tx_mode;
+};
+
+struct dp_aux_private {
+	struct device *dev;
+	struct dp_aux dp_aux;
+	struct dp_catalog_aux *catalog;
+
+	struct mutex mutex;
+	struct completion comp;
+
+	struct aux_cmd *cmds;
+	struct aux_buf txp;
+	struct aux_buf rxp;
+
+	u32 aux_error_num;
+
+	u8 txbuf[256];
+	u8 rxbuf[256];
+};
+
+static char *dp_aux_get_error(u32 aux_error)
+{
+	switch (aux_error) {
+	case DP_AUX_ERR_NONE:
+		return DP_AUX_ENUM_STR(DP_AUX_ERR_NONE);
+	case DP_AUX_ERR_ADDR:
+		return DP_AUX_ENUM_STR(DP_AUX_ERR_ADDR);
+	case DP_AUX_ERR_TOUT:
+		return DP_AUX_ENUM_STR(DP_AUX_ERR_TOUT);
+	case DP_AUX_ERR_NACK:
+		return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK);
+	case DP_AUX_ERR_DEFER:
+		return DP_AUX_ENUM_STR(DP_AUX_ERR_DEFER);
+	case DP_AUX_ERR_NACK_DEFER:
+		return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK_DEFER);
+	default:
+		return "unknown";
+	}
+}
+
+static void dp_aux_buf_init(struct aux_buf *buf, u8 *data, u32 size)
+{
+	buf->start     = data;
+	buf->size      = size;
+	buf->data      = buf->start;
+	buf->end       = buf->start + buf->size;
+	buf->len       = 0;
+	buf->trans_num = 0;
+	buf->tx_mode   = AUX_NATIVE;
+}
+
+static void dp_aux_buf_set(struct dp_aux_private *aux)
+{
+	init_completion(&aux->comp);
+	mutex_init(&aux->mutex);
+
+	dp_aux_buf_init(&aux->txp, aux->txbuf, sizeof(aux->txbuf));
+	dp_aux_buf_init(&aux->rxp, aux->rxbuf, sizeof(aux->rxbuf));
+}
+
+static void dp_aux_buf_reset(struct aux_buf *buf)
+{
+	buf->data      = buf->start;
+	buf->len       = 0;
+	buf->trans_num = 0;
+	buf->tx_mode   = AUX_NATIVE;
+
+	memset(buf->start, 0x0, 256);
+}
+
+static void dp_aux_buf_push(struct aux_buf *buf, u32 len)
+{
+	buf->data += len;
+	buf->len  += len;
+}
+
+static u32 dp_aux_buf_trailing(struct aux_buf *buf)
+{
+	return (u32)(buf->end - buf->data);
+}
+
+static u32 dp_aux_add_cmd(struct aux_buf *buf, struct aux_cmd *cmd)
+{
+	u8 data;
+	u8 *bp, *cp;
+	u32 i, len;
+
+	if (cmd->ex_mode == AUX_READ)
+		len = 4;
+	else
+		len = cmd->len + 4;
+
+	if (dp_aux_buf_trailing(buf) < len) {
+		pr_err("buf trailing error\n");
+		return 0;
+	}
+
+	/*
+	 * cmd fifo only has depth of 144 bytes
+	 * limit buf length to 128 bytes here
+	 */
+	if ((buf->len + len) > 128) {
+		pr_err("buf len error\n");
+		return 0;
+	}
+
+	bp = buf->data;
+	data = cmd->addr >> 16;
+	data &= 0x0f;  /* 4 addr bits */
+
+	if (cmd->ex_mode == AUX_READ)
+		data |=  BIT(4);
+
+	*bp++ = data;
+	*bp++ = cmd->addr >> 8;
+	*bp++ = cmd->addr;
+	*bp++ = cmd->len - 1;
+
+	if (cmd->ex_mode == AUX_WRITE) {
+		cp = cmd->buf;
+
+		for (i = 0; i < cmd->len; i++)
+			*bp++ = *cp++;
+	}
+
+	dp_aux_buf_push(buf, len);
+
+	buf->tx_mode = cmd->tx_mode;
+
+	buf->trans_num++;
+
+	return cmd->len - 1;
+}
+
+static u32 dp_aux_cmd_fifo_tx(struct dp_aux_private *aux)
+{
+	u8 *dp;
+	u32 data, len, cnt;
+	struct aux_buf *tp = &aux->txp;
+
+	len = tp->len;
+	if (len == 0) {
+		pr_err("invalid len\n");
+		return 0;
+	}
+
+	cnt = 0;
+	dp = tp->start;
+
+	while (cnt < len) {
+		data = *dp;
+		data <<= 8;
+		data &= 0x00ff00;
+		if (cnt == 0)
+			data |= BIT(31);
+
+		aux->catalog->data = data;
+		aux->catalog->write_data(aux->catalog);
+
+		cnt++;
+		dp++;
+	}
+
+	data = (tp->trans_num - 1);
+	if (tp->tx_mode == AUX_I2C) {
+		data |= BIT(8); /* I2C */
+		data |= BIT(10); /* NO SEND ADDR */
+		data |= BIT(11); /* NO SEND STOP */
+	}
+
+	data |= BIT(9); /* GO */
+	aux->catalog->data = data;
+	aux->catalog->write_trans(aux->catalog);
+
+	return tp->len;
+}
+
+static u32 dp_cmd_fifo_rx(struct dp_aux_private *aux, u32 len)
+{
+	u32 data;
+	u8 *dp;
+	u32 i;
+	struct aux_buf *rp = &aux->rxp;
+
+	data = 0;
+	data |= BIT(31); /* INDEX_WRITE */
+	data |= BIT(0);  /* read */
+
+	aux->catalog->data = data;
+	aux->catalog->write_data(aux->catalog);
+
+	dp = rp->data;
+
+	/* discard first byte */
+	data = aux->catalog->read_data(aux->catalog);
+
+	for (i = 0; i < len; i++) {
+		data = aux->catalog->read_data(aux->catalog);
+		*dp++ = (u8)((data >> 8) & 0xff);
+	}
+
+	rp->len = len;
+	return len;
+}
+
+static void dp_aux_native_handler(struct dp_aux_private *aux)
+{
+	u32 isr = aux->catalog->isr1;
+
+	if (isr & DP_INTR_AUX_I2C_DONE)
+		aux->aux_error_num = DP_AUX_ERR_NONE;
+	else if (isr & DP_INTR_WRONG_ADDR)
+		aux->aux_error_num = DP_AUX_ERR_ADDR;
+	else if (isr & DP_INTR_TIMEOUT)
+		aux->aux_error_num = DP_AUX_ERR_TOUT;
+	if (isr & DP_INTR_NACK_DEFER)
+		aux->aux_error_num = DP_AUX_ERR_NACK;
+
+	complete(&aux->comp);
+}
+
+static void dp_aux_i2c_handler(struct dp_aux_private *aux)
+{
+	u32 isr = aux->catalog->isr1;
+
+	if (isr & DP_INTR_AUX_I2C_DONE) {
+		if (isr & (DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER))
+			aux->aux_error_num = DP_AUX_ERR_NACK;
+		else
+			aux->aux_error_num = DP_AUX_ERR_NONE;
+	} else {
+		if (isr & DP_INTR_WRONG_ADDR)
+			aux->aux_error_num = DP_AUX_ERR_ADDR;
+		else if (isr & DP_INTR_TIMEOUT)
+			aux->aux_error_num = DP_AUX_ERR_TOUT;
+		if (isr & DP_INTR_NACK_DEFER)
+			aux->aux_error_num = DP_AUX_ERR_NACK_DEFER;
+		if (isr & DP_INTR_I2C_NACK)
+			aux->aux_error_num = DP_AUX_ERR_NACK;
+		if (isr & DP_INTR_I2C_DEFER)
+			aux->aux_error_num = DP_AUX_ERR_DEFER;
+	}
+
+	complete(&aux->comp);
+}
+
+static void dp_aux_isr(struct dp_aux *dp_aux)
+{
+	struct dp_aux_private *aux;
+
+	if (!dp_aux) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	aux->catalog->get_irq(aux->catalog);
+
+	if (aux->cmds->tx_mode == AUX_NATIVE)
+		dp_aux_native_handler(aux);
+	else
+		dp_aux_i2c_handler(aux);
+}
+
+
+
+static int dp_aux_write(struct dp_aux_private *aux)
+{
+	struct aux_cmd *cm;
+	struct aux_buf *tp;
+	u32 len, ret, timeout;
+
+	mutex_lock(&aux->mutex);
+
+	tp = &aux->txp;
+	dp_aux_buf_reset(tp);
+
+	cm = aux->cmds;
+	while (cm) {
+		ret = dp_aux_add_cmd(tp, cm);
+		if (ret <= 0)
+			break;
+
+		if (!cm->next)
+			break;
+		cm++;
+	}
+
+	reinit_completion(&aux->comp);
+
+	len = dp_aux_cmd_fifo_tx(aux);
+
+	timeout = wait_for_completion_timeout(&aux->comp, HZ/4);
+	if (!timeout)
+		pr_err("aux write timeout\n");
+
+	pr_debug("aux status %s\n",
+		dp_aux_get_error(aux->aux_error_num));
+
+	if (aux->aux_error_num == DP_AUX_ERR_NONE)
+		ret = len;
+	else
+		ret = aux->aux_error_num;
+
+	mutex_unlock(&aux->mutex);
+	return  ret;
+}
+
+static int dp_aux_read(struct dp_aux_private *aux)
+{
+	struct aux_cmd *cm;
+	struct aux_buf *tp, *rp;
+	u32 len, ret, timeout;
+
+	mutex_lock(&aux->mutex);
+
+	tp = &aux->txp;
+	rp = &aux->rxp;
+
+	dp_aux_buf_reset(tp);
+	dp_aux_buf_reset(rp);
+
+	cm = aux->cmds;
+	len = 0;
+
+	while (cm) {
+		ret = dp_aux_add_cmd(tp, cm);
+		len += cm->len;
+
+		if (ret <= 0)
+			break;
+
+		if (!cm->next)
+			break;
+		cm++;
+	}
+
+	reinit_completion(&aux->comp);
+
+	dp_aux_cmd_fifo_tx(aux);
+
+	timeout = wait_for_completion_timeout(&aux->comp, HZ/4);
+	if (!timeout)
+		pr_err("aux read timeout\n");
+
+	pr_debug("aux status %s\n",
+		dp_aux_get_error(aux->aux_error_num));
+
+	if (aux->aux_error_num == DP_AUX_ERR_NONE)
+		ret = dp_cmd_fifo_rx(aux, len);
+	else
+		ret = aux->aux_error_num;
+
+	aux->cmds->buf = rp->data;
+
+	mutex_unlock(&aux->mutex);
+
+	return ret;
+}
+
+static int dp_aux_write_ex(struct dp_aux *dp_aux, u32 addr, u32 len,
+				enum aux_tx_mode mode, u8 *buf)
+{
+	struct aux_cmd cmd = {0};
+	struct dp_aux_private *aux;
+
+	if (!dp_aux || !len) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	cmd.ex_mode = AUX_WRITE;
+	cmd.tx_mode = mode;
+	cmd.addr    = addr;
+	cmd.len     = len;
+	cmd.buf     = buf;
+
+	aux->cmds = &cmd;
+
+	return dp_aux_write(aux);
+}
+
+static int dp_aux_read_ex(struct dp_aux *dp_aux, u32 addr, u32 len,
+				enum aux_tx_mode mode, u8 **buf)
+{
+	int rc = 0;
+	struct aux_cmd cmd = {0};
+	struct dp_aux_private *aux;
+
+	if (!dp_aux || !len) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	cmd.ex_mode = AUX_READ;
+	cmd.tx_mode = mode;
+	cmd.addr    = addr;
+	cmd.len     = len;
+
+	aux->cmds = &cmd;
+
+	rc = dp_aux_read(aux);
+	if (rc <= 0) {
+		rc = -EINVAL;
+		goto end;
+	}
+
+	*buf = cmd.buf;
+end:
+	return rc;
+}
+
+static int dp_aux_process(struct dp_aux *dp_aux, struct aux_cmd *cmds)
+{
+	struct dp_aux_private *aux;
+
+	if (!dp_aux || !cmds) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	aux->cmds = cmds;
+
+	if (cmds->ex_mode == AUX_READ)
+		return dp_aux_read(aux);
+	else
+		return dp_aux_write(aux);
+}
+
+static bool dp_aux_ready(struct dp_aux *dp_aux)
+{
+	u8 data = 0;
+	int count, ret;
+	struct dp_aux_private *aux;
+
+	if (!dp_aux) {
+		pr_err("invalid input\n");
+		goto error;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	for (count = 5; count; count--) {
+		ret = dp_aux_write_ex(dp_aux, 0x50, 1, AUX_I2C, &data);
+		if (ret >= 0)
+			break;
+
+		msleep(100);
+	}
+
+	if (count <= 0) {
+		pr_err("aux chan NOT ready\n");
+		goto error;
+	}
+
+	return true;
+error:
+	return false;
+}
+
+static void dp_aux_init(struct dp_aux *dp_aux, u32 *aux_cfg)
+{
+	struct dp_aux_private *aux;
+
+	if (!dp_aux) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	aux->catalog->reset(aux->catalog);
+	aux->catalog->enable(aux->catalog, true);
+	aux->catalog->setup(aux->catalog, aux_cfg);
+}
+
+static void dp_aux_deinit(struct dp_aux *dp_aux)
+{
+	struct dp_aux_private *aux;
+
+	if (!dp_aux) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	aux->catalog->enable(aux->catalog, false);
+}
+
+struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog)
+{
+	int rc = 0;
+	struct dp_aux_private *aux;
+	struct dp_aux *dp_aux;
+
+	if (!catalog) {
+		pr_err("invalid input\n");
+		rc = -ENODEV;
+		goto error;
+	}
+
+	aux = devm_kzalloc(dev, sizeof(*aux), GFP_KERNEL);
+	if (!aux) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	aux->dev = dev;
+
+	dp_aux_buf_set(aux);
+
+	aux->catalog = catalog;
+
+	dp_aux = &aux->dp_aux;
+
+	dp_aux->process = dp_aux_process;
+	dp_aux->read    = dp_aux_read_ex;
+	dp_aux->write   = dp_aux_write_ex;
+	dp_aux->ready   = dp_aux_ready;
+	dp_aux->isr     = dp_aux_isr;
+	dp_aux->init    = dp_aux_init;
+	dp_aux->deinit  = dp_aux_deinit;
+
+	return dp_aux;
+error:
+	return ERR_PTR(rc);
+}
+
+void dp_aux_put(struct dp_aux *dp_aux)
+{
+	struct dp_aux_private *aux;
+
+	if (!dp_aux)
+		return;
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	devm_kfree(aux->dev, aux);
+}
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h
new file mode 100644
index 0000000..0603c15
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_aux.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _DP_AUX_H_
+#define _DP_AUX_H_
+
+#include "dp_catalog.h"
+
+enum dp_aux_error {
+	DP_AUX_ERR_NONE	= 0,
+	DP_AUX_ERR_ADDR	= -1,
+	DP_AUX_ERR_TOUT	= -2,
+	DP_AUX_ERR_NACK	= -3,
+	DP_AUX_ERR_DEFER	= -4,
+	DP_AUX_ERR_NACK_DEFER	= -5,
+};
+
+enum aux_tx_mode {
+	AUX_NATIVE,
+	AUX_I2C,
+};
+
+enum aux_exe_mode {
+	AUX_WRITE,
+	AUX_READ,
+};
+
+struct aux_cmd {
+	enum aux_exe_mode ex_mode;
+	enum aux_tx_mode tx_mode;
+	u32 addr;
+	u32 len;
+	u8 *buf;
+	bool next;
+};
+
+struct dp_aux {
+	int (*process)(struct dp_aux *aux, struct aux_cmd *cmd);
+	int (*write)(struct dp_aux *aux, u32 addr, u32 len,
+			enum aux_tx_mode mode, u8 *buf);
+	int (*read)(struct dp_aux *aux, u32 addr, u32 len,
+			enum aux_tx_mode mode, u8 **buf);
+	bool (*ready)(struct dp_aux *aux);
+	void (*isr)(struct dp_aux *aux);
+	void (*init)(struct dp_aux *aux, u32 *aux_cfg);
+	void (*deinit)(struct dp_aux *aux);
+};
+
+struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog);
+void dp_aux_put(struct dp_aux *aux);
+
+#endif /*__DP_AUX_H_*/
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c
new file mode 100644
index 0000000..722c436
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_parser.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__
+
+#include <linux/of_gpio.h>
+
+#include "dp_parser.h"
+
+static void dp_parser_unmap_io_resources(struct dp_parser *parser)
+{
+	struct dp_io *io = &parser->io;
+
+	if (&io->ctrl_io)
+		msm_dss_iounmap(&io->ctrl_io);
+	if (&io->phy_io)
+		msm_dss_iounmap(&io->phy_io);
+	if (&io->ln_tx0_io)
+		msm_dss_iounmap(&io->ln_tx0_io);
+	if (&io->ln_tx1_io)
+		msm_dss_iounmap(&io->ln_tx0_io);
+	if (&io->dp_pll_io)
+		msm_dss_iounmap(&io->dp_pll_io);
+	if (&io->dp_cc_io)
+		msm_dss_iounmap(&io->dp_cc_io);
+	if (&io->qfprom_io)
+		msm_dss_iounmap(&io->qfprom_io);
+	if (&io->hdcp_io)
+		msm_dss_iounmap(&io->hdcp_io);
+}
+
+static int dp_parser_ctrl_res(struct dp_parser *parser)
+{
+	int rc = 0;
+	u32 index;
+	struct platform_device *pdev = parser->pdev;
+	struct device_node *of_node = parser->pdev->dev.of_node;
+	struct dp_io *io = &parser->io;
+
+	rc = of_property_read_u32(of_node, "cell-index", &index);
+	if (rc) {
+		pr_err("cell-index not specified, rc=%d\n", rc);
+		goto err;
+	}
+
+	rc = msm_dss_ioremap_byname(pdev, &io->ctrl_io, "dp_ctrl");
+	if (rc) {
+		pr_err("unable to remap dp io resources\n");
+		goto err;
+	}
+
+	rc = msm_dss_ioremap_byname(pdev, &io->phy_io, "dp_phy");
+	if (rc) {
+		pr_err("unable to remap dp PHY resources\n");
+		goto err;
+	}
+
+	rc = msm_dss_ioremap_byname(pdev, &io->ln_tx0_io, "dp_ln_tx0");
+	if (rc) {
+		pr_err("unable to remap dp TX0 resources\n");
+		goto err;
+	}
+
+	rc = msm_dss_ioremap_byname(pdev, &io->ln_tx1_io, "dp_ln_tx1");
+	if (rc) {
+		pr_err("unable to remap dp TX1 resources\n");
+		goto err;
+	}
+
+	rc = msm_dss_ioremap_byname(pdev, &io->dp_pll_io, "dp_pll");
+	if (rc) {
+		pr_err("unable to remap DP PLL resources\n");
+		goto err;
+	}
+
+	if (msm_dss_ioremap_byname(pdev, &io->dp_cc_io, "dp_mmss_cc")) {
+		pr_err("unable to remap dp MMSS_CC resources\n");
+		goto err;
+	}
+
+	if (msm_dss_ioremap_byname(pdev, &io->qfprom_io, "qfprom_physical"))
+		pr_warn("unable to remap dp qfprom resources\n");
+
+	if (msm_dss_ioremap_byname(pdev, &io->hdcp_io, "hdcp_physical"))
+		pr_warn("unable to remap dp hdcp resources\n");
+
+	return 0;
+err:
+	dp_parser_unmap_io_resources(parser);
+	return rc;
+}
+
+static int dp_parser_aux(struct dp_parser *parser)
+{
+	int len = 0, i = 0, rc = 0;
+	struct device_node *of_node = parser->pdev->dev.of_node;
+	const char *data;
+
+	data = of_get_property(of_node, "qcom,aux-cfg-settings", &len);
+	if (!data || (len != AUX_CFG_LEN)) {
+		pr_err("Unable to read DP AUX CFG settings\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	for (i = 0; i < len; i++)
+		parser->aux_cfg[i] = data[i];
+end:
+	return rc;
+}
+
+static int dp_parser_misc(struct dp_parser *parser)
+{
+	int rc = 0;
+	struct device_node *of_node = parser->pdev->dev.of_node;
+
+	rc = of_property_read_u32(of_node,
+		"qcom,max-pclk-frequency-khz", &parser->max_pclk_khz);
+	if (rc)
+		parser->max_pclk_khz = DP_MAX_PIXEL_CLK_KHZ;
+
+	return 0;
+}
+
+static int dp_parser_pinctrl(struct dp_parser *parser)
+{
+	int rc = 0;
+	struct dp_pinctrl *pinctrl = &parser->pinctrl;
+
+	pinctrl->pin = devm_pinctrl_get(&parser->pdev->dev);
+
+	if (IS_ERR_OR_NULL(pinctrl->pin)) {
+		rc = PTR_ERR(pinctrl->pin);
+		pr_err("failed to get pinctrl, rc=%d\n", rc);
+		goto error;
+	}
+
+	pinctrl->state_active = pinctrl_lookup_state(pinctrl->pin,
+					"mdss_dp_active");
+	if (IS_ERR_OR_NULL(pinctrl->state_active)) {
+		rc = PTR_ERR(pinctrl->state_active);
+		pr_err("failed to get pinctrl active state, rc=%d\n", rc);
+		goto error;
+	}
+
+	pinctrl->state_suspend = pinctrl_lookup_state(pinctrl->pin,
+					"mdss_dp_sleep");
+	if (IS_ERR_OR_NULL(pinctrl->state_suspend)) {
+		rc = PTR_ERR(pinctrl->state_suspend);
+		pr_err("failed to get pinctrl suspend state, rc=%d\n", rc);
+		goto error;
+	}
+error:
+	return rc;
+}
+
+static int dp_parser_gpio(struct dp_parser *parser)
+{
+	int i = 0;
+	struct device *dev = &parser->pdev->dev;
+	struct device_node *of_node = dev->of_node;
+	struct dss_module_power *mp = &parser->mp[DP_CORE_PM];
+	static const char * const dp_gpios[] = {
+		"qcom,aux-en-gpio",
+		"qcom,aux-sel-gpio",
+		"qcom,usbplug-cc-gpio",
+	};
+
+	mp->gpio_config = devm_kzalloc(dev,
+		sizeof(struct dss_gpio) * ARRAY_SIZE(dp_gpios), GFP_KERNEL);
+	mp->num_gpio = ARRAY_SIZE(dp_gpios);
+
+	for (i = 0; i < ARRAY_SIZE(dp_gpios); i++) {
+		mp->gpio_config[i].gpio = of_get_named_gpio(of_node,
+			dp_gpios[i], 0);
+
+		if (!gpio_is_valid(mp->gpio_config[i].gpio)) {
+			pr_err("%s gpio not specified\n", dp_gpios[i]);
+			return -EINVAL;
+		}
+
+		strlcpy(mp->gpio_config[i].gpio_name, dp_gpios[i],
+			sizeof(mp->gpio_config[i].gpio_name));
+
+		mp->gpio_config[i].value = 0;
+	}
+
+	return 0;
+}
+
+static const char *dp_parser_supply_node_name(enum dp_pm_type module)
+{
+	switch (module) {
+	case DP_CORE_PM:	return "qcom,core-supply-entries";
+	case DP_CTRL_PM:	return "qcom,ctrl-supply-entries";
+	case DP_PHY_PM:		return "qcom,phy-supply-entries";
+	default:		return "???";
+	}
+}
+
+static int dp_parser_get_vreg(struct dp_parser *parser,
+		enum dp_pm_type module)
+{
+	int i = 0, rc = 0;
+	u32 tmp = 0;
+	const char *pm_supply_name = NULL;
+	struct device_node *supply_node = NULL;
+	struct device_node *of_node = parser->pdev->dev.of_node;
+	struct device_node *supply_root_node = NULL;
+	struct dss_module_power *mp = &parser->mp[module];
+
+	mp->num_vreg = 0;
+	pm_supply_name = dp_parser_supply_node_name(module);
+	supply_root_node = of_get_child_by_name(of_node, pm_supply_name);
+	if (!supply_root_node) {
+		pr_err("no supply entry present: %s\n", pm_supply_name);
+		goto novreg;
+	}
+
+	mp->num_vreg = of_get_available_child_count(supply_root_node);
+
+	if (mp->num_vreg == 0) {
+		pr_debug("no vreg\n");
+		goto novreg;
+	} else {
+		pr_debug("vreg found. count=%d\n", mp->num_vreg);
+	}
+
+	mp->vreg_config = devm_kzalloc(&parser->pdev->dev,
+		sizeof(struct dss_vreg) * mp->num_vreg, GFP_KERNEL);
+	if (!mp->vreg_config) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	for_each_child_of_node(supply_root_node, supply_node) {
+		const char *st = NULL;
+		/* vreg-name */
+		rc = of_property_read_string(supply_node,
+			"qcom,supply-name", &st);
+		if (rc) {
+			pr_err("error reading name. rc=%d\n",
+				 rc);
+			goto error;
+		}
+		snprintf(mp->vreg_config[i].vreg_name,
+			ARRAY_SIZE((mp->vreg_config[i].vreg_name)), "%s", st);
+		/* vreg-min-voltage */
+		rc = of_property_read_u32(supply_node,
+			"qcom,supply-min-voltage", &tmp);
+		if (rc) {
+			pr_err("error reading min volt. rc=%d\n",
+				rc);
+			goto error;
+		}
+		mp->vreg_config[i].min_voltage = tmp;
+
+		/* vreg-max-voltage */
+		rc = of_property_read_u32(supply_node,
+			"qcom,supply-max-voltage", &tmp);
+		if (rc) {
+			pr_err("error reading max volt. rc=%d\n",
+				rc);
+			goto error;
+		}
+		mp->vreg_config[i].max_voltage = tmp;
+
+		/* enable-load */
+		rc = of_property_read_u32(supply_node,
+			"qcom,supply-enable-load", &tmp);
+		if (rc) {
+			pr_err("error reading enable load. rc=%d\n",
+				rc);
+			goto error;
+		}
+		mp->vreg_config[i].enable_load = tmp;
+
+		/* disable-load */
+		rc = of_property_read_u32(supply_node,
+			"qcom,supply-disable-load", &tmp);
+		if (rc) {
+			pr_err("error reading disable load. rc=%d\n",
+				rc);
+			goto error;
+		}
+		mp->vreg_config[i].disable_load = tmp;
+
+		pr_debug("%s min=%d, max=%d, enable=%d, disable=%d\n",
+			mp->vreg_config[i].vreg_name,
+			mp->vreg_config[i].min_voltage,
+			mp->vreg_config[i].max_voltage,
+			mp->vreg_config[i].enable_load,
+			mp->vreg_config[i].disable_load
+			);
+		++i;
+	}
+
+	return rc;
+
+error:
+	if (mp->vreg_config) {
+		devm_kfree(&parser->pdev->dev, mp->vreg_config);
+		mp->vreg_config = NULL;
+	}
+novreg:
+	mp->num_vreg = 0;
+
+	return rc;
+}
+
+static void dp_parser_put_vreg_data(struct device *dev,
+	struct dss_module_power *mp)
+{
+	if (!mp) {
+		DEV_ERR("invalid input\n");
+		return;
+	}
+
+	if (mp->vreg_config) {
+		devm_kfree(dev, mp->vreg_config);
+		mp->vreg_config = NULL;
+	}
+	mp->num_vreg = 0;
+}
+
+static int dp_parser_regulator(struct dp_parser *parser)
+{
+	int i, rc = 0;
+	struct platform_device *pdev = parser->pdev;
+
+	/* Parse the regulator information */
+	for (i = DP_CORE_PM; i < DP_MAX_PM; i++) {
+		rc = dp_parser_get_vreg(parser, i);
+		if (rc) {
+			pr_err("get_dt_vreg_data failed for %s. rc=%d\n",
+				dp_parser_pm_name(i), rc);
+			i--;
+			for (; i >= DP_CORE_PM; i--)
+				dp_parser_put_vreg_data(&pdev->dev,
+					&parser->mp[i]);
+			break;
+		}
+	}
+
+	return rc;
+}
+
+static bool dp_parser_check_prefix(const char *clk_prefix, const char *clk_name)
+{
+	return !!strnstr(clk_name, clk_prefix, strlen(clk_name));
+}
+
+static void dp_parser_put_clk_data(struct device *dev,
+	struct dss_module_power *mp)
+{
+	if (!mp) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	if (mp->clk_config) {
+		devm_kfree(dev, mp->clk_config);
+		mp->clk_config = NULL;
+	}
+
+	mp->num_clk = 0;
+}
+
+static int dp_parser_init_clk_data(struct dp_parser *parser)
+{
+	int num_clk = 0, i = 0, rc = 0;
+	int core_clk_count = 0, ctrl_clk_count = 0;
+	const char *core_clk = "core";
+	const char *ctrl_clk = "ctrl";
+	const char *clk_name;
+	struct device *dev = &parser->pdev->dev;
+	struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
+	struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
+
+	num_clk = of_property_count_strings(dev->of_node, "clock-names");
+	if (num_clk <= 0) {
+		pr_err("no clocks are defined\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	for (i = 0; i < num_clk; i++) {
+		of_property_read_string_index(dev->of_node,
+				"clock-names", i, &clk_name);
+
+		if (dp_parser_check_prefix(core_clk, clk_name))
+			core_clk_count++;
+
+		if (dp_parser_check_prefix(ctrl_clk, clk_name))
+			ctrl_clk_count++;
+	}
+
+	/* Initialize the CORE power module */
+	if (core_clk_count <= 0) {
+		pr_err("no core clocks are defined\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	core_power->num_clk = core_clk_count;
+	core_power->clk_config = devm_kzalloc(dev,
+			sizeof(struct dss_clk) * core_power->num_clk,
+			GFP_KERNEL);
+	if (!core_power->clk_config) {
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	/* Initialize the CTRL power module */
+	if (ctrl_clk_count <= 0) {
+		pr_err("no ctrl clocks are defined\n");
+		rc = -EINVAL;
+		goto ctrl_clock_error;
+	}
+
+	ctrl_power->num_clk = ctrl_clk_count;
+	ctrl_power->clk_config = devm_kzalloc(dev,
+			sizeof(struct dss_clk) * ctrl_power->num_clk,
+			GFP_KERNEL);
+	if (!ctrl_power->clk_config) {
+		ctrl_power->num_clk = 0;
+		rc = -EINVAL;
+		goto ctrl_clock_error;
+	}
+
+	return rc;
+
+ctrl_clock_error:
+	dp_parser_put_clk_data(dev, core_power);
+exit:
+	return rc;
+}
+
+static int dp_parser_clock(struct dp_parser *parser)
+{
+	int rc = 0, i = 0;
+	int num_clk = 0;
+	int core_clk_index = 0, ctrl_clk_index = 0;
+	int core_clk_count = 0, ctrl_clk_count = 0;
+	const char *clk_name;
+	const char *core_clk = "core";
+	const char *ctrl_clk = "ctrl";
+	struct device *dev = &parser->pdev->dev;
+	struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
+	struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
+
+	core_power = &parser->mp[DP_CORE_PM];
+	ctrl_power = &parser->mp[DP_CTRL_PM];
+
+	rc =  dp_parser_init_clk_data(parser);
+	if (rc) {
+		pr_err("failed to initialize power data\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	core_clk_count = core_power->num_clk;
+	ctrl_clk_count = ctrl_power->num_clk;
+
+	num_clk = core_clk_count + ctrl_clk_count;
+
+	for (i = 0; i < num_clk; i++) {
+		of_property_read_string_index(dev->of_node, "clock-names",
+				i, &clk_name);
+
+		if (dp_parser_check_prefix(core_clk, clk_name) &&
+				core_clk_index < core_clk_count) {
+			struct dss_clk *clk =
+				&core_power->clk_config[core_clk_index];
+			strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
+			clk->type = DSS_CLK_AHB;
+			core_clk_index++;
+		} else if (dp_parser_check_prefix(ctrl_clk, clk_name) &&
+			   ctrl_clk_index < ctrl_clk_count) {
+			struct dss_clk *clk =
+				&ctrl_power->clk_config[ctrl_clk_index];
+			strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
+			ctrl_clk_index++;
+
+			if (!strcmp(clk_name, "ctrl_link_clk") ||
+			    !strcmp(clk_name, "ctrl_pixel_clk") ||
+			    !strcmp(clk_name, "ctrl_crypto_clk"))
+				clk->type = DSS_CLK_PCLK;
+			else
+				clk->type = DSS_CLK_AHB;
+		}
+	}
+
+	pr_debug("clock parsing successful\n");
+
+exit:
+	return rc;
+}
+
+static int dp_parser_parse(struct dp_parser *parser)
+{
+	int rc = 0;
+
+	if (!parser) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto err;
+	}
+
+	rc = dp_parser_ctrl_res(parser);
+	if (rc)
+		goto err;
+
+	rc = dp_parser_aux(parser);
+	if (rc)
+		goto err;
+
+	rc = dp_parser_misc(parser);
+	if (rc)
+		goto err;
+
+	rc = dp_parser_clock(parser);
+	if (rc)
+		goto err;
+
+	rc = dp_parser_regulator(parser);
+	if (rc)
+		goto err;
+
+	rc = dp_parser_gpio(parser);
+	if (rc)
+		goto err;
+
+	rc = dp_parser_pinctrl(parser);
+err:
+	return rc;
+}
+
+struct dp_parser *dp_parser_get(struct platform_device *pdev)
+{
+	struct dp_parser *parser;
+
+	parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL);
+	if (!parser)
+		return ERR_PTR(-ENOMEM);
+
+	parser->parse = dp_parser_parse;
+	parser->pdev = pdev;
+
+	return parser;
+}
+
+void dp_parser_put(struct dp_parser *parser)
+{
+	int i = 0;
+	struct dss_module_power *power = NULL;
+
+	if (!parser) {
+		pr_err("invalid parser module\n");
+		return;
+	}
+
+	power = parser->mp;
+
+	for (i = 0; i < DP_MAX_PM; i++) {
+		struct dss_module_power *mp = &power[i];
+
+		devm_kfree(&parser->pdev->dev, mp->clk_config);
+		devm_kfree(&parser->pdev->dev, mp->vreg_config);
+		devm_kfree(&parser->pdev->dev, mp->gpio_config);
+	}
+
+	devm_kfree(&parser->pdev->dev, parser);
+}
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h
new file mode 100644
index 0000000..fdcdd3a
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_parser.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _DP_PARSER_H_
+#define _DP_PARSER_H_
+
+#include <linux/sde_io_util.h>
+
+#define DP_LABEL "MDSS DP DISPLAY"
+#define AUX_CFG_LEN	10
+#define DP_MAX_PIXEL_CLK_KHZ	675000
+
+enum dp_pm_type {
+	DP_CORE_PM,
+	DP_CTRL_PM,
+	DP_PHY_PM,
+	DP_MAX_PM
+};
+
+static inline const char *dp_parser_pm_name(enum dp_pm_type module)
+{
+	switch (module) {
+	case DP_CORE_PM:	return "DP_CORE_PM";
+	case DP_CTRL_PM:	return "DP_CTRL_PM";
+	case DP_PHY_PM:		return "DP_PHY_PM";
+	default:		return "???";
+	}
+}
+
+/**
+ * struct dp_display_data  - display related device tree data.
+ *
+ * @ctrl_node: referece to controller device
+ * @phy_node:  reference to phy device
+ * @is_active: is the controller currently active
+ * @name: name of the display
+ * @display_type: type of the display
+ */
+struct dp_display_data {
+	struct device_node *ctrl_node;
+	struct device_node *phy_node;
+	bool is_active;
+	const char *name;
+	const char *display_type;
+};
+
+/**
+ * struct dp_ctrl_resource - controller's IO related data
+ *
+ * @ctrl_io: controller's mapped memory address
+ * @phy_io: phy's mapped memory address
+ * @ln_tx0_io: USB-DP lane TX0's mapped memory address
+ * @ln_tx1_io: USB-DP lane TX1's mapped memory address
+ * @dp_cc_io: DP cc's mapped memory address
+ * @qfprom_io: qfprom's mapped memory address
+ * @dp_pll_io: DP PLL mapped memory address
+ * @hdcp_io: hdcp's mapped memory address
+ */
+struct dp_io {
+	struct dss_io_data ctrl_io;
+	struct dss_io_data phy_io;
+	struct dss_io_data ln_tx0_io;
+	struct dss_io_data ln_tx1_io;
+	struct dss_io_data dp_cc_io;
+	struct dss_io_data qfprom_io;
+	struct dss_io_data dp_pll_io;
+	struct dss_io_data hdcp_io;
+};
+
+/**
+ * struct dp_pinctrl - DP's pin control
+ *
+ * @pin: pin-controller's instance
+ * @state_active: active state pin control
+ * @state_hpd_active: hpd active state pin control
+ * @state_suspend: suspend state pin control
+ */
+struct dp_pinctrl {
+	struct pinctrl *pin;
+	struct pinctrl_state *state_active;
+	struct pinctrl_state *state_hpd_active;
+	struct pinctrl_state *state_suspend;
+};
+
+/**
+ * struct dp_parser - DP parser's data exposed to clients
+ *
+ * @pdev: platform data of the client
+ * @mp: gpio, regulator and clock related data
+ * @pinctrl: pin-control related data
+ * @ctrl_resouce: controller's register address realated data
+ * @disp_data: controller's display related data
+ * @parse: function to be called by client to parse device tree.
+ */
+struct dp_parser {
+	struct platform_device *pdev;
+	struct dss_module_power mp[DP_MAX_PM];
+	struct dp_pinctrl pinctrl;
+	struct dp_io io;
+	struct dp_display_data disp_data;
+
+	u8 l_map[4];
+	u32 aux_cfg[AUX_CFG_LEN];
+	u32 max_pclk_khz;
+
+	int (*parse)(struct dp_parser *parser);
+};
+
+/**
+ * dp_parser_get() - get the DP's device tree parser module
+ *
+ * @pdev: platform data of the client
+ * return: pointer to dp_parser structure.
+ *
+ * This function provides client capability to parse the
+ * device tree and populate the data structures. The data
+ * related to clock, regulators, pin-control and other
+ * can be parsed using this module.
+ */
+struct dp_parser *dp_parser_get(struct platform_device *pdev);
+
+/**
+ * dp_parser_put() - cleans the dp_parser module
+ *
+ * @parser: pointer to the parser's data.
+ */
+void dp_parser_put(struct dp_parser *parser);
+#endif
diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c
new file mode 100644
index 0000000..54d4a10
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_power.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__
+
+#include <linux/clk.h>
+#include "dp_power.h"
+
+struct dp_power_private {
+	struct dp_parser *parser;
+	struct platform_device *pdev;
+	struct clk *pixel_clk_rcg;
+	struct clk *pixel_parent;
+
+	struct dp_power dp_power;
+
+	bool core_clks_on;
+	bool link_clks_on;
+};
+
+static int dp_power_regulator_init(struct dp_power_private *power)
+{
+	int rc = 0, i = 0, j = 0;
+	struct platform_device *pdev;
+	struct dp_parser *parser;
+
+	parser = power->parser;
+	pdev = power->pdev;
+
+	for (i = DP_CORE_PM; !rc && (i < DP_MAX_PM); i++) {
+		rc = msm_dss_config_vreg(&pdev->dev,
+			parser->mp[i].vreg_config,
+			parser->mp[i].num_vreg, 1);
+		if (rc) {
+			pr_err("failed to init vregs for %s\n",
+				dp_parser_pm_name(i));
+			for (j = i - 1; j >= DP_CORE_PM; j--) {
+				msm_dss_config_vreg(&pdev->dev,
+				parser->mp[j].vreg_config,
+				parser->mp[j].num_vreg, 0);
+			}
+
+			goto error;
+		}
+	}
+error:
+	return rc;
+}
+
+static int dp_power_regulator_ctrl(struct dp_power_private *power, bool enable)
+{
+	int rc = 0, i = 0, j = 0;
+	struct dp_parser *parser;
+
+	parser = power->parser;
+
+	for (i = DP_CORE_PM; i < DP_MAX_PM; i++) {
+		rc = msm_dss_enable_vreg(
+			parser->mp[i].vreg_config,
+			parser->mp[i].num_vreg, enable);
+		if (rc) {
+			pr_err("failed to '%s' vregs for %s\n",
+					enable ? "enable" : "disable",
+					dp_parser_pm_name(i));
+			if (enable) {
+				for (j = i-1; j >= DP_CORE_PM; j--) {
+					msm_dss_enable_vreg(
+					parser->mp[j].vreg_config,
+					parser->mp[j].num_vreg, 0);
+				}
+			}
+			goto error;
+		}
+	}
+error:
+	return rc;
+}
+
+static int dp_power_pinctrl_set(struct dp_power_private *power, bool active)
+{
+	int rc = -EFAULT;
+	struct pinctrl_state *pin_state;
+	struct dp_parser *parser;
+
+	parser = power->parser;
+
+	if (IS_ERR_OR_NULL(parser->pinctrl.pin))
+		return PTR_ERR(parser->pinctrl.pin);
+
+	pin_state = active ? parser->pinctrl.state_active
+				: parser->pinctrl.state_suspend;
+	if (!IS_ERR_OR_NULL(pin_state)) {
+		rc = pinctrl_select_state(parser->pinctrl.pin,
+				pin_state);
+		if (rc)
+			pr_err("can not set %s pins\n",
+			       active ? "dp_active"
+			       : "dp_sleep");
+	} else {
+		pr_err("invalid '%s' pinstate\n",
+		       active ? "dp_active"
+		       : "dp_sleep");
+	}
+
+	return rc;
+}
+
+static int dp_power_clk_init(struct dp_power_private *power, bool enable)
+{
+	int rc = 0;
+	struct dss_module_power *core, *ctrl;
+	struct device *dev;
+
+	core = &power->parser->mp[DP_CORE_PM];
+	ctrl = &power->parser->mp[DP_CTRL_PM];
+
+	dev = &power->pdev->dev;
+
+	if (!core || !ctrl) {
+		pr_err("invalid power_data\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	if (enable) {
+		rc = msm_dss_get_clk(dev, core->clk_config, core->num_clk);
+		if (rc) {
+			pr_err("failed to get %s clk. err=%d\n",
+				dp_parser_pm_name(DP_CORE_PM), rc);
+			goto exit;
+		}
+
+		rc = msm_dss_get_clk(dev, ctrl->clk_config, ctrl->num_clk);
+		if (rc) {
+			pr_err("failed to get %s clk. err=%d\n",
+				dp_parser_pm_name(DP_CTRL_PM), rc);
+			goto ctrl_get_error;
+		}
+
+		power->pixel_clk_rcg = devm_clk_get(dev, "pixel_clk_rcg");
+		if (IS_ERR(power->pixel_clk_rcg)) {
+			pr_debug("Unable to get DP pixel clk RCG\n");
+			power->pixel_clk_rcg = NULL;
+		}
+
+		power->pixel_parent = devm_clk_get(dev, "pixel_parent");
+		if (IS_ERR(power->pixel_parent)) {
+			pr_debug("Unable to get DP pixel RCG parent\n");
+			power->pixel_parent = NULL;
+		}
+	} else {
+		if (power->pixel_parent)
+			devm_clk_put(dev, power->pixel_parent);
+
+		if (power->pixel_clk_rcg)
+			devm_clk_put(dev, power->pixel_clk_rcg);
+
+		msm_dss_put_clk(ctrl->clk_config, ctrl->num_clk);
+		msm_dss_put_clk(core->clk_config, core->num_clk);
+	}
+
+	return rc;
+
+ctrl_get_error:
+	msm_dss_put_clk(core->clk_config, core->num_clk);
+exit:
+	return rc;
+}
+
+static int dp_power_clk_set_rate(struct dp_power_private *power,
+		enum dp_pm_type module, bool enable)
+{
+	int rc = 0;
+	struct dss_module_power *mp;
+
+	if (!power) {
+		pr_err("invalid power data\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	mp = &power->parser->mp[module];
+
+	if (enable) {
+		rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
+		if (rc) {
+			pr_err("failed to set clks rate.\n");
+			goto exit;
+		}
+
+		rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, 1);
+		if (rc) {
+			pr_err("failed to enable clks\n");
+			goto exit;
+		}
+	} else {
+		rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, 0);
+		if (rc) {
+			pr_err("failed to disable clks\n");
+				goto exit;
+		}
+	}
+exit:
+	return rc;
+}
+
+static int dp_power_clk_enable(struct dp_power *dp_power,
+		enum dp_pm_type pm_type, bool enable)
+{
+	int rc = 0;
+	struct dss_module_power *mp;
+	struct dp_power_private *power;
+
+	if (!dp_power) {
+		pr_err("invalid power data\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	power = container_of(dp_power, struct dp_power_private, dp_power);
+
+	mp = &power->parser->mp[pm_type];
+
+	if ((pm_type != DP_CORE_PM) && (pm_type != DP_CTRL_PM)) {
+		pr_err("unsupported power module: %s\n",
+				dp_parser_pm_name(pm_type));
+		return -EINVAL;
+	}
+
+	if (enable) {
+		if ((pm_type == DP_CORE_PM)
+			&& (power->core_clks_on)) {
+			pr_debug("core clks already enabled\n");
+			return 0;
+		}
+
+		if ((pm_type == DP_CTRL_PM)
+			&& (power->link_clks_on)) {
+			pr_debug("links clks already enabled\n");
+			return 0;
+		}
+
+		if ((pm_type == DP_CTRL_PM) && (!power->core_clks_on)) {
+			pr_debug("Need to enable core clks before link clks\n");
+
+			rc = dp_power_clk_set_rate(power, pm_type, enable);
+			if (rc) {
+				pr_err("failed to enable clks: %s. err=%d\n",
+					dp_parser_pm_name(DP_CORE_PM), rc);
+				goto error;
+			} else {
+				power->core_clks_on = true;
+			}
+		}
+	}
+
+	rc = dp_power_clk_set_rate(power, pm_type, enable);
+	if (rc) {
+		pr_err("failed to '%s' clks for: %s. err=%d\n",
+			enable ? "enable" : "disable",
+			dp_parser_pm_name(pm_type), rc);
+			goto error;
+	}
+
+	if (pm_type == DP_CORE_PM)
+		power->core_clks_on = enable;
+	else
+		power->link_clks_on = enable;
+
+	pr_debug("%s clocks for %s\n",
+			enable ? "enable" : "disable",
+			dp_parser_pm_name(pm_type));
+	pr_debug("link_clks:%s core_clks:%s\n",
+		power->link_clks_on ? "on" : "off",
+		power->core_clks_on ? "on" : "off");
+error:
+	return rc;
+}
+
+static int dp_power_request_gpios(struct dp_power_private *power)
+{
+	int rc = 0, i;
+	struct device *dev;
+	struct dss_module_power *mp;
+	static const char * const gpio_names[] = {
+		"aux_enable", "aux_sel", "usbplug_cc",
+	};
+
+	if (!power) {
+		pr_err("invalid power data\n");
+		return -EINVAL;
+	}
+
+	dev = &power->pdev->dev;
+	mp = &power->parser->mp[DP_CORE_PM];
+
+	for (i = 0; i < ARRAY_SIZE(gpio_names); i++) {
+		unsigned int gpio = mp->gpio_config[i].gpio;
+
+		if (gpio_is_valid(gpio)) {
+			rc = devm_gpio_request(dev, gpio, gpio_names[i]);
+			if (rc) {
+				pr_err("request %s gpio failed, rc=%d\n",
+					       gpio_names[i], rc);
+				goto error;
+			}
+		}
+	}
+	return 0;
+error:
+	for (i = 0; i < ARRAY_SIZE(gpio_names); i++) {
+		unsigned int gpio = mp->gpio_config[i].gpio;
+
+		if (gpio_is_valid(gpio))
+			gpio_free(gpio);
+	}
+	return rc;
+}
+
+static bool dp_power_find_gpio(const char *gpio1, const char *gpio2)
+{
+	return !!strnstr(gpio1, gpio2, strlen(gpio1));
+}
+
+static void dp_power_set_gpio(struct dp_power_private *power, bool flip)
+{
+	int i;
+	struct dss_module_power *mp = &power->parser->mp[DP_CORE_PM];
+	struct dss_gpio *config = mp->gpio_config;
+
+	for (i = 0; i < mp->num_gpio; i++) {
+		if (dp_power_find_gpio(config->gpio_name, "aux-sel"))
+			config->value = flip;
+
+		if (gpio_is_valid(config->gpio)) {
+			pr_debug("gpio %s, value %d\n", config->gpio_name,
+				config->value);
+
+			if (dp_power_find_gpio(config->gpio_name, "aux-en") ||
+			    dp_power_find_gpio(config->gpio_name, "aux-sel"))
+				gpio_direction_output(config->gpio,
+					config->value);
+			else
+				gpio_set_value(config->gpio, config->value);
+
+		}
+		config++;
+	}
+}
+
+static int dp_power_config_gpios(struct dp_power_private *power, bool flip,
+					bool enable)
+{
+	int rc = 0, i;
+	struct dss_module_power *mp;
+	struct dss_gpio *config;
+
+	mp = &power->parser->mp[DP_CORE_PM];
+	config = mp->gpio_config;
+
+	if (enable) {
+		rc = dp_power_request_gpios(power);
+		if (rc) {
+			pr_err("gpio request failed\n");
+			return rc;
+		}
+
+		dp_power_set_gpio(power, flip);
+	} else {
+		for (i = 0; i < mp->num_gpio; i++) {
+			gpio_set_value(config[i].gpio, 0);
+			gpio_free(config[i].gpio);
+		}
+	}
+
+	return 0;
+}
+
+static int dp_power_set_pixel_clk_parent(struct dp_power *dp_power)
+{
+	int rc = 0;
+	struct dp_power_private *power;
+
+	if (!dp_power) {
+		pr_err("invalid power data\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	power = container_of(dp_power, struct dp_power_private, dp_power);
+
+	if (power->pixel_clk_rcg && power->pixel_parent)
+		clk_set_parent(power->pixel_clk_rcg, power->pixel_parent);
+exit:
+	return rc;
+}
+
+static int dp_power_init(struct dp_power *dp_power, bool flip)
+{
+	int rc = 0;
+	struct dp_power_private *power;
+
+	if (!dp_power) {
+		pr_err("invalid power data\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	power = container_of(dp_power, struct dp_power_private, dp_power);
+
+	rc = dp_power_regulator_ctrl(power, true);
+	if (rc) {
+		pr_err("failed to enable regulators\n");
+		goto exit;
+	}
+
+	rc = dp_power_pinctrl_set(power, true);
+	if (rc) {
+		pr_err("failed to set pinctrl state\n");
+		goto err_pinctrl;
+	}
+
+	rc = dp_power_config_gpios(power, flip, true);
+	if (rc) {
+		pr_err("failed to enable gpios\n");
+		goto err_gpio;
+	}
+
+	rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
+	if (rc) {
+		pr_err("failed to enable DP core clocks\n");
+		goto err_clk;
+	}
+
+	return 0;
+
+err_clk:
+	dp_power_config_gpios(power, flip, false);
+err_gpio:
+	dp_power_pinctrl_set(power, false);
+err_pinctrl:
+	dp_power_regulator_ctrl(power, false);
+exit:
+	return rc;
+}
+
+static int dp_power_deinit(struct dp_power *dp_power)
+{
+	int rc = 0;
+	struct dp_power_private *power;
+
+	if (!dp_power) {
+		pr_err("invalid power data\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	power = container_of(dp_power, struct dp_power_private, dp_power);
+
+	dp_power_clk_enable(dp_power, DP_CORE_PM, false);
+	dp_power_config_gpios(power, false, false);
+	dp_power_pinctrl_set(power, false);
+	dp_power_regulator_ctrl(power, false);
+exit:
+	return rc;
+}
+
+struct dp_power *dp_power_get(struct dp_parser *parser)
+{
+	int rc = 0;
+	struct dp_power_private *power;
+	struct dp_power *dp_power;
+
+	if (!parser) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL);
+	if (!power) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	power->parser = parser;
+	power->pdev = parser->pdev;
+
+	dp_power = &power->dp_power;
+
+	dp_power->init = dp_power_init;
+	dp_power->deinit = dp_power_deinit;
+	dp_power->clk_enable = dp_power_clk_enable;
+	dp_power->set_pixel_clk_parent = dp_power_set_pixel_clk_parent;
+
+	rc = dp_power_regulator_init(power);
+	if (rc) {
+		pr_err("failed to init regulators\n");
+		goto error;
+	}
+
+	rc = dp_power_clk_init(power, true);
+	if (rc) {
+		pr_err("failed to init clocks\n");
+		goto error;
+	}
+
+	return dp_power;
+error:
+	return ERR_PTR(rc);
+}
+
+void dp_power_put(struct dp_power *dp_power)
+{
+	struct dp_power_private *power = container_of(dp_power,
+			struct dp_power_private, dp_power);
+
+	(void)dp_power_clk_init(power, false);
+	devm_kfree(&power->pdev->dev, power);
+}
diff --git a/drivers/gpu/drm/msm/dp/dp_power.h b/drivers/gpu/drm/msm/dp/dp_power.h
new file mode 100644
index 0000000..3d71695
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_power.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _DP_POWER_H_
+#define _DP_POWER_H_
+
+#include "dp_parser.h"
+
+/**
+ * sruct dp_power - DisplayPort's power related data
+ *
+ * @init: initializes the regulators/core clocks/GPIOs/pinctrl
+ * @deinit: turns off the regulators/core clocks/GPIOs/pinctrl
+ * @clk_enable: enable/disable the DP clocks
+ * @set_pixel_clk_parent: set the parent of DP pixel clock
+ */
+struct dp_power {
+	int (*init)(struct dp_power *power, bool flip);
+	int (*deinit)(struct dp_power *power);
+	int (*clk_enable)(struct dp_power *power, enum dp_pm_type pm_type,
+				bool enable);
+	int (*set_pixel_clk_parent)(struct dp_power *power);
+};
+
+/**
+ * dp_power_get() - configure and get the DisplayPort power module data
+ *
+ * @parser: instance of parser module
+ * return: pointer to allocated power module data
+ *
+ * This API will configure the DisplayPort's power module and provides
+ * methods to be called by the client to configure the power related
+ * modueles.
+ */
+struct dp_power *dp_power_get(struct dp_parser *parser);
+
+/**
+ * dp_power_put() - release the power related resources
+ *
+ * @power: pointer to the power module's data
+ */
+void dp_power_put(struct dp_power *power);
+#endif /* _DP_POWER_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
index 5dcdf46..2d7b174 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
@@ -142,7 +142,8 @@
 void dsi_ctrl_hw_cmn_setup_cmd_stream(struct dsi_ctrl_hw *ctrl,
 				     struct dsi_mode_info *mode,
 				     u32 h_stride,
-				     u32 vc_id);
+				     u32 vc_id,
+				     struct dsi_rect *roi);
 void dsi_ctrl_hw_cmn_phy_sw_reset(struct dsi_ctrl_hw *ctrl);
 void dsi_ctrl_hw_cmn_soft_reset(struct dsi_ctrl_hw *ctrl);
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index f187ad1..39b797e 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1558,7 +1558,6 @@
 
 int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl)
 {
-	struct dsi_mode_info video_timing;
 	int rc = 0;
 
 	if (!dsi_ctrl) {
@@ -1568,12 +1567,6 @@
 
 	mutex_lock(&dsi_ctrl->ctrl_lock);
 
-	/* replace video mode width with actual roi width */
-	memcpy(&video_timing, &dsi_ctrl->host_config.video_timing,
-			sizeof(video_timing));
-	video_timing.h_active = dsi_ctrl->roi.w;
-	video_timing.v_active = dsi_ctrl->roi.h;
-
 	dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw,
 					&dsi_ctrl->host_config.lane_map);
 
@@ -1586,9 +1579,10 @@
 					&dsi_ctrl->host_config.u.cmd_engine);
 
 		dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
-				&video_timing,
-				video_timing.h_active * 3,
-				0x0);
+				&dsi_ctrl->host_config.video_timing,
+				dsi_ctrl->host_config.video_timing.h_active * 3,
+				0x0,
+				&dsi_ctrl->roi);
 		dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, true);
 	} else {
 		dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw,
@@ -1690,7 +1684,8 @@
 		dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
 				&dsi_ctrl->host_config.video_timing,
 				dsi_ctrl->host_config.video_timing.h_active * 3,
-				0x0);
+				0x0,
+				NULL);
 	} else {
 		dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw,
 					&dsi_ctrl->host_config.common_config,
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
index 859d707..bb72807 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
@@ -319,7 +319,8 @@
 	void (*setup_cmd_stream)(struct dsi_ctrl_hw *ctrl,
 				 struct dsi_mode_info *mode,
 				 u32 h_stride,
-				 u32 vc_id);
+				 u32 vc_id,
+				 struct dsi_rect *roi);
 
 	/**
 	 * ctrl_en() - enable DSI controller engine
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
index 48c2370..a024c43 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
@@ -19,6 +19,7 @@
 #include "dsi_ctrl_hw.h"
 #include "dsi_ctrl_reg.h"
 #include "dsi_hw.h"
+#include "dsi_panel.h"
 
 #define MMSS_MISC_CLAMP_REG_OFF           0x0014
 #define DSI_CTRL_DYNAMIC_FORCE_ON         (0x23F|BIT(8)|BIT(9)|BIT(11)|BIT(21))
@@ -234,21 +235,36 @@
 void dsi_ctrl_hw_cmn_setup_cmd_stream(struct dsi_ctrl_hw *ctrl,
 				     struct dsi_mode_info *mode,
 				     u32 h_stride,
-				     u32 vc_id)
+				     u32 vc_id,
+				     struct dsi_rect *roi)
 {
-	u32 reg = 0;
 	u32 width_final, stride_final;
+	u32 height_final;
+	u32 stream_total = 0, stream_ctrl = 0;
+	u32 reg_ctrl = 0, reg_ctrl2 = 0;
+
+	if (roi && (!roi->w || !roi->h))
+		return;
 
 	if (mode->dsc_enabled && mode->dsc) {
+		u32 reg = 0;
 		u32 offset = 0;
-		u32 reg_ctrl, reg_ctrl2;
+		int pic_width, this_frame_slices, intf_ip_w;
+		struct msm_display_dsc_info dsc;
+
+		memcpy(&dsc, mode->dsc, sizeof(dsc));
+		pic_width = roi ? roi->w : mode->h_active;
+		this_frame_slices = pic_width / dsc.slice_width;
+		intf_ip_w = this_frame_slices * dsc.slice_width;
+		dsi_dsc_pclk_param_calc(&dsc, intf_ip_w);
 
 		if (vc_id != 0)
 			offset = 16;
 		reg_ctrl = DSI_R32(ctrl, DSI_COMMAND_COMPRESSION_MODE_CTRL);
 		reg_ctrl2 = DSI_R32(ctrl, DSI_COMMAND_COMPRESSION_MODE_CTRL2);
-		width_final = mode->dsc->pclk_per_line;
-		stride_final = mode->dsc->bytes_per_pkt;
+		width_final = dsc.pclk_per_line;
+		stride_final = dsc.bytes_per_pkt;
+		height_final = roi ? roi->h : mode->v_active;
 
 		reg = 0x39 << 8;
 		/*
@@ -258,34 +274,45 @@
 		 * 2 == 4 pkt
 		 * 3 pkt is not support
 		 */
-		if (mode->dsc->pkt_per_line == 4)
-			reg |= (mode->dsc->pkt_per_line - 2) << 6;
+		if (dsc.pkt_per_line == 4)
+			reg |= (dsc.pkt_per_line - 2) << 6;
 		else
-			reg |= (mode->dsc->pkt_per_line - 1) << 6;
-		reg |= mode->dsc->eol_byte_num << 4;
+			reg |= (dsc.pkt_per_line - 1) << 6;
+		reg |= dsc.eol_byte_num << 4;
 		reg |= 1;
 
 		reg_ctrl &= ~(0xFFFF << offset);
 		reg_ctrl |= (reg << offset);
 		reg_ctrl2 &= ~(0xFFFF << offset);
-		reg_ctrl2 |= (mode->dsc->bytes_in_slice << offset);
+		reg_ctrl2 |= (dsc.bytes_in_slice << offset);
 		DSI_W32(ctrl, DSI_COMMAND_COMPRESSION_MODE_CTRL, reg_ctrl);
 		DSI_W32(ctrl, DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2);
+
+		pr_debug("ctrl %d reg_ctrl 0x%x reg_ctrl2 0x%x\n", ctrl->index,
+				reg_ctrl, reg_ctrl2);
+	} else if (roi) {
+		width_final = roi->w;
+		stride_final = roi->w * 3;
+		height_final = roi->h;
 	} else {
 		width_final = mode->h_active;
 		stride_final = h_stride;
+		height_final = mode->v_active;
 	}
 
-	reg = (stride_final + 1) << 16;
-	reg |= (vc_id & 0x3) << 8;
-	reg |= 0x39; /* packet data type */
+	stream_ctrl = (stride_final + 1) << 16;
+	stream_ctrl |= (vc_id & 0x3) << 8;
+	stream_ctrl |= 0x39; /* packet data type */
 
-	DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_CTRL, reg);
-	DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_CTRL, reg);
+	DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_CTRL, stream_ctrl);
+	DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_CTRL, stream_ctrl);
 
-	reg = (mode->v_active << 16) | width_final;
-	DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_TOTAL, reg);
-	DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_TOTAL, reg);
+	stream_total = (height_final << 16) | width_final;
+	DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_TOTAL, stream_total);
+	DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_TOTAL, stream_total);
+
+	pr_debug("ctrl %d stream_ctrl 0x%x stream_total 0x%x\n", ctrl->index,
+			stream_ctrl, stream_total);
 }
 
 /**
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 53f0098..37ed411 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -357,6 +357,10 @@
 	case DSI_PANEL_ROTATE_V_FLIP:
 		sde_kms_info_add_keystr(info, "panel orientation", "vert flip");
 		break;
+	case DSI_PANEL_ROTATE_HV_FLIP:
+		sde_kms_info_add_keystr(info, "panel orientation",
+							"horz & vert flip");
+		break;
 	default:
 		pr_debug("invalid panel rotation:%d\n",
 						panel->phy_props.rotation);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
index 4c9fbbe..f254af5 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
@@ -249,4 +249,6 @@
 int dsi_panel_send_roi_dcs(struct dsi_panel *panel, int ctrl_idx,
 		struct dsi_rect *roi);
 
+void dsi_dsc_pclk_param_calc(struct msm_display_dsc_info *dsc, int intf_width);
+
 #endif /* _DSI_PANEL_H_ */
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 4e0b678..a3a9142 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1271,22 +1271,20 @@
 	return ret;
 }
 
-void msm_send_crtc_notification(struct drm_crtc *crtc,
-				struct drm_event *event, u8 *payload)
+void msm_mode_object_event_nofity(struct drm_mode_object *obj,
+		struct drm_device *dev, struct drm_event *event, u8 *payload)
 {
-	struct drm_device *dev = NULL;
 	struct msm_drm_private *priv = NULL;
 	unsigned long flags;
 	struct msm_drm_event *notify, *node;
 	int len = 0, ret;
 
-	if (!crtc || !event || !event->length || !payload) {
-		DRM_ERROR("err param crtc %pK event %pK len %d payload %pK\n",
-			crtc, event, ((event) ? (event->length) : -1),
+	if (!obj || !event || !event->length || !payload) {
+		DRM_ERROR("err param obj %pK event %pK len %d payload %pK\n",
+			obj, event, ((event) ? (event->length) : -1),
 			payload);
 		return;
 	}
-	dev = crtc->dev;
 	priv = (dev) ? dev->dev_private : NULL;
 	if (!dev || !priv) {
 		DRM_ERROR("invalid dev %pK priv %pK\n", dev, priv);
@@ -1296,7 +1294,7 @@
 	spin_lock_irqsave(&dev->event_lock, flags);
 	list_for_each_entry(node, &priv->client_event_list, base.link) {
 		if (node->event.type != event->type ||
-			crtc->base.id != node->info.object_id)
+			obj->id != node->info.object_id)
 			continue;
 		len = event->length + sizeof(struct drm_msm_event_resp);
 		if (node->base.file_priv->event_space < len) {
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index d50a185..f596989 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -710,13 +710,14 @@
 };
 
 /* *
- * msm_send_crtc_notification - notify user-space clients of crtc events.
- * @crtc: crtc that is generating the event.
+ * msm_mode_object_event_notify - notify user-space clients of drm object
+ *                                events.
+ * @obj: mode object (crtc/connector) that is generating the event.
  * @event: event that needs to be notified.
  * @payload: payload for the event.
  */
-void msm_send_crtc_notification(struct drm_crtc *crtc,
-		struct drm_event *event, u8 *payload);
+void msm_mode_object_event_nofity(struct drm_mode_object *obj,
+		struct drm_device *dev, struct drm_event *event, u8 *payload);
 #ifdef CONFIG_DRM_MSM_DSI
 void __init msm_dsi_register(void);
 void __exit msm_dsi_unregister(void);
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 3061099..acd7af5 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -341,7 +341,8 @@
 			if (obj->import_attach && mmu->funcs->map_dma_buf) {
 				ret = mmu->funcs->map_dma_buf(mmu, msm_obj->sgt,
 						obj->import_attach->dmabuf,
-						DMA_BIDIRECTIONAL);
+						DMA_BIDIRECTIONAL,
+						msm_obj->flags);
 				if (ret) {
 					DRM_ERROR("Unable to map dma buf\n");
 					return ret;
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 2cf170d..19c7726 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -23,6 +23,7 @@
 
 /* Additional internal-use only BO flags: */
 #define MSM_BO_STOLEN        0x10000000    /* try to use stolen/splash memory */
+#define MSM_BO_KEEPATTRS     0x20000000     /* keep h/w bus attributes */
 
 struct msm_gem_object {
 	struct drm_gem_object base;
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index ee93339..fbf7e7b 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -43,7 +43,7 @@
 	void (*unmap_sg)(struct msm_mmu *mmu, struct sg_table *sgt,
 		enum dma_data_direction dir);
 	int (*map_dma_buf)(struct msm_mmu *mmu, struct sg_table *sgt,
-			struct dma_buf *dma_buf, int dir);
+			struct dma_buf *dma_buf, int dir, u32 flags);
 	void (*unmap_dma_buf)(struct msm_mmu *mmu, struct sg_table *sgt,
 			struct dma_buf *dma_buf, int dir);
 	void (*destroy)(struct msm_mmu *mmu);
diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c
index c279d01..4d45898 100644
--- a/drivers/gpu/drm/msm/msm_smmu.c
+++ b/drivers/gpu/drm/msm/msm_smmu.c
@@ -25,6 +25,7 @@
 #include <soc/qcom/secure_buffer.h>
 
 #include "msm_drv.h"
+#include "msm_gem.h"
 #include "msm_mmu.h"
 
 #ifndef SZ_4G
@@ -220,14 +221,18 @@
 }
 
 static int msm_smmu_map_dma_buf(struct msm_mmu *mmu, struct sg_table *sgt,
-			struct dma_buf *dma_buf, int dir)
+			struct dma_buf *dma_buf, int dir, u32 flags)
 {
 	struct msm_smmu *smmu = to_msm_smmu(mmu);
 	struct msm_smmu_client *client = msm_smmu_to_client(smmu);
+	unsigned long attrs = 0x0;
 	int ret;
 
-	ret = msm_dma_map_sg_lazy(client->dev, sgt->sgl, sgt->nents, dir,
-			dma_buf);
+	if (flags & MSM_BO_KEEPATTRS)
+		attrs |= DMA_ATTR_IOMMU_USE_UPSTREAM_HINT;
+
+	ret = msm_dma_map_sg_attrs(client->dev, sgt->sgl, sgt->nents, dir,
+			dma_buf, attrs);
 	if (ret != sgt->nents) {
 		DRM_ERROR("dma map sg failed\n");
 		return -ENOMEM;
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index 79b39bd..b410302 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -180,7 +180,7 @@
 	struct drm_property_blob *blob = prop_node->blob_ptr;
 
 	if (!blob)
-		return -EINVAL;
+		return 0;
 	drm_property_unreference_blob(blob);
 	prop_node->blob_ptr = NULL;
 	return 0;
@@ -1164,7 +1164,7 @@
 		sde_cp_create_local_blob(crtc, SDE_CP_CRTC_DSPP_AD_CFG,
 			sizeof(struct drm_msm_ad4_cfg));
 		sde_cp_crtc_install_range_property(crtc,
-			"SDE_DSPP_AD_V4_ASSERTIVNESS",
+			"SDE_DSPP_AD_V4_ASSERTIVENESS",
 			SDE_CP_CRTC_DSPP_AD_ASSERTIVENESS, 0, (BIT(8) - 1), 0);
 		sde_cp_crtc_install_range_property(crtc, "SDE_DSPP_AD_V4_INPUT",
 			SDE_CP_CRTC_DSPP_AD_INPUT, 0, U16_MAX, 0);
@@ -1357,7 +1357,8 @@
 	hw_dspp->ops.ad_read_intr_resp(hw_dspp, AD4_BACKLIGHT, &bl);
 	event.length = sizeof(u32);
 	event.type = DRM_EVENT_AD_BACKLIGHT;
-	msm_send_crtc_notification(&crtc->base, &event, (u8 *)&bl);
+	msm_mode_object_event_nofity(&crtc_drm->base, crtc_drm->dev,
+			&event, (u8 *)&bl);
 }
 
 int sde_cp_ad_interrupt(struct drm_crtc *crtc_drm, bool en,
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 6593b47..f13c6c9 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -59,6 +59,7 @@
 	struct dsi_display *display;
 	struct sde_connector *c_conn;
 	int bl_lvl;
+	struct drm_event event;
 
 	brightness = bd->props.brightness;
 
@@ -79,8 +80,13 @@
 	if (!bl_lvl && brightness)
 		bl_lvl = 1;
 
-	if (c_conn->ops.set_backlight)
+	if (c_conn->ops.set_backlight) {
+		event.type = DRM_EVENT_SYS_BACKLIGHT;
+		event.length = sizeof(u32);
+		msm_mode_object_event_nofity(&c_conn->base.base,
+				c_conn->base.dev, &event, (u8 *)&brightness);
 		c_conn->ops.set_backlight(c_conn->display, bl_lvl);
+	}
 
 	return 0;
 }
@@ -1165,5 +1171,14 @@
 int sde_connector_register_custom_event(struct sde_kms *kms,
 		struct drm_connector *conn_drm, u32 event, bool val)
 {
-	return -EINVAL;
+	int ret = -EINVAL;
+
+	switch (event) {
+	case DRM_EVENT_SYS_BACKLIGHT:
+		ret = 0;
+		break;
+	default:
+		break;
+	}
+	return ret;
 }
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 02d6009..79fcfb7 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -51,8 +51,12 @@
 			struct sde_irq_callback *irq);
 };
 
+static int sde_crtc_power_interrupt_handler(struct drm_crtc *crtc_drm,
+	bool en, struct sde_irq_callback *ad_irq);
+
 static struct sde_crtc_custom_events custom_events[] = {
-	{DRM_EVENT_AD_BACKLIGHT, sde_cp_ad_interrupt}
+	{DRM_EVENT_AD_BACKLIGHT, sde_cp_ad_interrupt},
+	{DRM_EVENT_CRTC_POWER, sde_crtc_power_interrupt_handler}
 };
 
 /* default input fence timeout, in ms */
@@ -608,12 +612,15 @@
 	int i;
 
 	if (!dim_layer->rect.w || !dim_layer->rect.h) {
-		SDE_DEBUG("empty dim layer\n");
+		SDE_DEBUG("empty dim_layer\n");
 		return;
 	}
 
 	cstate = to_sde_crtc_state(crtc->state);
 
+	SDE_DEBUG("dim_layer - flags:%d, stage:%d\n",
+			dim_layer->flags, dim_layer->stage);
+
 	split_dim_layer.stage = dim_layer->stage;
 	split_dim_layer.color_fill = dim_layer->color_fill;
 
@@ -647,9 +654,13 @@
 		} else {
 			split_dim_layer.rect.x =
 					split_dim_layer.rect.x -
-					cstate->lm_bounds[i].w;
+						cstate->lm_bounds[i].x;
 		}
 
+		SDE_DEBUG("split_dim_layer - LM:%d, rect:{%d,%d,%d,%d}}\n",
+			i, split_dim_layer.rect.x, split_dim_layer.rect.y,
+			split_dim_layer.rect.w, split_dim_layer.rect.h);
+
 		lm = mixer[i].hw_lm;
 		mixer[i].mixer_op_mode |= 1 << split_dim_layer.stage;
 		lm->ops.setup_dim_layer(lm, &split_dim_layer);
@@ -731,7 +742,6 @@
 	struct sde_crtc *sde_crtc;
 	struct sde_crtc_state *crtc_state;
 	struct sde_rect *crtc_roi;
-	struct drm_clip_rect crtc_clip, *user_rect;
 	int i, num_attached_conns = 0;
 
 	if (!crtc || !state)
@@ -741,12 +751,6 @@
 	crtc_state = to_sde_crtc_state(state);
 	crtc_roi = &crtc_state->crtc_roi;
 
-	/* init to invalid range maxes */
-	crtc_clip.x1 = ~0;
-	crtc_clip.y1 = ~0;
-	crtc_clip.x2 = 0;
-	crtc_clip.y2 = 0;
-
 	for_each_connector_in_state(state->state, conn, conn_state, i) {
 		struct sde_connector_state *sde_conn_state;
 
@@ -771,36 +775,7 @@
 		}
 	}
 
-	/* aggregate all clipping rectangles together for overall crtc roi */
-	for (i = 0; i < crtc_state->user_roi_list.num_rects; i++) {
-		user_rect = &crtc_state->user_roi_list.roi[i];
-
-		crtc_clip.x1 = min(crtc_clip.x1, user_rect->x1);
-		crtc_clip.y1 = min(crtc_clip.y1, user_rect->y1);
-		crtc_clip.x2 = max(crtc_clip.x2, user_rect->x2);
-		crtc_clip.y2 = max(crtc_clip.y2, user_rect->y2);
-
-		SDE_DEBUG(
-			"%s: conn%d roi%d (%d,%d),(%d,%d) -> crtc (%d,%d),(%d,%d)\n",
-				sde_crtc->name, DRMID(crtc), i,
-				user_rect->x1, user_rect->y1,
-				user_rect->x2, user_rect->y2,
-				crtc_clip.x1, crtc_clip.y1,
-				crtc_clip.x2, crtc_clip.y2);
-
-	}
-
-	if (crtc_clip.x2  && crtc_clip.y2) {
-		crtc_roi->x = crtc_clip.x1;
-		crtc_roi->y = crtc_clip.y1;
-		crtc_roi->w = crtc_clip.x2 - crtc_clip.x1;
-		crtc_roi->h = crtc_clip.y2 - crtc_clip.y1;
-	} else {
-		crtc_roi->x = 0;
-		crtc_roi->y = 0;
-		crtc_roi->w = 0;
-		crtc_roi->h = 0;
-	}
+	sde_kms_rect_merge_rectangles(&crtc_state->user_roi_list, crtc_roi);
 
 	SDE_DEBUG("%s: crtc roi (%d,%d,%d,%d)\n", sde_crtc->name,
 			crtc_roi->x, crtc_roi->y, crtc_roi->w, crtc_roi->h);
@@ -890,9 +865,24 @@
 	sde_crtc = to_sde_crtc(crtc);
 	crtc_state = to_sde_crtc_state(state);
 
-	for (i = 0; i < sde_crtc->num_mixers; i++) {
-		if (!sde_kms_rect_is_null(&crtc_state->lm_roi[i]))
-			disp_bitmask |= BIT(i);
+	/* pingpong split: one ROI, one LM, two physical displays */
+	if (crtc_state->is_ppsplit) {
+		u32 lm_split_width = crtc_state->lm_bounds[0].w / 2;
+		struct sde_rect *roi = &crtc_state->lm_roi[0];
+
+		if (sde_kms_rect_is_null(roi))
+			disp_bitmask = 0;
+		else if ((u32)roi->x + (u32)roi->w <= lm_split_width)
+			disp_bitmask = BIT(0);		/* left only */
+		else if (roi->x >= lm_split_width)
+			disp_bitmask = BIT(1);		/* right only */
+		else
+			disp_bitmask = BIT(0) | BIT(1); /* left and right */
+	} else {
+		for (i = 0; i < sde_crtc->num_mixers; i++) {
+			if (!sde_kms_rect_is_null(&crtc_state->lm_roi[i]))
+				disp_bitmask |= BIT(i);
+		}
 	}
 
 	SDE_DEBUG("affected displays 0x%x\n", disp_bitmask);
@@ -913,9 +903,6 @@
 	sde_crtc = to_sde_crtc(crtc);
 	crtc_state = to_sde_crtc_state(state);
 
-	if (sde_crtc->num_mixers == 1)
-		return 0;
-
 	if (sde_crtc->num_mixers > CRTC_DUAL_MIXERS) {
 		SDE_ERROR("%s: unsupported number of mixers: %d\n",
 				sde_crtc->name, sde_crtc->num_mixers);
@@ -923,9 +910,41 @@
 	}
 
 	/*
-	 * On certain HW, ROIs must be centered on the split between LMs,
-	 * and be of equal width.
+	 * If using pingpong split: one ROI, one LM, two physical displays
+	 * then the ROI must be centered on the panel split boundary and
+	 * be of equal width across the split.
 	 */
+	if (crtc_state->is_ppsplit) {
+		u16 panel_split_width;
+		u32 display_mask;
+
+		roi[0] = &crtc_state->lm_roi[0];
+
+		if (sde_kms_rect_is_null(roi[0]))
+			return 0;
+
+		display_mask = _sde_crtc_get_displays_affected(crtc, state);
+		if (display_mask != (BIT(0) | BIT(1)))
+			return 0;
+
+		panel_split_width = crtc_state->lm_bounds[0].w / 2;
+		if (roi[0]->x + roi[0]->w / 2 != panel_split_width) {
+			SDE_ERROR("%s: roi x %d w %d split %d\n",
+					sde_crtc->name, roi[0]->x, roi[0]->w,
+					panel_split_width);
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+
+	/*
+	 * On certain HW, if using 2 LM, ROIs must be split evenly between the
+	 * LMs and be of equal width.
+	 */
+	if (sde_crtc->num_mixers == 1)
+		return 0;
+
 	roi[0] = &crtc_state->lm_roi[0];
 	roi[1] = &crtc_state->lm_roi[1];
 
@@ -1066,6 +1085,10 @@
 		if (sde_kms_rect_is_null(lm_roi))
 			continue;
 
+		hw_lm->cfg.out_width = lm_roi->w;
+		hw_lm->cfg.out_height = lm_roi->h;
+		hw_lm->cfg.right_mixer = lm_horiz_position;
+
 		cfg.out_width = lm_roi->w;
 		cfg.out_height = lm_roi->h;
 		cfg.right_mixer = lm_horiz_position++;
@@ -1209,6 +1232,69 @@
 	_sde_crtc_program_lm_output_roi(crtc);
 }
 
+static void _sde_crtc_swap_mixers_for_right_partial_update(
+		struct drm_crtc *crtc)
+{
+	struct sde_crtc *sde_crtc;
+	struct sde_crtc_state *cstate;
+	struct drm_encoder *drm_enc;
+	bool is_right_only;
+	bool encoder_in_dsc_merge = false;
+
+	if (!crtc || !crtc->state)
+		return;
+
+	sde_crtc = to_sde_crtc(crtc);
+	cstate = to_sde_crtc_state(crtc->state);
+
+	if (sde_crtc->num_mixers != CRTC_DUAL_MIXERS)
+		return;
+
+	drm_for_each_encoder(drm_enc, crtc->dev) {
+		if (drm_enc->crtc == crtc &&
+				sde_encoder_is_dsc_merge(drm_enc)) {
+			encoder_in_dsc_merge = true;
+			break;
+		}
+	}
+
+	/**
+	 * For right-only partial update with DSC merge, we swap LM0 & LM1.
+	 * This is due to two reasons:
+	 * - On 8996, there is a DSC HW requirement that in DSC Merge Mode,
+	 *   the left DSC must be used, right DSC cannot be used alone.
+	 *   For right-only partial update, this means swap layer mixers to map
+	 *   Left LM to Right INTF. On later HW this was relaxed.
+	 * - In DSC Merge mode, the physical encoder has already registered
+	 *   PP0 as the master, to switch to right-only we would have to
+	 *   reprogram to be driven by PP1 instead.
+	 * To support both cases, we prefer to support the mixer swap solution.
+	 */
+	if (!encoder_in_dsc_merge)
+		return;
+
+	is_right_only = sde_kms_rect_is_null(&cstate->lm_roi[0]) &&
+			!sde_kms_rect_is_null(&cstate->lm_roi[1]);
+
+	if (is_right_only && !sde_crtc->mixers_swapped) {
+		/* right-only update swap mixers */
+		swap(sde_crtc->mixers[0], sde_crtc->mixers[1]);
+		sde_crtc->mixers_swapped = true;
+	} else if (!is_right_only && sde_crtc->mixers_swapped) {
+		/* left-only or full update, swap back */
+		swap(sde_crtc->mixers[0], sde_crtc->mixers[1]);
+		sde_crtc->mixers_swapped = false;
+	}
+
+	SDE_DEBUG("%s: right_only %d swapped %d, mix0->lm%d, mix1->lm%d\n",
+			sde_crtc->name, is_right_only, sde_crtc->mixers_swapped,
+			sde_crtc->mixers[0].hw_lm->idx - LM_0,
+			sde_crtc->mixers[1].hw_lm->idx - LM_0);
+	SDE_EVT32(DRMID(crtc), is_right_only, sde_crtc->mixers_swapped,
+			sde_crtc->mixers[0].hw_lm->idx - LM_0,
+			sde_crtc->mixers[1].hw_lm->idx - LM_0);
+}
+
 /**
  * _sde_crtc_blend_setup - configure crtc mixers
  * @crtc: Pointer to drm crtc structure
@@ -1254,6 +1340,8 @@
 			lm->ops.clear_dim_layer(lm);
 	}
 
+	_sde_crtc_swap_mixers_for_right_partial_update(crtc);
+
 	/* initialize stage cfg */
 	memset(&sde_crtc->stage_cfg, 0, sizeof(struct sde_hw_stage_cfg));
 
@@ -1562,26 +1650,28 @@
 {
 	struct sde_drm_dim_layer_v1 dim_layer_v1;
 	struct sde_drm_dim_layer_cfg *user_cfg;
+	struct sde_hw_dim_layer *dim_layer;
 	u32 count, i;
 
 	if (!cstate) {
 		SDE_ERROR("invalid cstate\n");
 		return;
 	}
+	dim_layer = cstate->dim_layer;
 
 	if (!usr_ptr) {
-		SDE_DEBUG("dim layer data removed\n");
+		SDE_DEBUG("dim_layer data removed\n");
 		return;
 	}
 
 	if (copy_from_user(&dim_layer_v1, usr_ptr, sizeof(dim_layer_v1))) {
-		SDE_ERROR("failed to copy dim layer data\n");
+		SDE_ERROR("failed to copy dim_layer data\n");
 		return;
 	}
 
 	count = dim_layer_v1.num_layers;
-	if (!count || (count > SDE_MAX_DIM_LAYERS)) {
-		SDE_ERROR("invalid number of Dim Layers:%d", count);
+	if (count > SDE_MAX_DIM_LAYERS) {
+		SDE_ERROR("invalid number of dim_layers:%d", count);
 		return;
 	}
 
@@ -1589,22 +1679,31 @@
 	cstate->num_dim_layers = count;
 	for (i = 0; i < count; i++) {
 		user_cfg = &dim_layer_v1.layer_cfg[i];
-		cstate->dim_layer[i].flags = user_cfg->flags;
-		cstate->dim_layer[i].stage = user_cfg->stage + SDE_STAGE_0;
 
-		cstate->dim_layer[i].rect.x = user_cfg->rect.x1;
-		cstate->dim_layer[i].rect.y = user_cfg->rect.y1;
-		cstate->dim_layer[i].rect.w = user_cfg->rect.x2 -
-						user_cfg->rect.x1 + 1;
-		cstate->dim_layer[i].rect.h = user_cfg->rect.y2 -
-						user_cfg->rect.y1 + 1;
+		dim_layer[i].flags = user_cfg->flags;
+		dim_layer[i].stage = user_cfg->stage + SDE_STAGE_0;
 
-		cstate->dim_layer[i].color_fill = (struct sde_mdss_color) {
+		dim_layer[i].rect.x = user_cfg->rect.x1;
+		dim_layer[i].rect.y = user_cfg->rect.y1;
+		dim_layer[i].rect.w = user_cfg->rect.x2 - user_cfg->rect.x1;
+		dim_layer[i].rect.h = user_cfg->rect.y2 - user_cfg->rect.y1;
+
+		dim_layer[i].color_fill = (struct sde_mdss_color) {
 				user_cfg->color_fill.color_0,
 				user_cfg->color_fill.color_1,
 				user_cfg->color_fill.color_2,
 				user_cfg->color_fill.color_3,
 		};
+
+		SDE_DEBUG("dim_layer[%d] - flags:%d, stage:%d\n",
+				i, dim_layer[i].flags, dim_layer[i].stage);
+		SDE_DEBUG(" rect:{%d,%d,%d,%d}, color:{%d,%d,%d,%d}\n",
+				dim_layer[i].rect.x, dim_layer[i].rect.y,
+				dim_layer[i].rect.w, dim_layer[i].rect.h,
+				dim_layer[i].color_fill.color_0,
+				dim_layer[i].color_fill.color_1,
+				dim_layer[i].color_fill.color_2,
+				dim_layer[i].color_fill.color_3);
 	}
 }
 
@@ -1728,6 +1827,23 @@
 	mutex_unlock(&sde_crtc->crtc_lock);
 }
 
+static void _sde_crtc_setup_is_ppsplit(struct drm_crtc_state *state)
+{
+	int i;
+	struct sde_crtc_state *cstate;
+
+	cstate = to_sde_crtc_state(state);
+
+	cstate->is_ppsplit = false;
+	for (i = 0; i < cstate->num_connectors; i++) {
+		struct drm_connector *conn = cstate->connectors[i];
+
+		if (sde_connector_get_topology_name(conn) ==
+				SDE_RM_TOPOLOGY_PPSPLIT)
+			cstate->is_ppsplit = true;
+	}
+}
+
 static void _sde_crtc_setup_lm_bounds(struct drm_crtc *crtc,
 		struct drm_crtc_state *state)
 {
@@ -1792,6 +1908,7 @@
 
 	if (!sde_crtc->num_mixers) {
 		_sde_crtc_setup_mixers(crtc);
+		_sde_crtc_setup_is_ppsplit(crtc->state);
 		_sde_crtc_setup_lm_bounds(crtc, crtc->state);
 	}
 
@@ -2054,6 +2171,8 @@
 	struct sde_crtc *sde_crtc;
 	struct msm_drm_private *priv;
 	struct sde_kms *sde_kms;
+	struct drm_event event;
+	u32 power_on;
 
 	if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
 		SDE_ERROR("invalid crtc\n");
@@ -2072,13 +2191,18 @@
 
 	mutex_lock(&sde_crtc->crtc_lock);
 
+	event.type = DRM_EVENT_CRTC_POWER;
+	event.length = sizeof(u32);
 	/*
 	 * Update CP on suspend/resume transitions
 	 */
-	if (enable && !sde_crtc->suspend)
+	if (enable && !sde_crtc->suspend) {
 		sde_cp_crtc_suspend(crtc);
-	else if (!enable && sde_crtc->suspend)
+		power_on = 0;
+	} else if (!enable && sde_crtc->suspend) {
 		sde_cp_crtc_resume(crtc);
+		power_on = 1;
+	}
 
 	/*
 	 * If the vblank refcount != 0, release a power reference on suspend
@@ -2091,7 +2215,8 @@
 		_sde_crtc_vblank_enable_nolock(sde_crtc, !enable);
 
 	sde_crtc->suspend = enable;
-
+	msm_mode_object_event_nofity(&crtc->base, crtc->dev, &event,
+			(u8 *)&power_on);
 	mutex_unlock(&sde_crtc->crtc_lock);
 }
 
@@ -2506,6 +2631,7 @@
 
 	mixer_width = sde_crtc_mixer_width(sde_crtc, mode);
 
+	_sde_crtc_setup_is_ppsplit(state);
 	_sde_crtc_setup_lm_bounds(crtc, state);
 
 	 /* get plane state for all drm planes associated with crtc state */
@@ -2528,9 +2654,10 @@
 		/* check dim layer stage with every plane */
 		for (i = 0; i < cstate->num_dim_layers; i++) {
 			if (pstates[cnt].stage == cstate->dim_layer[i].stage) {
-				SDE_ERROR("plane%d/dimlayer in same stage:%d\n",
-						plane->base.id,
-						cstate->dim_layer[i].stage);
+				SDE_ERROR(
+					"plane:%d/dim_layer:%i-same stage:%d\n",
+					plane->base.id, i,
+					cstate->dim_layer[i].stage);
 				rc = -EINVAL;
 				goto end;
 			}
@@ -2563,11 +2690,14 @@
 	}
 
 	for (i = 1; i < SSPP_MAX; i++) {
-		if (pipe_staged[i] &&
-			is_sde_plane_virtual(pipe_staged[i]->plane)) {
-			SDE_ERROR("invalid use of virtual plane: %d\n",
+		if (pipe_staged[i]) {
+			sde_plane_clear_multirect(pipe_staged[i]);
+
+			if (is_sde_plane_virtual(pipe_staged[i]->plane)) {
+				SDE_ERROR("invalid use of virtual plane: %d\n",
 					pipe_staged[i]->plane->base.id);
-			goto end;
+				goto end;
+			}
 		}
 	}
 
@@ -2798,16 +2928,18 @@
 	msm_property_install_blob(&sde_crtc->property_info, "capabilities",
 		DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_INFO);
 
-	if (catalog->has_dim_layer) {
-		msm_property_install_volatile_range(&sde_crtc->property_info,
-			"dim_layer_v1", 0x0, 0, ~0, 0, CRTC_PROP_DIM_LAYER_V1);
-	}
-
 	msm_property_install_volatile_range(&sde_crtc->property_info,
 		"sde_drm_roi_v1", 0x0, 0, ~0, 0, CRTC_PROP_ROI_V1);
 
 	sde_kms_info_reset(info);
 
+	if (catalog->has_dim_layer) {
+		msm_property_install_volatile_range(&sde_crtc->property_info,
+			"dim_layer_v1", 0x0, 0, ~0, 0, CRTC_PROP_DIM_LAYER_V1);
+		sde_kms_info_add_keyint(info, "dim_layer_v1_max_layers",
+				SDE_MAX_DIM_LAYERS);
+	}
+
 	sde_kms_info_add_keyint(info, "hw_version", catalog->hwversion);
 	sde_kms_info_add_keyint(info, "max_linewidth",
 			catalog->max_mixer_width);
@@ -3007,6 +3139,7 @@
 	struct drm_display_mode *mode;
 	struct drm_framebuffer *fb;
 	struct drm_plane_state *state;
+	struct sde_crtc_state *cstate;
 
 	int i, out_width;
 
@@ -3015,6 +3148,7 @@
 
 	sde_crtc = s->private;
 	crtc = &sde_crtc->base;
+	cstate = to_sde_crtc_state(crtc->state);
 
 	mutex_lock(&sde_crtc->crtc_lock);
 	mode = &crtc->state->adjusted_mode;
@@ -3039,6 +3173,23 @@
 
 	seq_puts(s, "\n");
 
+	for (i = 0; i < cstate->num_dim_layers; i++) {
+		struct sde_hw_dim_layer *dim_layer = &cstate->dim_layer[i];
+
+		seq_printf(s, "\tdim_layer:%d] stage:%d flags:%d\n",
+				i, dim_layer->stage, dim_layer->flags);
+		seq_printf(s, "\tdst_x:%d dst_y:%d dst_w:%d dst_h:%d\n",
+				dim_layer->rect.x, dim_layer->rect.y,
+				dim_layer->rect.w, dim_layer->rect.h);
+		seq_printf(s,
+			"\tcolor_0:%d color_1:%d color_2:%d color_3:%d\n",
+				dim_layer->color_fill.color_0,
+				dim_layer->color_fill.color_1,
+				dim_layer->color_fill.color_2,
+				dim_layer->color_fill.color_3);
+		seq_puts(s, "\n");
+	}
+
 	drm_atomic_crtc_for_each_plane(plane, crtc) {
 		pstate = to_sde_plane_state(plane->state);
 		state = plane->state;
@@ -3081,6 +3232,13 @@
 		seq_printf(s, "\tdst x:%4d dst_y:%4d dst_w:%4d dst_h:%4d\n",
 			state->crtc_x, state->crtc_y, state->crtc_w,
 			state->crtc_h);
+		seq_printf(s, "\tmultirect: mode: %d index: %d\n",
+			pstate->multirect_mode, pstate->multirect_index);
+
+		seq_printf(s, "\texcl_rect: x:%4d y:%4d w:%4d h:%4d\n",
+			pstate->excl_rect.x, pstate->excl_rect.y,
+			pstate->excl_rect.w, pstate->excl_rect.h);
+
 		seq_puts(s, "\n");
 	}
 
@@ -3642,3 +3800,9 @@
 
 	return ret;
 }
+
+static int sde_crtc_power_interrupt_handler(struct drm_crtc *crtc_drm,
+	bool en, struct sde_irq_callback *irq)
+{
+	return 0;
+}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 6a22115..9ef6f25 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -108,6 +108,8 @@
  * @name          : ASCII description of this crtc
  * @num_ctls      : Number of ctl paths in use
  * @num_mixers    : Number of mixers in use
+ * @mixers_swapped: Whether the mixers have been swapped for left/right update
+ *                  especially in the case of DSC Merge.
  * @mixers        : List of active mixers
  * @event         : Pointer to last received drm vblank event. If there is a
  *                  pending vblank event, this will be non-null.
@@ -147,6 +149,7 @@
 	/* HW Resources reserved for the crtc */
 	u32 num_ctls;
 	u32 num_mixers;
+	bool mixers_swapped;
 	struct sde_crtc_mixer mixers[CRTC_DUAL_MIXERS];
 
 	struct drm_pending_vblank_event *event;
@@ -251,6 +254,7 @@
  * @num_connectors: Number of associated drm connectors
  * @intf_mode     : Interface mode of the primary connector
  * @rsc_client    : sde rsc client when mode is valid
+ * @is_ppsplit    : Whether current topology requires PPSplit special handling
  * @crtc_roi      : Current CRTC ROI. Possibly sub-rectangle of mode.
  *                  Origin top left of CRTC.
  * @lm_bounds     : LM boundaries based on current mode full resolution, no ROI.
@@ -277,6 +281,7 @@
 	struct sde_rsc_client *rsc_client;
 	bool rsc_update;
 
+	bool is_ppsplit;
 	struct sde_rect crtc_roi;
 	struct sde_rect lm_bounds[CRTC_DUAL_MIXERS];
 	struct sde_rect lm_roi[CRTC_DUAL_MIXERS];
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index f11ba51..e3ad960 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -123,8 +123,11 @@
  * @cur_master:		Pointer to the current master in this mode. Optimization
  *			Only valid after enable. Cleared as disable.
  * @hw_pp		Handle to the pingpong blocks used for the display. No.
- *                      pingpong blocks can be different than num_phys_encs.
+ *			pingpong blocks can be different than num_phys_encs.
  * @hw_dsc:		Array of DSC block handles used for the display.
+ * @intfs_swapped	Whether or not the phys_enc interfaces have been swapped
+ *			for partial update right-only cases, such as pingpong
+ *			split where virtual pingpong does not generate IRQs
  * @crtc_vblank_cb:	Callback into the upper layer / CRTC for
  *			notification of the VBLANK
  * @crtc_vblank_cb_data:	Data from upper layer for VBLANK notification
@@ -155,6 +158,8 @@
  * @topology:                   topology of the display
  * @mode_set_complete:          flag to indicate modeset completion
  * @rsc_cfg:			rsc configuration
+ * @cur_conn_roi:		current connector roi
+ * @prv_conn_roi:		previous connector roi to optimize if unchanged
  */
 struct sde_encoder_virt {
 	struct drm_encoder base;
@@ -169,6 +174,8 @@
 	struct sde_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
 	struct sde_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
 
+	bool intfs_swapped;
+
 	void (*crtc_vblank_cb)(void *);
 	void *crtc_vblank_cb_data;
 
@@ -195,17 +202,51 @@
 	bool mode_set_complete;
 
 	struct sde_encoder_rsc_config rsc_cfg;
+	struct sde_rect cur_conn_roi;
+	struct sde_rect prv_conn_roi;
 };
 
 #define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
 
-inline bool _sde_is_dsc_enabled(struct sde_encoder_virt *sde_enc)
+bool sde_encoder_is_dsc_enabled(struct drm_encoder *drm_enc)
+
 {
-	struct msm_compression_info *comp_info = &sde_enc->disp_info.comp_info;
+	struct sde_encoder_virt *sde_enc;
+	struct msm_compression_info *comp_info;
+
+	if (!drm_enc)
+		return false;
+
+	sde_enc = to_sde_encoder_virt(drm_enc);
+	comp_info = &sde_enc->disp_info.comp_info;
 
 	return (comp_info->comp_type == MSM_DISPLAY_COMPRESSION_DSC);
 }
 
+bool sde_encoder_is_dsc_merge(struct drm_encoder *drm_enc)
+{
+	enum sde_rm_topology_name topology;
+	struct sde_encoder_virt *sde_enc;
+	struct drm_connector *drm_conn;
+
+	if (!drm_enc)
+		return false;
+
+	sde_enc = to_sde_encoder_virt(drm_enc);
+	if (!sde_enc->cur_master)
+		return false;
+
+	drm_conn = sde_enc->cur_master->connector;
+	if (!drm_conn)
+		return false;
+
+	topology = sde_connector_get_topology_name(drm_conn);
+	if (topology == SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE)
+		return true;
+
+	return false;
+}
+
 static inline int _sde_encoder_power_enable(struct sde_encoder_virt *sde_enc,
 								bool enable)
 {
@@ -320,7 +361,22 @@
 
 	sde_enc = to_sde_encoder_virt(phys_enc->parent);
 	hw_mdptop = phys_enc->hw_mdptop;
-	cfg.en = phys_enc->split_role != ENC_ROLE_SOLO;
+
+	/**
+	 * disable split modes since encoder will be operating in as the only
+	 * encoder, either for the entire use case in the case of, for example,
+	 * single DSI, or for this frame in the case of left/right only partial
+	 * update.
+	 */
+	if (phys_enc->split_role == ENC_ROLE_SOLO) {
+		if (hw_mdptop->ops.setup_split_pipe)
+			hw_mdptop->ops.setup_split_pipe(hw_mdptop, &cfg);
+		if (hw_mdptop->ops.setup_pp_split)
+			hw_mdptop->ops.setup_pp_split(hw_mdptop, &cfg);
+		return;
+	}
+
+	cfg.en = true;
 	cfg.mode = phys_enc->intf_mode;
 	cfg.intf = interface;
 
@@ -334,8 +390,7 @@
 	else
 		cfg.pp_split_slave = INTF_MAX;
 
-	if (phys_enc->split_role != ENC_ROLE_SLAVE) {
-		/* master/solo encoder */
+	if (phys_enc->split_role == ENC_ROLE_MASTER) {
 		SDE_DEBUG_ENC(sde_enc, "enable %d\n", cfg.en);
 
 		if (hw_mdptop->ops.setup_split_pipe)
@@ -555,8 +610,14 @@
 
 static void _sde_encoder_dsc_pipe_cfg(struct sde_hw_dsc *hw_dsc,
 		struct sde_hw_pingpong *hw_pp, struct msm_display_dsc_info *dsc,
-		u32 common_mode, bool ich_reset)
+		u32 common_mode, bool ich_reset, bool enable)
 {
+	if (!enable) {
+		if (hw_pp->ops.disable_dsc)
+			hw_pp->ops.disable_dsc(hw_pp);
+		return;
+	}
+
 	if (hw_dsc->ops.dsc_config)
 		hw_dsc->ops.dsc_config(hw_dsc, dsc, common_mode, ich_reset);
 
@@ -570,9 +631,27 @@
 		hw_pp->ops.enable_dsc(hw_pp);
 }
 
+static void _sde_encoder_get_connector_roi(
+		struct sde_encoder_virt *sde_enc,
+		struct sde_rect *merged_conn_roi)
+{
+	struct drm_connector *drm_conn;
+	struct sde_connector_state *c_state;
+
+	if (!sde_enc || !merged_conn_roi)
+		return;
+
+	drm_conn = sde_enc->phys_encs[0]->connector;
+
+	if (!drm_conn || !drm_conn->state)
+		return;
+
+	c_state = to_sde_connector_state(drm_conn->state);
+	sde_kms_rect_merge_rectangles(&c_state->rois, merged_conn_roi);
+}
+
 static int _sde_encoder_dsc_1_lm_1_enc_1_intf(struct sde_encoder_virt *sde_enc)
 {
-	int pic_width, pic_height;
 	int this_frame_slices;
 	int intf_ip_w, enc_ip_w;
 	int ich_res, dsc_common_mode = 0;
@@ -580,22 +659,18 @@
 	struct sde_hw_pingpong *hw_pp = sde_enc->hw_pp[0];
 	struct sde_hw_dsc *hw_dsc = sde_enc->hw_dsc[0];
 	struct sde_encoder_phys *enc_master = sde_enc->cur_master;
-	struct sde_hw_mdp *hw_mdp_top  = enc_master->hw_mdptop;
+	const struct sde_rect *roi = &sde_enc->cur_conn_roi;
 	struct msm_display_dsc_info *dsc =
 		&sde_enc->disp_info.comp_info.dsc_info;
 
-	if (dsc == NULL || hw_dsc == NULL || hw_pp == NULL ||
-						hw_mdp_top == NULL) {
+	if (dsc == NULL || hw_dsc == NULL || hw_pp == NULL || !enc_master) {
 		SDE_ERROR_ENC(sde_enc, "invalid params for DSC\n");
 		return -EINVAL;
 	}
 
-	pic_width = dsc->pic_width;
-	pic_height = dsc->pic_height;
+	_sde_encoder_dsc_update_pic_dim(dsc, roi->w, roi->h);
 
-	_sde_encoder_dsc_update_pic_dim(dsc, pic_width, pic_height);
-
-	this_frame_slices = pic_width / dsc->slice_width;
+	this_frame_slices = roi->w / dsc->slice_width;
 	intf_ip_w = this_frame_slices * dsc->slice_width;
 	_sde_encoder_dsc_pclk_param_calc(dsc, intf_ip_w);
 
@@ -608,132 +683,208 @@
 		dsc_common_mode = DSC_MODE_VIDEO;
 
 	SDE_DEBUG_ENC(sde_enc, "pic_w: %d pic_h: %d mode:%d\n",
-		pic_width, pic_height, dsc_common_mode);
-	SDE_EVT32(DRMID(&sde_enc->base), pic_width, pic_height,
-			dsc_common_mode);
+		roi->w, roi->h, dsc_common_mode);
+	SDE_EVT32(DRMID(&sde_enc->base), roi->w, roi->h, dsc_common_mode);
 
 	_sde_encoder_dsc_pipe_cfg(hw_dsc, hw_pp, dsc, dsc_common_mode,
-			ich_res);
+			ich_res, true);
 
 	return 0;
 }
-static int _sde_encoder_dsc_2_lm_2_enc_2_intf(struct sde_encoder_virt *sde_enc)
+static int _sde_encoder_dsc_2_lm_2_enc_2_intf(struct sde_encoder_virt *sde_enc,
+		struct sde_encoder_kickoff_params *params)
 {
-	int pic_width, pic_height;
 	int this_frame_slices;
 	int intf_ip_w, enc_ip_w;
 	int ich_res, dsc_common_mode;
 
 	struct sde_encoder_phys *enc_master = sde_enc->cur_master;
-	struct sde_hw_dsc *l_hw_dsc = sde_enc->hw_dsc[0];
-	struct sde_hw_dsc *r_hw_dsc = sde_enc->hw_dsc[1];
-	struct sde_hw_pingpong *l_hw_pp = sde_enc->hw_pp[0];
-	struct sde_hw_pingpong *r_hw_pp = sde_enc->hw_pp[1];
-	struct sde_hw_mdp *hw_mdp_top  = enc_master->hw_mdptop;
-	struct msm_display_dsc_info *dsc =
-		&sde_enc->disp_info.comp_info.dsc_info;
+	const struct sde_rect *roi = &sde_enc->cur_conn_roi;
+	struct sde_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
+	struct sde_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+	struct msm_display_dsc_info dsc[MAX_CHANNELS_PER_ENC];
+	bool half_panel_partial_update;
+	int i;
 
-	if (l_hw_dsc == NULL || r_hw_dsc == NULL || hw_mdp_top == NULL ||
-		l_hw_pp == NULL || r_hw_pp == NULL) {
-		SDE_ERROR_ENC(sde_enc, "invalid params for DSC\n");
-		return -EINVAL;
+	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
+		hw_pp[i] = sde_enc->hw_pp[i];
+		hw_dsc[i] = sde_enc->hw_dsc[i];
+
+		if (!hw_pp[i] || !hw_dsc[i]) {
+			SDE_ERROR_ENC(sde_enc, "invalid params for DSC\n");
+			return -EINVAL;
+		}
 	}
 
-	pic_width = dsc->pic_width * sde_enc->display_num_of_h_tiles;
-	pic_height = dsc->pic_height;
+	half_panel_partial_update =
+			hweight_long(params->affected_displays) == 1;
 
-	_sde_encoder_dsc_update_pic_dim(dsc, pic_width, pic_height);
-
-	this_frame_slices = pic_width / dsc->slice_width;
-	intf_ip_w = this_frame_slices * dsc->slice_width;
-
-	intf_ip_w /= 2;
-	_sde_encoder_dsc_pclk_param_calc(dsc, intf_ip_w);
-
-	enc_ip_w = intf_ip_w;
-	_sde_encoder_dsc_initial_line_calc(dsc, enc_ip_w);
-
-	ich_res = _sde_encoder_dsc_ich_reset_override_needed(false, dsc);
-
-	dsc_common_mode = DSC_MODE_SPLIT_PANEL;
+	dsc_common_mode = 0;
+	if (!half_panel_partial_update)
+		dsc_common_mode |= DSC_MODE_SPLIT_PANEL;
 	if (enc_master->intf_mode == INTF_MODE_VIDEO)
 		dsc_common_mode |= DSC_MODE_VIDEO;
 
-	SDE_DEBUG_ENC(sde_enc, "pic_w: %d pic_h: %d mode:%d\n",
-		pic_width, pic_height, dsc_common_mode);
-	SDE_EVT32(DRMID(&sde_enc->base), pic_width, pic_height,
-			dsc_common_mode);
+	memcpy(&dsc[0], &sde_enc->disp_info.comp_info.dsc_info, sizeof(dsc[0]));
+	memcpy(&dsc[1], &sde_enc->disp_info.comp_info.dsc_info, sizeof(dsc[1]));
 
-	_sde_encoder_dsc_pipe_cfg(l_hw_dsc, l_hw_pp, dsc, dsc_common_mode,
-			ich_res);
-	_sde_encoder_dsc_pipe_cfg(r_hw_dsc, r_hw_pp, dsc, dsc_common_mode,
-			ich_res);
+	/*
+	 * Since both DSC use same pic dimension, set same pic dimension
+	 * to both DSC structures.
+	 */
+	_sde_encoder_dsc_update_pic_dim(&dsc[0], roi->w, roi->h);
+	_sde_encoder_dsc_update_pic_dim(&dsc[1], roi->w, roi->h);
+
+	this_frame_slices = roi->w / dsc[0].slice_width;
+	intf_ip_w = this_frame_slices * dsc[0].slice_width;
+
+	if (!half_panel_partial_update)
+		intf_ip_w /= 2;
+
+	/*
+	 * In this topology when both interfaces are active, they have same
+	 * load so intf_ip_w will be same.
+	 */
+	_sde_encoder_dsc_pclk_param_calc(&dsc[0], intf_ip_w);
+	_sde_encoder_dsc_pclk_param_calc(&dsc[1], intf_ip_w);
+
+	/*
+	 * In this topology, since there is no dsc_merge, uncompressed input
+	 * to encoder and interface is same.
+	 */
+	enc_ip_w = intf_ip_w;
+	_sde_encoder_dsc_initial_line_calc(&dsc[0], enc_ip_w);
+	_sde_encoder_dsc_initial_line_calc(&dsc[1], enc_ip_w);
+
+	/*
+	 * __is_ich_reset_override_needed should be called only after
+	 * updating pic dimension, mdss_panel_dsc_update_pic_dim.
+	 */
+	ich_res = _sde_encoder_dsc_ich_reset_override_needed(
+			half_panel_partial_update, &dsc[0]);
+
+	SDE_DEBUG_ENC(sde_enc, "pic_w: %d pic_h: %d mode:%d\n",
+			roi->w, roi->h, dsc_common_mode);
+
+	for (i = 0; i < sde_enc->num_phys_encs; i++) {
+		bool active = !!((1 << i) & params->affected_displays);
+
+		SDE_EVT32(DRMID(&sde_enc->base), roi->w, roi->h,
+				dsc_common_mode, i, active);
+		_sde_encoder_dsc_pipe_cfg(hw_dsc[i], hw_pp[i], &dsc[i],
+				dsc_common_mode, ich_res, active);
+	}
 
 	return 0;
 }
 
-static int _sde_encoder_dsc_2_lm_2_enc_1_intf(struct sde_encoder_virt *sde_enc)
+static int _sde_encoder_dsc_2_lm_2_enc_1_intf(struct sde_encoder_virt *sde_enc,
+		struct sde_encoder_kickoff_params *params)
 {
-	int pic_width, pic_height;
 	int this_frame_slices;
 	int intf_ip_w, enc_ip_w;
 	int ich_res, dsc_common_mode;
 
 	struct sde_encoder_phys *enc_master = sde_enc->cur_master;
-	struct sde_hw_dsc *l_hw_dsc = sde_enc->hw_dsc[0];
-	struct sde_hw_dsc *r_hw_dsc = sde_enc->hw_dsc[1];
-	struct sde_hw_pingpong *l_hw_pp = sde_enc->hw_pp[0];
-	struct sde_hw_pingpong *r_hw_pp = sde_enc->hw_pp[1];
-	struct sde_hw_mdp *hw_mdp_top  = enc_master->hw_mdptop;
+	const struct sde_rect *roi = &sde_enc->cur_conn_roi;
+	struct sde_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
+	struct sde_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
 	struct msm_display_dsc_info *dsc =
 		&sde_enc->disp_info.comp_info.dsc_info;
+	bool half_panel_partial_update;
+	int i;
 
-	if (l_hw_dsc == NULL || r_hw_dsc == NULL || hw_mdp_top == NULL ||
-					l_hw_pp == NULL || r_hw_pp == NULL) {
-		SDE_ERROR_ENC(sde_enc, "invalid params for DSC\n");
-		return -EINVAL;
+	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
+		hw_pp[i] = sde_enc->hw_pp[i];
+		hw_dsc[i] = sde_enc->hw_dsc[i];
+
+		if (!hw_pp[i] || !hw_dsc[i]) {
+			SDE_ERROR_ENC(sde_enc, "invalid params for DSC\n");
+			return -EINVAL;
+		}
 	}
 
-	pic_width = dsc->pic_width;
-	pic_height = dsc->pic_height;
-	_sde_encoder_dsc_update_pic_dim(dsc, pic_width, pic_height);
+	half_panel_partial_update =
+			hweight_long(params->affected_displays) == 1;
 
-	this_frame_slices = pic_width / dsc->slice_width;
+	dsc_common_mode = 0;
+	if (!half_panel_partial_update)
+		dsc_common_mode |= DSC_MODE_SPLIT_PANEL | DSC_MODE_MULTIPLEX;
+	if (enc_master->intf_mode == INTF_MODE_VIDEO)
+		dsc_common_mode |= DSC_MODE_VIDEO;
+
+	_sde_encoder_dsc_update_pic_dim(dsc, roi->w, roi->h);
+
+	this_frame_slices = roi->w / dsc->slice_width;
 	intf_ip_w = this_frame_slices * dsc->slice_width;
 	_sde_encoder_dsc_pclk_param_calc(dsc, intf_ip_w);
 
 	/*
-	 * when using 2 encoders for the same stream, no. of slices
-	 * need to be same on both the encoders.
+	 * dsc merge case: when using 2 encoders for the same stream,
+	 * no. of slices need to be same on both the encoders.
 	 */
 	enc_ip_w = intf_ip_w / 2;
 	_sde_encoder_dsc_initial_line_calc(dsc, enc_ip_w);
 
-	ich_res = _sde_encoder_dsc_ich_reset_override_needed(false, dsc);
-
-	dsc_common_mode = DSC_MODE_MULTIPLEX | DSC_MODE_SPLIT_PANEL;
-	if (enc_master->intf_mode == INTF_MODE_VIDEO)
-		dsc_common_mode |= DSC_MODE_VIDEO;
+	ich_res = _sde_encoder_dsc_ich_reset_override_needed(
+			half_panel_partial_update, dsc);
 
 	SDE_DEBUG_ENC(sde_enc, "pic_w: %d pic_h: %d mode:%d\n",
-		pic_width, pic_height, dsc_common_mode);
-	SDE_EVT32(DRMID(&sde_enc->base), pic_width, pic_height,
-			dsc_common_mode);
+			roi->w, roi->h, dsc_common_mode);
+	SDE_EVT32(DRMID(&sde_enc->base), roi->w, roi->h,
+			dsc_common_mode, i, params->affected_displays);
 
-	_sde_encoder_dsc_pipe_cfg(l_hw_dsc, l_hw_pp, dsc, dsc_common_mode,
-			ich_res);
-	_sde_encoder_dsc_pipe_cfg(r_hw_dsc, r_hw_pp, dsc, dsc_common_mode,
-			ich_res);
+	_sde_encoder_dsc_pipe_cfg(hw_dsc[0], hw_pp[0], dsc, dsc_common_mode,
+			ich_res, true);
+	_sde_encoder_dsc_pipe_cfg(hw_dsc[1], hw_pp[1], dsc, dsc_common_mode,
+			ich_res, !half_panel_partial_update);
 
 	return 0;
 }
 
-static int _sde_encoder_dsc_setup(struct sde_encoder_virt *sde_enc)
+static int _sde_encoder_update_roi(struct drm_encoder *drm_enc)
+{
+	struct sde_encoder_virt *sde_enc;
+	struct drm_connector *drm_conn;
+	struct drm_display_mode *adj_mode;
+	struct sde_rect roi;
+
+	if (!drm_enc || !drm_enc->crtc || !drm_enc->crtc->state)
+		return -EINVAL;
+	sde_enc = to_sde_encoder_virt(drm_enc);
+
+	if (!sde_enc->cur_master)
+		return -EINVAL;
+
+	adj_mode = &sde_enc->base.crtc->state->adjusted_mode;
+	drm_conn = sde_enc->cur_master->connector;
+
+	_sde_encoder_get_connector_roi(sde_enc, &roi);
+	if (sde_kms_rect_is_null(&roi)) {
+		roi.w = adj_mode->hdisplay;
+		roi.h = adj_mode->vdisplay;
+	}
+
+	memcpy(&sde_enc->prv_conn_roi, &sde_enc->cur_conn_roi,
+			sizeof(sde_enc->prv_conn_roi));
+	memcpy(&sde_enc->cur_conn_roi, &roi, sizeof(sde_enc->cur_conn_roi));
+
+	return 0;
+}
+
+static int _sde_encoder_dsc_setup(struct sde_encoder_virt *sde_enc,
+		struct sde_encoder_kickoff_params *params)
 {
 	enum sde_rm_topology_name topology;
-	struct drm_connector *drm_conn = sde_enc->phys_encs[0]->connector;
+	struct drm_connector *drm_conn;
 	int ret = 0;
 
+	if (!sde_enc || !params || !sde_enc->phys_encs[0] ||
+			!sde_enc->phys_encs[0]->connector)
+		return -EINVAL;
+
+	drm_conn = sde_enc->phys_encs[0]->connector;
+
 	topology = sde_connector_get_topology_name(drm_conn);
 	if (topology == SDE_RM_TOPOLOGY_NONE) {
 		SDE_ERROR_ENC(sde_enc, "topology not set yet\n");
@@ -743,15 +894,19 @@
 	SDE_DEBUG_ENC(sde_enc, "\n");
 	SDE_EVT32(DRMID(&sde_enc->base));
 
+	if (sde_kms_rect_is_equal(&sde_enc->cur_conn_roi,
+			&sde_enc->prv_conn_roi))
+		return ret;
+
 	switch (topology) {
 	case SDE_RM_TOPOLOGY_SINGLEPIPE_DSC:
 		ret = _sde_encoder_dsc_1_lm_1_enc_1_intf(sde_enc);
 		break;
 	case SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE:
-		ret = _sde_encoder_dsc_2_lm_2_enc_1_intf(sde_enc);
+		ret = _sde_encoder_dsc_2_lm_2_enc_1_intf(sde_enc, params);
 		break;
 	case SDE_RM_TOPOLOGY_DUALPIPE_DSC:
-		ret = _sde_encoder_dsc_2_lm_2_enc_2_intf(sde_enc);
+		ret = _sde_encoder_dsc_2_lm_2_enc_2_intf(sde_enc, params);
 		break;
 	default:
 		SDE_ERROR_ENC(sde_enc, "No DSC support for topology %d",
@@ -1217,7 +1372,6 @@
 	struct sde_kms *sde_kms;
 	struct sde_hw_mdp *hw_mdptop;
 	int i = 0;
-	int ret = 0;
 	struct sde_watchdog_te_status te_cfg = { 0 };
 
 	if (!drm_enc || !drm_enc->dev || !drm_enc->dev->dev_private) {
@@ -1252,12 +1406,6 @@
 				sde_enc->cur_master->hw_mdptop,
 				sde_kms->catalog);
 
-	if (_sde_is_dsc_enabled(sde_enc)) {
-		ret = _sde_encoder_dsc_setup(sde_enc);
-		if (ret)
-			SDE_ERROR_ENC(sde_enc, "failed to setup DSC:%d\n", ret);
-	}
-
 	if (hw_mdptop->ops.setup_vsync_sel) {
 		for (i = 0; i < sde_enc->num_phys_encs; i++)
 			te_cfg.ppnumber[i] = sde_enc->hw_pp[i]->idx;
@@ -1763,6 +1911,65 @@
 	spin_unlock_irqrestore(&sde_enc->enc_spinlock, lock_flags);
 }
 
+static void _sde_encoder_ppsplit_swap_intf_for_right_only_update(
+		struct drm_encoder *drm_enc,
+		unsigned long *affected_displays,
+		int num_active_phys)
+{
+	struct sde_encoder_virt *sde_enc;
+	struct sde_encoder_phys *master;
+	enum sde_rm_topology_name topology;
+	bool is_right_only;
+
+	if (!drm_enc || !affected_displays)
+		return;
+
+	sde_enc = to_sde_encoder_virt(drm_enc);
+	master = sde_enc->cur_master;
+	if (!master || !master->connector)
+		return;
+
+	topology = sde_connector_get_topology_name(master->connector);
+	if (topology != SDE_RM_TOPOLOGY_PPSPLIT)
+		return;
+
+	/*
+	 * For pingpong split, the slave pingpong won't generate IRQs. For
+	 * right-only updates, we can't swap pingpongs, or simply swap the
+	 * master/slave assignment, we actually have to swap the interfaces
+	 * so that the master physical encoder will use a pingpong/interface
+	 * that generates irqs on which to wait.
+	 */
+	is_right_only = !test_bit(0, affected_displays) &&
+			test_bit(1, affected_displays);
+
+	if (is_right_only && !sde_enc->intfs_swapped) {
+		/* right-only update swap interfaces */
+		swap(sde_enc->phys_encs[0]->intf_idx,
+				sde_enc->phys_encs[1]->intf_idx);
+		sde_enc->intfs_swapped = true;
+	} else if (!is_right_only && sde_enc->intfs_swapped) {
+		/* left-only or full update, swap back */
+		swap(sde_enc->phys_encs[0]->intf_idx,
+				sde_enc->phys_encs[1]->intf_idx);
+		sde_enc->intfs_swapped = false;
+	}
+
+	SDE_DEBUG_ENC(sde_enc,
+			"right_only %d swapped %d phys0->intf%d, phys1->intf%d\n",
+			is_right_only, sde_enc->intfs_swapped,
+			sde_enc->phys_encs[0]->intf_idx - INTF_0,
+			sde_enc->phys_encs[1]->intf_idx - INTF_0);
+	SDE_EVT32(DRMID(drm_enc), is_right_only, sde_enc->intfs_swapped,
+			sde_enc->phys_encs[0]->intf_idx - INTF_0,
+			sde_enc->phys_encs[1]->intf_idx - INTF_0,
+			*affected_displays);
+
+	/* ppsplit always uses master since ppslave invalid for irqs*/
+	if (num_active_phys == 1)
+		*affected_displays = BIT(0);
+}
+
 static void _sde_encoder_update_master(struct drm_encoder *drm_enc,
 		struct sde_encoder_kickoff_params *params)
 {
@@ -1785,6 +1992,10 @@
 	SDE_DEBUG_ENC(sde_enc, "affected_displays 0x%lx num_active_phys %d\n",
 			params->affected_displays, num_active_phys);
 
+	/* for left/right only update, ppsplit master switches interface */
+	_sde_encoder_ppsplit_swap_intf_for_right_only_update(drm_enc,
+			&params->affected_displays, num_active_phys);
+
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {
 		enum sde_enc_split_role prv_role, new_role;
 		bool active;
@@ -1814,6 +2025,9 @@
 		SDE_DEBUG_ENC(sde_enc, "pp %d role prv %d new %d active %d\n",
 				phys->hw_pp->idx - PINGPONG_0, prv_role,
 				phys->split_role, active);
+		SDE_EVT32(DRMID(drm_enc), params->affected_displays,
+				phys->hw_pp->idx - PINGPONG_0, prv_role,
+				phys->split_role, active, num_active_phys);
 	}
 }
 
@@ -1892,6 +2106,8 @@
 
 	_sde_encoder_update_master(drm_enc, params);
 
+	_sde_encoder_update_roi(drm_enc);
+
 	if (sde_enc->cur_master && sde_enc->cur_master->connector) {
 		rc = sde_connector_pre_kickoff(sde_enc->cur_master->connector);
 		if (rc)
@@ -1899,6 +2115,12 @@
 					sde_enc->cur_master->connector->base.id,
 					rc);
 	}
+
+	if (sde_encoder_is_dsc_enabled(drm_enc)) {
+		rc = _sde_encoder_dsc_setup(sde_enc, params);
+		if (rc)
+			SDE_ERROR_ENC(sde_enc, "failed to setup DSC: %d\n", rc);
+	}
 }
 
 void sde_encoder_kickoff(struct drm_encoder *drm_enc)
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h
index 7292a12..6ef245b 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.h
@@ -149,6 +149,20 @@
 void sde_encoder_virt_restore(struct drm_encoder *encoder);
 
 /**
+ * sde_encoder_is_dsc_enabled - check if encoder is in DSC mode
+ * @drm_enc: Pointer to drm encoder object
+ * @Return: true if encoder is in DSC mode
+ */
+bool sde_encoder_is_dsc_enabled(struct drm_encoder *drm_enc);
+
+/**
+ * sde_encoder_is_dsc_merge - check if encoder is in DSC merge mode
+ * @drm_enc: Pointer to drm encoder object
+ * @Return: true if encoder is in DSC merge mode
+ */
+bool sde_encoder_is_dsc_merge(struct drm_encoder *drm_enc);
+
+/**
  * sde_encoder_init - initialize virtual encoder object
  * @dev:        Pointer to drm device structure
  * @disp_info:  Pointer to display information structure
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 572bd9e..53f5b89 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -615,7 +615,8 @@
 			phys_enc->hw_pp->idx - PINGPONG_0);
 	drm_mode_debug_printmodeline(&phys_enc->cached_mode);
 
-	_sde_encoder_phys_cmd_update_intf_cfg(phys_enc);
+	if (!_sde_encoder_phys_is_ppsplit_slave(phys_enc))
+		_sde_encoder_phys_cmd_update_intf_cfg(phys_enc);
 	sde_encoder_phys_cmd_tearcheck_config(phys_enc);
 }
 
@@ -832,15 +833,28 @@
 		struct sde_encoder_phys *phys_enc,
 		enum sde_enc_split_role role)
 {
-	struct sde_encoder_phys_cmd *cmd_enc =
-		to_sde_encoder_phys_cmd(phys_enc);
-	enum sde_enc_split_role old_role = phys_enc->split_role;
+	struct sde_encoder_phys_cmd *cmd_enc;
+	enum sde_enc_split_role old_role;
+	bool is_ppsplit;
+
+	if (!phys_enc)
+		return;
+
+	cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
+	old_role = phys_enc->split_role;
+	is_ppsplit = _sde_encoder_phys_is_ppsplit(phys_enc);
+
+	phys_enc->split_role = role;
 
 	SDE_DEBUG_CMDENC(cmd_enc, "old role %d new role %d\n",
 			old_role, role);
 
-	phys_enc->split_role = role;
-	if (role == ENC_ROLE_SKIP || role == old_role)
+	/*
+	 * ppsplit solo needs to reprogram because intf may have swapped without
+	 * role changing on left-only, right-only back-to-back commits
+	 */
+	if (!(is_ppsplit && role == ENC_ROLE_SOLO) &&
+			(role == old_role || role == ENC_ROLE_SKIP))
 		return;
 
 	sde_encoder_helper_split_config(phys_enc, phys_enc->intf_idx);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ad4.c b/drivers/gpu/drm/msm/sde/sde_hw_ad4.c
index 7d2f67d..b02cc06 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_ad4.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_ad4.c
@@ -17,8 +17,8 @@
 #include "sde_ad4.h"
 
 #define IDLE_2_RUN(x) ((x) == (ad4_init | ad4_cfg | ad4_mode | ad4_input))
-#define MERGE_WIDTH_RIGHT 4
-#define MERGE_WIDTH_LEFT 3
+#define MERGE_WIDTH_RIGHT 6
+#define MERGE_WIDTH_LEFT 5
 
 enum ad4_ops_bitmask {
 	ad4_init = BIT(AD_INIT),
@@ -179,7 +179,7 @@
 			cfg->hw_cfg->displayh, cfg->hw_cfg->displayv);
 		return -EINVAL;
 	} else if (hw_lm->cfg.out_height != cfg->hw_cfg->displayv &&
-		    hw_lm->cfg.out_width != (cfg->hw_cfg->displayh >> 2)) {
+		    hw_lm->cfg.out_width != (cfg->hw_cfg->displayh >> 1)) {
 		DRM_ERROR("dual_lm lmh %d lmw %d displayh %d displayw %d\n",
 			hw_lm->cfg.out_height, hw_lm->cfg.out_width,
 			cfg->hw_cfg->displayh, cfg->hw_cfg->displayv);
@@ -250,6 +250,7 @@
 				MERGE_WIDTH_LEFT;
 			proc_start = 0;
 			proc_end = (cfg->hw_cfg->displayh >> 1) - 1;
+			tile_ctl |= 0x10;
 		}
 	}
 
@@ -769,7 +770,8 @@
 					(cfg->hw_cfg->payload));
 	info[dspp->idx].completed_ops_mask |= ad4_mode;
 
-	if (IDLE_2_RUN(info[dspp->idx].completed_ops_mask))
+	if (IDLE_2_RUN(info[dspp->idx].completed_ops_mask) ||
+					info[dspp->idx].cached_mode == AD4_OFF)
 		ad4_mode_setup(dspp, info[dspp->idx].cached_mode);
 
 	return 0;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_color_proc_common_v4.h b/drivers/gpu/drm/msm/sde/sde_hw_color_proc_common_v4.h
index 28479ab..8f7764d 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_color_proc_common_v4.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_color_proc_common_v4.h
@@ -21,6 +21,7 @@
 #define GAMUT_MAP_EN BIT(1)
 #define GAMUT_EN BIT(0)
 #define GAMUT_MODE_13B_OFF 640
+#define GAMUT_MODE_5_OFF 1248
 
 enum {
 	gamut_mode_17 = 0,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
index c33e520..0dcbb7e 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
@@ -347,10 +347,9 @@
 		break;
 	case GAMUT_3D_MODE_5:
 		*tbl_len = GAMUT_3D_MODE5_TBL_SZ * sizeof(u32) * 2;
-		*tbl_off = 0;
+		*tbl_off = GAMUT_MODE_5_OFF;
 		*scale_off = GAMUT_SCALEB_OFFSET_OFF;
 		*opcode = gamut_mode_5 << 2;
-		*opcode |= GAMUT_MAP_EN;
 		break;
 	case GAMUT_3D_MODE_13:
 		*tbl_len = GAMUT_3D_MODE13_TBL_SZ * sizeof(u32) * 2;
@@ -364,7 +363,6 @@
 		*scale_off = (*opcode == gamut_mode_13a) ?
 			GAMUT_SCALEA_OFFSET_OFF : GAMUT_SCALEB_OFFSET_OFF;
 		*opcode <<= 2;
-		*opcode |= GAMUT_MAP_EN;
 		break;
 	default:
 		rc = -EINVAL;
@@ -377,6 +375,45 @@
 	return rc;
 }
 
+static void dspp_3d_gamutv4_off(struct sde_hw_dspp *ctx, void *cfg)
+{
+	struct sde_reg_dma_kickoff_cfg kick_off;
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	u32 op_mode;
+	struct sde_hw_reg_dma_ops *dma_ops;
+	struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
+	int rc;
+
+	dma_ops = sde_reg_dma_get_ops();
+	dma_ops->reset_reg_dma_buf(dspp_buf[GAMUT][ctx->idx]);
+
+	REG_DMA_INIT_OPS(dma_write_cfg, dspp_mapping[ctx->idx], GAMUT,
+			dspp_buf[GAMUT][ctx->idx]);
+
+	REG_DMA_SETUP_OPS(dma_write_cfg, 0, NULL, 0, HW_BLK_SELECT, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("write decode select failed ret %d\n", rc);
+		return;
+	}
+
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->gamut.base,
+		&op_mode, sizeof(op_mode), REG_SINGLE_WRITE, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("opmode write single reg failed ret %d\n", rc);
+		return;
+	}
+
+	REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[GAMUT][ctx->idx],
+			REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE);
+	kick_off.last_command = hw_cfg->last_feature;
+	rc = dma_ops->kick_off(&kick_off);
+	if (rc)
+		DRM_ERROR("failed to kick off ret %d\n", rc);
+}
+
 void reg_dmav1_setup_dspp_3d_gamutv4(struct sde_hw_dspp *ctx, void *cfg)
 {
 	struct drm_msm_3d_gamut *payload;
@@ -394,7 +431,7 @@
 	op_mode = SDE_REG_READ(&ctx->hw, ctx->cap->sblk->gamut.base);
 	if (!hw_cfg->payload) {
 		DRM_DEBUG_DRIVER("disable gamut feature\n");
-		SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gamut.base, 0);
+		dspp_3d_gamutv4_off(ctx, cfg);
 		return;
 	}
 
@@ -436,7 +473,7 @@
 		}
 		REG_DMA_SETUP_OPS(dma_write_cfg,
 		    ctx->cap->sblk->gamut.base + GAMUT_LOWER_COLOR_OFF,
-		    &payload->col[i][0].c0, tbl_len,
+		    &payload->col[i][0].c2_c1, tbl_len,
 		    REG_BLK_WRITE_MULTIPLE, 2, 0);
 		rc = dma_ops->setup_payload(&dma_write_cfg);
 		if (rc) {
@@ -529,16 +566,36 @@
 		REG_DMA_SETUP_OPS(dma_write_cfg,
 			ctx->cap->sblk->gc.base + GC_C0_OFF +
 			(i * sizeof(u32) * 2),
-			lut_cfg->c0 + ARRAY_SIZE(lut_cfg->c0),
+			lut_cfg->c0 + (ARRAY_SIZE(lut_cfg->c0) * i),
 			PGC_TBL_LEN * sizeof(u32),
 			REG_BLK_WRITE_INC, 0, 0);
 		rc = dma_ops->setup_payload(&dma_write_cfg);
 		if (rc) {
-			DRM_ERROR("index init failed ret %d\n", rc);
+			DRM_ERROR("lut write failed ret %d\n", rc);
 			return;
 		}
 	}
 
+	reg = BIT(0);
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->gc.base + GC_LUT_SWAP_OFF,
+		&reg, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("setting swap offset failed ret %d\n", rc);
+		return;
+	}
+
+	reg = GC_EN | ((lut_cfg->flags & PGC_8B_ROUND) ? GC_8B_ROUND_EN : 0);
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->gc.base,
+		&reg, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("enabling gamma correction failed ret %d\n", rc);
+		return;
+	}
+
 	REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[GC][ctx->idx],
 			REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE);
 	kick_off.last_command = hw_cfg->last_feature;
@@ -547,11 +604,6 @@
 		DRM_ERROR("failed to kick off ret %d\n", rc);
 		return;
 	}
-
-	reg = GC_EN | ((lut_cfg->flags & PGC_8B_ROUND) ? GC_8B_ROUND_EN : 0);
-	SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base + GC_LUT_SWAP_OFF,
-			BIT(0));
-	SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base, reg);
 }
 
 int reg_dmav1_deinit_dspp_ops(enum sde_dspp idx)
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_rot.c b/drivers/gpu/drm/msm/sde/sde_hw_rot.c
index d15b804..d5f03a6a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_rot.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_rot.c
@@ -563,6 +563,10 @@
 	case SDE_HW_ROT_CMD_COMMIT:
 		cmd_type = SDE_ROTATOR_INLINE_CMD_COMMIT;
 		break;
+	case SDE_HW_ROT_CMD_START:
+		cmd_type = SDE_ROTATOR_INLINE_CMD_START;
+		priv_handle = data->priv_handle;
+		break;
 	case SDE_HW_ROT_CMD_CLEANUP:
 		cmd_type = SDE_ROTATOR_INLINE_CMD_CLEANUP;
 		priv_handle = data->priv_handle;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_rot.h b/drivers/gpu/drm/msm/sde/sde_hw_rot.h
index a4f5b49..e490052 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_rot.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_rot.h
@@ -24,11 +24,13 @@
  * enum sde_hw_rot_cmd_type - type of rotator hardware command
  * @SDE_HW_ROT_CMD_VALDIATE: validate rotator command; do not commit
  * @SDE_HW_ROT_CMD_COMMIT: commit/execute rotator command
+ * @SDE_HW_ROT_CMD_START: mdp is ready to start
  * @SDE_HW_ROT_CMD_CLEANUP: cleanup rotator command after it is done
  */
 enum sde_hw_rot_cmd_type {
 	SDE_HW_ROT_CMD_VALIDATE,
 	SDE_HW_ROT_CMD_COMMIT,
+	SDE_HW_ROT_CMD_START,
 	SDE_HW_ROT_CMD_CLEANUP,
 };
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index c045067..a1f5cee 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -299,7 +299,7 @@
 {
 	struct sde_hw_blk_reg_map *c;
 	u32 chroma_samp, unpack, src_format;
-	u32 secure = 0;
+	u32 secure = 0, secure_bit_mask;
 	u32 opmode = 0;
 	u32 op_mode_off, unpack_pat_off, format_off;
 	u32 idx;
@@ -311,10 +311,12 @@
 		op_mode_off = SSPP_SRC_OP_MODE;
 		unpack_pat_off = SSPP_SRC_UNPACK_PATTERN;
 		format_off = SSPP_SRC_FORMAT;
+		secure_bit_mask = (rect_mode == SDE_SSPP_RECT_SOLO) ? 0xF : 0x5;
 	} else {
 		op_mode_off = SSPP_SRC_OP_MODE_REC1;
 		unpack_pat_off = SSPP_SRC_UNPACK_PATTERN_REC1;
 		format_off = SSPP_SRC_FORMAT_REC1;
+		secure_bit_mask = 0xA;
 	}
 
 	c = &ctx->hw;
@@ -322,16 +324,11 @@
 	opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD |
 			MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE);
 
-	if (flags & SDE_SSPP_SECURE_OVERLAY_SESSION) {
-		secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
-
-		if (rect_mode == SDE_SSPP_RECT_SOLO)
-			secure |= 0xF;
-		else if (rect_mode == SDE_SSPP_RECT_0)
-			secure |= 0x5;
-		else if (rect_mode == SDE_SSPP_RECT_1)
-			secure |= 0xA;
-	}
+	secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
+	if (flags & SDE_SSPP_SECURE_OVERLAY_SESSION)
+		secure |= secure_bit_mask;
+	else
+		secure &= ~secure_bit_mask;
 
 	if (flags & SDE_SSPP_FLIP_LR)
 		opmode |= MDSS_MDP_OP_FLIP_LR;
@@ -803,11 +800,17 @@
 		ystride1 = SDE_REG_READ(c, SSPP_SRC_YSTRIDE1 + idx);
 
 		if (rect_index == SDE_SSPP_RECT_0) {
-			ystride0 |= cfg->layout.plane_pitch[0];
-			ystride1 |= cfg->layout.plane_pitch[2];
-		}  else {
-			ystride0 |= cfg->layout.plane_pitch[0] << 16;
-			ystride1 |= cfg->layout.plane_pitch[2] << 16;
+			ystride0 = (ystride0 & 0xFFFF0000) |
+				(cfg->layout.plane_pitch[0] & 0x0000FFFF);
+			ystride1 = (ystride1 & 0xFFFF0000)|
+				(cfg->layout.plane_pitch[2] & 0x0000FFFF);
+		} else {
+			ystride0 = (ystride0 & 0x0000FFFF) |
+				((cfg->layout.plane_pitch[0] << 16) &
+				 0xFFFF0000);
+			ystride1 = (ystride1 & 0x0000FFFF) |
+				((cfg->layout.plane_pitch[2] << 16) &
+				 0xFFFF0000);
 		}
 	}
 
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index 01a5535..1f56d73 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -407,6 +407,14 @@
 		struct sde_rect *result);
 
 /**
+ * sde_kms_rect_merge_rectangles - merge a rectangle list into one rect
+ * @rois: pointer to the list of rois
+ * @result: output rectangle, all 0 on error
+ */
+void sde_kms_rect_merge_rectangles(const struct msm_roi_list *rois,
+		struct sde_rect *result);
+
+/**
  * sde_kms_rect_is_equal - compares two rects
  * @r1: rect value to compare
  * @r2: rect value to compare
diff --git a/drivers/gpu/drm/msm/sde/sde_kms_utils.c b/drivers/gpu/drm/msm/sde/sde_kms_utils.c
index b956be5..b77d64d 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms_utils.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms_utils.c
@@ -166,7 +166,7 @@
 	r = min((r1->x + r1->w), (r2->x + r2->w));
 	b = min((r1->y + r1->h), (r2->y + r2->h));
 
-	if (r < l || b < t) {
+	if (r <= l || b <= t) {
 		memset(result, 0, sizeof(*result));
 	} else {
 		result->x = l;
@@ -175,3 +175,46 @@
 		result->h = b - t;
 	}
 }
+
+void sde_kms_rect_merge_rectangles(const struct msm_roi_list *rois,
+		struct sde_rect *result)
+{
+	struct drm_clip_rect clip;
+	const struct drm_clip_rect *roi_rect;
+	int i;
+
+	if (!rois || !result)
+		return;
+
+	memset(result, 0, sizeof(*result));
+
+	/* init to invalid range maxes */
+	clip.x1 = ~0;
+	clip.y1 = ~0;
+	clip.x2 = 0;
+	clip.y2 = 0;
+
+	/* aggregate all clipping rectangles together for overall roi */
+	for (i = 0; i < rois->num_rects; i++) {
+		roi_rect = &rois->roi[i];
+
+		clip.x1 = min(clip.x1, roi_rect->x1);
+		clip.y1 = min(clip.y1, roi_rect->y1);
+		clip.x2 = max(clip.x2, roi_rect->x2);
+		clip.y2 = max(clip.y2, roi_rect->y2);
+
+		SDE_DEBUG("roi%d (%d,%d),(%d,%d) -> crtc (%d,%d),(%d,%d)\n", i,
+				roi_rect->x1, roi_rect->y1,
+				roi_rect->x2, roi_rect->y2,
+				clip.x1, clip.y1,
+				clip.x2, clip.y2);
+	}
+
+	if (clip.x2  && clip.y2) {
+		result->x = clip.x1;
+		result->y = clip.y1;
+		result->w = clip.x2 - clip.x1;
+		result->h = clip.y2 - clip.y1;
+	}
+}
+
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index deca83e..1721c67 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -2041,6 +2041,23 @@
 }
 
 /**
+ * sde_plane_rot_flush - perform final flush related rotator options
+ * @plane: Pointer to drm plane
+ * @pstate: Pointer to sde plane state
+ */
+static void sde_plane_rot_flush(struct drm_plane *plane,
+		struct sde_plane_state *pstate)
+{
+	if (!plane || !pstate || !pstate->rot.rot_hw ||
+			!pstate->rot.rot_hw->ops.commit)
+		return;
+
+	pstate->rot.rot_hw->ops.commit(pstate->rot.rot_hw,
+			&pstate->rot.rot_cmd,
+			SDE_HW_ROT_CMD_START);
+}
+
+/**
  * sde_plane_rot_destroy_state - destroy state for rotator stage
  * @plane: Pointer to drm plane
  * @state: Pointer to state to be destroyed
@@ -2208,274 +2225,17 @@
 		DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
 }
 
-static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
-				struct drm_plane_state *state)
+void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
 {
-	uint32_t nplanes, src_flags;
-	struct sde_plane *psde;
 	struct sde_plane_state *pstate;
-	struct sde_plane_rot_state *rstate;
-	const struct sde_format *fmt;
-	struct drm_crtc *crtc;
-	struct drm_framebuffer *fb;
-	struct sde_rect src, dst;
-	const struct sde_rect *crtc_roi;
-	bool q16_data = true;
-	int idx;
 
-	if (!plane) {
-		SDE_ERROR("invalid plane\n");
-		return -EINVAL;
-	} else if (!plane->state) {
-		SDE_ERROR("invalid plane state\n");
-		return -EINVAL;
-	}
+	if (!drm_state)
+		return;
 
-	psde = to_sde_plane(plane);
-	pstate = to_sde_plane_state(plane->state);
-	rstate = &pstate->rot;
+	pstate = to_sde_plane_state(drm_state);
 
-	crtc = state->crtc;
-	fb = rstate->out_fb;
-	if (!crtc || !fb) {
-		SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
-				crtc != 0, fb != 0);
-		return -EINVAL;
-	}
-	fmt = to_sde_format(msm_framebuffer_format(fb));
-	nplanes = fmt->num_planes;
-
-	SDE_DEBUG(
-		"plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
-			plane->base.id, rstate->sequence_id,
-			rstate->out_fb_width, rstate->out_fb_height,
-			(char *) &rstate->out_fb_pixel_format,
-			rstate->out_fb_modifier[0],
-			rstate->out_src_w >> 16, rstate->out_src_h >> 16,
-			rstate->out_src_x >> 16, rstate->out_src_y >> 16,
-			rstate->out_rotation,
-			state->crtc_w, state->crtc_h,
-			state->crtc_x, state->crtc_y);
-
-	/* force reprogramming of all the parameters, if the flag is set */
-	if (psde->revalidate) {
-		SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
-				plane->base.id);
-		pstate->dirty = SDE_PLANE_DIRTY_ALL;
-		psde->revalidate = false;
-	}
-
-	/* determine what needs to be refreshed */
-	while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
-		switch (idx) {
-		case PLANE_PROP_SCALER_V1:
-		case PLANE_PROP_SCALER_V2:
-		case PLANE_PROP_H_DECIMATE:
-		case PLANE_PROP_V_DECIMATE:
-		case PLANE_PROP_SRC_CONFIG:
-		case PLANE_PROP_ZPOS:
-		case PLANE_PROP_EXCL_RECT_V1:
-			pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
-			break;
-		case PLANE_PROP_CSC_V1:
-			pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
-			break;
-		case PLANE_PROP_COLOR_FILL:
-			/* potentially need to refresh everything */
-			pstate->dirty = SDE_PLANE_DIRTY_ALL;
-			break;
-		case PLANE_PROP_ROTATION:
-			pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
-			break;
-		case PLANE_PROP_INFO:
-		case PLANE_PROP_ALPHA:
-		case PLANE_PROP_INPUT_FENCE:
-		case PLANE_PROP_BLEND_OP:
-			/* no special action required */
-			break;
-		case PLANE_PROP_ROT_DST_X:
-		case PLANE_PROP_ROT_DST_Y:
-		case PLANE_PROP_ROT_DST_W:
-		case PLANE_PROP_ROT_DST_H:
-			/* handled by rotator atomic update */
-			break;
-		default:
-			/* unknown property, refresh everything */
-			pstate->dirty |= SDE_PLANE_DIRTY_ALL;
-			SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
-			break;
-		}
-	}
-
-	/* re-program the output rects always in the case of partial update */
-	sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
-	if (!sde_kms_rect_is_null(crtc_roi))
-		pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
-
-	if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
-		memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
-
-	_sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
-
-	/* early out if nothing dirty */
-	if (!pstate->dirty)
-		return 0;
-	pstate->pending = true;
-
-	psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
-	_sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
-
-	/* update roi config */
-	if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
-		POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
-			rstate->out_src_w, rstate->out_src_h, q16_data);
-		POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
-			state->crtc_w, state->crtc_h, !q16_data);
-
-		SDE_DEBUG_PLANE(psde,
-			"FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
-				fb->base.id, src.x, src.y, src.w, src.h,
-				crtc->base.id, dst.x, dst.y, dst.w, dst.h,
-				(char *)&fmt->base.pixel_format,
-				SDE_FORMAT_IS_UBWC(fmt));
-
-		if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
-			BIT(SDE_DRM_DEINTERLACE)) {
-			SDE_DEBUG_PLANE(psde, "deinterlace\n");
-			for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
-				psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
-			src.h /= 2;
-			src.y  = DIV_ROUND_UP(src.y, 2);
-			src.y &= ~0x1;
-		}
-
-		/*
-		 * adjust layer mixer position of the sspp in the presence
-		 * of a partial update to the active lm origin
-		 */
-		dst.x -= crtc_roi->x;
-		dst.y -= crtc_roi->y;
-
-		psde->pipe_cfg.src_rect = src;
-		psde->pipe_cfg.dst_rect = dst;
-
-		_sde_plane_setup_scaler(psde, fmt, pstate);
-
-		/* check for color fill */
-		psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
-				PLANE_PROP_COLOR_FILL);
-		if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
-			/* skip remaining processing on color fill */
-			pstate->dirty = 0x0;
-		} else if (psde->pipe_hw->ops.setup_rects) {
-			psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
-					&psde->pipe_cfg,
-					pstate->multirect_index);
-		}
-
-		if (psde->pipe_hw->ops.setup_pe)
-			psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
-					&psde->pixel_ext);
-
-		if (psde->pipe_hw->ops.setup_scaler)
-			psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
-					&psde->pipe_cfg, &psde->pixel_ext,
-					psde->scaler3_cfg);
-
-		/* update excl rect */
-		if (psde->pipe_hw->ops.setup_excl_rect)
-			psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
-					&pstate->excl_rect,
-					pstate->multirect_index);
-
-		if (psde->pipe_hw->ops.setup_multirect)
-			psde->pipe_hw->ops.setup_multirect(
-					psde->pipe_hw,
-					pstate->multirect_index,
-					pstate->multirect_mode);
-	}
-
-	if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
-			psde->pipe_hw->ops.setup_format) {
-		src_flags = 0x0;
-		SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
-		if (rstate->out_rotation & DRM_REFLECT_X)
-			src_flags |= SDE_SSPP_FLIP_LR;
-		if (rstate->out_rotation & DRM_REFLECT_Y)
-			src_flags |= SDE_SSPP_FLIP_UD;
-
-		/* update format */
-		psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
-				pstate->multirect_index);
-
-		if (psde->pipe_hw->ops.setup_sys_cache) {
-			if (rstate->out_sbuf) {
-				if (rstate->nplane < 2)
-					pstate->sc_cfg.op_mode =
-					SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
-				else if (rstate->out_xpos == 0)
-					pstate->sc_cfg.op_mode =
-						SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
-				else
-					pstate->sc_cfg.op_mode =
-					SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
-
-				pstate->sc_cfg.rd_en = true;
-				pstate->sc_cfg.rd_scid =
-						rstate->rot_hw->caps->scid;
-				pstate->sc_cfg.rd_noallocate = true;
-				pstate->sc_cfg.rd_op_type =
-					SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
-			} else {
-				pstate->sc_cfg.op_mode =
-						SDE_PIPE_SC_OP_MODE_OFFLINE;
-				pstate->sc_cfg.rd_en = false;
-				pstate->sc_cfg.rd_scid = 0;
-				pstate->sc_cfg.rd_noallocate = false;
-				pstate->sc_cfg.rd_op_type =
-					SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
-			}
-
-			psde->pipe_hw->ops.setup_sys_cache(
-					psde->pipe_hw, &pstate->sc_cfg);
-		}
-
-		/* update csc */
-		if (SDE_FORMAT_IS_YUV(fmt))
-			_sde_plane_setup_csc(psde);
-		else
-			psde->csc_ptr = 0;
-	}
-
-	sde_color_process_plane_setup(plane);
-
-	/* update sharpening */
-	if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
-		psde->pipe_hw->ops.setup_sharpening) {
-		psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
-		psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
-		psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
-		psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
-
-		psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
-				&psde->sharp_cfg);
-	}
-
-	_sde_plane_set_qos_lut(plane, fb);
-	_sde_plane_set_danger_lut(plane, fb);
-
-	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
-		_sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
-		_sde_plane_set_ot_limit(plane, crtc);
-	}
-
-	/* clear dirty */
-	pstate->dirty = 0x0;
-
-	/* clear multirect mode*/
 	pstate->multirect_index = SDE_SSPP_RECT_SOLO;
 	pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
-	return 0;
 }
 
 int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
@@ -2486,11 +2246,12 @@
 	struct sde_plane *sde_plane[R_MAX];
 	const struct sde_format *fmt[R_MAX];
 	bool q16_data = true;
-	int i, max_sspp_linewidth;
-	int buffer_lines = TX_MODE_BUFFER_LINE_THRES;
+	int i, buffer_lines = TX_MODE_BUFFER_LINE_THRES;
+	bool parallel_fetch_qualified = true;
 
 	for (i = 0; i < R_MAX; i++) {
 		const struct msm_format *msm_fmt;
+		int width_threshold;
 
 		drm_state[i] = i ? plane->r1 : plane->r0;
 		pstate[i] = to_sde_plane_state(drm_state[i]);
@@ -2521,15 +2282,27 @@
 				"Unsupported format for multirect mode\n");
 			return -EINVAL;
 		}
-	}
 
-	max_sspp_linewidth = sde_plane[R0]->pipe_sblk->maxlinewidth;
+		/**
+		 * SSPP PD_MEM is split half - one for each RECT.
+		 * Tiled formats need 5 lines of buffering while fetching
+		 * whereas linear formats need only 2 lines.
+		 * So we cannot support more than half of the supported SSPP
+		 * width for tiled formats.
+		 */
+		width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
+		if (SDE_FORMAT_IS_UBWC(fmt[i]))
+			width_threshold /= 2;
+
+		if (parallel_fetch_qualified && src[i].w > width_threshold)
+			parallel_fetch_qualified = false;
+
+	}
 
 	/* Validate RECT's and set the mode */
 
 	/* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
-	if (src[R0].w <= max_sspp_linewidth/2 &&
-			src[R1].w <= max_sspp_linewidth/2) {
+	if (parallel_fetch_qualified) {
 		if (dst[R0].x <= dst[R1].x) {
 			pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
 			pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
@@ -2564,6 +2337,10 @@
 	pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
 	pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
 done:
+	SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
+		pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
+	SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
+		pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
 	return 0;
 }
 
@@ -2667,6 +2444,10 @@
 	} else if (to_sde_plane_state(old_state)->pending) {
 		SDE_DEBUG_PLANE(psde, "still pending\n");
 		pstate->dirty |= SDE_PLANE_DIRTY_ALL;
+	} else if (pstate->multirect_index != old_pstate->multirect_index ||
+			pstate->multirect_mode != old_pstate->multirect_mode) {
+		SDE_DEBUG_PLANE(psde, "multirect config updated\n");
+		pstate->dirty |= SDE_PLANE_DIRTY_ALL;
 	} else if (rstate->out_src_w != old_rstate->out_src_w ||
 		   rstate->out_src_h != old_rstate->out_src_h ||
 		   rstate->out_src_x != old_rstate->out_src_x ||
@@ -2683,11 +2464,7 @@
 		   pstate->excl_rect.h != old_pstate->excl_rect.h ||
 		   pstate->excl_rect.x != old_pstate->excl_rect.x ||
 		   pstate->excl_rect.y != old_pstate->excl_rect.y) {
-		SDE_DEBUG_PLANE(psde, "excl rect updated\n");
-		pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
-	} else if (pstate->multirect_index != old_pstate->multirect_index ||
-			pstate->multirect_mode != old_pstate->multirect_mode) {
-		SDE_DEBUG_PLANE(psde, "multirect config updated\n");
+		SDE_DEBUG_PLANE(psde, "excl_rect updated\n");
 		pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
 	}
 
@@ -2900,6 +2677,9 @@
 				(char *)&fmt->base.pixel_format);
 			ret = -EINVAL;
 		}
+		SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
+				pstate->excl_rect.x, pstate->excl_rect.y,
+				pstate->excl_rect.w, pstate->excl_rect.h);
 	}
 
 modeset_update:
@@ -2946,13 +2726,15 @@
 void sde_plane_flush(struct drm_plane *plane)
 {
 	struct sde_plane *psde;
+	struct sde_plane_state *pstate;
 
-	if (!plane) {
+	if (!plane || !plane->state) {
 		SDE_ERROR("invalid plane\n");
 		return;
 	}
 
 	psde = to_sde_plane(plane);
+	pstate = to_sde_plane_state(plane->state);
 
 	/*
 	 * These updates have to be done immediately before the plane flush
@@ -2973,7 +2755,303 @@
 
 	/* flag h/w flush complete */
 	if (plane->state)
-		to_sde_plane_state(plane->state)->pending = false;
+		pstate->pending = false;
+
+	/* signal inline rotator start */
+	sde_plane_rot_flush(plane, pstate);
+}
+
+static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
+				struct drm_plane_state *old_state)
+{
+	uint32_t nplanes, src_flags;
+	struct sde_plane *psde;
+	struct drm_plane_state *state;
+	struct sde_plane_state *pstate;
+	struct sde_plane_state *old_pstate;
+	struct sde_plane_rot_state *rstate;
+	const struct sde_format *fmt;
+	struct drm_crtc *crtc;
+	struct drm_framebuffer *fb;
+	struct sde_rect src, dst;
+	const struct sde_rect *crtc_roi;
+	bool q16_data = true;
+	int idx;
+
+	if (!plane) {
+		SDE_ERROR("invalid plane\n");
+		return -EINVAL;
+	} else if (!plane->state) {
+		SDE_ERROR("invalid plane state\n");
+		return -EINVAL;
+	} else if (!old_state) {
+		SDE_ERROR("invalid old state\n");
+		return -EINVAL;
+	}
+
+	psde = to_sde_plane(plane);
+	state = plane->state;
+
+	pstate = to_sde_plane_state(state);
+	rstate = &pstate->rot;
+
+	old_pstate = to_sde_plane_state(old_state);
+
+	crtc = state->crtc;
+	fb = rstate->out_fb;
+	if (!crtc || !fb) {
+		SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
+				crtc != 0, fb != 0);
+		return -EINVAL;
+	}
+	fmt = to_sde_format(msm_framebuffer_format(fb));
+	nplanes = fmt->num_planes;
+
+	SDE_DEBUG(
+		"plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
+			plane->base.id, rstate->sequence_id,
+			rstate->out_fb_width, rstate->out_fb_height,
+			(char *) &rstate->out_fb_pixel_format,
+			rstate->out_fb_modifier[0],
+			rstate->out_src_w >> 16, rstate->out_src_h >> 16,
+			rstate->out_src_x >> 16, rstate->out_src_y >> 16,
+			rstate->out_rotation,
+			state->crtc_w, state->crtc_h,
+			state->crtc_x, state->crtc_y);
+
+	/* force reprogramming of all the parameters, if the flag is set */
+	if (psde->revalidate) {
+		SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
+				plane->base.id);
+		pstate->dirty = SDE_PLANE_DIRTY_ALL;
+		psde->revalidate = false;
+	}
+
+	/* determine what needs to be refreshed */
+	while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
+		switch (idx) {
+		case PLANE_PROP_SCALER_V1:
+		case PLANE_PROP_SCALER_V2:
+		case PLANE_PROP_H_DECIMATE:
+		case PLANE_PROP_V_DECIMATE:
+		case PLANE_PROP_SRC_CONFIG:
+		case PLANE_PROP_ZPOS:
+		case PLANE_PROP_EXCL_RECT_V1:
+			pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
+			break;
+		case PLANE_PROP_CSC_V1:
+			pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
+			break;
+		case PLANE_PROP_COLOR_FILL:
+			/* potentially need to refresh everything */
+			pstate->dirty = SDE_PLANE_DIRTY_ALL;
+			break;
+		case PLANE_PROP_ROTATION:
+			pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
+			break;
+		case PLANE_PROP_INFO:
+		case PLANE_PROP_ALPHA:
+		case PLANE_PROP_INPUT_FENCE:
+		case PLANE_PROP_BLEND_OP:
+			/* no special action required */
+			break;
+		case PLANE_PROP_ROT_DST_X:
+		case PLANE_PROP_ROT_DST_Y:
+		case PLANE_PROP_ROT_DST_W:
+		case PLANE_PROP_ROT_DST_H:
+			/* handled by rotator atomic update */
+			break;
+		default:
+			/* unknown property, refresh everything */
+			pstate->dirty |= SDE_PLANE_DIRTY_ALL;
+			SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
+			break;
+		}
+	}
+
+	/**
+	 * since plane_atomic_check is invoked before crtc_atomic_check
+	 * in the commit sequence, all the parameters for updating the
+	 * plane dirty flag will not be available during
+	 * plane_atomic_check as some features params are updated
+	 * in crtc_atomic_check (eg.:sDMA). So check for mode_change
+	 * before sspp update.
+	 */
+	_sde_plane_sspp_atomic_check_mode_changed(psde, state,
+								old_state);
+
+	/* re-program the output rects always in the case of partial update */
+	sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
+	if (!sde_kms_rect_is_null(crtc_roi))
+		pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
+
+	if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
+		memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
+
+	_sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
+
+	/* early out if nothing dirty */
+	if (!pstate->dirty)
+		return 0;
+	pstate->pending = true;
+
+	psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
+	_sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
+
+	/* update roi config */
+	if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
+		POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
+			rstate->out_src_w, rstate->out_src_h, q16_data);
+		POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
+			state->crtc_w, state->crtc_h, !q16_data);
+
+		SDE_DEBUG_PLANE(psde,
+			"FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
+				fb->base.id, src.x, src.y, src.w, src.h,
+				crtc->base.id, dst.x, dst.y, dst.w, dst.h,
+				(char *)&fmt->base.pixel_format,
+				SDE_FORMAT_IS_UBWC(fmt));
+
+		if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
+			BIT(SDE_DRM_DEINTERLACE)) {
+			SDE_DEBUG_PLANE(psde, "deinterlace\n");
+			for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
+				psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
+			src.h /= 2;
+			src.y  = DIV_ROUND_UP(src.y, 2);
+			src.y &= ~0x1;
+		}
+
+		/*
+		 * adjust layer mixer position of the sspp in the presence
+		 * of a partial update to the active lm origin
+		 */
+		dst.x -= crtc_roi->x;
+		dst.y -= crtc_roi->y;
+
+		psde->pipe_cfg.src_rect = src;
+		psde->pipe_cfg.dst_rect = dst;
+
+		_sde_plane_setup_scaler(psde, fmt, pstate);
+
+		/* check for color fill */
+		psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
+				PLANE_PROP_COLOR_FILL);
+		if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
+			/* skip remaining processing on color fill */
+			pstate->dirty = 0x0;
+		} else if (psde->pipe_hw->ops.setup_rects) {
+			psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
+					&psde->pipe_cfg,
+					pstate->multirect_index);
+		}
+
+		if (psde->pipe_hw->ops.setup_pe)
+			psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
+					&psde->pixel_ext);
+
+		/**
+		 * when programmed in multirect mode, scalar block will be
+		 * bypassed. Still we need to update alpha and bitwidth
+		 * ONLY for RECT0
+		 */
+		if (psde->pipe_hw->ops.setup_scaler &&
+				pstate->multirect_index != SDE_SSPP_RECT_1)
+			psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
+					&psde->pipe_cfg, &psde->pixel_ext,
+					psde->scaler3_cfg);
+
+		/* update excl rect */
+		if (psde->pipe_hw->ops.setup_excl_rect)
+			psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
+					&pstate->excl_rect,
+					pstate->multirect_index);
+
+		if (psde->pipe_hw->ops.setup_multirect)
+			psde->pipe_hw->ops.setup_multirect(
+					psde->pipe_hw,
+					pstate->multirect_index,
+					pstate->multirect_mode);
+	}
+
+	if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
+			psde->pipe_hw->ops.setup_format) {
+		src_flags = 0x0;
+		SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
+		if (rstate->out_rotation & DRM_REFLECT_X)
+			src_flags |= SDE_SSPP_FLIP_LR;
+		if (rstate->out_rotation & DRM_REFLECT_Y)
+			src_flags |= SDE_SSPP_FLIP_UD;
+
+		/* update format */
+		psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
+				pstate->multirect_index);
+
+		if (psde->pipe_hw->ops.setup_sys_cache) {
+			if (rstate->out_sbuf) {
+				if (rstate->nplane < 2)
+					pstate->sc_cfg.op_mode =
+					SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
+				else if (rstate->out_xpos == 0)
+					pstate->sc_cfg.op_mode =
+						SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
+				else
+					pstate->sc_cfg.op_mode =
+					SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
+
+				pstate->sc_cfg.rd_en = true;
+				pstate->sc_cfg.rd_scid =
+						rstate->rot_hw->caps->scid;
+				pstate->sc_cfg.rd_noallocate = true;
+				pstate->sc_cfg.rd_op_type =
+					SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
+			} else {
+				pstate->sc_cfg.op_mode =
+						SDE_PIPE_SC_OP_MODE_OFFLINE;
+				pstate->sc_cfg.rd_en = false;
+				pstate->sc_cfg.rd_scid = 0;
+				pstate->sc_cfg.rd_noallocate = false;
+				pstate->sc_cfg.rd_op_type =
+					SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
+			}
+
+			psde->pipe_hw->ops.setup_sys_cache(
+					psde->pipe_hw, &pstate->sc_cfg);
+		}
+
+		/* update csc */
+		if (SDE_FORMAT_IS_YUV(fmt))
+			_sde_plane_setup_csc(psde);
+		else
+			psde->csc_ptr = 0;
+	}
+
+	sde_color_process_plane_setup(plane);
+
+	/* update sharpening */
+	if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
+		psde->pipe_hw->ops.setup_sharpening) {
+		psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
+		psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
+		psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
+		psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
+
+		psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
+				&psde->sharp_cfg);
+	}
+
+	_sde_plane_set_qos_lut(plane, fb);
+	_sde_plane_set_danger_lut(plane, fb);
+
+	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+		_sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
+		_sde_plane_set_ot_limit(plane, crtc);
+	}
+
+	/* clear dirty */
+	pstate->dirty = 0x0;
+
+	return 0;
 }
 
 static void sde_plane_atomic_update(struct drm_plane *plane,
@@ -3007,7 +3085,7 @@
 	} else {
 		int ret;
 
-		ret = sde_plane_sspp_atomic_update(plane, state);
+		ret = sde_plane_sspp_atomic_update(plane, old_state);
 		/* atomic_check should have ensured that this doesn't fail */
 		WARN_ON(ret < 0);
 	}
@@ -3427,20 +3505,24 @@
 	}
 
 	if (!usr_ptr) {
-		SDE_DEBUG_PLANE(psde, "excl rect data removed\n");
+		SDE_DEBUG_PLANE(psde, "invalid  excl_rect user data\n");
 		return;
 	}
 
 	if (copy_from_user(&excl_rect_v1, usr_ptr, sizeof(excl_rect_v1))) {
-		SDE_ERROR_PLANE(psde, "failed to copy excl rect data\n");
+		SDE_ERROR_PLANE(psde, "failed to copy excl_rect data\n");
 		return;
 	}
 
 	/* populate from user space */
 	pstate->excl_rect.x = excl_rect_v1.x1;
 	pstate->excl_rect.y = excl_rect_v1.y1;
-	pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1 + 1;
-	pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1 + 1;
+	pstate->excl_rect.w = excl_rect_v1.x2 - excl_rect_v1.x1;
+	pstate->excl_rect.h = excl_rect_v1.y2 - excl_rect_v1.y1;
+
+	SDE_DEBUG_PLANE(psde, "excl_rect: {%d,%d,%d,%d}\n",
+			pstate->excl_rect.x, pstate->excl_rect.y,
+			pstate->excl_rect.w, pstate->excl_rect.h);
 }
 
 static int sde_plane_atomic_set_property(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index ac70542..2056a70 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -207,10 +207,15 @@
  *				      against hw limitations
  * @plane: drm plate states of the multirect pair
  */
-
 int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane);
 
 /**
+ * sde_plane_clear_multirect - clear multirect bits for the given pipe
+ * @drm_state: Pointer to DRM plane state
+ */
+void sde_plane_clear_multirect(const struct drm_plane_state *drm_state);
+
+/**
  * sde_plane_wait_input_fence - wait for input fence object
  * @plane:   Pointer to DRM plane object
  * @wait_ms: Wait timeout value
diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h
index da68139..38bf21f 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.h
+++ b/drivers/gpu/drm/msm/sde_power_handle.h
@@ -16,9 +16,9 @@
 
 #define MAX_CLIENT_NAME_LEN 128
 
-#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA	2000000
+#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA	6000000000
 #define SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA	0
-#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA	2000000
+#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA	6000000000
 #define SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA	0
 
 #include <linux/sde_io_util.h>
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index 3413ee7..cab7e0f 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -416,6 +416,11 @@
 	if (config)
 		sde_rsc_timer_calculate(rsc, config);
 
+	if (rsc->current_state == SDE_RSC_CMD_STATE) {
+		rc = 0;
+		goto vsync_wait;
+	}
+
 	/* any one client in video state blocks the cmd state switch */
 	list_for_each_entry(client, &rsc->client_list, list)
 		if (client->current_state == SDE_RSC_VID_STATE)
@@ -427,15 +432,17 @@
 			rpmh_mode_solver_set(rsc->disp_rsc, true);
 	}
 
-	/* wait for vsync for vid to cmd state switch */
-	if (!rc && (rsc->current_state == SDE_RSC_VID_STATE))
+vsync_wait:
+	/* wait for vsync for vid to cmd state switch and config update */
+	if (!rc && (rsc->current_state == SDE_RSC_VID_STATE ||
+			rsc->current_state == SDE_RSC_CMD_STATE))
 		drm_wait_one_vblank(rsc->master_drm,
 						rsc->primary_client->crtc_id);
 end:
 	return rc;
 }
 
-static bool sde_rsc_switch_to_clk(struct sde_rsc_priv *rsc)
+static int sde_rsc_switch_to_clk(struct sde_rsc_priv *rsc)
 {
 	struct sde_rsc_client *client;
 	int rc = STATE_UPDATE_NOT_ALLOWED;
@@ -460,7 +467,7 @@
 	return rc;
 }
 
-static bool sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,
+static int sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,
 	struct sde_rsc_cmd_config *config,
 	struct sde_rsc_client *caller_client)
 {
@@ -470,6 +477,10 @@
 	if (config && (caller_client == rsc->primary_client))
 		sde_rsc_timer_calculate(rsc, config);
 
+	/* early exit without vsync wait for vid state */
+	if (rsc->current_state == SDE_RSC_VID_STATE)
+		goto end;
+
 	/* video state switch should be done immediately */
 	if (rsc->hw_ops.state_update) {
 		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_VID_STATE);
@@ -482,6 +493,8 @@
 			(rsc->current_state == SDE_RSC_CMD_STATE))
 		drm_wait_one_vblank(rsc->master_drm,
 						rsc->primary_client->crtc_id);
+
+end:
 	return rc;
 }
 
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index 925c60d..e982afe 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -382,6 +382,7 @@
 #define A6XX_RBBM_PERFCTR_RBBM_SEL_1             0x508
 #define A6XX_RBBM_PERFCTR_RBBM_SEL_2             0x509
 #define A6XX_RBBM_PERFCTR_RBBM_SEL_3             0x50A
+#define A6XX_RBBM_PERFCTR_GPU_BUSY_MASKED        0x50B
 
 #define A6XX_RBBM_ISDB_CNT                       0x533
 
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index d186760..627b351 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1506,8 +1506,7 @@
 			PERFCOUNTER_FLAG_KERNEL);
 
 		if (ret) {
-			KGSL_DRV_ERR(device,
-				"Unable to get the perf counters for DCVS\n");
+			WARN_ONCE(1, "Unable to get perf counters for DCVS\n");
 			adreno_dev->perfctr_pwr_lo = 0;
 		}
 	}
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 0b7f42a..6e025c8 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -383,6 +383,10 @@
 
 	adreno_vbif_start(adreno_dev, a6xx_vbif_platforms,
 			ARRAY_SIZE(a6xx_vbif_platforms));
+
+	/* Make all blocks contribute to the GPU BUSY perf counter */
+	kgsl_regwrite(device, A6XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
+
 	/*
 	 * Set UCHE_WRITE_THRU_BASE to the UCHE_TRAP_BASE effectively
 	 * disabling L2 bypass
@@ -809,12 +813,12 @@
 
 	t = jiffies + msecs_to_jiffies(timeout);
 
-	while (!time_after(jiffies, t)) {
+	do {
 		kgsl_gmu_regread(device, offset, &value);
 		if ((value & mask) == expected_ret)
 			return 0;
 		cpu_relax();
-	}
+	} while (!time_after(jiffies, t));
 
 	return -EINVAL;
 }
@@ -948,7 +952,7 @@
 	int ret = 0;
 
 	if (!kgsl_gmu_isenabled(device))
-		return -ENODEV;
+		return 0;
 
 	kgsl_gmu_regwrite(device, A6XX_GMU_HOST2GMU_INTR_SET, set_mask);
 
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index 63dbde0..17ee6e6 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -640,6 +640,9 @@
 	unsigned int *data = (unsigned int *)(buf + sizeof(*header));
 	int i, j;
 
+	if (!device->snapshot_legacy)
+		return 0;
+
 	if (remain < sizeof(*header)) {
 		SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
 		return 0;
@@ -748,6 +751,9 @@
 	unsigned int read_sel;
 	int i, j;
 
+	if (!device->snapshot_legacy)
+		return 0;
+
 	/* Figure out how many registers we are going to dump */
 	for (i = 0; i < regs->num_sets; i++) {
 		int start = regs->regs[i * 2];
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 35df143..ee4e7ef 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -294,6 +294,8 @@
 
 	/* Use CP Crash dumper to get GPU snapshot*/
 	bool snapshot_crashdumper;
+	/* Use HOST side register reads to get GPU snapshot*/
+	bool snapshot_legacy;
 
 	struct kobject snapshot_kobj;
 
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 850edf7..7354e82 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -858,14 +858,6 @@
 	}
 
 	if (is_gmu) {
-		if (!devm_request_mem_region(&gmu->pdev->dev, res->start,
-					resource_size(res),
-					res->name)) {
-			dev_err(&gmu->pdev->dev,
-				"GMU regs request mem region failed\n");
-			return -ENOMEM;
-		}
-
 		gmu->reg_phys = res->start;
 		gmu->reg_len = resource_size(res);
 		gmu->reg_virt = devm_ioremap(&gmu->pdev->dev, res->start,
@@ -1530,7 +1522,7 @@
 
 	if (hfi->hfi_interrupt_num) {
 		devm_free_irq(&gmu->pdev->dev,
-				hfi->hfi_interrupt_num, gmu);
+				hfi->hfi_interrupt_num, hfi);
 		hfi->hfi_interrupt_num = 0;
 	}
 
diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c
index 30e1d7c..b05e18d 100644
--- a/drivers/gpu/msm/kgsl_hfi.c
+++ b/drivers/gpu/msm/kgsl_hfi.c
@@ -573,44 +573,41 @@
 	if (result)
 		return result;
 
-	if (boot_state == GMU_COLD_BOOT) {
-		major = adreno_dev->gpucore->gpmu_major;
-		minor = adreno_dev->gpucore->gpmu_minor;
+	major = adreno_dev->gpucore->gpmu_major;
+	minor = adreno_dev->gpucore->gpmu_minor;
+	result = hfi_get_fw_version(gmu,
+			FW_VERSION(major, minor), &ver);
+	if (result)
+		dev_err(dev, "Failed to get FW version via HFI\n");
 
-		result = hfi_get_fw_version(gmu,
-				FW_VERSION(major, minor), &ver);
-		if (result)
-			dev_err(dev, "Failed to get FW version via HFI\n");
+	gmu->ver = ver;
+	if (major != FW_VER_MAJOR(ver))
+		dev_err(dev, "FW version major %d error (expect %d)\n",
+				FW_VER_MAJOR(ver),
+				adreno_dev->gpucore->gpmu_major);
 
-		gmu->ver = ver;
-		if (major != FW_VER_MAJOR(ver))
-			dev_err(dev, "FW version major %d error (expect %d)\n",
-					FW_VER_MAJOR(ver),
-					adreno_dev->gpucore->gpmu_major);
+	if (minor > FW_VER_MINOR(ver))
+		dev_err(dev, "FW version minor %d error (expect %d)\n",
+				FW_VER_MINOR(ver),
+				adreno_dev->gpucore->gpmu_minor);
 
-		if (minor > FW_VER_MINOR(ver))
-			dev_err(dev, "FW version minor %d error (expect %d)\n",
-					FW_VER_MINOR(ver),
-					adreno_dev->gpucore->gpmu_minor);
+	result = hfi_send_perftbl(gmu);
+	if (result)
+		return result;
 
-		result = hfi_send_perftbl(gmu);
-		if (result)
-			return result;
+	result = hfi_send_bwtbl(gmu);
+	if (result)
+		return result;
 
-		result = hfi_send_bwtbl(gmu);
-		if (result)
-			return result;
-
-		/*
-		 * FW is not ready for LM configuration
-		 * without powering on GPU.
-		 */
-		/*
-		 * result = hfi_send_lmconfig(gmu);
-		 * if (result)
-		 * return result;
-		 */
-	}
+	/*
+	 * FW is not ready for LM configuration
+	 * without powering on GPU.
+	 */
+	/*
+	 * result = hfi_send_lmconfig(gmu);
+	 * if (result)
+	 * return result;
+	 */
 
 	set_bit(GMU_HFI_ON, &gmu->flags);
 	return 0;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 40d239c..7cbda72 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -875,6 +875,25 @@
 	return snprintf(buf, PAGE_SIZE, "%lu\n", timestamp);
 }
 
+static ssize_t snapshot_legacy_show(struct kgsl_device *device, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", device->snapshot_legacy);
+}
+
+static ssize_t snapshot_legacy_store(struct kgsl_device *device,
+	const char *buf, size_t count)
+{
+	unsigned int val = 0;
+	int ret;
+
+	ret = kgsl_sysfs_store(buf, &val);
+
+	if (!ret && device)
+		device->snapshot_legacy = (bool)val;
+
+	return (ssize_t) ret < 0 ? ret : count;
+}
+
 static struct bin_attribute snapshot_attr = {
 	.attr.name = "dump",
 	.attr.mode = 0444,
@@ -894,6 +913,8 @@
 static SNAPSHOT_ATTR(force_panic, 0644, force_panic_show, force_panic_store);
 static SNAPSHOT_ATTR(snapshot_crashdumper, 0644, snapshot_crashdumper_show,
 	snapshot_crashdumper_store);
+static SNAPSHOT_ATTR(snapshot_legacy, 0644, snapshot_legacy_show,
+	snapshot_legacy_store);
 
 static ssize_t snapshot_sysfs_show(struct kobject *kobj,
 	struct attribute *attr, char *buf)
@@ -975,6 +996,7 @@
 	device->snapshot_faultcount = 0;
 	device->force_panic = 0;
 	device->snapshot_crashdumper = 1;
+	device->snapshot_legacy = 0;
 
 	ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot,
 		&device->dev->kobj, "snapshot");
@@ -1000,6 +1022,12 @@
 
 	ret  = sysfs_create_file(&device->snapshot_kobj,
 			&attr_snapshot_crashdumper.attr);
+	if (ret)
+		goto done;
+
+	ret  = sysfs_create_file(&device->snapshot_kobj,
+			&attr_snapshot_legacy.attr);
+
 done:
 	return ret;
 }
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 622ccbc..989af91 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -23,6 +23,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
 #include <linux/qcom-geni-se.h>
 
 #define SE_I2C_TX_TRANS_LEN		(0x26C)
@@ -87,17 +88,31 @@
 	u32 m_stat = readl_relaxed(gi2c->base + SE_GENI_M_IRQ_STATUS);
 	u32 tx_stat = readl_relaxed(gi2c->base + SE_GENI_TX_FIFO_STATUS);
 	u32 rx_stat = readl_relaxed(gi2c->base + SE_GENI_RX_FIFO_STATUS);
+	u32 dm_tx_st = readl_relaxed(gi2c->base + SE_DMA_TX_IRQ_STAT);
+	u32 dm_rx_st = readl_relaxed(gi2c->base + SE_DMA_RX_IRQ_STAT);
+	u32 dma = readl_relaxed(gi2c->base + SE_GENI_DMA_MODE_EN);
 	struct i2c_msg *cur = gi2c->cur;
 
 	dev_dbg(gi2c->dev,
 		"got i2c irq:%d, stat:0x%x, tx stat:0x%x, rx stat:0x%x\n",
 		irq, m_stat, tx_stat, rx_stat);
-	if (!cur || m_stat & SE_I2C_ERR) {
-		dev_err(gi2c->dev, "i2c txn err");
-		writel_relaxed(0, (gi2c->base + SE_GENI_TX_WATERMARK_REG));
+	if (!cur || (m_stat & SE_I2C_ERR) || (dm_tx_st & TX_SBE) ||
+		    (dm_rx_st & RX_SBE)) {
+		dev_err(gi2c->dev, "i2c err:st:0x%x, dm_t: 0x%x, dm_r: 0x%x\n",
+				   m_stat, dm_tx_st, dm_tx_st);
+		if (!dma)
+			writel_relaxed(0, (gi2c->base +
+					   SE_GENI_TX_WATERMARK_REG));
 		gi2c->err = -EIO;
 		goto irqret;
 	}
+
+	if (dma) {
+		dev_dbg(gi2c->dev, "i2c dma tx:0x%x, dma rx:0x%x\n", dm_tx_st,
+			dm_rx_st);
+		goto irqret;
+	}
+
 	if (((m_stat & M_RX_FIFO_WATERMARK_EN) ||
 		(m_stat & M_RX_FIFO_LAST_EN)) && (cur->flags & I2C_M_RD)) {
 		u32 rxcnt = rx_stat & RX_FIFO_WC_MSK;
@@ -112,10 +127,11 @@
 				cur->buf[i] = (u8) ((temp >> (p * 8)) & 0xff);
 			gi2c->cur_rd = i;
 			if (gi2c->cur_rd == cur->len) {
-				dev_dbg(gi2c->dev, "i:%d,read 0x%x\n", i, temp);
+				dev_dbg(gi2c->dev, "FIFO i:%d,read 0x%x\n",
+					i, temp);
 				break;
 			}
-			dev_dbg(gi2c->dev, "i: %d, read 0x%x\n", i, temp);
+			dev_dbg(gi2c->dev, "FIFO i: %d, read 0x%x\n", i, temp);
 		}
 	} else if ((m_stat & M_TX_FIFO_WATERMARK_EN) &&
 					!(cur->flags & I2C_M_RD)) {
@@ -128,9 +144,9 @@
 				temp |= (((u32)(cur->buf[i]) << (p * 8)));
 			writel_relaxed(temp, gi2c->base + SE_GENI_TX_FIFOn);
 			gi2c->cur_wr = i;
-			dev_dbg(gi2c->dev, "i:%d,wrote 0x%x\n", i, temp);
+			dev_dbg(gi2c->dev, "FIFO i:%d,wrote 0x%x\n", i, temp);
 			if (gi2c->cur_wr == cur->len) {
-				dev_dbg(gi2c->dev, "i2c bytes done writing\n");
+				dev_dbg(gi2c->dev, "FIFO i2c bytes done writing\n");
 				writel_relaxed(0,
 				(gi2c->base + SE_GENI_TX_WATERMARK_REG));
 				break;
@@ -138,15 +154,25 @@
 		}
 	}
 irqret:
-	writel_relaxed(m_stat, gi2c->base + SE_GENI_M_IRQ_CLEAR);
-	/* Ensure all writes are done before returning from ISR. */
-	wmb();
-	/* if this is err with done-bit not set, handle that thr' timeout. */
-	if (m_stat & M_CMD_DONE_EN) {
-		dev_dbg(gi2c->dev, "i2c irq: err:%d, stat:0x%x\n",
-							gi2c->err, m_stat);
-		complete(&gi2c->xfer);
+	if (m_stat)
+		writel_relaxed(m_stat, gi2c->base + SE_GENI_M_IRQ_CLEAR);
+
+	if (dma) {
+		if (dm_tx_st)
+			writel_relaxed(dm_tx_st, gi2c->base +
+				       SE_DMA_TX_IRQ_CLR);
+		if (dm_rx_st)
+			writel_relaxed(dm_rx_st, gi2c->base +
+				       SE_DMA_RX_IRQ_CLR);
+		/* Ensure all writes are done before returning from ISR. */
+		wmb();
 	}
+	/* 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))
+		complete(&gi2c->xfer);
+
 	return IRQ_HANDLED;
 }
 
@@ -175,11 +201,21 @@
 		int stretch = (i < (num - 1));
 		u32 m_param = 0;
 		u32 m_cmd = 0;
+		dma_addr_t tx_dma = 0;
+		dma_addr_t rx_dma = 0;
+		enum se_xfer_mode mode = FIFO_MODE;
 
 		m_param |= (stretch ? STOP_STRETCH : 0);
 		m_param |= ((msgs[i].addr & 0x7F) << SLV_ADDR_SHFT);
 
 		gi2c->cur = &msgs[i];
+		mode = msgs[i].len > 32 ? SE_DMA : FIFO_MODE;
+		ret = geni_se_select_mode(gi2c->base, mode);
+		if (ret) {
+			dev_err(gi2c->dev, "%s: Error mode init %d:%d:%d\n",
+				__func__, mode, i, msgs[i].len);
+			break;
+		}
 		if (msgs[i].flags & I2C_M_RD) {
 			dev_dbg(gi2c->dev,
 				"READ,n:%d,i:%d len:%d, stretch:%d\n",
@@ -188,22 +224,41 @@
 				       gi2c->base, SE_I2C_RX_TRANS_LEN);
 			m_cmd = I2C_READ;
 			geni_setup_m_cmd(gi2c->base, m_cmd, m_param);
+			if (mode == SE_DMA) {
+				ret = geni_se_rx_dma_prep(gi2c->wrapper_dev,
+							gi2c->base, msgs[i].buf,
+							msgs[i].len, &rx_dma);
+				if (ret)
+					mode = FIFO_MODE;
+			}
+			if (mode == FIFO_MODE)
+				geni_se_select_mode(gi2c->base, mode);
 		} else {
 			dev_dbg(gi2c->dev,
-				"WRITE:n:%d,i%d len:%d, stretch:%d\n",
-					num, i, msgs[i].len, stretch);
+				"WRITE:n:%d,i:%d len:%d, stretch:%d, m_param:0x%x\n",
+					num, i, msgs[i].len, stretch, m_param);
 			geni_write_reg(msgs[i].len, gi2c->base,
 						SE_I2C_TX_TRANS_LEN);
 			m_cmd = I2C_WRITE;
 			geni_setup_m_cmd(gi2c->base, m_cmd, m_param);
-			/* Get FIFO IRQ */
-			geni_write_reg(1, gi2c->base, SE_GENI_TX_WATERMARK_REG);
+			if (mode == SE_DMA) {
+				ret = geni_se_tx_dma_prep(gi2c->wrapper_dev,
+							gi2c->base, msgs[i].buf,
+							msgs[i].len, &tx_dma);
+				if (ret)
+					mode = FIFO_MODE;
+			}
+			if (mode == FIFO_MODE) {
+				geni_se_select_mode(gi2c->base, mode);
+				/* Get FIFO IRQ */
+				geni_write_reg(1, gi2c->base,
+						SE_GENI_TX_WATERMARK_REG);
+			}
 		}
 		/* Ensure FIFO write go through before waiting for Done evet */
 		mb();
 		timeout = wait_for_completion_timeout(&gi2c->xfer, HZ);
 		if (!timeout) {
-			dev_err(gi2c->dev, "Timed out\n");
 			gi2c->err = -ETIMEDOUT;
 			gi2c->cur = NULL;
 			geni_abort_m_cmd(gi2c->base);
@@ -211,9 +266,24 @@
 		}
 		gi2c->cur_wr = 0;
 		gi2c->cur_rd = 0;
+		if (mode == SE_DMA) {
+			if (gi2c->err) {
+				if (msgs[i].flags != I2C_M_RD)
+					writel_relaxed(1, gi2c->base +
+							SE_DMA_TX_FSM_RST);
+				else
+					writel_relaxed(1, gi2c->base +
+							SE_DMA_RX_FSM_RST);
+				wait_for_completion_timeout(&gi2c->xfer, HZ);
+			}
+			geni_se_rx_dma_unprep(gi2c->wrapper_dev, rx_dma,
+					      msgs[i].len);
+			geni_se_tx_dma_unprep(gi2c->wrapper_dev, tx_dma,
+					      msgs[i].len);
+		}
+		ret = gi2c->err;
 		if (gi2c->err) {
 			dev_err(gi2c->dev, "i2c error :%d\n", gi2c->err);
-			ret = gi2c->err;
 			break;
 		}
 	}
@@ -352,6 +422,7 @@
 	pm_runtime_enable(gi2c->dev);
 	i2c_add_adapter(&gi2c->adap);
 
+	dev_dbg(gi2c->dev, "I2C probed\n");
 	return 0;
 }
 
@@ -393,7 +464,6 @@
 
 		gi2c->tx_wm = gi2c_tx_depth - 1;
 		geni_se_init(gi2c->base, gi2c->tx_wm, gi2c_tx_depth);
-		geni_se_select_mode(gi2c->base, FIFO_MODE);
 		se_config_packing(gi2c->base, 8, 4, true);
 	}
 	enable_irq(gi2c->irq);
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index c1fb545..42de5f2 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -1301,7 +1301,7 @@
 	free_port_list_attributes(device);
 
 err_unregister:
-	device_unregister(class_dev);
+	device_del(class_dev);
 
 err:
 	return ret;
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 8368764..0e64b52 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -1516,7 +1516,9 @@
 
 	if (!qp->device->attach_mcast)
 		return -ENOSYS;
-	if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
+	if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD ||
+	    lid < be16_to_cpu(IB_MULTICAST_LID_BASE) ||
+	    lid == be16_to_cpu(IB_LID_PERMISSIVE))
 		return -EINVAL;
 
 	ret = qp->device->attach_mcast(qp, gid, lid);
@@ -1532,7 +1534,9 @@
 
 	if (!qp->device->detach_mcast)
 		return -ENOSYS;
-	if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
+	if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD ||
+	    lid < be16_to_cpu(IB_MULTICAST_LID_BASE) ||
+	    lid == be16_to_cpu(IB_LID_PERMISSIVE))
 		return -EINVAL;
 
 	ret = qp->device->detach_mcast(qp, gid, lid);
diff --git a/drivers/infiniband/hw/hfi1/ruc.c b/drivers/infiniband/hw/hfi1/ruc.c
index a1576ae..9f768b4 100644
--- a/drivers/infiniband/hw/hfi1/ruc.c
+++ b/drivers/infiniband/hw/hfi1/ruc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2015, 2016 Intel Corporation.
+ * Copyright(c) 2015 - 2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
@@ -833,23 +833,29 @@
 /* when sending, force a reschedule every one of these periods */
 #define SEND_RESCHED_TIMEOUT (5 * HZ)  /* 5s in jiffies */
 
+void hfi1_do_send_from_rvt(struct rvt_qp *qp)
+{
+	hfi1_do_send(qp, false);
+}
+
 void _hfi1_do_send(struct work_struct *work)
 {
 	struct iowait *wait = container_of(work, struct iowait, iowork);
 	struct rvt_qp *qp = iowait_to_qp(wait);
 
-	hfi1_do_send(qp);
+	hfi1_do_send(qp, true);
 }
 
 /**
  * hfi1_do_send - perform a send on a QP
  * @work: contains a pointer to the QP
+ * @in_thread: true if in a workqueue thread
  *
  * Process entries in the send work queue until credit or queue is
  * exhausted.  Only allow one CPU to send a packet per QP.
  * Otherwise, two threads could send packets out of order.
  */
-void hfi1_do_send(struct rvt_qp *qp)
+void hfi1_do_send(struct rvt_qp *qp, bool in_thread)
 {
 	struct hfi1_pkt_state ps;
 	struct hfi1_qp_priv *priv = qp->priv;
@@ -917,8 +923,10 @@
 			qp->s_hdrwords = 0;
 			/* allow other tasks to run */
 			if (unlikely(time_after(jiffies, timeout))) {
-				if (workqueue_congested(cpu,
-							ps.ppd->hfi1_wq)) {
+				if (!in_thread ||
+				    workqueue_congested(
+						cpu,
+						ps.ppd->hfi1_wq)) {
 					spin_lock_irqsave(
 						&qp->s_lock,
 						ps.flags);
@@ -931,11 +939,9 @@
 						*ps.ppd->dd->send_schedule);
 					return;
 				}
-				if (!irqs_disabled()) {
-					cond_resched();
-					this_cpu_inc(
-					   *ps.ppd->dd->send_schedule);
-				}
+				cond_resched();
+				this_cpu_inc(
+					*ps.ppd->dd->send_schedule);
 				timeout = jiffies + (timeout_int) / 8;
 			}
 			spin_lock_irqsave(&qp->s_lock, ps.flags);
diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c
index 4b7a16c..01a380e 100644
--- a/drivers/infiniband/hw/hfi1/verbs.c
+++ b/drivers/infiniband/hw/hfi1/verbs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2015, 2016 Intel Corporation.
+ * Copyright(c) 2015 - 2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
@@ -1697,7 +1697,7 @@
 	dd->verbs_dev.rdi.driver_f.qp_priv_free = qp_priv_free;
 	dd->verbs_dev.rdi.driver_f.free_all_qps = free_all_qps;
 	dd->verbs_dev.rdi.driver_f.notify_qp_reset = notify_qp_reset;
-	dd->verbs_dev.rdi.driver_f.do_send = hfi1_do_send;
+	dd->verbs_dev.rdi.driver_f.do_send = hfi1_do_send_from_rvt;
 	dd->verbs_dev.rdi.driver_f.schedule_send = hfi1_schedule_send;
 	dd->verbs_dev.rdi.driver_f.schedule_send_no_lock = _hfi1_schedule_send;
 	dd->verbs_dev.rdi.driver_f.get_pmtu_from_attr = get_pmtu_from_attr;
diff --git a/drivers/infiniband/hw/hfi1/verbs.h b/drivers/infiniband/hw/hfi1/verbs.h
index 1c3815d..bac84f8 100644
--- a/drivers/infiniband/hw/hfi1/verbs.h
+++ b/drivers/infiniband/hw/hfi1/verbs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2015, 2016 Intel Corporation.
+ * Copyright(c) 2015 - 2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
@@ -372,7 +372,9 @@
 
 void _hfi1_do_send(struct work_struct *work);
 
-void hfi1_do_send(struct rvt_qp *qp);
+void hfi1_do_send_from_rvt(struct rvt_qp *qp);
+
+void hfi1_do_send(struct rvt_qp *qp, bool in_thread);
 
 void hfi1_send_complete(struct rvt_qp *qp, struct rvt_swqe *wqe,
 			enum ib_wc_status status);
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 46ad995..f2a885e 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -2926,6 +2926,7 @@
 		mlx4_ib_delete_counters_table(ibdev, &ibdev->counters_table[i]);
 
 err_map:
+	mlx4_ib_free_eqs(dev, ibdev);
 	iounmap(ibdev->uar_map);
 
 err_uar:
diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c
index a21d37f..e6ea81c 100644
--- a/drivers/infiniband/hw/mlx4/mcg.c
+++ b/drivers/infiniband/hw/mlx4/mcg.c
@@ -1102,7 +1102,8 @@
 	while ((p = rb_first(&ctx->mcg_table)) != NULL) {
 		group = rb_entry(p, struct mcast_group, node);
 		if (atomic_read(&group->refcount))
-			mcg_warn_group(group, "group refcount %d!!! (pointer %p)\n", atomic_read(&group->refcount), group);
+			mcg_debug_group(group, "group refcount %d!!! (pointer %p)\n",
+					atomic_read(&group->refcount), group);
 
 		force_clean_group(group);
 	}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 6bd5740..09396bd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -281,8 +281,11 @@
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
+	WARN_ONCE(!priv->mcg_dentry, "null mcg debug file\n");
+	WARN_ONCE(!priv->path_dentry, "null path debug file\n");
 	debugfs_remove(priv->mcg_dentry);
 	debugfs_remove(priv->path_dentry);
+	priv->mcg_dentry = priv->path_dentry = NULL;
 }
 
 int ipoib_register_debugfs(void)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 3ef7b8f..08c4b02 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -108,6 +108,33 @@
 	.get_net_dev_by_params = ipoib_get_net_dev_by_params,
 };
 
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+static int ipoib_netdev_event(struct notifier_block *this,
+			      unsigned long event, void *ptr)
+{
+	struct netdev_notifier_info *ni = ptr;
+	struct net_device *dev = ni->dev;
+
+	if (dev->netdev_ops->ndo_open != ipoib_open)
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case NETDEV_REGISTER:
+		ipoib_create_debug_files(dev);
+		break;
+	case NETDEV_CHANGENAME:
+		ipoib_delete_debug_files(dev);
+		ipoib_create_debug_files(dev);
+		break;
+	case NETDEV_UNREGISTER:
+		ipoib_delete_debug_files(dev);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+#endif
+
 int ipoib_open(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -1655,8 +1682,6 @@
 
 	ASSERT_RTNL();
 
-	ipoib_delete_debug_files(dev);
-
 	/* Delete any child interfaces first */
 	list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) {
 		/* Stop GC on child */
@@ -2074,8 +2099,6 @@
 		goto register_failed;
 	}
 
-	ipoib_create_debug_files(priv->dev);
-
 	if (ipoib_cm_add_mode_attr(priv->dev))
 		goto sysfs_failed;
 	if (ipoib_add_pkey_attr(priv->dev))
@@ -2090,7 +2113,6 @@
 	return priv->dev;
 
 sysfs_failed:
-	ipoib_delete_debug_files(priv->dev);
 	unregister_netdev(priv->dev);
 
 register_failed:
@@ -2175,6 +2197,12 @@
 	kfree(dev_list);
 }
 
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+static struct notifier_block ipoib_netdev_notifier = {
+	.notifier_call = ipoib_netdev_event,
+};
+#endif
+
 static int __init ipoib_init_module(void)
 {
 	int ret;
@@ -2227,6 +2255,9 @@
 	if (ret)
 		goto err_client;
 
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+	register_netdevice_notifier(&ipoib_netdev_notifier);
+#endif
 	return 0;
 
 err_client:
@@ -2244,6 +2275,9 @@
 
 static void __exit ipoib_cleanup_module(void)
 {
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+	unregister_netdevice_notifier(&ipoib_netdev_notifier);
+#endif
 	ipoib_netlink_fini();
 	ib_unregister_client(&ipoib_client);
 	ib_sa_unregister_client(&ipoib_sa_client);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index a2f9f29..57eadd2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -87,8 +87,6 @@
 		goto register_failed;
 	}
 
-	ipoib_create_debug_files(priv->dev);
-
 	/* RTNL childs don't need proprietary sysfs entries */
 	if (type == IPOIB_LEGACY_CHILD) {
 		if (ipoib_cm_add_mode_attr(priv->dev))
@@ -109,7 +107,6 @@
 
 sysfs_failed:
 	result = -ENOMEM;
-	ipoib_delete_debug_files(priv->dev);
 	unregister_netdevice(priv->dev);
 
 register_failed:
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index c5ab866..2db0d64 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -432,13 +432,12 @@
 	return ret;
 }
 
-dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
-		unsigned long offset, size_t size, int prot)
+static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
+		size_t size, int prot)
 {
 	dma_addr_t dma_addr;
 	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
 	struct iova_domain *iovad = cookie_iovad(domain);
-	phys_addr_t phys = page_to_phys(page) + offset;
 	size_t iova_off = iova_offset(iovad, phys);
 	size_t len = iova_align(iovad, size + iova_off);
 	struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev));
@@ -454,6 +453,12 @@
 	return dma_addr + iova_off;
 }
 
+dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
+		unsigned long offset, size_t size, int prot)
+{
+	return __iommu_dma_map(dev, page_to_phys(page) + offset, size, prot);
+}
+
 void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
 		enum dma_data_direction dir, unsigned long attrs)
 {
@@ -624,6 +629,19 @@
 	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), sg_dma_address(sg));
 }
 
+dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
+		size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+	return __iommu_dma_map(dev, phys, size,
+			dma_direction_to_prot(dir, false) | IOMMU_MMIO);
+}
+
+void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
+}
+
 int iommu_dma_supported(struct device *dev, u64 mask)
 {
 	/*
diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c
index 8ba6da4..ac3059d 100644
--- a/drivers/iommu/dma-mapping-fast.c
+++ b/drivers/iommu/dma-mapping-fast.c
@@ -611,6 +611,55 @@
 	return ret;
 }
 
+static dma_addr_t fast_smmu_dma_map_resource(
+			struct device *dev, phys_addr_t phys_addr,
+			size_t size, enum dma_data_direction dir,
+			unsigned long attrs)
+{
+	struct dma_fast_smmu_mapping *mapping = dev->archdata.mapping->fast;
+	size_t offset = phys_addr & ~FAST_PAGE_MASK;
+	size_t len = round_up(size + offset, FAST_PAGE_SIZE);
+	dma_addr_t dma_addr;
+	int prot;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mapping->lock, flags);
+	dma_addr = __fast_smmu_alloc_iova(mapping, attrs, len);
+	spin_unlock_irqrestore(&mapping->lock, flags);
+
+	if (dma_addr == DMA_ERROR_CODE)
+		return dma_addr;
+
+	prot = __fast_dma_direction_to_prot(dir);
+	prot |= IOMMU_MMIO;
+
+	if (iommu_map(mapping->domain, dma_addr, phys_addr - offset,
+			len, prot)) {
+		spin_lock_irqsave(&mapping->lock, flags);
+		__fast_smmu_free_iova(mapping, dma_addr, len);
+		spin_unlock_irqrestore(&mapping->lock, flags);
+		return DMA_ERROR_CODE;
+	}
+	return dma_addr + offset;
+}
+
+static void fast_smmu_dma_unmap_resource(
+			struct device *dev, dma_addr_t addr,
+			size_t size, enum dma_data_direction dir,
+			unsigned long attrs)
+{
+	struct dma_fast_smmu_mapping *mapping = dev->archdata.mapping->fast;
+	size_t offset = addr & ~FAST_PAGE_MASK;
+	size_t len = round_up(size + offset, FAST_PAGE_SIZE);
+	unsigned long flags;
+
+	iommu_unmap(mapping->domain, addr - offset, len);
+	spin_lock_irqsave(&mapping->lock, flags);
+	__fast_smmu_free_iova(mapping, addr, len);
+	spin_unlock_irqrestore(&mapping->lock, flags);
+}
+
+
 static int fast_smmu_dma_supported(struct device *dev, u64 mask)
 {
 	return mask <= 0xffffffff;
@@ -667,6 +716,8 @@
 	.unmap_sg = fast_smmu_unmap_sg,
 	.sync_sg_for_cpu = fast_smmu_sync_sg_for_cpu,
 	.sync_sg_for_device = fast_smmu_sync_sg_for_device,
+	.map_resource = fast_smmu_dma_map_resource,
+	.unmap_resource = fast_smmu_dma_unmap_resource,
 	.dma_supported = fast_smmu_dma_supported,
 	.mapping_error = fast_smmu_mapping_error,
 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 41515bb..ee50a61 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -299,3 +299,5 @@
 config STM32_EXTI
 	bool
 	select IRQ_DOMAIN
+
+source "drivers/irqchip/qcom/Kconfig"
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 987bd89..450059c 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -75,3 +75,4 @@
 obj-$(CONFIG_EZNPS_GIC)			+= irq-eznps.o
 obj-$(CONFIG_ARCH_ASPEED)		+= irq-aspeed-vic.o
 obj-$(CONFIG_STM32_EXTI) 		+= irq-stm32-exti.o
+obj-$(CONFIG_QTI_PDC)			+= qcom/
diff --git a/drivers/irqchip/qcom/Kconfig b/drivers/irqchip/qcom/Kconfig
new file mode 100644
index 0000000..e4a7a88
--- /dev/null
+++ b/drivers/irqchip/qcom/Kconfig
@@ -0,0 +1,15 @@
+config QTI_PDC
+        bool "QTI PDC"
+        depends on ARCH_QCOM
+	select IRQ_DOMAIN
+	select IRQ_DOMAIN_HIERARCHY
+        help
+          QTI Power Domain Controller driver to manage and configure wakeup
+          IRQs
+
+config QTI_PDC_SDM845
+        bool "QTI PDC SDM845"
+        select QTI_PDC
+        default y if ARCH_SDM845
+        help
+          QTI Power Domain Controller for SDM845
diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile
new file mode 100644
index 0000000..1b7856d
--- /dev/null
+++ b/drivers/irqchip/qcom/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_QTI_PDC)			+= pdc.o
+obj-$(CONFIG_QTI_PDC_SDM845)		+= pdc-sdm845.o
diff --git a/drivers/irqchip/qcom/pdc-sdm845.c b/drivers/irqchip/qcom/pdc-sdm845.c
new file mode 100644
index 0000000..178cf1f0
--- /dev/null
+++ b/drivers/irqchip/qcom/pdc-sdm845.c
@@ -0,0 +1,139 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/irqchip.h>
+#include "pdc.h"
+
+static struct pdc_pin sdm845_data[] = {
+	{0, 512}, /* rpmh_wake */
+	{1, 513}, /* ee0_apps_hlos_spmi_periph_irq */
+	{2, 514}, /* ee1_apps_trustzone_spmi_periph_irq */
+	{3, 515}, /* secure_wdog_expired */
+	{4, 516}, /* secure_wdog_bark_irq */
+	{5, 517}, /* aop_wdog_expired_irq */
+	{6, 518}, /* qmp_usb3_lfps_rxterm_irq */
+	{7, 519}, /* qmp_usb3_lfps_rxterm_irq */
+	{8, 520}, /* eud_p0_dmse_int_mx */
+	{9, 521}, /* eud_p0_dpse_int_mx */
+	{10, 522}, /* eud_p1_dmse_int_mx */
+	{11, 523}, /* eud_p1_dpse_int_mx */
+	{12, 524}, /* eud_int_mx[1] */
+	{13, 525}, /* ssc_xpu_irq_summary */
+	{14, 526}, /* wd_bite_apps */
+	{15, 527}, /* ssc_vmidmt_irq_summary */
+	{16, 528}, /* q6ss_irq_out_apps_ipc[4] */
+	{17, 529}, /* not-connected */
+	{18, 530}, /* aoss_pmic_arb_mpu_xpu_summary_irq */
+	{19, 531}, /* apps_pdc_irq_in_19 */
+	{20, 532}, /* apps_pdc_irq_in_20 */
+	{21, 533}, /* apps_pdc_irq_in_21 */
+	{22, 534}, /* pdc_apps_epcb_timeout_summary_irq */
+	{23, 535}, /* spmi_protocol_irq */
+	{24, 536}, /* tsense0_tsense_max_min_int */
+	{25, 537}, /* tsense1_tsense_max_min_int */
+	{26, 538}, /* tsense0_upper_lower_intr */
+	{27, 539}, /* tsense1_upper_lower_intr */
+	{28, 540}, /* tsense0_critical_intr */
+	{29, 541}, /* tsense1_critical_intr */
+	{30, 542}, /* core_bi_px_gpio_1 */
+	{31, 543}, /* core_bi_px_gpio_3 */
+	{32, 544}, /* core_bi_px_gpio_5 */
+	{33, 545}, /* core_bi_px_gpio_10 */
+	{34, 546}, /* core_bi_px_gpio_11 */
+	{35, 547}, /* core_bi_px_gpio_20 */
+	{36, 548}, /* core_bi_px_gpio_22 */
+	{37, 549}, /* core_bi_px_gpio_24 */
+	{38, 550}, /* core_bi_px_gpio_26 */
+	{39, 551}, /* core_bi_px_gpio_30 */
+	{41, 553}, /* core_bi_px_gpio_32 */
+	{42, 554}, /* core_bi_px_gpio_34 */
+	{43, 555}, /* core_bi_px_gpio_36 */
+	{44, 556}, /* core_bi_px_gpio_37 */
+	{45, 557}, /* core_bi_px_gpio_38 */
+	{46, 558}, /* core_bi_px_gpio_39 */
+	{47, 559}, /* core_bi_px_gpio_40 */
+	{49, 561}, /* core_bi_px_gpio_43 */
+	{50, 562}, /* core_bi_px_gpio_44 */
+	{51, 563}, /* core_bi_px_gpio_46 */
+	{52, 564}, /* core_bi_px_gpio_48 */
+	{54, 566}, /* core_bi_px_gpio_52 */
+	{55, 567}, /* core_bi_px_gpio_53 */
+	{56, 568}, /* core_bi_px_gpio_54 */
+	{57, 569}, /* core_bi_px_gpio_56 */
+	{58, 570}, /* core_bi_px_gpio_57 */
+	{59, 571}, /* core_bi_px_gpio_58 */
+	{60, 572}, /* core_bi_px_gpio_59 */
+	{61, 573}, /* core_bi_px_gpio_60 */
+	{62, 574}, /* core_bi_px_gpio_61 */
+	{63, 575}, /* core_bi_px_gpio_62 */
+	{64, 576}, /* core_bi_px_gpio_63 */
+	{65, 577}, /* core_bi_px_gpio_64 */
+	{66, 578}, /* core_bi_px_gpio_66 */
+	{67, 579}, /* core_bi_px_gpio_68 */
+	{68, 580}, /* core_bi_px_gpio_71 */
+	{69, 581}, /* core_bi_px_gpio_73 */
+	{70, 582}, /* core_bi_px_gpio_77 */
+	{71, 583}, /* core_bi_px_gpio_78 */
+	{72, 584}, /* core_bi_px_gpio_79 */
+	{73, 585}, /* core_bi_px_gpio_80 */
+	{74, 586}, /* core_bi_px_gpio_84 */
+	{75, 587}, /* core_bi_px_gpio_85 */
+	{76, 588}, /* core_bi_px_gpio_86 */
+	{77, 589}, /* core_bi_px_gpio_88 */
+	{79, 591}, /* core_bi_px_gpio_91 */
+	{80, 592}, /* core_bi_px_gpio_92 */
+	{81, 593}, /* core_bi_px_gpio_95 */
+	{82, 594}, /* core_bi_px_gpio_96 */
+	{83, 595}, /* core_bi_px_gpio_97 */
+	{84, 596}, /* core_bi_px_gpio_101 */
+	{85, 597}, /* core_bi_px_gpio_103 */
+	{86, 598}, /* core_bi_px_gpio_104 */
+	{87, 599}, /* core_bi_px_to_mpm[6] */
+	{88, 600}, /* core_bi_px_to_mpm[0] */
+	{89, 601}, /* core_bi_px_to_mpm[1] */
+	{90, 602}, /* core_bi_px_gpio_115 */
+	{91, 603}, /* core_bi_px_gpio_116 */
+	{92, 604}, /* core_bi_px_gpio_117 */
+	{93, 605}, /* core_bi_px_gpio_118 */
+	{94, 641}, /* core_bi_px_gpio_119 */
+	{95, 642}, /* core_bi_px_gpio_120 */
+	{96, 643}, /* core_bi_px_gpio_121 */
+	{97, 644}, /* core_bi_px_gpio_122 */
+	{98, 645}, /* core_bi_px_gpio_123 */
+	{99, 646}, /* core_bi_px_gpio_124 */
+	{100, 647}, /* core_bi_px_gpio_125 */
+	{101, 648}, /* core_bi_px_to_mpm[5] */
+	{102, 649}, /* core_bi_px_gpio_127 */
+	{103, 650}, /* core_bi_px_gpio_128 */
+	{104, 651}, /* core_bi_px_gpio_129 */
+	{105, 652}, /* core_bi_px_gpio_130 */
+	{106, 653}, /* core_bi_px_gpio_132 */
+	{107, 654}, /* core_bi_px_gpio_133 */
+	{108, 655}, /* core_bi_px_gpio_145 */
+	{119, 666}, /* core_bi_px_to_mpm[2] */
+	{120, 667}, /* core_bi_px_to_mpm[3] */
+	{121, 668}, /* core_bi_px_to_mpm[4] */
+	{122, 669}, /* core_bi_px_gpio_41 */
+	{123, 670}, /* core_bi_px_gpio_89 */
+	{124, 671}, /* core_bi_px_gpio_31 */
+	{125, 672}, /* core_bi_px_gpio_49 */
+	{-1}
+};
+
+static int __init qcom_pdc_gic_init(struct device_node *node,
+		struct device_node *parent)
+{
+	return qcom_pdc_init(node, parent, sdm845_data);
+}
+
+IRQCHIP_DECLARE(pdc_sdm845, "qcom,pdc-sdm845", qcom_pdc_gic_init);
diff --git a/drivers/irqchip/qcom/pdc.c b/drivers/irqchip/qcom/pdc.c
new file mode 100644
index 0000000..923552f
--- /dev/null
+++ b/drivers/irqchip/qcom/pdc.c
@@ -0,0 +1,299 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include "pdc.h"
+#define CREATE_TRACE_POINTS
+#include "trace/events/pdc.h"
+
+#define MAX_IRQS 126
+#define CLEAR_INTR(reg, intr) (reg & ~(1 << intr))
+#define ENABLE_INTR(reg, intr) (reg | (1 << intr))
+
+enum pdc_register_offsets {
+	IRQ_ENABLE_BANK = 0x10,
+	IRQ_i_CFG = 0x110,
+};
+
+static DEFINE_SPINLOCK(pdc_lock);
+static void __iomem *pdc_base;
+
+static int get_pdc_pin(irq_hw_number_t hwirq, void *data)
+{
+	int i;
+	struct pdc_pin *pdc_data = (struct pdc_pin *) data;
+
+	for (i = 0; pdc_data[i].pin >= 0; i++) {
+		if (pdc_data[i].hwirq == hwirq)
+			return pdc_data[i].pin;
+	}
+
+	return -EINVAL;
+}
+
+static inline int pdc_enable_intr(struct irq_data *d, bool on)
+{
+	int pin_out = get_pdc_pin(d->hwirq, d->chip_data);
+	unsigned int index, mask;
+	u32 enable, r_enable;
+	unsigned long flags;
+
+	if (pin_out < 0)
+		return 0;
+
+	index = pin_out / 32;
+	mask = pin_out % 32;
+	spin_lock_irqsave(&pdc_lock, flags);
+
+	enable = readl_relaxed(pdc_base + IRQ_ENABLE_BANK + (index *
+					sizeof(uint32_t)));
+	if (on)
+		enable = ENABLE_INTR(enable, mask);
+	else
+		enable = CLEAR_INTR(enable, mask);
+
+	writel_relaxed(enable, pdc_base + IRQ_ENABLE_BANK + (index *
+						sizeof(uint32_t)));
+
+	do {
+		r_enable = readl_relaxed(pdc_base + IRQ_ENABLE_BANK +
+					(index * sizeof(uint32_t)));
+		if (r_enable == enable)
+			break;
+		udelay(5);
+	} while (1);
+
+	spin_unlock_irqrestore(&pdc_lock, flags);
+
+	trace_irq_pin_config("enable", (u32)pin_out, (u32)d->hwirq,
+			0, on);
+
+	return 0;
+}
+
+static void qcom_pdc_gic_mask(struct irq_data *d)
+{
+	pdc_enable_intr(d, false);
+	irq_chip_mask_parent(d);
+}
+
+static void qcom_pdc_gic_unmask(struct irq_data *d)
+{
+	pdc_enable_intr(d, true);
+	irq_chip_unmask_parent(d);
+}
+
+static void qcom_pdc_gic_enable(struct irq_data *d)
+{
+	pdc_enable_intr(d, true);
+	irq_chip_enable_parent(d);
+}
+
+static void qcom_pdc_gic_disable(struct irq_data *d)
+{
+	pdc_enable_intr(d, false);
+	irq_chip_disable_parent(d);
+}
+
+/*
+ * GIC does not handle falling edge or active low. To allow falling edge and
+ * active low interrupts to be handled at GIC, PDC has an inverter that inverts
+ * falling edge into a rising edge and active low into an active high.
+ * For the inverter to work, the polarity bit in the IRQ_CONFIG register has to
+ * set as per the table below.
+ * (polarity, falling edge, rising edge )  ORIG          POL CONV     POLARITY
+ * 3'b0 00  Level sensitive active low    (~~~|_____)   (___|~~~~~)   LOW
+ * 3'b0 01  Rising edge sensitive         (___|~~|__)   (~~~|__|~~)   NOT USED
+ * 3'b0 10  Falling edge sensitive        (~~~|__|~~)   (___|~~|__)   LOW
+ * 3'b0 11  Dual Edge sensitive                                       NOT USED
+ * 3'b1 00  Level senstive active High    (___|~~~~~)   (___|~~~~~)   HIGH
+ * 3'b1 01  Falling Edge sensitive        (~~~|__|~~)   (~~~|__|~~)   NOT USED
+ * 3'b1 10  Rising edge sensitive         (___|~~|__)   (___|~~|__)   HIGH
+ * 3'b1 11  Dual Edge sensitive                                       HIGH
+ */
+enum pdc_irq_config_bits {
+	POLARITY_LOW = 0, //0 00
+	FALLING_EDGE = 2, //0 10
+	POLARITY_HIGH = 4,//1 00
+	RISING_EDGE = 6,  //1 10
+	DUAL_EDGE = 7,    //1 11
+};
+
+static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
+{
+	int pin_out = get_pdc_pin(d->hwirq, d->chip_data);
+	u32 pdc_type = 0, config;
+
+	if (pin_out < 0)
+		goto fwd_to_parent;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		pdc_type = RISING_EDGE;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		pdc_type = FALLING_EDGE;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		pdc_type = DUAL_EDGE;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		pdc_type = POLARITY_HIGH;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		pdc_type = POLARITY_LOW;
+		break;
+	default:
+		pdc_type = POLARITY_HIGH;
+		break;
+	}
+	writel_relaxed(pdc_type, pdc_base + IRQ_i_CFG +
+			(pin_out * sizeof(uint32_t)));
+
+	do {
+		config = readl_relaxed(pdc_base + IRQ_i_CFG +
+				(pin_out * sizeof(uint32_t)));
+		if (config == pdc_type)
+			break;
+		udelay(5);
+	} while (1);
+
+	trace_irq_pin_config("type_config", (u32)pin_out, (u32)d->hwirq,
+			pdc_type, 0);
+
+	/*
+	 * If type is edge triggered, forward that as Rising edge as PDC
+	 * takes care of converting falling edge to rising edge signal
+	 */
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+		type = IRQ_TYPE_EDGE_RISING;
+
+	/*
+	 * If type is level, then forward that as level high as PDC
+	 * takes care of converting falling edge to rising edge signal
+	 */
+	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+		type = IRQ_TYPE_LEVEL_HIGH;
+
+fwd_to_parent:
+
+	return irq_chip_set_type_parent(d, type);
+}
+
+static struct irq_chip qcom_pdc_gic_chip = {
+	.name			= "PDC-GIC",
+	.irq_eoi		= irq_chip_eoi_parent,
+	.irq_mask		= qcom_pdc_gic_mask,
+	.irq_enable		= qcom_pdc_gic_enable,
+	.irq_unmask		= qcom_pdc_gic_unmask,
+	.irq_disable		= qcom_pdc_gic_disable,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
+	.irq_set_type		= qcom_pdc_gic_set_type,
+	.flags			= IRQCHIP_MASK_ON_SUSPEND |
+					IRQCHIP_SET_TYPE_MASKED |
+					IRQCHIP_SKIP_SET_WAKE,
+	.irq_set_vcpu_affinity	= irq_chip_set_vcpu_affinity_parent,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= irq_chip_set_affinity_parent,
+#endif
+};
+
+static int qcom_pdc_translate(struct irq_domain *d,
+	struct irq_fwspec *fwspec, unsigned long *hwirq, unsigned int *type)
+{
+	return d->parent->ops->translate(d->parent, fwspec, hwirq, type);
+}
+
+static int qcom_pdc_alloc(struct irq_domain *domain,
+	unsigned int virq, unsigned int nr_irqs, void *data)
+{
+	struct irq_fwspec *fwspec = data;
+	struct irq_fwspec parent_fwspec;
+	irq_hw_number_t hwirq;
+	int i;
+	unsigned int type;
+	int ret;
+
+	ret = qcom_pdc_translate(domain, fwspec, &hwirq, &type);
+	if (ret)
+		return -EINVAL;
+
+	for (i = 0; i < nr_irqs; i++)
+		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+			&qcom_pdc_gic_chip, domain->host_data);
+
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+					    &parent_fwspec);
+}
+
+static const struct irq_domain_ops qcom_pdc_ops = {
+	.translate	= qcom_pdc_translate,
+	.alloc		= qcom_pdc_alloc,
+	.free		= irq_domain_free_irqs_common,
+};
+
+int qcom_pdc_init(struct device_node *node,
+		struct device_node *parent, void *data)
+{
+	struct irq_domain *parent_domain;
+	int ret;
+	struct irq_domain *pdc_domain;
+
+	pdc_base = of_iomap(node, 0);
+	if (!pdc_base) {
+		pr_err("%s(): unable to map PDC registers\n", node->full_name);
+		return -ENXIO;
+	}
+
+	parent_domain = irq_find_host(parent);
+	if (!parent_domain) {
+		pr_err("unable to obtain PDC parent domain\n");
+		ret = -ENXIO;
+		goto failure;
+	}
+
+	pdc_domain = irq_domain_add_hierarchy(parent_domain, 0, MAX_IRQS,
+			node, &qcom_pdc_ops, data);
+	if (!pdc_domain) {
+		pr_err("GIC domain add failed\n");
+		ret = -ENOMEM;
+		goto failure;
+	}
+
+	pdc_domain->name = "qcom,pdc";
+
+	return 0;
+
+failure:
+	iounmap(pdc_base);
+
+	return ret;
+}
+EXPORT_SYMBOL(qcom_pdc_init);
diff --git a/drivers/irqchip/qcom/pdc.h b/drivers/irqchip/qcom/pdc.h
new file mode 100644
index 0000000..7c4d89c
--- /dev/null
+++ b/drivers/irqchip/qcom/pdc.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/device.h>
+
+struct pdc_pin {
+	int pin;
+	irq_hw_number_t hwirq;
+};
+
+int qcom_pdc_init(struct device_node *node,
+		struct device_node *parent, void *data);
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index bf2b267..80e3df1 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -961,18 +961,18 @@
 		}
 	}
 
-	r = save_sm_root(md);
-	if (r) {
-		DMERR("%s: save_sm_root failed", __func__);
-		return r;
-	}
-
 	r = dm_tm_pre_commit(md->tm);
 	if (r) {
 		DMERR("%s: pre commit failed", __func__);
 		return r;
 	}
 
+	r = save_sm_root(md);
+	if (r) {
+		DMERR("%s: save_sm_root failed", __func__);
+		return r;
+	}
+
 	r = superblock_lock(md, &sblock);
 	if (r) {
 		DMERR("%s: superblock lock failed", __func__);
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index 2c96542..ba7c4c6 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -997,10 +997,14 @@
 	dm_init_md_queue(md);
 
 	/* backfill 'mq' sysfs registration normally done in blk_register_queue */
-	blk_mq_register_dev(disk_to_dev(md->disk), q);
+	err = blk_mq_register_dev(disk_to_dev(md->disk), q);
+	if (err)
+		goto out_cleanup_queue;
 
 	return 0;
 
+out_cleanup_queue:
+	blk_cleanup_queue(q);
 out_tag_set:
 	blk_mq_free_tag_set(md->tag_set);
 out_kfree_tag_set:
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index d1c05c1..be869a9 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -1070,6 +1070,7 @@
 	 * to unmap (we ignore err).
 	 */
 	queue_passdown_pt2(bio->bi_private);
+	bio_put(bio);
 }
 
 static void process_prepared_discard_passdown_pt1(struct dm_thin_new_mapping *m)
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 76dd1f3..5a4e6e9 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
@@ -59,15 +59,22 @@
 		}
 
 		if (!bubble_state) {
-			CDBG("%s: Sync success: fd 0x%x\n", __func__,
+			CDBG("%s: Sync with success: fd 0x%x\n", __func__,
 				   req_isp->fence_map_out[j].sync_id);
-			cam_sync_signal(req_isp->fence_map_out[j].sync_id,
+			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
 				CAM_SYNC_STATE_SIGNALED_SUCCESS);
+			if (rc)
+				pr_err("%s: Sync failed with rc = %d\n",
+					__func__, rc);
+
 		} else if (!req_isp->bubble_report) {
-			CDBG("%s: Sync failure: fd 0x%x\n", __func__,
+			CDBG("%s: Sync with failure: fd 0x%x\n", __func__,
 				   req_isp->fence_map_out[j].sync_id);
-			cam_sync_signal(req_isp->fence_map_out[j].sync_id,
+			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
 				CAM_SYNC_STATE_SIGNALED_ERROR);
+			if (rc)
+				pr_err("%s: Sync failed with rc = %d\n",
+					__func__, rc);
 		} else {
 			/*
 			 * Ignore the buffer done if bubble detect is on
@@ -277,7 +284,7 @@
 
 	ctx_isp->frame_id++;
 	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
-	pr_err("%s: next substate %d\n", __func__,
+	CDBG("%s: next substate %d\n", __func__,
 		ctx_isp->substate_activated);
 
 	return rc;
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 259e773..49085d7 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
@@ -1493,19 +1493,6 @@
 	if (i == ctx->num_base)
 		master_base_idx = ctx->base[0].idx;
 
-	/* Stop the master CIDs first */
-	cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid,
-			master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
-
-	/* stop rest of the CIDs  */
-	for (i = 0; i < ctx->num_base; i++) {
-		if (i == master_base_idx)
-			continue;
-		cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid,
-			ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
-	}
-
-
 	/* Stop the master CSID path first */
 	cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
 			master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
@@ -1519,6 +1506,18 @@
 			ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
 	}
 
+	/* Stop the master CIDs first */
+	cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid,
+			master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+
+	/* stop rest of the CIDs  */
+	for (i = 0; i < ctx->num_base; i++) {
+		if (i == master_base_idx)
+			continue;
+		cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid,
+			ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+	}
+
 	if (cam_cdm_stream_off(ctx->cdm_handle))
 		pr_err("%s%d: CDM stream off failed %d\n",
 			__func__, __LINE__, ctx->cdm_handle);
@@ -2884,7 +2883,7 @@
 	int i, j;
 	struct cam_iommu_handle cdm_handles;
 
-	pr_info("%s: Enter\n", __func__);
+	CDBG("%s: Enter\n", __func__);
 
 	memset(&g_ife_hw_mgr, 0, sizeof(g_ife_hw_mgr));
 
@@ -3037,7 +3036,7 @@
 	hw_mgr_intf->hw_prepare_update = cam_ife_mgr_prepare_hw_update;
 	hw_mgr_intf->hw_config = cam_ife_mgr_config_hw;
 
-	pr_info("%s: Exit\n", __func__);
+	CDBG("%s: Exit\n", __func__);
 	return 0;
 end:
 	if (rc) {
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 6306df3..3ec9aa6 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
@@ -1133,7 +1133,7 @@
 	if (rc)
 		return rc;
 
-	/**
+	/*
 	 * configure the IPP and enable the time stamp capture.
 	 * enable the HW measrurement blocks
 	 */
@@ -1417,7 +1417,7 @@
 	if (rc)
 		return rc;
 
-	/**
+	/*
 	 * RDI path config and enable the time stamp capture
 	 * Enable the measurement blocks
 	 */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index 7a03bdc..c837232 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -974,7 +974,7 @@
 						del_req_id, rc);
 			}
 		} else {
-			pr_err("%s:%d Invalid/NOP request to apply: %lld\n",
+			CDBG("%s:%d Invalid/NOP request to apply: %lld\n",
 				__func__, __LINE__, req_id);
 		}
 	}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c
index 1709fd3..40a69ef 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c
@@ -146,11 +146,9 @@
 	for (i = 0; i < delay_ms; i++) {
 		rc = cam_cci_i2c_compare(client,
 			addr, data, data_mask, data_type, addr_type);
-		if (!rc) {
-			pr_err("%s:%d Fail in comparing the data in poll\n",
-				__func__, __LINE__);
+		if (!rc)
 			return rc;
-		}
+
 		usleep_range(1000, 1010);
 	}
 
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 34243e6..15b8a2d 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
@@ -227,9 +227,10 @@
 {
 	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
 	u32 ot_lim;
-	u32 reg_off_vbif_lim_conf = (params->xin_id / 4) * 4 +
-		params->reg_off_vbif_lim_conf;
-	u32 bit_off_vbif_lim_conf = (params->xin_id % 4) * 8;
+	u32 reg_off_vbif_lim_conf = ((params->xin_id / mdata->npriority_lvl)
+					* mdata->npriority_lvl)
+					+ params->reg_off_vbif_lim_conf;
+	u32 bit_off_vbif_lim_conf = (params->xin_id % mdata->npriority_lvl) * 8;
 	u32 reg_val;
 	u32 sts;
 	bool forced_on;
@@ -420,6 +421,136 @@
 	}
 }
 
+static void sde_mdp_parse_cdp_setting(struct platform_device *pdev,
+		struct sde_rot_data_type *mdata)
+{
+	int rc;
+	u32 len, data[SDE_ROT_OP_MAX] = {0};
+
+	len = sde_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-rot-cdp-setting");
+	if (len == SDE_ROT_OP_MAX) {
+		rc = sde_mdp_parse_dt_handler(pdev,
+			"qcom,mdss-rot-cdp-setting", data, len);
+		if (rc) {
+			SDEROT_ERR("invalid CDP setting\n");
+			goto end;
+		}
+
+		set_bit(SDE_QOS_CDP, mdata->sde_qos_map);
+		mdata->enable_cdp[SDE_ROT_RD] = data[SDE_ROT_RD];
+		mdata->enable_cdp[SDE_ROT_WR] = data[SDE_ROT_WR];
+		return;
+	}
+end:
+	clear_bit(SDE_QOS_CDP, mdata->sde_qos_map);
+}
+
+static void sde_mdp_parse_rot_lut_setting(struct platform_device *pdev,
+		struct sde_rot_data_type *mdata)
+{
+	int rc;
+	u32 len, data[4];
+
+	len = sde_mdp_parse_dt_prop_len(pdev, "qcom,mdss-rot-qos-lut");
+	if (len == 4) {
+		rc = sde_mdp_parse_dt_handler(pdev,
+			"qcom,mdss-rot-qos-lut", data, len);
+		if (!rc) {
+			mdata->lut_cfg[SDE_ROT_RD].creq_lut_0 = data[0];
+			mdata->lut_cfg[SDE_ROT_RD].creq_lut_1 = data[1];
+			mdata->lut_cfg[SDE_ROT_WR].creq_lut_0 = data[2];
+			mdata->lut_cfg[SDE_ROT_WR].creq_lut_1 = data[3];
+			set_bit(SDE_QOS_LUT, mdata->sde_qos_map);
+		} else {
+			SDEROT_DBG("qos lut setting not found\n");
+		}
+	}
+
+	len = sde_mdp_parse_dt_prop_len(pdev, "qcom,mdss-rot-danger-lut");
+	if (len == SDE_ROT_OP_MAX) {
+		rc = sde_mdp_parse_dt_handler(pdev,
+			"qcom,mdss-rot-danger-lut", data, len);
+		if (!rc) {
+			mdata->lut_cfg[SDE_ROT_RD].danger_lut
+							= data[SDE_ROT_RD];
+			mdata->lut_cfg[SDE_ROT_WR].danger_lut
+							= data[SDE_ROT_WR];
+			set_bit(SDE_QOS_DANGER_LUT, mdata->sde_qos_map);
+		} else {
+			SDEROT_DBG("danger lut setting not found\n");
+		}
+	}
+
+	len = sde_mdp_parse_dt_prop_len(pdev, "qcom,mdss-rot-safe-lut");
+	if (len == SDE_ROT_OP_MAX) {
+		rc = sde_mdp_parse_dt_handler(pdev,
+			"qcom,mdss-rot-safe-lut", data, len);
+		if (!rc) {
+			mdata->lut_cfg[SDE_ROT_RD].safe_lut = data[SDE_ROT_RD];
+			mdata->lut_cfg[SDE_ROT_WR].safe_lut = data[SDE_ROT_WR];
+			set_bit(SDE_QOS_SAFE_LUT, mdata->sde_qos_map);
+		} else {
+			SDEROT_DBG("safe lut setting not found\n");
+		}
+	}
+}
+
+static void sde_mdp_parse_inline_rot_lut_setting(struct platform_device *pdev,
+		struct sde_rot_data_type *mdata)
+{
+	int rc;
+	u32 len, data[4];
+
+	len = sde_mdp_parse_dt_prop_len(pdev, "qcom,mdss-inline-rot-qos-lut");
+	if (len == 4) {
+		rc = sde_mdp_parse_dt_handler(pdev,
+			"qcom,mdss-inline-rot-qos-lut", data, len);
+		if (!rc) {
+			mdata->inline_lut_cfg[SDE_ROT_RD].creq_lut_0 = data[0];
+			mdata->inline_lut_cfg[SDE_ROT_RD].creq_lut_1 = data[1];
+			mdata->inline_lut_cfg[SDE_ROT_WR].creq_lut_0 = data[2];
+			mdata->inline_lut_cfg[SDE_ROT_WR].creq_lut_1 = data[3];
+			set_bit(SDE_INLINE_QOS_LUT, mdata->sde_inline_qos_map);
+		} else {
+			SDEROT_DBG("inline qos lut setting not found\n");
+		}
+	}
+
+	len = sde_mdp_parse_dt_prop_len(pdev,
+				"qcom,mdss-inline-rot-danger-lut");
+	if (len == SDE_ROT_OP_MAX) {
+		rc = sde_mdp_parse_dt_handler(pdev,
+			"qcom,mdss-inline-rot-danger-lut", data, len);
+		if (!rc) {
+			mdata->inline_lut_cfg[SDE_ROT_RD].danger_lut
+							= data[SDE_ROT_RD];
+			mdata->inline_lut_cfg[SDE_ROT_WR].danger_lut
+							= data[SDE_ROT_WR];
+			set_bit(SDE_INLINE_QOS_DANGER_LUT,
+					mdata->sde_inline_qos_map);
+		} else {
+			SDEROT_DBG("inline danger lut setting not found\n");
+		}
+	}
+
+	len = sde_mdp_parse_dt_prop_len(pdev, "qcom,mdss-inline-rot-safe-lut");
+	if (len == SDE_ROT_OP_MAX) {
+		rc = sde_mdp_parse_dt_handler(pdev,
+			"qcom,mdss-inline-rot-safe-lut", data, len);
+		if (!rc) {
+			mdata->inline_lut_cfg[SDE_ROT_RD].safe_lut
+							= data[SDE_ROT_RD];
+			mdata->inline_lut_cfg[SDE_ROT_WR].safe_lut
+							= data[SDE_ROT_WR];
+			set_bit(SDE_INLINE_QOS_SAFE_LUT,
+					mdata->sde_inline_qos_map);
+		} else {
+			SDEROT_DBG("inline safe lut setting not found\n");
+		}
+	}
+}
+
 static int sde_mdp_parse_dt_misc(struct platform_device *pdev,
 		struct sde_rot_data_type *mdata)
 {
@@ -444,8 +575,14 @@
 		SDEROT_DBG(
 			"Could not read optional property: highest bank bit\n");
 
+	sde_mdp_parse_cdp_setting(pdev, mdata);
+
 	sde_mdp_parse_vbif_qos(pdev, mdata);
 
+	sde_mdp_parse_rot_lut_setting(pdev, mdata);
+
+	sde_mdp_parse_inline_rot_lut_setting(pdev, mdata);
+
 	mdata->mdp_base = mdata->sde_io.base + SDE_MDP_OFFSET;
 
 	return 0;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
index 9194b44..313c709 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
@@ -40,6 +40,9 @@
 #define SDE_MDP_HW_REV_301	SDE_MDP_REV(3, 0, 1)	/* 8998 v1.1 */
 #define SDE_MDP_HW_REV_400	SDE_MDP_REV(4, 0, 0)	/* sdm845 v1.0 */
 
+#define SDE_MDP_VBIF_4_LEVEL_REMAPPER	4
+#define SDE_MDP_VBIF_8_LEVEL_REMAPPER	8
+
 struct sde_mult_factor {
 	uint32_t numer;
 	uint32_t denom;
@@ -77,9 +80,19 @@
 	SDE_QOS_PER_PIPE_LUT,
 	SDE_QOS_SIMPLIFIED_PREFILL,
 	SDE_QOS_VBLANK_PANIC_CTRL,
+	SDE_QOS_LUT,
+	SDE_QOS_DANGER_LUT,
+	SDE_QOS_SAFE_LUT,
 	SDE_QOS_MAX,
 };
 
+enum sde_inline_qos_settings {
+	SDE_INLINE_QOS_LUT,
+	SDE_INLINE_QOS_DANGER_LUT,
+	SDE_INLINE_QOS_SAFE_LUT,
+	SDE_INLINE_QOS_MAX,
+};
+
 /**
  * enum sde_rot_type: SDE rotator HW version
  * @SDE_ROT_TYPE_V1_0: V1.0 HW version
@@ -98,6 +111,7 @@
  * @SDE_CAPS_R3_1P5_DOWNSCALE: 1.5x downscale rotator support
  * @SDE_CAPS_SBUF_1: stream buffer support for inline rotation
  * @SDE_CAPS_UBWC_2: universal bandwidth compression version 2
+ * @SDE_CAPS_PARTIALWR: partial write override
  */
 enum sde_caps_settings {
 	SDE_CAPS_R1_WB,
@@ -106,6 +120,7 @@
 	SDE_CAPS_SEC_ATTACH_DETACH_SMMU,
 	SDE_CAPS_SBUF_1,
 	SDE_CAPS_UBWC_2,
+	SDE_CAPS_PARTIALWR,
 	SDE_CAPS_MAX,
 };
 
@@ -115,6 +130,12 @@
 	SDE_MAX_BUS_CLIENTS
 };
 
+enum sde_rot_op {
+	SDE_ROT_RD,
+	SDE_ROT_WR,
+	SDE_ROT_OP_MAX
+};
+
 enum sde_rot_regdump_access {
 	SDE_ROT_REGDUMP_READ,
 	SDE_ROT_REGDUMP_WRITE,
@@ -165,6 +186,13 @@
 	enum sde_rot_regdump_access access;
 };
 
+struct sde_rot_lut_cfg {
+	u32 creq_lut_0;
+	u32 creq_lut_1;
+	u32 danger_lut;
+	u32 safe_lut;
+};
+
 struct sde_rot_data_type {
 	u32 mdss_version;
 
@@ -177,6 +205,7 @@
 
 	/* bitmap to track qos applicable settings */
 	DECLARE_BITMAP(sde_qos_map, SDE_QOS_MAX);
+	DECLARE_BITMAP(sde_inline_qos_map, SDE_QOS_MAX);
 
 	/* bitmap to track capability settings */
 	DECLARE_BITMAP(sde_caps_map, SDE_CAPS_MAX);
@@ -210,6 +239,11 @@
 	void *sde_rot_hw;
 	int sec_cam_en;
 
+	u32 enable_cdp[SDE_ROT_OP_MAX];
+
+	struct sde_rot_lut_cfg lut_cfg[SDE_ROT_OP_MAX];
+	struct sde_rot_lut_cfg inline_lut_cfg[SDE_ROT_OP_MAX];
+
 	struct ion_client *iclient;
 
 	bool clk_always_on;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index 30fda07..b3dc213 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -60,6 +60,9 @@
 /* waiting for hw time out, 3 vsync for 30fps*/
 #define ROT_HW_ACQUIRE_TIMEOUT_IN_MS 100
 
+/* waiting for inline hw start */
+#define ROT_INLINE_START_TIMEOUT_IN_MS 2000
+
 /* default pixel per clock ratio */
 #define ROT_PIXEL_PER_CLK_NUMERATOR	36
 #define ROT_PIXEL_PER_CLK_DENOMINATOR	10
@@ -1508,6 +1511,8 @@
 	if (entry->item.ts)
 		entry->item.ts[SDE_ROTATOR_TS_FLUSH] = ktime_get();
 
+	SDEROT_EVTLOG(entry->item.session_id, 1);
+
 	queue_work(entry->doneq->rot_work_queue, &entry->done_work);
 	sde_rot_mgr_unlock(mgr);
 	return;
@@ -1564,6 +1569,13 @@
 		entry->item.flags,
 		entry->dnsc_factor_w, entry->dnsc_factor_h);
 
+	wait_for_completion_timeout(
+			&entry->item.inline_start,
+			msecs_to_jiffies(ROT_INLINE_START_TIMEOUT_IN_MS));
+
+	if (entry->item.ts)
+		entry->item.ts[SDE_ROTATOR_TS_START] = ktime_get();
+
 	SDEROT_EVTLOG(entry->item.session_id, 0);
 	ret = mgr->ops_wait_for_entry(hw, entry);
 	if (ret) {
@@ -2332,11 +2344,36 @@
 	for (i = 0; i < count; i++) {
 		req->entries[i].item = items[i];
 		req->entries[i].private = private;
+
+		init_completion(&req->entries[i].item.inline_start);
+		complete_all(&req->entries[i].item.inline_start);
 	}
 
 	return req;
 }
 
+void sde_rotator_req_reset_start(struct sde_rot_entry_container *req)
+{
+	int i;
+
+	if (!req)
+		return;
+
+	for (i = 0; i < req->count; i++)
+		reinit_completion(&req->entries[i].item.inline_start);
+}
+
+void sde_rotator_req_set_start(struct sde_rot_entry_container *req)
+{
+	int i;
+
+	if (!req)
+		return;
+
+	for (i = 0; i < req->count; i++)
+		complete_all(&req->entries[i].item.inline_start);
+}
+
 void sde_rotator_req_finish(struct sde_rot_mgr *mgr,
 	struct sde_rot_file_private *private,
 	struct sde_rot_entry_container *req)
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
index 0051e96..7b8a066 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
@@ -21,6 +21,7 @@
 #include <linux/types.h>
 #include <linux/cdev.h>
 #include <linux/pm_runtime.h>
+#include <linux/completion.h>
 
 #include "sde_rotator_base.h"
 #include "sde_rotator_util.h"
@@ -115,6 +116,7 @@
 	SDE_ROTATOR_TS_QUEUE,		/* wait for h/w resource */
 	SDE_ROTATOR_TS_COMMIT,		/* prepare h/w command */
 	SDE_ROTATOR_TS_FLUSH,		/* initiate h/w processing */
+	SDE_ROTATOR_TS_START,		/* h/w triggered (if inline) */
 	SDE_ROTATOR_TS_DONE,		/* receive h/w completion */
 	SDE_ROTATOR_TS_RETIRE,		/* signal destination buffer fence */
 	SDE_ROTATOR_TS_SRCDQB,		/* dequeue source buffer */
@@ -199,6 +201,9 @@
 
 	/* Time stamp for profiling purposes */
 	ktime_t		*ts;
+
+	/* Completion structure for inline rotation */
+	struct completion inline_start;
 };
 
 /*
@@ -604,6 +609,23 @@
 	u32 count, u32 flags);
 
 /*
+ * sde_rotator_req_reset_start - reset inline h/w 'start' indicator
+ *	For inline rotations, the time of rotation start is not controlled
+ *	by the rotator driver. This function resets an internal 'start'
+ *	indicator that allows the rotator to delay its rotator
+ *	timeout waiting until such time as the inline rotation has
+ *	really started.
+ * @req: Pointer to rotation request
+ */
+void sde_rotator_req_reset_start(struct sde_rot_entry_container *req);
+
+/*
+ * sde_rotator_req_set_start - set inline h/w 'start' indicator
+ * @req: Pointer to rotation request
+ */
+void sde_rotator_req_set_start(struct sde_rot_entry_container *req);
+
+/*
  * sde_rotator_req_finish - notify manager that client is finished with the
  *	given request and manager can release the request as required
  * @rot_dev: Pointer to rotator device
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
index e9ff67c..3e686e9 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
@@ -789,7 +789,7 @@
 					start_time));
 
 		seq_printf(s,
-			"s:%d sq:%lld dq:%lld fe:%lld q:%lld c:%lld fl:%lld d:%lld sdq:%lld ddq:%lld t:%lld oht:%lld\n",
+			"s:%d sq:%lld dq:%lld fe:%lld q:%lld c:%lld fl:%lld st:%lld d:%lld sdq:%lld ddq:%lld t:%lld oht:%lld\n",
 			i,
 			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_FENCE],
 					ts[SDE_ROTATOR_TS_SRCQB])),
@@ -801,8 +801,10 @@
 					ts[SDE_ROTATOR_TS_QUEUE])),
 			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_FLUSH],
 					ts[SDE_ROTATOR_TS_COMMIT])),
-			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_DONE],
+			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_START],
 					ts[SDE_ROTATOR_TS_FLUSH])),
+			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_DONE],
+					ts[SDE_ROTATOR_TS_START])),
 			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_RETIRE],
 					ts[SDE_ROTATOR_TS_DONE])),
 			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_SRCDQB],
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index 90b7194..2e91d54 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -1467,7 +1467,9 @@
 		int scid = llcc_get_slice_id(ctx->slice);
 
 		/* allocate slot for timestamp */
-		ts = stats->ts[stats->count++ % SDE_ROTATOR_NUM_EVENTS];
+		ts = stats->ts[stats->count % SDE_ROTATOR_NUM_EVENTS];
+		if (cmd_type == SDE_ROTATOR_INLINE_CMD_COMMIT)
+			stats->count++;
 
 		if (cmd->rot90)
 			flags |= SDE_ROTATION_90;
@@ -1637,6 +1639,8 @@
 			goto error_handle_request;
 		}
 
+		sde_rotator_req_reset_start(req);
+
 		sde_rotator_commit_request(rot_dev->mgr, ctx->private, req);
 
 		request->committed = true;
@@ -1644,6 +1648,15 @@
 		/* save request in private handle */
 		cmd->priv_handle = request;
 
+	} else if (cmd_type == SDE_ROTATOR_INLINE_CMD_START) {
+		if (!cmd->priv_handle) {
+			ret = -EINVAL;
+			SDEROT_ERR("invalid private handle\n");
+			goto error_invalid_handle;
+		}
+
+		request = cmd->priv_handle;
+		sde_rotator_req_set_start(request->req);
 	} else if (cmd_type == SDE_ROTATOR_INLINE_CMD_CLEANUP) {
 		if (!cmd->priv_handle) {
 			ret = -EINVAL;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_hwio.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_hwio.h
index 051db78..de448a4 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_hwio.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_hwio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -65,6 +65,8 @@
 #define MMSS_VBIF_NRT_VBIF_IN_WR_LIM_CONF2		0x00C8
 #define MMSS_VBIF_NRT_VBIF_OUT_RD_LIM_CONF0		0x00D0
 #define MMSS_VBIF_NRT_VBIF_OUT_WR_LIM_CONF0		0x00D4
+#define MMSS_VBIF_NRT_VBIF_QOS_RP_REMAP_000		0x0550
+#define MMSS_VBIF_NRT_VBIF_QOS_LVL_REMAP_000		0x0590
 
 #define SDE_MDP_REG_TRAFFIC_SHAPER_EN			BIT(31)
 #define SDE_MDP_REG_TRAFFIC_SHAPER_RD_CLIENT(num)	(0x030 + (num * 4))
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h
index 27fd0c3..705eb27 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h
@@ -25,11 +25,13 @@
  * enum sde_rotator_inline_cmd_type - inline rotator command stages
  * @SDE_ROTATOR_INLINE_CMD_VALIDATE: validate command only
  * @SDE_ROTATOR_INLINE_CMD_COMMIT: commit command to hardware
+ * @SDE_ROTATOR_INLINE_CMD_START: ready to start inline rotation
  * @SDE_ROTATOR_INLINE_CMD_CLEANUP: cleanup after commit is done
  */
 enum sde_rotator_inline_cmd_type {
 	SDE_ROTATOR_INLINE_CMD_VALIDATE,
 	SDE_ROTATOR_INLINE_CMD_COMMIT,
+	SDE_ROTATOR_INLINE_CMD_START,
 	SDE_ROTATOR_INLINE_CMD_CLEANUP,
 };
 
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index 980df9f..6ebfc1a 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -493,6 +493,12 @@
 		SDE_ROT_REGDUMP_VBIF },
 };
 
+struct sde_rot_cdp_params {
+	bool enable;
+	struct sde_mdp_format_params *fmt;
+	u32 offset;
+};
+
 /* Invalid software timestamp value for initialization */
 #define SDE_REGDMA_SWTS_INVALID	(~0)
 
@@ -741,6 +747,76 @@
 }
 
 /*
+ * sde_hw_rotator_vbif_setting - helper function to set vbif QoS remapper
+ * levels, enable write gather enable and avoid clk gating setting for
+ * debug purpose.
+ *
+ * @rot: Pointer to rotator hw
+ */
+static void sde_hw_rotator_vbif_setting(struct sde_hw_rotator *rot)
+{
+	u32 i, mask, vbif_qos, reg_val = 0;
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+
+	/* VBIF_ROT QoS remapper setting */
+	switch (mdata->npriority_lvl) {
+
+	case SDE_MDP_VBIF_4_LEVEL_REMAPPER:
+		for (i = 0; i < mdata->npriority_lvl; i++) {
+			reg_val = SDE_VBIF_READ(mdata,
+					MMSS_VBIF_NRT_VBIF_QOS_REMAP_00 + i*4);
+			mask = 0x3 << (XIN_SSPP * 2);
+			vbif_qos = mdata->vbif_nrt_qos[i];
+			reg_val |= vbif_qos << (XIN_SSPP * 2);
+			/* ensure write is issued after the read operation */
+			mb();
+			SDE_VBIF_WRITE(mdata,
+					MMSS_VBIF_NRT_VBIF_QOS_REMAP_00 + i*4,
+					reg_val);
+		}
+		break;
+
+	case SDE_MDP_VBIF_8_LEVEL_REMAPPER:
+		mask = mdata->npriority_lvl - 1;
+		for (i = 0; i < mdata->npriority_lvl; i++) {
+			/* RD and WR client */
+			reg_val |= (mdata->vbif_nrt_qos[i] & mask)
+							<< (XIN_SSPP * 4);
+			reg_val |= (mdata->vbif_nrt_qos[i] & mask)
+							<< (XIN_WRITEBACK * 4);
+
+			SDE_VBIF_WRITE(mdata,
+				MMSS_VBIF_NRT_VBIF_QOS_RP_REMAP_000 + i*8,
+				reg_val);
+			SDE_VBIF_WRITE(mdata,
+				MMSS_VBIF_NRT_VBIF_QOS_LVL_REMAP_000 + i*8,
+				reg_val);
+		}
+		break;
+
+	default:
+		SDEROT_DBG("invalid vbif remapper levels\n");
+	}
+
+	/* Enable write gather for writeback to remove write gaps, which
+	 * may hang AXI/BIMC/SDE.
+	 */
+	SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_WRITE_GATHTER_EN,
+			BIT(XIN_WRITEBACK));
+
+	/*
+	 * For debug purpose, disable clock gating, i.e. Clocks always on
+	 */
+	if (mdata->clk_always_on) {
+		SDE_VBIF_WRITE(mdata, MMSS_VBIF_CLKON, 0x3);
+		SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0, 0x3);
+		SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL1,
+				0xFFFF);
+		SDE_ROTREG_WRITE(rot->mdss_base, ROTTOP_CLK_CTRL, 1);
+	}
+}
+
+/*
  * sde_hw_rotator_setup_timestamp_packet - setup timestamp writeback command
  * @ctx: Pointer to rotator context
  * @mask: Bit mask location of the timestamp
@@ -796,6 +872,156 @@
 }
 
 /*
+ * sde_hw_rotator_cdp_configs - configures the CDP registers
+ * @ctx: Pointer to rotator context
+ * @params: Pointer to parameters needed for CDP configs
+ */
+static void sde_hw_rotator_cdp_configs(struct sde_hw_rotator_context *ctx,
+		struct sde_rot_cdp_params *params)
+{
+	int reg_val;
+	u32 *wrptr = sde_hw_rotator_get_regdma_segment(ctx);
+
+	if (!params->enable) {
+		SDE_REGDMA_WRITE(wrptr, params->offset, 0x0);
+		goto end;
+	}
+
+	reg_val = BIT(0); /* enable cdp */
+
+	if (sde_mdp_is_ubwc_format(params->fmt))
+		reg_val |= BIT(1); /* enable UBWC meta cdp */
+
+	if (sde_mdp_is_ubwc_format(params->fmt)
+			|| sde_mdp_is_tilea4x_format(params->fmt)
+			|| sde_mdp_is_tilea5x_format(params->fmt))
+		reg_val |= BIT(2); /* enable tile amortize */
+
+	reg_val |= BIT(3); /* enable preload addr ahead cnt 64 */
+
+	SDE_REGDMA_WRITE(wrptr, params->offset, reg_val);
+
+end:
+	sde_hw_rotator_put_regdma_segment(ctx, wrptr);
+}
+
+/*
+ * sde_hw_rotator_setup_qos_lut_wr - Set QoS LUT/Danger LUT/Safe LUT configs
+ * for the WRITEBACK rotator for inline and offline rotation.
+ *
+ * @ctx: Pointer to rotator context
+ */
+static void sde_hw_rotator_setup_qos_lut_wr(struct sde_hw_rotator_context *ctx)
+{
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+	u32 *wrptr = sde_hw_rotator_get_regdma_segment(ctx);
+
+	/* Offline rotation setting */
+	if (!ctx->sbuf_mode) {
+		/* QOS LUT WR setting */
+		if (test_bit(SDE_QOS_LUT, mdata->sde_qos_map)) {
+			SDE_REGDMA_WRITE(wrptr, ROT_WB_CREQ_LUT_0,
+					mdata->lut_cfg[SDE_ROT_WR].creq_lut_0);
+			SDE_REGDMA_WRITE(wrptr, ROT_WB_CREQ_LUT_1,
+					mdata->lut_cfg[SDE_ROT_WR].creq_lut_1);
+		}
+
+		/* Danger LUT WR setting */
+		if (test_bit(SDE_QOS_DANGER_LUT, mdata->sde_qos_map))
+			SDE_REGDMA_WRITE(wrptr, ROT_WB_DANGER_LUT,
+					mdata->lut_cfg[SDE_ROT_WR].danger_lut);
+
+		/* Safe LUT WR setting */
+		if (test_bit(SDE_QOS_SAFE_LUT, mdata->sde_qos_map))
+			SDE_REGDMA_WRITE(wrptr, ROT_WB_SAFE_LUT,
+					mdata->lut_cfg[SDE_ROT_WR].safe_lut);
+
+	/* Inline rotation setting */
+	} else {
+		/* QOS LUT WR setting */
+		if (test_bit(SDE_INLINE_QOS_LUT, mdata->sde_inline_qos_map)) {
+			SDE_REGDMA_WRITE(wrptr, ROT_WB_CREQ_LUT_0,
+				mdata->inline_lut_cfg[SDE_ROT_WR].creq_lut_0);
+			SDE_REGDMA_WRITE(wrptr, ROT_WB_CREQ_LUT_1,
+				mdata->inline_lut_cfg[SDE_ROT_WR].creq_lut_1);
+		}
+
+		/* Danger LUT WR setting */
+		if (test_bit(SDE_INLINE_QOS_DANGER_LUT,
+					mdata->sde_inline_qos_map))
+			SDE_REGDMA_WRITE(wrptr, ROT_WB_DANGER_LUT,
+				mdata->inline_lut_cfg[SDE_ROT_WR].danger_lut);
+
+		/* Safe LUT WR setting */
+		if (test_bit(SDE_INLINE_QOS_SAFE_LUT,
+					mdata->sde_inline_qos_map))
+			SDE_REGDMA_WRITE(wrptr, ROT_WB_SAFE_LUT,
+				mdata->inline_lut_cfg[SDE_ROT_WR].safe_lut);
+	}
+
+	/* Update command queue write ptr */
+	sde_hw_rotator_put_regdma_segment(ctx, wrptr);
+}
+
+/*
+ * sde_hw_rotator_setup_qos_lut_rd - Set QoS LUT/Danger LUT/Safe LUT configs
+ * for the SSPP rotator for inline and offline rotation.
+ *
+ * @ctx: Pointer to rotator context
+ */
+static void sde_hw_rotator_setup_qos_lut_rd(struct sde_hw_rotator_context *ctx)
+{
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+	u32 *wrptr = sde_hw_rotator_get_regdma_segment(ctx);
+
+	/* Offline rotation setting */
+	if (!ctx->sbuf_mode) {
+		/* QOS LUT RD setting */
+		if (test_bit(SDE_QOS_LUT, mdata->sde_qos_map)) {
+			SDE_REGDMA_WRITE(wrptr, ROT_SSPP_CREQ_LUT_0,
+					mdata->lut_cfg[SDE_ROT_RD].creq_lut_0);
+			SDE_REGDMA_WRITE(wrptr, ROT_SSPP_CREQ_LUT_1,
+					mdata->lut_cfg[SDE_ROT_RD].creq_lut_1);
+		}
+
+		/* Danger LUT RD setting */
+		if (test_bit(SDE_QOS_DANGER_LUT, mdata->sde_qos_map))
+			SDE_REGDMA_WRITE(wrptr, ROT_SSPP_DANGER_LUT,
+					mdata->lut_cfg[SDE_ROT_RD].danger_lut);
+
+		/* Safe LUT RD setting */
+		if (test_bit(SDE_QOS_SAFE_LUT, mdata->sde_qos_map))
+			SDE_REGDMA_WRITE(wrptr, ROT_SSPP_SAFE_LUT,
+					mdata->lut_cfg[SDE_ROT_RD].safe_lut);
+
+	/* inline rotation setting */
+	} else {
+		/* QOS LUT RD setting */
+		if (test_bit(SDE_INLINE_QOS_LUT, mdata->sde_inline_qos_map)) {
+			SDE_REGDMA_WRITE(wrptr, ROT_SSPP_CREQ_LUT_0,
+				mdata->inline_lut_cfg[SDE_ROT_RD].creq_lut_0);
+			SDE_REGDMA_WRITE(wrptr, ROT_SSPP_CREQ_LUT_1,
+				mdata->inline_lut_cfg[SDE_ROT_RD].creq_lut_1);
+		}
+
+		/* Danger LUT RD setting */
+		if (test_bit(SDE_INLINE_QOS_DANGER_LUT,
+					mdata->sde_inline_qos_map))
+			SDE_REGDMA_WRITE(wrptr, ROT_SSPP_DANGER_LUT,
+				mdata->inline_lut_cfg[SDE_ROT_RD].danger_lut);
+
+		/* Safe LUT RD setting */
+		if (test_bit(SDE_INLINE_QOS_SAFE_LUT,
+					mdata->sde_inline_qos_map))
+			SDE_REGDMA_WRITE(wrptr, ROT_SSPP_SAFE_LUT,
+				mdata->inline_lut_cfg[SDE_ROT_RD].safe_lut);
+	}
+
+	/* Update command queue write ptr */
+	sde_hw_rotator_put_regdma_segment(ctx, wrptr);
+}
+
+/*
  * sde_hw_rotator_setup_fetchengine - setup fetch engine
  * @ctx: Pointer to rotator context
  * @queue_id: Priority queue identifier
@@ -814,6 +1040,7 @@
 	struct sde_hw_rotator *rot = ctx->rot;
 	struct sde_mdp_format_params *fmt;
 	struct sde_mdp_data *data;
+	struct sde_rot_cdp_params cdp_params = {0};
 	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
 	u32 *wrptr;
 	u32 opmode = 0;
@@ -985,13 +1212,29 @@
 		ctx->is_secure = false;
 	}
 
+	/* Update command queue write ptr */
+	sde_hw_rotator_put_regdma_segment(ctx, wrptr);
+
+	/* CDP register RD setting */
+	cdp_params.enable = test_bit(SDE_QOS_CDP, mdata->sde_qos_map) ?
+					 mdata->enable_cdp[SDE_ROT_RD] : false;
+	cdp_params.fmt = fmt;
+	cdp_params.offset = ROT_SSPP_CDP_CNTL;
+	sde_hw_rotator_cdp_configs(ctx, &cdp_params);
+
+	/* QOS LUT/ Danger LUT/ Safe Lut WR setting */
+	sde_hw_rotator_setup_qos_lut_rd(ctx);
+
+	wrptr = sde_hw_rotator_get_regdma_segment(ctx);
+
 	/*
 	 * Determine if traffic shaping is required. Only enable traffic
 	 * shaping when content is 4k@30fps. The actual traffic shaping
 	 * bandwidth calculation is done in output setup.
 	 */
-	if (((cfg->src_rect->w * cfg->src_rect->h) >= RES_UHD) &&
-			(cfg->fps <= 30)) {
+	if (((!ctx->sbuf_mode)
+			&& (cfg->src_rect->w * cfg->src_rect->h) >= RES_UHD)
+			&& (cfg->fps <= 30)) {
 		SDEROT_DBG("Enable Traffic Shaper\n");
 		ctx->is_traffic_shaping = true;
 	} else {
@@ -1017,9 +1260,11 @@
 {
 	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
 	struct sde_mdp_format_params *fmt;
+	struct sde_rot_cdp_params cdp_params = {0};
 	u32 *wrptr;
 	u32 pack = 0;
 	u32 dst_format = 0;
+	u32 partial_write = 0;
 	int i;
 
 	wrptr = sde_hw_rotator_get_regdma_segment(ctx);
@@ -1103,8 +1348,13 @@
 			cfg->v_downscale_factor |
 			(cfg->h_downscale_factor << 16));
 
+	/* partial write check */
+	if (test_bit(SDE_CAPS_PARTIALWR, mdata->sde_caps_map) &&
+			!sde_mdp_is_ubwc_format(fmt))
+		partial_write = BIT(10);
+
 	/* write config setup for bank configuration */
-	SDE_REGDMA_WRITE(wrptr, ROT_WB_DST_WRITE_CONFIG,
+	SDE_REGDMA_WRITE(wrptr, ROT_WB_DST_WRITE_CONFIG, partial_write |
 			(ctx->rot->highest_bank & 0x3) << 8);
 
 	if (test_bit(SDE_CAPS_UBWC_2, mdata->sde_caps_map))
@@ -1120,8 +1370,23 @@
 	SDE_REGDMA_WRITE(wrptr, ROTTOP_OP_MODE, ctx->op_mode |
 			(flags & SDE_ROT_FLAG_ROT_90 ? BIT(1) : 0) | BIT(0));
 
+	sde_hw_rotator_put_regdma_segment(ctx, wrptr);
+
+	/* CDP register WR setting */
+	cdp_params.enable = test_bit(SDE_QOS_CDP, mdata->sde_qos_map) ?
+					mdata->enable_cdp[SDE_ROT_WR] : false;
+	cdp_params.fmt = fmt;
+	cdp_params.offset = ROT_WB_CDP_CNTL;
+	sde_hw_rotator_cdp_configs(ctx, &cdp_params);
+
+	/* QOS LUT/ Danger LUT/ Safe LUT WR setting */
+	sde_hw_rotator_setup_qos_lut_wr(ctx);
+
+	wrptr = sde_hw_rotator_get_regdma_segment(ctx);
+
 	/* setup traffic shaper for 4k 30fps content or if prefill_bw is set */
-	if (ctx->is_traffic_shaping || cfg->prefill_bw) {
+	if (!ctx->sbuf_mode &&
+			(ctx->is_traffic_shaping || cfg->prefill_bw)) {
 		u32 bw;
 
 		/*
@@ -2136,7 +2401,7 @@
 			item->input.format, item->output.format,
 			entry->perf->config.frame_rate);
 
-	if (mdata->default_ot_rd_limit) {
+	if (!ctx->sbuf_mode && mdata->default_ot_rd_limit) {
 		struct sde_mdp_set_ot_params ot_params;
 
 		memset(&ot_params, 0, sizeof(struct sde_mdp_set_ot_params));
@@ -2158,7 +2423,7 @@
 		sde_mdp_set_ot_limit(&ot_params);
 	}
 
-	if (mdata->default_ot_wr_limit) {
+	if (!ctx->sbuf_mode && mdata->default_ot_wr_limit) {
 		struct sde_mdp_set_ot_params ot_params;
 
 		memset(&ot_params, 0, sizeof(struct sde_mdp_set_ot_params));
@@ -2189,46 +2454,9 @@
 		SDE_ROTREG_WRITE(rot->mdss_base, ROT_SSPP_CREQ_LUT, qos_lut);
 	}
 
-	/* Set CDP control registers to 0 if CDP is disabled */
-	if (!test_bit(SDE_QOS_CDP, mdata->sde_qos_map)) {
-		SDE_ROTREG_WRITE(rot->mdss_base, ROT_SSPP_CDP_CNTL, 0x0);
-		SDE_ROTREG_WRITE(rot->mdss_base, ROT_WB_CDP_CNTL, 0x0);
-	}
-
-	if (mdata->npriority_lvl > 0) {
-		u32 mask, reg_val, i, vbif_qos;
-
-		for (i = 0; i < mdata->npriority_lvl; i++) {
-			reg_val = SDE_VBIF_READ(mdata,
-					MMSS_VBIF_NRT_VBIF_QOS_REMAP_00 + i*4);
-			mask = 0x3 << (XIN_SSPP * 2);
-			reg_val &= ~(mask);
-			vbif_qos = mdata->vbif_nrt_qos[i];
-			reg_val |= vbif_qos << (XIN_SSPP * 2);
-			/* ensure write is issued after the read operation */
-			mb();
-			SDE_VBIF_WRITE(mdata,
-					MMSS_VBIF_NRT_VBIF_QOS_REMAP_00 + i*4,
-					reg_val);
-		}
-	}
-
-	/* Enable write gather for writeback to remove write gaps, which
-	 * may hang AXI/BIMC/SDE.
-	 */
-	SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_WRITE_GATHTER_EN,
-			BIT(XIN_WRITEBACK));
-
-	/*
-	 * For debug purpose, disable clock gating, i.e. Clocks always on
-	 */
-	if (mdata->clk_always_on) {
-		SDE_VBIF_WRITE(mdata, MMSS_VBIF_CLKON, 0x3);
-		SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0, 0x3);
-		SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL1,
-				0xFFFF);
-		SDE_ROTREG_WRITE(rot->mdss_base, ROTTOP_CLK_CTRL, 1);
-	}
+	/* VBIF QoS and other settings */
+	if (!ctx->sbuf_mode)
+		sde_hw_rotator_vbif_setting(rot);
 
 	return 0;
 
@@ -2337,7 +2565,6 @@
 
 	clear_bit(SDE_QOS_PER_PIPE_IB, mdata->sde_qos_map);
 	set_bit(SDE_QOS_OVERHEAD_FACTOR, mdata->sde_qos_map);
-	clear_bit(SDE_QOS_CDP, mdata->sde_qos_map);
 	set_bit(SDE_QOS_OTLIM, mdata->sde_qos_map);
 	set_bit(SDE_QOS_PER_PIPE_LUT, mdata->sde_qos_map);
 	clear_bit(SDE_QOS_SIMPLIFIED_PREFILL, mdata->sde_qos_map);
@@ -2368,6 +2595,7 @@
 		SDEROT_DBG("Supporting sys cache inline rotation\n");
 		set_bit(SDE_CAPS_SBUF_1,  mdata->sde_caps_map);
 		set_bit(SDE_CAPS_UBWC_2,  mdata->sde_caps_map);
+		set_bit(SDE_CAPS_PARTIALWR,  mdata->sde_caps_map);
 		rot->inpixfmts = sde_hw_rotator_v4_inpixfmts;
 		rot->num_inpixfmt = ARRAY_SIZE(sde_hw_rotator_v4_inpixfmts);
 		rot->outpixfmts = sde_hw_rotator_v4_outpixfmts;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
index aa762dd..d2b81d5 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_hwio.h
@@ -81,6 +81,8 @@
 #define ROT_SSPP_CREQ_LUT                       (SDE_ROT_SSPP_OFFSET+0x68)
 #define ROT_SSPP_QOS_CTRL                       (SDE_ROT_SSPP_OFFSET+0x6C)
 #define ROT_SSPP_SRC_ADDR_SW_STATUS             (SDE_ROT_SSPP_OFFSET+0x70)
+#define ROT_SSPP_CREQ_LUT_0                     (SDE_ROT_SSPP_OFFSET+0x74)
+#define ROT_SSPP_CREQ_LUT_1                     (SDE_ROT_SSPP_OFFSET+0x78)
 #define ROT_SSPP_CURRENT_SRC0_ADDR              (SDE_ROT_SSPP_OFFSET+0xA4)
 #define ROT_SSPP_CURRENT_SRC1_ADDR              (SDE_ROT_SSPP_OFFSET+0xA8)
 #define ROT_SSPP_CURRENT_SRC2_ADDR              (SDE_ROT_SSPP_OFFSET+0xAC)
@@ -167,6 +169,8 @@
 #define ROT_WB_CREQ_LUT                         (SDE_ROT_WB_OFFSET+0x08C)
 #define ROT_WB_QOS_CTRL                         (SDE_ROT_WB_OFFSET+0x090)
 #define ROT_WB_SYS_CACHE_MODE                   (SDE_ROT_WB_OFFSET+0x094)
+#define ROT_WB_CREQ_LUT_0                       (SDE_ROT_WB_OFFSET+0x098)
+#define ROT_WB_CREQ_LUT_1                       (SDE_ROT_WB_OFFSET+0x09C)
 #define ROT_WB_UBWC_STATIC_CTRL                 (SDE_ROT_WB_OFFSET+0x144)
 #define ROT_WB_SBUF_STATUS_PLANE0               (SDE_ROT_WB_OFFSET+0x148)
 #define ROT_WB_SBUF_STATUS_PLANE1               (SDE_ROT_WB_OFFSET+0x14C)
diff --git a/drivers/media/platform/msm/vidc/Kconfig b/drivers/media/platform/msm/vidc/Kconfig
index db12cae..d6297d4 100644
--- a/drivers/media/platform/msm/vidc/Kconfig
+++ b/drivers/media/platform/msm/vidc/Kconfig
@@ -7,5 +7,4 @@
 		depends on ARCH_QCOM && VIDEO_V4L2
 		select VIDEOBUF2_CORE
 
-source "drivers/media/platform/msm/vidc/vmem/Kconfig"
 source "drivers/media/platform/msm/vidc/governors/Kconfig"
diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
index 12b5b04..f7ce757 100644
--- a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
+++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
@@ -22,8 +22,7 @@
 
 enum governor_mode {
 	GOVERNOR_DDR,
-	GOVERNOR_VMEM,
-	GOVERNOR_VMEM_PLUS,
+	GOVERNOR_LLCC,
 };
 
 struct governor {
@@ -275,38 +274,6 @@
 	}
 }
 
-static unsigned long __calculate_vmem_plus_ab(struct vidc_bus_vote_data *d)
-{
-	unsigned long i = 0, vmem_plus = 0;
-
-	if (!d->imem_ab_tbl || !d->imem_ab_tbl_size) {
-		vmem_plus = 1; /* Vote for the min ab value */
-		goto exit;
-	}
-
-	/* Pick up vmem frequency based on venus core frequency */
-	for (i = 0; i < d->imem_ab_tbl_size; i++) {
-		if (d->imem_ab_tbl[i].core_freq == d->core_freq) {
-			vmem_plus = d->imem_ab_tbl[i].imem_ab;
-			break;
-		}
-	}
-
-	/*
-	 * Incase we get an unsupported freq throw a warning
-	 * and set ab to the minimum value.
-	 */
-	if (!vmem_plus) {
-		vmem_plus = 1;
-		dprintk(VIDC_WARN,
-			"could not calculate vmem ab value due to core freq mismatch\n");
-		WARN_ON(1);
-	}
-
-exit:
-	return vmem_plus;
-}
-
 static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d,
 		enum governor_mode gm) {
 	/*
@@ -611,12 +578,9 @@
 	case GOVERNOR_DDR:
 		ret = kbps(fp_round(ddr.total));
 		break;
-	case GOVERNOR_VMEM:
+	case GOVERNOR_LLCC:
 		ret = kbps(fp_round(vmem.total));
 		break;
-	case GOVERNOR_VMEM_PLUS:
-		ret = __calculate_vmem_plus_ab(d);
-		break;
 	default:
 		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
 	}
@@ -1016,12 +980,9 @@
 	case GOVERNOR_DDR:
 		ret = kbps(fp_round(ddr.total));
 		break;
-	case GOVERNOR_VMEM:
+	case GOVERNOR_LLCC:
 		ret = kbps(fp_round(vmem.total));
 		break;
-	case GOVERNOR_VMEM_PLUS:
-		ret = __calculate_vmem_plus_ab(d);
-		break;
 	default:
 		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
 	}
@@ -1107,17 +1068,9 @@
 		},
 	},
 	{
-		.mode = GOVERNOR_VMEM,
+		.mode = GOVERNOR_LLCC,
 		.devfreq_gov = {
-			.name = "msm-vidc-vmem",
-			.get_target_freq = __get_target_freq,
-			.event_handler = __event_handler,
-		},
-	},
-	{
-		.mode = GOVERNOR_VMEM_PLUS,
-		.devfreq_gov = {
-			.name = "msm-vidc-vmem+",
+			.name = "msm-vidc-llcc",
 			.get_target_freq = __get_target_freq,
 			.event_handler = __event_handler,
 		},
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 9331c94..e7e9278 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -332,37 +332,56 @@
 
 int create_pkt_cmd_sys_set_resource(
 		struct hfi_cmd_sys_set_resource_packet *pkt,
-		struct vidc_resource_hdr *resource_hdr,
-		void *resource_value)
+		struct vidc_resource_hdr *res_hdr,
+		void *res_value)
 {
 	int rc = 0;
+	u32 i = 0;
 
-	if (!pkt || !resource_hdr || !resource_value)
+	if (!pkt || !res_hdr || !res_value) {
+		dprintk(VIDC_ERR,
+			"Invalid paramas pkt %pK res_hdr %pK res_value %pK\n",
+				pkt, res_hdr, res_value);
 		return -EINVAL;
+	}
 
 	pkt->packet_type = HFI_CMD_SYS_SET_RESOURCE;
 	pkt->size = sizeof(struct hfi_cmd_sys_set_resource_packet);
-	pkt->resource_handle = hash32_ptr(resource_hdr->resource_handle);
+	pkt->resource_handle = hash32_ptr(res_hdr->resource_handle);
 
-	switch (resource_hdr->resource_id) {
-	case VIDC_RESOURCE_OCMEM:
-	case VIDC_RESOURCE_VMEM:
+	switch (res_hdr->resource_id) {
+	case VIDC_RESOURCE_SYSCACHE:
 	{
-		struct hfi_resource_ocmem *hfioc_mem =
-			(struct hfi_resource_ocmem *)
-			&pkt->rg_resource_data[0];
+		struct hfi_resource_syscache_info_type *res_sc_info =
+			(struct hfi_resource_syscache_info_type *) res_value;
+		struct hfi_resource_subcache_type *res_sc =
+			(struct hfi_resource_subcache_type *)
+				&(res_sc_info->rg_subcache_entries[0]);
 
-		phys_addr_t imem_addr = (phys_addr_t)resource_value;
+		struct hfi_resource_syscache_info_type *hfi_sc_info =
+			(struct hfi_resource_syscache_info_type *)
+				&pkt->rg_resource_data[0];
 
-		pkt->resource_type = HFI_RESOURCE_OCMEM;
-		pkt->size += sizeof(struct hfi_resource_ocmem) - sizeof(u32);
-		hfioc_mem->size = (u32)resource_hdr->size;
-		hfioc_mem->mem = imem_addr;
+		struct hfi_resource_subcache_type *hfi_sc =
+			(struct hfi_resource_subcache_type *)
+			&(hfi_sc_info->rg_subcache_entries[0]);
+
+		pkt->resource_type = HFI_RESOURCE_SYSCACHE;
+		hfi_sc_info->num_entries = res_sc_info->num_entries;
+
+		pkt->size += (sizeof(struct hfi_resource_subcache_type))
+				 * hfi_sc_info->num_entries;
+
+		for (i = 0; i < hfi_sc_info->num_entries; i++) {
+			hfi_sc[i] = res_sc[i];
+		dprintk(VIDC_DBG, "entry hfi#%d, sc_id %d, size %d\n",
+				 i, hfi_sc[i].sc_id, hfi_sc[i].size);
+		}
 		break;
 	}
 	default:
-		dprintk(VIDC_ERR, "Invalid resource_id %d\n",
-					resource_hdr->resource_id);
+		dprintk(VIDC_ERR,
+			"Invalid resource_id %d\n", res_hdr->resource_id);
 		rc = -ENOTSUPP;
 	}
 
@@ -371,28 +390,35 @@
 
 int create_pkt_cmd_sys_release_resource(
 		struct hfi_cmd_sys_release_resource_packet *pkt,
-		struct vidc_resource_hdr *resource_hdr)
+		struct vidc_resource_hdr *res_hdr)
 {
 	int rc = 0;
 
-	if (!pkt)
+	if (!pkt || !res_hdr) {
+		dprintk(VIDC_ERR,
+			"Invalid paramas pkt %pK res_hdr %pK\n",
+				pkt, res_hdr);
 		return -EINVAL;
+	}
 
 	pkt->size = sizeof(struct hfi_cmd_sys_release_resource_packet);
 	pkt->packet_type = HFI_CMD_SYS_RELEASE_RESOURCE;
-	pkt->resource_handle = hash32_ptr(resource_hdr->resource_handle);
+	pkt->resource_handle = hash32_ptr(res_hdr->resource_handle);
 
-	switch (resource_hdr->resource_id) {
-	case VIDC_RESOURCE_OCMEM:
-	case VIDC_RESOURCE_VMEM:
-		pkt->resource_type = HFI_RESOURCE_OCMEM;
+	switch (res_hdr->resource_id) {
+	case VIDC_RESOURCE_SYSCACHE:
+		pkt->resource_type = HFI_RESOURCE_SYSCACHE;
 		break;
 	default:
-		dprintk(VIDC_ERR, "Invalid resource_id %d\n",
-					resource_hdr->resource_id);
+		dprintk(VIDC_ERR,
+			 "Invalid resource_id %d\n", res_hdr->resource_id);
 		rc = -ENOTSUPP;
 	}
 
+	dprintk(VIDC_DBG,
+		"rel_res: pkt_type 0x%x res_type 0x%x prepared\n",
+		pkt->packet_type, pkt->resource_type);
+
 	return rc;
 }
 
@@ -489,13 +515,13 @@
 		buffer = HFI_BUFFER_EXTRADATA_OUTPUT2;
 		break;
 	case HAL_BUFFER_INTERNAL_SCRATCH:
-		buffer = HFI_BUFFER_INTERNAL_SCRATCH;
+		buffer = HFI_BUFFER_COMMON_INTERNAL_SCRATCH;
 		break;
 	case HAL_BUFFER_INTERNAL_SCRATCH_1:
-		buffer = HFI_BUFFER_INTERNAL_SCRATCH_1;
+		buffer = HFI_BUFFER_COMMON_INTERNAL_SCRATCH_1;
 		break;
 	case HAL_BUFFER_INTERNAL_SCRATCH_2:
-		buffer = HFI_BUFFER_INTERNAL_SCRATCH_2;
+		buffer = HFI_BUFFER_COMMON_INTERNAL_SCRATCH_2;
 		break;
 	case HAL_BUFFER_INTERNAL_PERSIST:
 		buffer = HFI_BUFFER_INTERNAL_PERSIST;
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index b424fbb..89e8356 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1082,19 +1082,19 @@
 			buffreq->buffer[5].buffer_type =
 				HAL_BUFFER_EXTRADATA_OUTPUT2;
 			break;
-		case HFI_BUFFER_INTERNAL_SCRATCH:
+		case HFI_BUFFER_COMMON_INTERNAL_SCRATCH:
 			memcpy(&buffreq->buffer[6], hfi_buf_req,
 			sizeof(struct hfi_buffer_requirements));
 			buffreq->buffer[6].buffer_type =
 				HAL_BUFFER_INTERNAL_SCRATCH;
 			break;
-		case HFI_BUFFER_INTERNAL_SCRATCH_1:
+		case HFI_BUFFER_COMMON_INTERNAL_SCRATCH_1:
 			memcpy(&buffreq->buffer[7], hfi_buf_req,
 				sizeof(struct hfi_buffer_requirements));
 			buffreq->buffer[7].buffer_type =
 				HAL_BUFFER_INTERNAL_SCRATCH_1;
 			break;
-		case HFI_BUFFER_INTERNAL_SCRATCH_2:
+		case HFI_BUFFER_COMMON_INTERNAL_SCRATCH_2:
 			memcpy(&buffreq->buffer[8], hfi_buf_req,
 				sizeof(struct hfi_buffer_requirements));
 			buffreq->buffer[8].buffer_type =
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index 19a1e3f..074ea4fa 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.c
@@ -94,9 +94,18 @@
 		trace_msm_smem_buffer_iommu_op_start("MAP", 0, 0,
 			align, *iova, *buffer_size);
 
-		/* Map a scatterlist into an SMMU */
-		rc = msm_dma_map_sg_lazy(cb->dev, table->sgl, table->nents,
-				DMA_BIDIRECTIONAL, buf);
+		/* Map a scatterlist into SMMU */
+		if (smem_client->res->sys_cache_present) {
+			/* with sys cache attribute & delayed unmap */
+			rc = msm_dma_map_sg_attrs(cb->dev, table->sgl,
+				table->nents, DMA_BIDIRECTIONAL,
+				buf, DMA_ATTR_IOMMU_USE_UPSTREAM_HINT);
+		} else {
+			/* with delayed unmap */
+			rc = msm_dma_map_sg_lazy(cb->dev, table->sgl,
+				table->nents, DMA_BIDIRECTIONAL, buf);
+		}
+
 		if (rc != table->nents) {
 			dprintk(VIDC_ERR,
 				"Mapping failed with rc(%d), expected rc(%d)\n",
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 8906027..14eb3ab 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -86,7 +86,6 @@
 };
 
 static const char *const hevc_tier_level[] = {
-	"Level unknown"
 	"Main Tier Level 1",
 	"Main Tier Level 2",
 	"Main Tier Level 2.1",
@@ -113,6 +112,7 @@
 	"High Tier Level 6",
 	"High Tier Level 6.1",
 	"High Tier Level 6.2",
+	"Level unknown",
 };
 
 static const char *const hevc_profile[] = {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 89da0a1..04876d2 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1267,10 +1267,9 @@
 			return -EINVAL;
 		}
 		if (*num_buffers < bufreq->buffer_count_min_host) {
-			dprintk(VIDC_ERR,
-				"Invalid parameters : Req = %d Act = %d\n",
+			dprintk(VIDC_DBG,
+				"Client passed num buffers %d less than the min_host count %d\n",
 				*num_buffers, bufreq->buffer_count_min_host);
-			return -EINVAL;
 		}
 		*num_planes = inst->bufq[OUTPUT_PORT].num_planes;
 		if (*num_buffers < MIN_NUM_OUTPUT_BUFFERS ||
@@ -1299,11 +1298,10 @@
 		if (inst->session_type != MSM_VIDC_DECODER &&
 			inst->state > MSM_VIDC_LOAD_RESOURCES_DONE) {
 			if (*num_buffers < bufreq->buffer_count_min_host) {
-				dprintk(VIDC_ERR,
-					"Invalid parameters : Req = %d Act = %d\n",
+				dprintk(VIDC_DBG,
+					"Client passed num buffers %d less than the min_host count %d\n",
 						*num_buffers,
 						bufreq->buffer_count_min_host);
-				return -EINVAL;
 			}
 		}
 		*num_planes = inst->bufq[CAPTURE_PORT].num_planes;
@@ -1888,16 +1886,30 @@
 	switch (ctrl->id) {
 
 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
-	case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE:
+		ctrl->val = msm_comm_hal_to_v4l2(
+			V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+			inst->profile);
+		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
-		ctrl->val = inst->profile;
+		ctrl->val = msm_comm_hal_to_v4l2(
+			V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE,
+			inst->profile);
 		break;
 
 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+		ctrl->val = msm_comm_hal_to_v4l2(
+			V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+			inst->level);
+		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
-	case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL:
+		ctrl->val = msm_comm_hal_to_v4l2(
+			V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL,
+			inst->level);
+		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
-		ctrl->val = inst->level;
+		ctrl->val = msm_comm_hal_to_v4l2(
+			V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL,
+			inst->level);
 		break;
 
 	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 25cc1e4..a52fe05 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -968,6 +968,8 @@
 
 decision_done:
 	core_info.video_core_enable_mask = inst->clk_data.core_id;
+	dprintk(VIDC_DBG,
+		"Core Enable Mask %d\n", core_info.video_core_enable_mask);
 
 	rc = call_hfi_op(hdev, session_set_property,
 			(void *)inst->session,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 7b75d70..b1a8e8b 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -199,6 +199,8 @@
 			return V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
 		case HAL_H264_LEVEL_51:
 			return V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
+		case HAL_H264_LEVEL_52:
+			return V4L2_MPEG_VIDEO_H264_LEVEL_5_2;
 		default:
 			goto unknown_value;
 		}
@@ -212,7 +214,91 @@
 		default:
 			goto unknown_value;
 		}
+	case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
+		switch (value) {
+		case HAL_HEVC_PROFILE_MAIN:
+			return V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN;
+		case HAL_HEVC_PROFILE_MAIN10:
+			return V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10;
+		case HAL_HEVC_PROFILE_MAIN_STILL_PIC:
+			return V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC;
+		default:
+			goto unknown_value;
+		}
+	case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
+	switch (value) {
+	case HAL_HEVC_MAIN_TIER_LEVEL_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1;
+	case HAL_HEVC_MAIN_TIER_LEVEL_2:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2;
+	case HAL_HEVC_MAIN_TIER_LEVEL_2_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1;
+	case HAL_HEVC_MAIN_TIER_LEVEL_3:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3;
+	case HAL_HEVC_MAIN_TIER_LEVEL_3_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1;
+	case HAL_HEVC_MAIN_TIER_LEVEL_4:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4;
+	case HAL_HEVC_MAIN_TIER_LEVEL_4_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1;
+	case HAL_HEVC_MAIN_TIER_LEVEL_5:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5;
+	case HAL_HEVC_MAIN_TIER_LEVEL_5_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1;
+	case HAL_HEVC_MAIN_TIER_LEVEL_5_2:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2;
+	case HAL_HEVC_MAIN_TIER_LEVEL_6:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6;
+	case HAL_HEVC_MAIN_TIER_LEVEL_6_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1;
+	case HAL_HEVC_MAIN_TIER_LEVEL_6_2:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2;
+	case HAL_HEVC_HIGH_TIER_LEVEL_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1;
+	case HAL_HEVC_HIGH_TIER_LEVEL_2:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2;
+	case HAL_HEVC_HIGH_TIER_LEVEL_2_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1;
+	case HAL_HEVC_HIGH_TIER_LEVEL_3:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3;
+	case HAL_HEVC_HIGH_TIER_LEVEL_3_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1;
+	case HAL_HEVC_HIGH_TIER_LEVEL_4:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4;
+	case HAL_HEVC_HIGH_TIER_LEVEL_4_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1;
+	case HAL_HEVC_HIGH_TIER_LEVEL_5:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5;
+	case HAL_HEVC_HIGH_TIER_LEVEL_5_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1;
+	case HAL_HEVC_HIGH_TIER_LEVEL_5_2:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2;
+	case HAL_HEVC_HIGH_TIER_LEVEL_6:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6;
+	case HAL_HEVC_HIGH_TIER_LEVEL_6_1:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1;
+	case HAL_HEVC_HIGH_TIER_LEVEL_6_2:
+		return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_2;
+	case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_UNKNOWN:
+		return HAL_HEVC_TIER_LEVEL_UNKNOWN;
+	default:
+		goto unknown_value;
+	}
 	case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
+		switch (value) {
+		case HAL_VPX_LEVEL_VERSION_0:
+			return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0;
+		case HAL_VPX_LEVEL_VERSION_1:
+			return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1;
+		case HAL_VPX_LEVEL_VERSION_2:
+			return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_2;
+		case HAL_VPX_LEVEL_VERSION_3:
+			return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3;
+		case HAL_VPX_LEVEL_UNUSED:
+			return V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED;
+		default:
+			goto unknown_value;
+		}
 	case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE:
 	case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL:
 		/*
@@ -396,6 +482,8 @@
 			return HAL_HEVC_HIGH_TIER_LEVEL_6;
 		case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1:
 			return HAL_HEVC_HIGH_TIER_LEVEL_6_1;
+		case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_2:
+			return HAL_HEVC_HIGH_TIER_LEVEL_6_2;
 		case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_UNKNOWN:
 			return HAL_HEVC_TIER_LEVEL_UNKNOWN;
 		default:
@@ -1463,15 +1551,9 @@
 	* ptr[4] = colour space
 	*/
 
-	inst->entropy_mode = msm_comm_hal_to_v4l2(
-		V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
-			event_notify->entropy_mode);
-	inst->profile = msm_comm_hal_to_v4l2(
-		V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-			event_notify->profile);
-	inst->level = msm_comm_hal_to_v4l2(
-		V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-			event_notify->level);
+	inst->entropy_mode = event_notify->entropy_mode;
+	inst->profile = event_notify->profile;
+	inst->level = event_notify->level;
 
 	ptr = (u32 *)seq_changed_event.u.data;
 	ptr[0] = event_notify->height;
@@ -2342,7 +2424,7 @@
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOS)
 			vbuf->flags |= V4L2_QCOM_BUF_FLAG_EOS;
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_CODECCONFIG)
-			vbuf->flags &= ~V4L2_QCOM_BUF_FLAG_CODECCONFIG;
+			vbuf->flags |= V4L2_QCOM_BUF_FLAG_CODECCONFIG;
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_SYNCFRAME)
 			vbuf->flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOSEQ)
@@ -5553,3 +5635,4 @@
 {
 	return VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
 }
+
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 61df652..7534593 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -103,4 +103,5 @@
 u32 get_frame_size_rgba(int plane, u32 height, u32 width);
 u32 get_frame_size_nv21(int plane, u32 height, u32 width);
 u32 get_frame_size_tp10_ubwc(int plane, u32 height, u32 width);
+void msm_comm_set_use_sys_cache(struct msm_vidc_inst *inst);
 #endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index f62c132..a8f776f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -31,6 +31,7 @@
 bool msm_vidc_thermal_mitigation_disabled = !true;
 bool msm_vidc_clock_scaling = true;
 bool msm_vidc_debug_timeout = !true;
+bool msm_vidc_syscache_disable = true;
 
 #define MAX_DBG_BUF_SIZE 4096
 
@@ -186,6 +187,8 @@
 			&msm_vidc_clock_scaling) &&
 	__debugfs_create(bool, "debug_timeout",
 			&msm_vidc_debug_timeout);
+	__debugfs_create(bool, "disable_video_syscache",
+			&msm_vidc_syscache_disable);
 
 #undef __debugfs_create
 
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
index f5c8e5a..c23ff82 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
@@ -64,6 +64,7 @@
 extern bool msm_vidc_thermal_mitigation_disabled;
 extern bool msm_vidc_clock_scaling;
 extern bool msm_vidc_debug_timeout;
+extern bool msm_vidc_syscache_disable;
 
 #define VIDC_MSG_PRIO2STRING(__level) ({ \
 	char *__str; \
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 0a6de41..d259072 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -59,19 +59,6 @@
 	return 0;
 }
 
-static inline enum imem_type read_imem_type(struct platform_device *pdev)
-{
-	bool is_compatible(char *compat)
-	{
-		return !!of_find_compatible_node(NULL, NULL, compat);
-	}
-
-	return is_compatible("qcom,msm-ocmem") ? IMEM_OCMEM :
-		is_compatible("qcom,msm-vmem") ? IMEM_VMEM :
-						IMEM_NONE;
-
-}
-
 static inline void msm_vidc_free_allowed_clocks_table(
 		struct msm_vidc_platform_resources *res)
 {
@@ -90,12 +77,6 @@
 	res->pf_ver_tbl = NULL;
 }
 
-static inline void msm_vidc_free_imem_ab_table(
-		struct msm_vidc_platform_resources *res)
-{
-	res->imem_ab_tbl = NULL;
-}
-
 static inline void msm_vidc_free_reg_table(
 			struct msm_vidc_platform_resources *res)
 {
@@ -262,43 +243,48 @@
 	return rc;
 }
 
-static int msm_vidc_load_imem_ab_table(struct msm_vidc_platform_resources *res)
+static int msm_vidc_load_subcache_info(struct msm_vidc_platform_resources *res)
 {
-	int num_elements = 0;
+	int rc = 0, num_subcaches = 0, c;
 	struct platform_device *pdev = res->pdev;
+	struct subcache_set *subcaches = &res->subcache_set;
 
-	if (!of_find_property(pdev->dev.of_node, "qcom,imem-ab-tbl", NULL)) {
-		/* optional property */
-		dprintk(VIDC_DBG, "qcom,imem-freq-tbl not found\n");
-		return 0;
+	num_subcaches = of_property_count_strings(pdev->dev.of_node,
+		"cache-slice-names");
+	if (num_subcaches <= 0) {
+		dprintk(VIDC_DBG, "No subcaches found\n");
+		goto err_load_subcache_table_fail;
 	}
 
-	num_elements = get_u32_array_num_elements(pdev->dev.of_node,
-			"qcom,imem-ab-tbl");
-	num_elements /= (sizeof(*res->imem_ab_tbl) / sizeof(u32));
-	if (!num_elements) {
-		dprintk(VIDC_ERR, "no elements in imem ab table\n");
-		return -EINVAL;
+	subcaches->subcache_tbl = devm_kzalloc(&pdev->dev,
+		sizeof(*subcaches->subcache_tbl) * num_subcaches, GFP_KERNEL);
+	if (!subcaches->subcache_tbl) {
+		dprintk(VIDC_ERR,
+			"Failed to allocate memory for subcache tbl\n");
+		rc = -ENOMEM;
+		goto err_load_subcache_table_fail;
 	}
 
-	res->imem_ab_tbl = devm_kzalloc(&pdev->dev, num_elements *
-			sizeof(*res->imem_ab_tbl), GFP_KERNEL);
-	if (!res->imem_ab_tbl) {
-		dprintk(VIDC_ERR, "Failed to alloc imem_ab_tbl\n");
-		return -ENOMEM;
+	subcaches->count = num_subcaches;
+	dprintk(VIDC_DBG, "Found %d subcaches\n", num_subcaches);
+
+	for (c = 0; c < num_subcaches; ++c) {
+		struct subcache_info *vsc = &res->subcache_set.subcache_tbl[c];
+
+		of_property_read_string_index(pdev->dev.of_node,
+			"cache-slice-names", c, &vsc->name);
 	}
 
-	if (of_property_read_u32_array(pdev->dev.of_node,
-		"qcom,imem-ab-tbl", (u32 *)res->imem_ab_tbl,
-		num_elements * sizeof(*res->imem_ab_tbl) / sizeof(u32))) {
-		dprintk(VIDC_ERR, "Failed to read imem_ab_tbl\n");
-		msm_vidc_free_imem_ab_table(res);
-		return -EINVAL;
-	}
-
-	res->imem_ab_tbl_size = num_elements;
+	res->sys_cache_present = true;
 
 	return 0;
+
+err_load_subcache_table_fail:
+	res->sys_cache_present = false;
+	subcaches->count = 0;
+	subcaches->subcache_tbl = NULL;
+
+	return rc;
 }
 
 /**
@@ -856,10 +842,6 @@
 	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	res->irq = kres ? kres->start : -1;
 
-	of_property_read_u32(pdev->dev.of_node,
-			"qcom,imem-size", &res->imem_size);
-	res->imem_type = read_imem_type(pdev);
-
 	res->sys_idle_indicator = of_property_read_bool(pdev->dev.of_node,
 			"qcom,enable-idle-indicator");
 
@@ -884,9 +866,9 @@
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to load pf version table: %d\n", rc);
 
-	rc = msm_vidc_load_imem_ab_table(res);
+	rc = msm_vidc_load_subcache_info(res);
 	if (rc)
-		dprintk(VIDC_WARN, "Failed to load freq table: %d\n", rc);
+		dprintk(VIDC_WARN, "Failed to load subcache info: %d\n", rc);
 
 	rc = msm_vidc_load_qdss_table(res);
 	if (rc)
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 20b0ffc..b07785a 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -17,6 +17,8 @@
 #include <linux/devfreq.h>
 #include <linux/platform_device.h>
 #include <media/msm_vidc.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
 #define MAX_BUFFER_TYPES 32
 
 struct platform_version_table {
@@ -36,11 +38,6 @@
 	u32 fps;
 };
 
-struct imem_ab_table {
-	u32 core_freq;
-	u32 imem_ab;
-};
-
 struct reg_value_pair {
 	u32 reg;
 	u32 value;
@@ -122,13 +119,6 @@
 	u32 count;
 };
 
-enum imem_type {
-	IMEM_NONE,
-	IMEM_OCMEM,
-	IMEM_VMEM,
-	IMEM_MAX,
-};
-
 struct allowed_clock_rates_table {
 	u32 clock_rate;
 };
@@ -145,6 +135,18 @@
 	u32 count;
 };
 
+struct subcache_info {
+	const char *name;
+	bool isactive;
+	bool isset;
+	struct llcc_slice_desc *subcache;
+};
+
+struct subcache_set {
+	struct subcache_info *subcache_tbl;
+	u32 count;
+};
+
 struct msm_vidc_platform_resources {
 	phys_addr_t firmware_base;
 	phys_addr_t register_base;
@@ -157,13 +159,12 @@
 	struct dcvs_table *dcvs_tbl;
 	uint32_t dcvs_tbl_size;
 	struct dcvs_limit *dcvs_limit;
-	struct imem_ab_table *imem_ab_tbl;
-	u32 imem_ab_tbl_size;
+	bool sys_cache_present;
+	bool sys_cache_enabled;
+	struct subcache_set subcache_set;
 	struct reg_set reg_set;
 	struct addr_set qdss_addr_set;
 	struct buffer_usage_set buffer_usage_set;
-	uint32_t imem_size;
-	enum imem_type imem_type;
 	uint32_t max_load;
 	uint32_t max_hq_mbs_per_frame;
 	uint32_t max_hq_fps;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 1a1078d..8968764 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -27,6 +27,8 @@
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/llcc-qcom.h>
 #include <soc/qcom/scm.h>
 #include <soc/qcom/smem.h>
 #include <soc/qcom/subsystem_restart.h>
@@ -72,7 +74,6 @@
 const struct msm_vidc_gov_data DEFAULT_BUS_VOTE = {
 	.data = NULL,
 	.data_count = 0,
-	.imem_size = 0,
 };
 
 const int max_packets = 1000;
@@ -95,6 +96,8 @@
 static int __load_fw(struct venus_hfi_device *device);
 static void __unload_fw(struct venus_hfi_device *device);
 static int __tzbsp_set_video_state(enum tzbsp_video_state state);
+static int __enable_subcaches(struct venus_hfi_device *device);
+static int __disable_subcaches(struct venus_hfi_device *device);
 
 
 /**
@@ -117,6 +120,11 @@
 	return device->state != VENUS_STATE_DEINIT;
 }
 
+static inline bool is_sys_cache_present(struct venus_hfi_device *device)
+{
+	return device->res->sys_cache_present;
+}
+
 static void __dump_packet(u8 *packet, enum vidc_msg_prio log_level)
 {
 	u32 c = 0, packet_size = *(u32 *)packet;
@@ -875,7 +883,6 @@
 	kfree(device->bus_vote.data);
 	device->bus_vote.data = new_data;
 	device->bus_vote.data_count = num_data;
-	device->bus_vote.imem_size = device->res->imem_size;
 
 	venus_hfi_for_each_bus(device, bus) {
 		if (bus && bus->devfreq) {
@@ -939,140 +946,33 @@
 	return rc;
 }
 
-static int __alloc_imem(struct venus_hfi_device *device, unsigned long size)
+static int __core_release_resource(struct venus_hfi_device *device,
+		struct vidc_resource_hdr *resource_hdr)
 {
-	struct imem *imem = NULL;
+	struct hfi_cmd_sys_release_resource_packet *pkt;
+	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
 	int rc = 0;
 
-	if (!device)
-		return -EINVAL;
-
-	imem = &device->resources.imem;
-	if (imem->type) {
-		dprintk(VIDC_ERR, "IMEM of type %d already allocated\n",
-				imem->type);
-		return -ENOMEM;
-	}
-
-	switch (device->res->imem_type) {
-	case IMEM_VMEM:
-	{
-		phys_addr_t vmem_buffer = 0;
-
-		rc = vmem_allocate(size, &vmem_buffer);
-		if (rc) {
-			if (rc == -ENOTSUPP) {
-				dprintk(VIDC_DBG,
-					"Target does not support vmem\n");
-				rc = 0;
-			}
-			goto imem_alloc_failed;
-		} else if (!vmem_buffer) {
-			rc = -ENOMEM;
-			goto imem_alloc_failed;
-		}
-
-		imem->vmem = vmem_buffer;
-		break;
-	}
-	case IMEM_NONE:
-		rc = 0;
-		break;
-
-	default:
-		rc = -ENOTSUPP;
-		goto imem_alloc_failed;
-	}
-
-	imem->type = device->res->imem_type;
-	dprintk(VIDC_DBG, "Allocated %ld bytes of IMEM of type %d\n", size,
-			imem->type);
-	return 0;
-imem_alloc_failed:
-	imem->type = IMEM_NONE;
-	return rc;
-}
-
-static int __free_imem(struct venus_hfi_device *device)
-{
-	struct imem *imem = NULL;
-	int rc = 0;
-
-	if (!device)
-		return -EINVAL;
-
-	imem = &device->resources.imem;
-	switch (imem->type) {
-	case IMEM_NONE:
-		/* Follow the semantics of free(NULL), which is a no-op. */
-		break;
-	case IMEM_VMEM:
-		vmem_free(imem->vmem);
-		break;
-	default:
-		rc = -ENOTSUPP;
-		goto imem_free_failed;
-	}
-
-	imem->type = IMEM_NONE;
-	return 0;
-
-imem_free_failed:
-	return rc;
-}
-
-static int __set_imem(struct venus_hfi_device *device, struct imem *imem)
-{
-	struct vidc_resource_hdr rhdr;
-	phys_addr_t addr = 0;
-	int rc = 0;
-
-	if (!device || !device->res || !imem) {
-		dprintk(VIDC_ERR, "Invalid params, core: %pK, imem: %pK\n",
-			device, imem);
+	if (!device || !resource_hdr) {
+		dprintk(VIDC_ERR, "release_res: Invalid Params\n");
 		return -EINVAL;
 	}
 
-	rhdr.resource_handle = imem; /* cookie */
-	rhdr.size = device->res->imem_size;
-	rhdr.resource_id = VIDC_RESOURCE_NONE;
+	pkt = (struct hfi_cmd_sys_release_resource_packet *) packet;
 
-	switch (imem->type) {
-	case IMEM_VMEM:
-		rhdr.resource_id = VIDC_RESOURCE_VMEM;
-		addr = imem->vmem;
-		break;
-	case IMEM_NONE:
-		dprintk(VIDC_DBG, "%s Target does not support IMEM", __func__);
-		rc = 0;
-		goto imem_set_failed;
-	default:
-		dprintk(VIDC_ERR, "IMEM of type %d unsupported\n", imem->type);
-		rc = -ENOTSUPP;
-		goto imem_set_failed;
-	}
+	rc = call_hfi_pkt_op(device, sys_release_resource,
+			pkt, resource_hdr);
 
-	MSM_VIDC_ERROR(!addr);
-
-	rc = __core_set_resource(device, &rhdr, (void *)addr);
 	if (rc) {
-		dprintk(VIDC_ERR, "Failed to set IMEM on driver\n");
-		goto imem_set_failed;
+		dprintk(VIDC_ERR, "release_res: failed to create packet\n");
+		goto err_create_pkt;
 	}
 
-	dprintk(VIDC_DBG,
-			"Managed to set IMEM buffer of type %d sized %d bytes at %pa\n",
-			rhdr.resource_id, rhdr.size, &addr);
+	rc = __iface_cmdq_write(device, pkt);
+	if (rc)
+		rc = -ENOTEMPTY;
 
-	rc = __vote_buses(device, device->bus_vote.data,
-			device->bus_vote.data_count);
-	if (rc) {
-		dprintk(VIDC_ERR,
-				"Failed to vote for buses after setting imem: %d\n",
-				rc);
-	}
-
-imem_set_failed:
+err_create_pkt:
 	return rc;
 }
 
@@ -1931,6 +1831,12 @@
 	if (rc || __iface_cmdq_write(dev, &version_pkt))
 		dprintk(VIDC_WARN, "Failed to send image version pkt to f/w\n");
 
+	rc = __enable_subcaches(device);
+	if (rc) {
+		dprintk(VIDC_WARN,
+			"Failed to enable subcaches, err = %d\n", rc);
+	}
+
 	if (dev->res->pm_qos_latency_us) {
 #ifdef CONFIG_SMP
 		dev->qos.type = PM_QOS_REQ_AFFINE_IRQ;
@@ -2848,6 +2754,8 @@
 		return;
 	}
 
+	dprintk(VIDC_PROF,
+		"Entering venus_hfi_pm_handler\n");
 	/*
 	 * It is ok to check this variable outside the lock since
 	 * it is being updated in this context only
@@ -3094,12 +3002,7 @@
 			break;
 		case HAL_SYS_INIT_DONE:
 			dprintk(VIDC_DBG, "Received SYS_INIT_DONE\n");
-			/* Video driver intentionally does not unset
-			 * IMEM on venus to simplify power collapse.
-			 */
-			if (__set_imem(device, &device->resources.imem))
-				dprintk(VIDC_WARN,
-				"Failed to set IMEM. Performance will be impacted\n");
+
 			sys_init_done.capabilities =
 				device->sys_init_capabilities;
 			hfi_process_sys_init_done_prop_read(
@@ -3584,6 +3487,68 @@
 	return rc;
 }
 
+static void __deinit_subcaches(struct venus_hfi_device *device)
+{
+	struct subcache_info *sinfo = NULL;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "deinit_subcaches: invalid device %pK\n",
+			device);
+		goto exit;
+	}
+
+	if (!is_sys_cache_present(device))
+		goto exit;
+
+	venus_hfi_for_each_subcache_reverse(device, sinfo) {
+		if (sinfo->subcache) {
+			dprintk(VIDC_DBG, "deinit_subcaches: %s\n",
+				sinfo->name);
+			llcc_slice_putd(sinfo->subcache);
+			sinfo->subcache = NULL;
+		}
+	}
+
+exit:
+	return;
+}
+
+static int __init_subcaches(struct venus_hfi_device *device)
+{
+	int rc = 0;
+	struct subcache_info *sinfo = NULL;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "init_subcaches: invalid device %pK\n",
+			device);
+		return -EINVAL;
+	}
+
+	if (!is_sys_cache_present(device))
+		return 0;
+
+	venus_hfi_for_each_subcache(device, sinfo) {
+		sinfo->subcache = llcc_slice_getd(&device->res->pdev->dev,
+			sinfo->name);
+		if (IS_ERR_OR_NULL(sinfo->subcache)) {
+			rc = PTR_ERR(sinfo->subcache) ? : -EBADHANDLE;
+			dprintk(VIDC_ERR,
+				 "init_subcaches: invalid subcache: %s rc %d\n",
+				sinfo->name, rc);
+			sinfo->subcache = NULL;
+			goto err_subcache_get;
+		}
+		dprintk(VIDC_DBG, "init_subcaches: %s\n",
+			sinfo->name);
+	}
+
+	return 0;
+
+err_subcache_get:
+	__deinit_subcaches(device);
+	return rc;
+}
+
 static int __init_resources(struct venus_hfi_device *device,
 				struct msm_vidc_platform_resources *res)
 {
@@ -3608,6 +3573,10 @@
 		goto err_init_bus;
 	}
 
+	rc = __init_subcaches(device);
+	if (rc)
+		dprintk(VIDC_WARN, "Failed to init subcaches: %d\n", rc);
+
 	device->sys_init_capabilities =
 		kzalloc(sizeof(struct msm_vidc_capability)
 		* VIDC_MAX_SESSIONS, GFP_TEMPORARY);
@@ -3623,6 +3592,7 @@
 
 static void __deinit_resources(struct venus_hfi_device *device)
 {
+	__deinit_subcaches(device);
 	__deinit_bus(device);
 	__deinit_clocks(device);
 	__deinit_regulators(device);
@@ -3789,6 +3759,136 @@
 	return rc;
 }
 
+static int __enable_subcaches(struct venus_hfi_device *device)
+{
+	int rc = 0;
+	u32 c = 0;
+	struct subcache_info *sinfo;
+	u32 resource[VIDC_MAX_SUBCACHE_SIZE];
+	struct hfi_resource_syscache_info_type *sc_res_info;
+	struct hfi_resource_subcache_type *sc_res;
+	struct vidc_resource_hdr rhdr;
+
+	if (msm_vidc_syscache_disable || !is_sys_cache_present(device))
+		return 0;
+
+	memset((void *)resource, 0x0, (sizeof(u32) * VIDC_MAX_SUBCACHE_SIZE));
+
+	sc_res_info = (struct hfi_resource_syscache_info_type *)resource;
+	sc_res = &(sc_res_info->rg_subcache_entries[0]);
+
+	/* Activate subcaches */
+	venus_hfi_for_each_subcache(device, sinfo) {
+		rc = llcc_slice_activate(sinfo->subcache);
+		if (rc) {
+			dprintk(VIDC_ERR, "Failed to activate %s: %d\n",
+				sinfo->name, rc);
+			continue;
+		}
+		sinfo->isactive = true;
+
+		/* Update the entry */
+		sc_res[c].size = sinfo->subcache->llcc_slice_size;
+		sc_res[c].sc_id = sinfo->subcache->llcc_slice_id;
+		dprintk(VIDC_DBG, "Activate subcache %s\n", sinfo->name);
+		c++;
+	}
+
+	/* Set resource to Venus for activated subcaches */
+	if (c) {
+		dprintk(VIDC_DBG, "Setting Subcaches\n");
+
+		rhdr.resource_handle = sc_res_info; /* cookie */
+		rhdr.resource_id = VIDC_RESOURCE_SYSCACHE;
+
+		sc_res_info->num_entries = c;
+
+		rc = __core_set_resource(device, &rhdr, (void *)sc_res_info);
+		if (rc) {
+			dprintk(VIDC_ERR, "Failed to set subcaches %d\n", rc);
+			goto err_fail_set_subacaches;
+		}
+	}
+
+	venus_hfi_for_each_subcache(device, sinfo) {
+		if (sinfo->isactive == true)
+			sinfo->isset = true;
+	}
+
+	dprintk(VIDC_DBG, "Activated & Set Subcaches to Venus\n");
+
+	device->res->sys_cache_enabled = true;
+
+	return 0;
+
+err_fail_set_subacaches:
+	__disable_subcaches(device);
+
+	return rc;
+}
+
+static int __disable_subcaches(struct venus_hfi_device *device)
+{
+	struct subcache_info *sinfo;
+	int rc = 0;
+	u32 c = 0;
+	u32 resource[VIDC_MAX_SUBCACHE_SIZE];
+	struct hfi_resource_syscache_info_type *sc_res_info;
+	struct hfi_resource_subcache_type *sc_res;
+	struct vidc_resource_hdr rhdr;
+
+	if (msm_vidc_syscache_disable || !is_sys_cache_present(device))
+		return 0;
+
+	dprintk(VIDC_DBG, "Disabling Subcaches\n");
+
+	memset((void *)resource, 0x0, (sizeof(u32) * VIDC_MAX_SUBCACHE_SIZE));
+
+	sc_res_info = (struct hfi_resource_syscache_info_type *)resource;
+	sc_res = &(sc_res_info->rg_subcache_entries[0]);
+
+	/* Release resource command to Venus */
+	venus_hfi_for_each_subcache_reverse(device, sinfo) {
+		if (sinfo->isset == true) {
+			/* Update the entry */
+			sc_res[c].size = sinfo->subcache->llcc_slice_size;
+			sc_res[c].sc_id = sinfo->subcache->llcc_slice_id;
+			c++;
+			sinfo->isset = false;
+		}
+	}
+
+	if (c > 0) {
+		rhdr.resource_handle = sc_res_info; /* cookie */
+		rhdr.resource_id = VIDC_RESOURCE_SYSCACHE;
+
+		rc = __core_release_resource(device, &rhdr);
+		if (rc)
+			dprintk(VIDC_ERR, "Failed to release subcaches\n");
+
+		dprintk(VIDC_DBG, "Release %d subcaches\n", c);
+	}
+
+	/* De-activate subcaches */
+	venus_hfi_for_each_subcache_reverse(device, sinfo) {
+		if (sinfo->isactive == true) {
+			dprintk(VIDC_DBG, "De-activate subcache %s\n",
+				sinfo->name);
+			rc = llcc_slice_deactivate(sinfo->subcache);
+			if (rc) {
+				dprintk(VIDC_ERR,
+					"Failed to de-activate %s: %d\n",
+					sinfo->name, rc);
+			}
+			sinfo->isactive = false;
+		}
+	}
+
+	device->res->sys_cache_enabled = false;
+
+	return rc;
+}
+
 static int __venus_power_on(struct venus_hfi_device *device)
 {
 	int rc = 0;
@@ -3805,12 +3905,6 @@
 		goto fail_vote_buses;
 	}
 
-	rc = __alloc_imem(device, device->res->imem_size);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to allocate IMEM\n");
-		goto fail_alloc_imem;
-	}
-
 	rc = __enable_regulators(device);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to enable GDSC, err = %d\n", rc);
@@ -3855,8 +3949,6 @@
 fail_enable_clks:
 	__disable_regulators(device);
 fail_enable_gdsc:
-	__free_imem(device);
-fail_alloc_imem:
 	__unvote_buses(device);
 fail_vote_buses:
 	device->power_enabled = false;
@@ -3876,8 +3968,6 @@
 	if (__disable_regulators(device))
 		dprintk(VIDC_WARN, "Failed to disable regulators\n");
 
-	__free_imem(device);
-
 	if (__unvote_buses(device))
 		dprintk(VIDC_WARN, "Failed to unvote for buses\n");
 	device->power_enabled = false;
@@ -3897,6 +3987,9 @@
 
 	dprintk(VIDC_PROF, "Entering power collapse\n");
 
+	if (__disable_subcaches(device))
+		dprintk(VIDC_ERR, "Failed to disable subcaches\n");
+
 	if (device->res->pm_qos_latency_us &&
 		pm_qos_request_active(&device->qos))
 		pm_qos_remove_request(&device->qos);
@@ -3966,6 +4059,15 @@
 		pm_qos_add_request(&device->qos, PM_QOS_CPU_DMA_LATENCY,
 				device->res->pm_qos_latency_us);
 	}
+
+	__sys_set_debug(device, msm_vidc_fw_debug);
+
+	rc = __enable_subcaches(device);
+	if (rc) {
+		dprintk(VIDC_WARN,
+			"Failed to enable subcaches, err = %d\n", rc);
+	}
+
 	dprintk(VIDC_PROF, "Resumed from power collapse\n");
 exit:
 	device->skip_pc_count = 0;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 76ede70..925918c 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -19,7 +19,6 @@
 #include <linux/platform_device.h>
 #include <linux/pm_qos.h>
 #include <linux/spinlock.h>
-#include "vmem/vmem.h"
 #include "vidc_hfi_api.h"
 #include "vidc_hfi_helper.h"
 #include "vidc_hfi_api.h"
@@ -48,6 +47,9 @@
 
 #define VIDC_MAX_NAME_LENGTH 64
 #define VIDC_MAX_PC_SKIP_COUNT 10
+#define VIDC_MAX_SUBCACHES 4
+#define VIDC_MAX_SUBCACHE_SIZE 52
+
 struct hfi_queue_table_header {
 	u32 qtbl_version;
 	u32 qtbl_size;
@@ -198,6 +200,11 @@
 #define venus_hfi_for_each_bus_reverse(__device, __binfo) \
 	venus_hfi_for_each_thing_reverse(__device, __binfo, bus)
 
+/* Subcache set helpers */
+#define venus_hfi_for_each_subcache(__device, __sinfo) \
+	venus_hfi_for_each_thing(__device, __sinfo, subcache)
+#define venus_hfi_for_each_subcache_reverse(__device, __sinfo) \
+	venus_hfi_for_each_thing_reverse(__device, __sinfo, subcache)
 
 /* Internal data used in vidc_hal not exposed to msm_vidc*/
 struct hal_data {
@@ -207,16 +214,8 @@
 	u32 register_size;
 };
 
-struct imem {
-	enum imem_type type;
-	union {
-		phys_addr_t vmem;
-	};
-};
-
 struct venus_resources {
 	struct msm_vidc_fw fw;
-	struct imem imem;
 };
 
 enum venus_hfi_state {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 48a6f17..5601f1b 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -56,13 +56,6 @@
 #define  HFI_ERR_SESSION_START_CODE_NOT_FOUND		\
 	(HFI_OX_BASE + 0x1004)
 
-#define HFI_BUFFER_INTERNAL_SCRATCH (HFI_OX_BASE + 0x1)
-#define HFI_BUFFER_EXTRADATA_INPUT (HFI_OX_BASE + 0x2)
-#define HFI_BUFFER_EXTRADATA_OUTPUT (HFI_OX_BASE + 0x3)
-#define HFI_BUFFER_EXTRADATA_OUTPUT2 (HFI_OX_BASE + 0x4)
-#define HFI_BUFFER_INTERNAL_SCRATCH_1 (HFI_OX_BASE + 0x5)
-#define HFI_BUFFER_INTERNAL_SCRATCH_2 (HFI_OX_BASE + 0x6)
-#define HFI_BUFFER_INTERNAL_RECON (HFI_OX_BASE + 0x9)
 
 #define HFI_BUFFER_MODE_DYNAMIC (HFI_OX_BASE + 0x3)
 
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 537a1c6..cc35bb3 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -376,11 +376,11 @@
 };
 
 enum hal_vpx_level {
+	HAL_VPX_LEVEL_UNUSED = 0x00000000,
 	HAL_VPX_LEVEL_VERSION_0 = 0x00000001,
 	HAL_VPX_LEVEL_VERSION_1 = 0x00000002,
 	HAL_VPX_LEVEL_VERSION_2 = 0x00000004,
 	HAL_VPX_LEVEL_VERSION_3 = 0x00000008,
-	HAL_VPX_LEVEL_UNUSED = 0x10000000,
 };
 
 struct hal_frame_rate {
@@ -870,15 +870,13 @@
 
 enum vidc_resource_id {
 	VIDC_RESOURCE_NONE,
-	VIDC_RESOURCE_OCMEM,
-	VIDC_RESOURCE_VMEM,
+	VIDC_RESOURCE_SYSCACHE,
 	VIDC_UNUSED_RESOURCE = 0x10000000,
 };
 
 struct vidc_resource_hdr {
 	enum vidc_resource_id resource_id;
 	void *resource_handle;
-	u32 size;
 };
 
 struct vidc_buffer_addr_info {
@@ -1293,7 +1291,6 @@
 struct msm_vidc_gov_data {
 	struct vidc_bus_vote_data *data;
 	u32 data_count;
-	int imem_size;
 };
 
 enum msm_vidc_power_mode {
@@ -1309,9 +1306,6 @@
 	int num_formats; /* 1 = DPB-OPB unified; 2 = split */
 	int height, width, fps;
 	enum msm_vidc_power_mode power_mode;
-	struct imem_ab_table *imem_ab_tbl;
-	u32 imem_ab_tbl_size;
-	unsigned long core_freq;
 };
 
 struct vidc_clk_scale_data {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index eaba920..0df4812 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -155,6 +155,13 @@
 #define HFI_BUFFER_OUTPUT2				(HFI_COMMON_BASE + 0x3)
 #define HFI_BUFFER_INTERNAL_PERSIST		(HFI_COMMON_BASE + 0x4)
 #define HFI_BUFFER_INTERNAL_PERSIST_1		(HFI_COMMON_BASE + 0x5)
+#define HFI_BUFFER_COMMON_INTERNAL_SCRATCH	(HFI_COMMON_BASE + 0x6)
+#define HFI_BUFFER_COMMON_INTERNAL_SCRATCH_1	(HFI_COMMON_BASE + 0x7)
+#define HFI_BUFFER_COMMON_INTERNAL_SCRATCH_2	(HFI_COMMON_BASE + 0x8)
+#define HFI_BUFFER_COMMON_INTERNAL_RECON	(HFI_COMMON_BASE + 0x9)
+#define HFI_BUFFER_EXTRADATA_OUTPUT		(HFI_COMMON_BASE + 0xA)
+#define HFI_BUFFER_EXTRADATA_OUTPUT2		(HFI_COMMON_BASE + 0xB)
+#define HFI_BUFFER_EXTRADATA_INPUT		(HFI_COMMON_BASE + 0xC)
 
 #define  HFI_BITDEPTH_8				(HFI_COMMON_BASE + 0x0)
 #define  HFI_BITDEPTH_9				(HFI_COMMON_BASE + 0x1)
@@ -718,23 +725,16 @@
 	u32 flip;
 };
 
-#define HFI_RESOURCE_OCMEM 0x00000001
+#define HFI_RESOURCE_SYSCACHE 0x00000002
 
-struct hfi_resource_ocmem {
+struct hfi_resource_subcache_type {
 	u32 size;
-	u32 mem;
+	u32 sc_id;
 };
 
-struct hfi_resource_ocmem_requirement {
-	u32 session_domain;
-	u32 width;
-	u32 height;
-	u32 size;
-};
-
-struct hfi_resource_ocmem_requirement_info {
+struct hfi_resource_syscache_info_type {
 	u32 num_entries;
-	struct hfi_resource_ocmem_requirement rg_requirements[1];
+	struct hfi_resource_subcache_type rg_subcache_entries[1];
 };
 
 struct hfi_property_sys_image_version_info_type {
diff --git a/drivers/media/platform/msm/vidc/vmem/Kconfig b/drivers/media/platform/msm/vidc/vmem/Kconfig
deleted file mode 100644
index 99260a9..0000000
--- a/drivers/media/platform/msm/vidc/vmem/Kconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-menuconfig MSM_VIDC_VMEM
-	tristate "Qualcomm Technologies, Inc. MSM VMEM driver"
-	depends on ARCH_QCOM && MSM_VIDC_V4L2
diff --git a/drivers/media/platform/msm/vidc/vmem/Makefile b/drivers/media/platform/msm/vidc/vmem/Makefile
deleted file mode 100644
index a56ad95..0000000
--- a/drivers/media/platform/msm/vidc/vmem/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-ccflags-y += -I$(srctree)/drivers/media/platform/msm/vidc/
-ccflags-y += -I$(srctree)/drivers/media/platform/msm/vidc/vmem/
-
-msm-vidc-vmem-objs := vmem.o \
-                      vmem_debugfs.o
-
-obj-$(CONFIG_MSM_VIDC_VMEM) := msm-vidc-vmem.o
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.c b/drivers/media/platform/msm/vidc/vmem/vmem.c
deleted file mode 100644
index c75f02d..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem.c
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * 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) KBUILD_MODNAME ": " fmt
-
-#include <linux/bitops.h>
-#include <linux/clk.h>
-#include <linux/clk/qcom.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/msm-bus.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include "vmem.h"
-#include "vmem_debugfs.h"
-
-/* Registers */
-#define OCIMEM_BASE(v)               ((uint8_t *)(v)->reg.base)
-#define OCIMEM_HW_VERSION(v)         (OCIMEM_BASE(v) + 0x00)
-#define OCIMEM_HW_PROFILE(v)         (OCIMEM_BASE(v) + 0x04)
-#define OCIMEM_GEN_CTL(v)            (OCIMEM_BASE(v) + 0x08)
-#define OCIMEM_GEN_STAT(v)           (OCIMEM_BASE(v) + 0x0C)
-#define OCIMEM_INTC_CLR(v)           (OCIMEM_BASE(v) + 0x10)
-#define OCIMEM_INTC_MASK(v)          (OCIMEM_BASE(v) + 0x14)
-#define OCIMEM_INTC_STAT(v)          (OCIMEM_BASE(v) + 0x18)
-#define OCIMEM_OSW_STATUS(v)         (OCIMEM_BASE(v) + 0x1C)
-#define OCIMEM_PSCGC_TIMERS(v)       (OCIMEM_BASE(v) + 0x34)
-#define OCIMEM_PSCGC_STAT(v)         (OCIMEM_BASE(v) + 0x38)
-#define OCIMEM_PSCGC_M0_M7_CTL(v)    (OCIMEM_BASE(v) + 0x3C)
-#define OCIMEM_ERR_ADDRESS(v)        (OCIMEM_BASE(v) + 0x60)
-#define OCIMEM_AXI_ERR_SYNDROME(v)   (OCIMEM_BASE(v) + 0x64)
-#define OCIMEM_DEBUG_CTL(v)          (OCIMEM_BASE(v) + 0x68)
-
-/*
- * Helper macro to help out with masks and shifts for values packed into
- * registers.
- */
-#define DECLARE_TYPE(__type, __end, __start)                                   \
-	static const unsigned int __type##_BITS = (__end) - (__start) + 1;     \
-	static const unsigned int __type##_SHIFT = (__start);                  \
-	static const unsigned int __type##_MASK = GENMASK((__end), (__start)); \
-	static inline unsigned int __type(uint32_t val)                        \
-	{                                                                      \
-		return (val & __type##_MASK) >> __type##_SHIFT;                \
-	}                                                                      \
-	static inline uint32_t __type##_UPDATE(unsigned int val)               \
-	{                                                                      \
-		return (val << __type##_SHIFT) & __type##_MASK;                \
-	}
-
-/* Register masks */
-/* OCIMEM_PSCGC_M0_M7_CTL */
-DECLARE_TYPE(BANK0_STATE, 3, 0);
-DECLARE_TYPE(BANK1_STATE, 7, 4);
-DECLARE_TYPE(BANK2_STATE, 11, 8);
-DECLARE_TYPE(BANK3_STATE, 15, 12);
-/* OCIMEM_PSCGC_TIMERS */
-DECLARE_TYPE(TIMERS_WAKEUP, 3, 0);
-DECLARE_TYPE(TIMERS_SLEEP, 11, 8);
-/* OCIMEM_HW_VERSION */
-DECLARE_TYPE(VERSION_STEP, 15, 0);
-DECLARE_TYPE(VERSION_MINOR, 27, 16);
-DECLARE_TYPE(VERSION_MAJOR, 31, 28);
-/* OCIMEM_HW_PROFILE */
-DECLARE_TYPE(PROFILE_BANKS, 16, 12);
-/* OCIMEM_AXI_ERR_SYNDROME */
-DECLARE_TYPE(ERR_SYN_ATID, 14, 8);
-DECLARE_TYPE(ERR_SYN_AMID, 23, 16);
-DECLARE_TYPE(ERR_SYN_APID, 28, 24);
-DECLARE_TYPE(ERR_SYN_ABID, 31, 29);
-/* OCIMEM_INTC_MASK */
-DECLARE_TYPE(AXI_ERR_INT, 0, 0);
-
-/* Internal stuff */
-#define MAX_BANKS 4
-
-enum bank_state {
-	BANK_STATE_NORM_PASSTHRU = 0x000,
-	BANK_STATE_NORM_FORCE_CORE_ON = 0x002,
-	BANK_STATE_NORM_FORCE_PERIPH_ON = 0x001,
-	BANK_STATE_NORM_FORCE_ALL_ON = 0x03,
-	BANK_STATE_SLEEP_RET = 0x6,
-	BANK_STATE_SLEEP_RET_PERIPH_ON = 0x7,
-	BANK_STATE_SLEEP_NO_RET = 0x4,
-};
-
-struct vmem {
-	int irq;
-	int num_banks;
-	int bank_size;
-	struct {
-		struct resource *resource;
-		void __iomem *base;
-	} reg, mem;
-	struct regulator *vdd;
-	struct {
-		const char *name;
-		struct clk *clk;
-		bool has_mem_retention;
-	} *clocks;
-	int num_clocks;
-	struct {
-		struct msm_bus_scale_pdata *pdata;
-		uint32_t priv;
-	} bus;
-	atomic_t alloc_count;
-	struct dentry *debugfs_root;
-};
-
-static struct vmem *vmem;
-
-static inline u32 __readl(void * __iomem addr)
-{
-	u32 value = 0;
-
-	pr_debug("read %pK ", addr);
-	value = readl_relaxed(addr);
-	pr_debug("-> %08x\n", value);
-
-	return value;
-}
-
-static inline void __writel(u32 val, void * __iomem addr)
-{
-	pr_debug("write %08x -> %pK\n", val, addr);
-	writel_relaxed(val, addr);
-	/*
-	 * Commit all writes via a mem barrier, as subsequent __readl()
-	 * will depend on the state that's set via __writel().
-	 */
-	mb();
-}
-
-static inline void __wait_timer(struct vmem *v, bool wakeup)
-{
-	uint32_t ticks = 0;
-	unsigned int (*timer)(uint32_t) = wakeup ?
-		TIMERS_WAKEUP : TIMERS_SLEEP;
-
-	ticks = timer(__readl(OCIMEM_PSCGC_TIMERS(v)));
-
-	/* Sleep for `ticks` nanoseconds as per h/w spec */
-	ndelay(ticks);
-}
-
-static inline void __wait_wakeup(struct vmem *v)
-{
-	return __wait_timer(v, true);
-}
-
-static inline void __wait_sleep(struct vmem *v)
-{
-	return __wait_timer(v, false);
-}
-
-static inline int __power_on(struct vmem *v)
-{
-	int rc = 0, c = 0;
-
-	rc = msm_bus_scale_client_update_request(v->bus.priv, 1);
-	if (rc) {
-		pr_err("Failed to vote for buses (%d)\n", rc);
-		goto exit;
-	}
-	pr_debug("Voted for buses\n");
-
-	rc = regulator_enable(v->vdd);
-	if (rc) {
-		pr_err("Failed to power on gdsc (%d)", rc);
-		goto unvote_bus;
-	}
-	pr_debug("Enabled regulator vdd\n");
-
-	for (c = 0; c < v->num_clocks; ++c) {
-		if (v->clocks[c].has_mem_retention) {
-			rc = clk_set_flags(v->clocks[c].clk,
-				       CLKFLAG_NORETAIN_PERIPH);
-			if (rc) {
-				pr_warn("Failed set flag NORETAIN_PERIPH %s\n",
-					v->clocks[c].name);
-			}
-			rc = clk_set_flags(v->clocks[c].clk,
-				       CLKFLAG_NORETAIN_MEM);
-			if (rc) {
-				pr_warn("Failed set flag NORETAIN_MEM %s\n",
-					v->clocks[c].name);
-			}
-		}
-
-		rc = clk_prepare_enable(v->clocks[c].clk);
-		if (rc) {
-			pr_err("Failed to enable %s clock (%d)\n",
-					v->clocks[c].name, rc);
-			goto disable_clocks;
-		}
-
-		pr_debug("Enabled clock %s\n", v->clocks[c].name);
-	}
-
-	return 0;
-disable_clocks:
-	for (--c; c >= 0; c--)
-		clk_disable_unprepare(v->clocks[c].clk);
-	regulator_disable(v->vdd);
-unvote_bus:
-	msm_bus_scale_client_update_request(v->bus.priv, 0);
-exit:
-	return rc;
-}
-
-static inline int __power_off(struct vmem *v)
-{
-	int c = v->num_clocks;
-
-	for (c--; c >= 0; --c) {
-		clk_disable_unprepare(v->clocks[c].clk);
-		pr_debug("Disabled clock %s\n", v->clocks[c].name);
-	}
-
-	regulator_disable(v->vdd);
-	pr_debug("Disabled regulator vdd\n");
-
-	msm_bus_scale_client_update_request(v->bus.priv, 0);
-	pr_debug("Unvoted for buses\n");
-
-	return 0;
-}
-
-static inline enum bank_state __bank_get_state(struct vmem *v,
-		unsigned int bank)
-{
-	unsigned int (*func[MAX_BANKS])(uint32_t) = {
-		BANK0_STATE, BANK1_STATE, BANK2_STATE, BANK3_STATE
-	};
-
-	VMEM_ERROR(bank >= ARRAY_SIZE(func));
-	return func[bank](__readl(OCIMEM_PSCGC_M0_M7_CTL(v)));
-}
-
-static inline void __bank_set_state(struct vmem *v, unsigned int bank,
-		enum bank_state state)
-{
-	uint32_t bank_state = 0;
-	struct {
-		uint32_t (*update)(unsigned int);
-		uint32_t mask;
-	} banks[MAX_BANKS] = {
-		{BANK0_STATE_UPDATE, BANK0_STATE_MASK},
-		{BANK1_STATE_UPDATE, BANK1_STATE_MASK},
-		{BANK2_STATE_UPDATE, BANK2_STATE_MASK},
-		{BANK3_STATE_UPDATE, BANK3_STATE_MASK},
-	};
-
-	VMEM_ERROR(bank >= ARRAY_SIZE(banks));
-
-	bank_state = __readl(OCIMEM_PSCGC_M0_M7_CTL(v));
-	bank_state &= ~banks[bank].mask;
-	bank_state |= banks[bank].update(state);
-
-	__writel(bank_state, OCIMEM_PSCGC_M0_M7_CTL(v));
-}
-
-static inline void __toggle_interrupts(struct vmem *v, bool enable)
-{
-	uint32_t ints = __readl(OCIMEM_INTC_MASK(v)),
-		mask = AXI_ERR_INT_MASK,
-		update = AXI_ERR_INT_UPDATE(!enable);
-
-	ints &= ~mask;
-	ints |= update;
-
-	__writel(ints, OCIMEM_INTC_MASK(v));
-}
-
-static void __enable_interrupts(struct vmem *v)
-{
-	pr_debug("Enabling interrupts\n");
-	enable_irq(v->irq);
-	__toggle_interrupts(v, true);
-}
-
-static void __disable_interrupts(struct vmem *v)
-{
-	pr_debug("Disabling interrupts\n");
-	__toggle_interrupts(v, false);
-	disable_irq_nosync(v->irq);
-}
-
-/**
- * vmem_allocate: - Allocates memory from VMEM.  Allocations have a few
- * restrictions: only allocations of the entire VMEM memory are allowed, and
- * , as a result, only single outstanding allocations are allowed.
- *
- * @size: amount of bytes to allocate
- * @addr: A pointer to phys_addr_t where the physical address of the memory
- * allocated is stored.
- *
- * Return: 0 in case of successful allocation (i.e. *addr != NULL). -ENOTSUPP,
- * if platform doesn't support VMEM. -EEXIST, if there are outstanding VMEM
- * allocations.  -ENOMEM, if platform can't support allocation of `size` bytes.
- * -EAGAIN, if `size` does not allocate the entire VMEM region.  -EIO in case of
- * internal errors.
- */
-int vmem_allocate(size_t size, phys_addr_t *addr)
-{
-	int rc = 0, c = 0;
-	resource_size_t max_size = 0;
-
-	if (!vmem) {
-		pr_err("No vmem, try rebooting your device\n");
-		rc = -ENOTSUPP;
-		goto exit;
-	}
-	if (!size) {
-		pr_err("%s Invalid size %zu\n", __func__, size);
-		rc = -EINVAL;
-		goto exit;
-	}
-
-	max_size = resource_size(vmem->mem.resource);
-
-	if (atomic_read(&vmem->alloc_count)) {
-		pr_err("Only single allocations allowed for vmem\n");
-		rc = -EEXIST;
-		goto exit;
-	} else if (size > max_size) {
-		pr_err("Out of memory, have max %pa\n", &max_size);
-		rc = -ENOMEM;
-		goto exit;
-	} else if (size != max_size) {
-		pr_err("Only support allocations of size %pa\n", &max_size);
-		rc = -EAGAIN;
-		goto exit;
-	}
-
-	rc = __power_on(vmem);
-	if (rc) {
-		pr_err("Failed power on (%d)\n", rc);
-		goto exit;
-	}
-
-	VMEM_ERROR(vmem->num_banks != DIV_ROUND_UP(size, vmem->bank_size));
-
-	/* Turn on the necessary banks */
-	for (c = 0; c < vmem->num_banks; ++c) {
-		__bank_set_state(vmem, c, BANK_STATE_NORM_FORCE_CORE_ON);
-		__wait_wakeup(vmem);
-	}
-
-	/* Enable interrupts to detect faults */
-	__enable_interrupts(vmem);
-
-	atomic_inc(&vmem->alloc_count);
-	*addr = (phys_addr_t)vmem->mem.resource->start;
-	return 0;
-exit:
-	return rc;
-}
-EXPORT_SYMBOL(vmem_allocate);
-
-/**
- * vmem_free: - Frees the memory allocated via vmem_allocate.  Undefined
- * behaviour if to_free is a not a pointer returned via vmem_allocate
- */
-void vmem_free(phys_addr_t to_free)
-{
-	int c = 0;
-
-	if (!to_free || !vmem)
-		return;
-
-	VMEM_ERROR(atomic_read(&vmem->alloc_count) == 0);
-
-	for (c = 0; c < vmem->num_banks; ++c) {
-		enum bank_state curr_state = __bank_get_state(vmem, c);
-
-		if (curr_state != BANK_STATE_NORM_FORCE_CORE_ON) {
-			pr_warn("When freeing, expected bank state to be %d, was instead %d\n",
-					BANK_STATE_NORM_FORCE_CORE_ON,
-					curr_state);
-		}
-
-		__bank_set_state(vmem, c, BANK_STATE_SLEEP_NO_RET);
-	}
-
-	__disable_interrupts(vmem);
-	__power_off(vmem);
-	atomic_dec(&vmem->alloc_count);
-}
-EXPORT_SYMBOL(vmem_free);
-
-struct vmem_interrupt_cookie {
-	struct vmem *vmem;
-	struct work_struct work;
-};
-
-static void __irq_helper(struct work_struct *work)
-{
-	struct vmem_interrupt_cookie *cookie = container_of(work,
-			struct vmem_interrupt_cookie, work);
-	struct vmem *v = cookie->vmem;
-	unsigned int stat, gen_stat, pscgc_stat, err_addr_abs,
-		err_addr_rel, err_syn;
-
-	stat = __readl(OCIMEM_INTC_STAT(v));
-	gen_stat = __readl(OCIMEM_GEN_CTL(v));
-	pscgc_stat = __readl(OCIMEM_PSCGC_STAT(v));
-
-	err_addr_abs = __readl(OCIMEM_ERR_ADDRESS(v));
-	err_addr_rel = v->mem.resource->start - err_addr_abs;
-
-	err_syn = __readl(OCIMEM_AXI_ERR_SYNDROME(v));
-
-	pr_crit("Detected a fault on VMEM:\n");
-	pr_cont("\tinterrupt status: %x\n", stat);
-	pr_cont("\tgeneral status: %x\n", gen_stat);
-	pr_cont("\tmemory status: %x\n", pscgc_stat);
-	pr_cont("\tfault address: %x (absolute), %x (relative)\n",
-			err_addr_abs, err_addr_rel);
-	pr_cont("\tfault bank: %x\n", err_addr_rel / v->bank_size);
-	pr_cont("\tfault core: %u (mid), %u (pid), %u (bid)\n",
-			ERR_SYN_AMID(err_syn), ERR_SYN_APID(err_syn),
-			ERR_SYN_ABID(err_syn));
-
-	/* Clear the interrupt */
-	__writel(0, OCIMEM_INTC_CLR(v));
-
-	__enable_interrupts(v);
-}
-
-static struct vmem_interrupt_cookie interrupt_cookie;
-
-static irqreturn_t __irq_handler(int irq, void *cookie)
-{
-	struct vmem *v = cookie;
-	irqreturn_t status = __readl(OCIMEM_INTC_STAT(vmem)) ?
-		IRQ_HANDLED : IRQ_NONE;
-
-	if (status != IRQ_NONE) {
-		/* Mask further interrupts while handling this one */
-		__disable_interrupts(v);
-
-		interrupt_cookie.vmem = v;
-		INIT_WORK(&interrupt_cookie.work, __irq_helper);
-		schedule_work(&interrupt_cookie.work);
-	}
-
-	return status;
-}
-
-static inline int __init_resources(struct vmem *v,
-		struct platform_device *pdev)
-{
-	int rc = 0, c = 0;
-	int *clock_props = NULL;
-
-	v->irq = platform_get_irq(pdev, 0);
-	if (v->irq < 0) {
-		rc = v->irq;
-		pr_err("Failed to get irq (%d)\n", rc);
-		v->irq = 0;
-		goto exit;
-	}
-
-	/* Registers and memory */
-	v->reg.resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-			"reg-base");
-	if (!v->reg.resource) {
-		pr_err("Failed to find register base\n");
-		rc = -ENOENT;
-		goto exit;
-	}
-
-	v->reg.base = devm_ioremap_resource(&pdev->dev, v->reg.resource);
-	if (IS_ERR_OR_NULL(v->reg.base)) {
-		rc = PTR_ERR(v->reg.base) ?: -EIO;
-		pr_err("Failed to map register base into kernel (%d)\n", rc);
-		v->reg.base = NULL;
-		goto exit;
-	}
-
-	pr_debug("Register range: %pa -> %pa\n", &v->reg.resource->start,
-			&v->reg.resource->end);
-
-	v->mem.resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-			"mem-base");
-	if (!v->mem.resource) {
-		pr_err("Failed to find memory base\n");
-		rc = -ENOENT;
-		goto exit;
-	}
-
-	v->mem.base = NULL;
-	pr_debug("Memory range: %pa -> %pa\n", &v->mem.resource->start,
-			&v->mem.resource->end);
-
-	/* Buses, Clocks & Regulators*/
-	v->num_clocks = of_property_count_strings(pdev->dev.of_node,
-			"clock-names");
-	if (v->num_clocks <= 0) {
-		pr_err("Can't find any clocks\n");
-		goto exit;
-	}
-
-	v->clocks = devm_kzalloc(&pdev->dev, sizeof(*v->clocks) * v->num_clocks,
-			GFP_KERNEL);
-	if (!v->clocks) {
-		rc = -ENOMEM;
-		goto exit;
-	}
-
-	clock_props = devm_kzalloc(&pdev->dev,
-					v->num_clocks * sizeof(*clock_props),
-					GFP_KERNEL);
-	if (!clock_props) {
-		pr_err("Failed to allocate clock config table\n");
-		goto exit;
-	}
-
-	rc = of_property_read_u32_array(pdev->dev.of_node, "clock-config",
-			clock_props, v->num_clocks);
-	if (rc) {
-		pr_err("Failed to read clock config\n");
-		goto exit;
-	}
-
-	for (c = 0; c < v->num_clocks; ++c) {
-		const char *name = NULL;
-		struct clk *temp = NULL;
-
-		of_property_read_string_index(pdev->dev.of_node, "clock-names",
-				c, &name);
-		temp = devm_clk_get(&pdev->dev, name);
-		if (IS_ERR_OR_NULL(temp)) {
-			rc = PTR_ERR(temp) ?: -ENOENT;
-			pr_err("Failed to find %s (%d)\n", name, rc);
-			goto exit;
-		}
-
-		v->clocks[c].clk = temp;
-		v->clocks[c].name = name;
-		v->clocks[c].has_mem_retention = clock_props[c];
-	}
-
-	v->vdd = devm_regulator_get(&pdev->dev, "vdd");
-	if (IS_ERR_OR_NULL(v->vdd)) {
-		rc = PTR_ERR(v->vdd) ?: -ENOENT;
-		pr_err("Failed to find regulator (vdd) (%d)\n", rc);
-		goto exit;
-	}
-
-	v->bus.pdata = msm_bus_cl_get_pdata(pdev);
-	if (IS_ERR_OR_NULL(v->bus.pdata)) {
-		rc = PTR_ERR(v->bus.pdata) ?: -ENOENT;
-		pr_err("Failed to find bus vectors (%d)\n", rc);
-		goto exit;
-	}
-
-	v->bus.priv = msm_bus_scale_register_client(v->bus.pdata);
-	if (!v->bus.priv) {
-		rc = -EBADHANDLE;
-		pr_err("Failed to register bus client\n");
-		goto free_pdata;
-	}
-
-	/* Misc. */
-	rc = of_property_read_u32(pdev->dev.of_node, "qcom,bank-size",
-			&v->bank_size);
-	if (rc || !v->bank_size) {
-		pr_err("Failed reading (or found invalid) qcom,bank-size in %s (%d)\n",
-				of_node_full_name(pdev->dev.of_node), rc);
-		rc = -ENOENT;
-		goto free_pdata;
-	}
-
-	v->num_banks = resource_size(v->mem.resource) / v->bank_size;
-
-	pr_debug("Found configuration with %d banks with size %d\n",
-			v->num_banks, v->bank_size);
-
-	return 0;
-free_pdata:
-	msm_bus_cl_clear_pdata(v->bus.pdata);
-exit:
-	return rc;
-}
-
-static inline void __uninit_resources(struct vmem *v,
-		struct platform_device *pdev)
-{
-	int c = 0;
-
-	msm_bus_cl_clear_pdata(v->bus.pdata);
-	v->bus.pdata = NULL;
-	v->bus.priv = 0;
-
-	for (c = 0; c < v->num_clocks; ++c) {
-		v->clocks[c].clk = NULL;
-		v->clocks[c].name = NULL;
-	}
-
-	v->vdd = NULL;
-}
-
-static int vmem_probe(struct platform_device *pdev)
-{
-	uint32_t version = 0, num_banks = 0, rc = 0;
-	struct vmem *v = NULL;
-
-	if (vmem) {
-		pr_err("Only one instance of %s allowed", pdev->name);
-		return -EEXIST;
-	}
-
-	v = devm_kzalloc(&pdev->dev, sizeof(*v), GFP_KERNEL);
-	if (!v)
-		return -ENOMEM;
-
-
-	rc = __init_resources(v, pdev);
-	if (rc) {
-		pr_err("Failed to read resources\n");
-		goto exit;
-	}
-
-	/*
-	 * For now, only support up to 4 banks. It's unrealistic that VMEM has
-	 * more banks than that (even in the future).
-	 */
-	if (v->num_banks > MAX_BANKS) {
-		pr_err("Number of banks (%d) exceeds what's supported (%d)\n",
-			v->num_banks, MAX_BANKS);
-		rc = -ENOTSUPP;
-		goto exit;
-	}
-
-	/* Cross check the platform resources with what's available on chip */
-	rc = __power_on(v);
-	if (rc) {
-		pr_err("Failed to power on (%d)\n", rc);
-		goto exit;
-	}
-
-	version = __readl(OCIMEM_HW_VERSION(v));
-	pr_debug("v%d.%d.%d\n", VERSION_MAJOR(version), VERSION_MINOR(version),
-			VERSION_STEP(version));
-
-	num_banks = PROFILE_BANKS(__readl(OCIMEM_HW_PROFILE(v)));
-	pr_debug("Found %d banks on chip\n", num_banks);
-	if (v->num_banks != num_banks) {
-		pr_err("Platform configuration of %d banks differs from what's available on chip (%d)\n",
-				v->num_banks, num_banks);
-		rc = -EINVAL;
-		goto disable_clocks;
-	}
-
-	rc = devm_request_irq(&pdev->dev, v->irq, __irq_handler,
-			IRQF_TRIGGER_HIGH, "vmem", v);
-	if (rc) {
-		pr_err("Failed to setup irq (%d)\n", rc);
-		goto disable_clocks;
-	}
-
-	__disable_interrupts(v);
-
-	/* Everything good so far, set up the global context and debug hooks */
-	pr_info("Up and running with %d banks of memory from %pR\n",
-			v->num_banks, &v->mem.resource);
-	v->debugfs_root = vmem_debugfs_init(pdev);
-	platform_set_drvdata(pdev, v);
-	vmem = v;
-
-disable_clocks:
-	__power_off(v);
-exit:
-	return rc;
-}
-
-static int vmem_remove(struct platform_device *pdev)
-{
-	struct vmem *v = platform_get_drvdata(pdev);
-
-	VMEM_ERROR(v != vmem);
-
-	__uninit_resources(v, pdev);
-	vmem_debugfs_deinit(v->debugfs_root);
-	vmem = NULL;
-
-	return 0;
-}
-
-static const struct of_device_id vmem_of_match[] = {
-	{.compatible = "qcom,msm-vmem"},
-	{}
-};
-
-MODULE_DEVICE_TABLE(of, vmem_of_match);
-
-static struct platform_driver vmem_driver = {
-	.probe = vmem_probe,
-	.remove = vmem_remove,
-	.driver = {
-		.name = "msm_vidc_vmem",
-		.owner = THIS_MODULE,
-		.of_match_table = vmem_of_match,
-	},
-};
-
-static int __init vmem_init(void)
-{
-	return platform_driver_register(&vmem_driver);
-}
-
-static void __exit vmem_exit(void)
-{
-	platform_driver_unregister(&vmem_driver);
-}
-
-module_init(vmem_init);
-module_exit(vmem_exit);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.h b/drivers/media/platform/msm/vidc/vmem/vmem.h
deleted file mode 100644
index 0376427..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2014, 2016-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __VMEM_H__
-#define __VMEM_H__
-
-#define VMEM_ERROR(value)	\
-	do {			\
-		pr_info("%s : Fatal Level = %d\n", KBUILD_MODNAME, value);\
-		BUG_ON(value);  \
-	} while (0)
-
-#if (defined CONFIG_MSM_VIDC_VMEM) || (defined CONFIG_MSM_VIDC_VMEM_MODULE)
-
-int vmem_allocate(size_t size, phys_addr_t *addr);
-void vmem_free(phys_addr_t to_free);
-
-#else
-
-static inline int vmem_allocate(size_t size, phys_addr_t *addr)
-{
-	return -ENODEV;
-}
-
-static inline void vmem_free(phys_addr_t to_free)
-{
-}
-
-#endif
-
-#endif /* __VMEM_H__ */
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.c b/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.c
deleted file mode 100644
index 7d2d524..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2014, 2017 The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * 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/debugfs.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include "vmem.h"
-
-struct vmem_debugfs_cookie {
-	phys_addr_t addr;
-	size_t size;
-};
-
-static int __vmem_alloc_get(void *priv, u64 *val)
-{
-	struct vmem_debugfs_cookie *cookie = priv;
-
-	*val = cookie->size;
-	return 0;
-}
-
-static int __vmem_alloc_set(void *priv, u64 val)
-{
-	struct vmem_debugfs_cookie *cookie = priv;
-	int rc = 0;
-
-	switch (val) {
-	case 0: /* free */
-		vmem_free(cookie->addr);
-		cookie->size = 0;
-		break;
-	default:
-		rc = vmem_allocate(val, &cookie->addr);
-		cookie->size = val;
-		break;
-	}
-
-	return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(fops_vmem_alloc, __vmem_alloc_get,
-		__vmem_alloc_set, "%llu");
-
-struct dentry *vmem_debugfs_init(struct platform_device *pdev)
-{
-	struct vmem_debugfs_cookie *alloc_cookie = NULL;
-	struct dentry *debugfs_root = NULL;
-
-	alloc_cookie = devm_kzalloc(&pdev->dev, sizeof(*alloc_cookie),
-			GFP_KERNEL);
-	if (!alloc_cookie)
-		goto exit;
-
-	debugfs_root = debugfs_create_dir("vmem", NULL);
-	if (IS_ERR_OR_NULL(debugfs_root)) {
-		pr_warn("Failed to create '<debugfs>/vmem'\n");
-		debugfs_root = NULL;
-		goto exit;
-	}
-
-	debugfs_create_file("alloc", 0600, debugfs_root,
-			alloc_cookie, &fops_vmem_alloc);
-
-exit:
-	return debugfs_root;
-}
-
-void vmem_debugfs_deinit(struct dentry *debugfs_root)
-{
-	debugfs_remove_recursive(debugfs_root);
-}
-
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.h b/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.h
deleted file mode 100644
index 8b716cc..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2014, 2017 The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * 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 __VMEM_DEBUGFS_H__
-#define __VMEM_DEBUGFS_H__
-
-#include <linux/debugfs.h>
-
-struct dentry *vmem_debugfs_init(struct platform_device *pdev);
-void vmem_debugfs_deinit(struct dentry *debugfs_root);
-
-#endif /* __VMEM_DEBUGFS_H__ */
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index 6c033c9..78cb3e2 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -538,7 +538,8 @@
 		nd_pfn->npfns = le64_to_cpu(pfn_sb->npfns);
 		altmap = NULL;
 	} else if (nd_pfn->mode == PFN_MODE_PMEM) {
-		nd_pfn->npfns = (resource_size(res) - offset) / PAGE_SIZE;
+		nd_pfn->npfns = PFN_SECTION_ALIGN_UP((resource_size(res)
+					- offset) / PAGE_SIZE);
 		if (le64_to_cpu(nd_pfn->pfn_sb->npfns) > nd_pfn->npfns)
 			dev_info(&nd_pfn->dev,
 					"number of pfns truncated from %lld to %ld\n",
@@ -625,7 +626,8 @@
 	 */
 	start += start_pad;
 	size = resource_size(&nsio->res);
-	npfns = (size - start_pad - end_trunc - SZ_8K) / SZ_4K;
+	npfns = PFN_SECTION_ALIGN_UP((size - start_pad - end_trunc - SZ_8K)
+			/ PAGE_SIZE);
 	if (nd_pfn->mode == PFN_MODE_PMEM) {
 		/*
 		 * vmemmap_populate_hugepages() allocates the memmap array in
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 2461843..b480859 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -383,12 +383,12 @@
 
 static void nd_pmem_notify(struct device *dev, enum nvdimm_event event)
 {
-	struct pmem_device *pmem = dev_get_drvdata(dev);
-	struct nd_region *nd_region = to_region(pmem);
+	struct nd_region *nd_region;
 	resource_size_t offset = 0, end_trunc = 0;
 	struct nd_namespace_common *ndns;
 	struct nd_namespace_io *nsio;
 	struct resource res;
+	struct badblocks *bb;
 
 	if (event != NVDIMM_REVALIDATE_POISON)
 		return;
@@ -397,20 +397,33 @@
 		struct nd_btt *nd_btt = to_nd_btt(dev);
 
 		ndns = nd_btt->ndns;
-	} else if (is_nd_pfn(dev)) {
-		struct nd_pfn *nd_pfn = to_nd_pfn(dev);
-		struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
+		nd_region = to_nd_region(ndns->dev.parent);
+		nsio = to_nd_namespace_io(&ndns->dev);
+		bb = &nsio->bb;
+	} else {
+		struct pmem_device *pmem = dev_get_drvdata(dev);
 
-		ndns = nd_pfn->ndns;
-		offset = pmem->data_offset + __le32_to_cpu(pfn_sb->start_pad);
-		end_trunc = __le32_to_cpu(pfn_sb->end_trunc);
-	} else
-		ndns = to_ndns(dev);
+		nd_region = to_region(pmem);
+		bb = &pmem->bb;
 
-	nsio = to_nd_namespace_io(&ndns->dev);
+		if (is_nd_pfn(dev)) {
+			struct nd_pfn *nd_pfn = to_nd_pfn(dev);
+			struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
+
+			ndns = nd_pfn->ndns;
+			offset = pmem->data_offset +
+					__le32_to_cpu(pfn_sb->start_pad);
+			end_trunc = __le32_to_cpu(pfn_sb->end_trunc);
+		} else {
+			ndns = to_ndns(dev);
+		}
+
+		nsio = to_nd_namespace_io(&ndns->dev);
+	}
+
 	res.start = nsio->res.start + offset;
 	res.end = nsio->res.end - end_trunc;
-	nvdimm_badblocks_populate(nd_region, &pmem->bb, &res);
+	nvdimm_badblocks_populate(nd_region, bb, &res);
 }
 
 MODULE_ALIAS("pmem");
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 9cf6f1a..f623062 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -968,17 +968,20 @@
  */
 int nvdimm_has_flush(struct nd_region *nd_region)
 {
-	struct nd_region_data *ndrd = dev_get_drvdata(&nd_region->dev);
 	int i;
 
 	/* no nvdimm == flushing capability unknown */
 	if (nd_region->ndr_mappings == 0)
 		return -ENXIO;
 
-	for (i = 0; i < nd_region->ndr_mappings; i++)
-		/* flush hints present, flushing required */
-		if (ndrd_get_flush_wpq(ndrd, i, 0))
+	for (i = 0; i < nd_region->ndr_mappings; i++) {
+		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
+		struct nvdimm *nvdimm = nd_mapping->nvdimm;
+
+		/* flush hints present / available */
+		if (nvdimm->num_flush)
 			return 1;
+	}
 
 	/*
 	 * The platform defines dimm devices without hints, assume
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 2a1367e..9520166 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/pinctrl.h>
@@ -31,7 +32,7 @@
 #include <linux/reboot.h>
 #include <linux/pm.h>
 #include <linux/log2.h>
-
+#include <linux/irq.h>
 #include "../core.h"
 #include "../pinconf.h"
 #include "pinctrl-msm.h"
@@ -749,6 +750,91 @@
 	.irq_set_wake   = msm_gpio_irq_set_wake,
 };
 
+static void msm_dirconn_irq_mask(struct irq_data *d)
+{
+	struct irq_desc *desc = irq_data_to_desc(d);
+	struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+
+	if (parent_data->chip->irq_mask)
+		parent_data->chip->irq_mask(parent_data);
+}
+
+static void msm_dirconn_irq_unmask(struct irq_data *d)
+{
+	struct irq_desc *desc = irq_data_to_desc(d);
+	struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+
+	if (parent_data->chip->irq_unmask)
+		parent_data->chip->irq_unmask(parent_data);
+}
+
+static void msm_dirconn_irq_ack(struct irq_data *d)
+{
+	struct irq_desc *desc = irq_data_to_desc(d);
+	struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+
+	if (parent_data->chip->irq_ack)
+		parent_data->chip->irq_ack(parent_data);
+}
+
+static void msm_dirconn_irq_eoi(struct irq_data *d)
+{
+	struct irq_desc *desc = irq_data_to_desc(d);
+	struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+
+	if (parent_data->chip->irq_eoi)
+		parent_data->chip->irq_eoi(parent_data);
+}
+
+static int msm_dirconn_irq_set_affinity(struct irq_data *d,
+		const struct cpumask *maskval, bool force)
+{
+	struct irq_desc *desc = irq_data_to_desc(d);
+	struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+
+	if (parent_data->chip->irq_set_affinity)
+		return parent_data->chip->irq_set_affinity(parent_data,
+				maskval, force);
+	return 0;
+}
+
+static int msm_dirconn_irq_set_vcpu_affinity(struct irq_data *d,
+		void *vcpu_info)
+{
+	struct irq_desc *desc = irq_data_to_desc(d);
+	struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+
+	if (parent_data->chip->irq_set_vcpu_affinity)
+		return parent_data->chip->irq_set_vcpu_affinity(parent_data,
+				vcpu_info);
+	return 0;
+}
+
+static int msm_dirconn_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct irq_desc *desc = irq_data_to_desc(d);
+	struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+
+	if (parent_data->chip->irq_set_type)
+		return parent_data->chip->irq_set_type(parent_data, type);
+
+	return 0;
+}
+
+static struct irq_chip msm_dirconn_irq_chip = {
+	.name			= "msmgpio-dc",
+	.irq_mask		= msm_dirconn_irq_mask,
+	.irq_unmask		= msm_dirconn_irq_unmask,
+	.irq_eoi		= msm_dirconn_irq_eoi,
+	.irq_ack		= msm_dirconn_irq_ack,
+	.irq_set_type		= msm_dirconn_irq_set_type,
+	.irq_set_affinity	= msm_dirconn_irq_set_affinity,
+	.irq_set_vcpu_affinity	= msm_dirconn_irq_set_vcpu_affinity,
+	.flags			= IRQCHIP_SKIP_SET_WAKE
+					| IRQCHIP_MASK_ON_SUSPEND
+					| IRQCHIP_SET_TYPE_MASKED,
+};
+
 static void msm_gpio_irq_handler(struct irq_desc *desc)
 {
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
@@ -783,6 +869,55 @@
 	chained_irq_exit(chip, desc);
 }
 
+static void msm_gpio_dirconn_handler(struct irq_desc *desc)
+{
+	struct irq_data *irqd = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+	generic_handle_irq(irqd->irq);
+	chained_irq_exit(chip, desc);
+}
+
+static void msm_gpio_setup_dir_connects(struct msm_pinctrl *pctrl)
+{
+	struct device_node *parent_node;
+	struct irq_domain *parent_domain;
+	struct irq_fwspec fwspec;
+	unsigned int i;
+
+	parent_node = of_irq_find_parent(pctrl->dev->of_node);
+
+	if (!parent_node)
+		return;
+
+	parent_domain = irq_find_host(parent_node);
+	if (!parent_domain)
+		return;
+
+	fwspec.fwnode = parent_domain->fwnode;
+	for (i = 0; i < pctrl->soc->n_dir_conns; i++) {
+		const struct msm_dir_conn *dirconn = &pctrl->soc->dir_conn[i];
+		unsigned int parent_irq;
+		int irq;
+
+		fwspec.param[0] = 0; /* SPI */
+		fwspec.param[1] = dirconn->hwirq;
+		fwspec.param[2] = IRQ_TYPE_NONE;
+		fwspec.param_count = 3;
+		parent_irq = irq_create_fwspec_mapping(&fwspec);
+
+		irq = irq_find_mapping(pctrl->chip.irqdomain, dirconn->gpio);
+
+		irq_set_parent(irq, parent_irq);
+		irq_set_chip(irq, &msm_dirconn_irq_chip);
+		irq_set_chip_data(irq, irq_get_irq_data(parent_irq));
+		__irq_set_handler(parent_irq, msm_gpio_dirconn_handler,
+				false, NULL);
+		irq_set_handler_data(parent_irq, irq_get_irq_data(irq));
+	}
+}
+
 static int msm_gpio_init(struct msm_pinctrl *pctrl)
 {
 	struct gpio_chip *chip;
@@ -827,6 +962,7 @@
 	gpiochip_set_chained_irqchip(chip, &msm_gpio_irq_chip, pctrl->irq,
 				     msm_gpio_irq_handler);
 
+	msm_gpio_setup_dir_connects(pctrl);
 	return 0;
 }
 
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index e986fda..0e223e0 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -95,6 +95,16 @@
 	unsigned intr_polarity_bit:5;
 	unsigned intr_detection_bit:5;
 	unsigned intr_detection_width:5;
+}
+
+/**
+ * struct msm_dir_conn - Direct GPIO connect configuration
+ * @gpio:	GPIO pin number
+ * @hwirq:	The GIC interrupt that the pin is connected to
+ */;
+struct msm_dir_conn {
+	unsigned int gpio;
+	irq_hw_number_t hwirq;
 };
 
 /**
@@ -106,6 +116,8 @@
  * @groups:     An array describing all pin groups the pin SoC supports.
  * @ngroups:    The numbmer of entries in @groups.
  * @ngpio:      The number of pingroups the driver should expose as GPIOs.
+ * @dir_conn:   An array describing all the pins directly connected to GIC.
+ * @ndirconns:  The number of pins directly connected to GIC
  */
 struct msm_pinctrl_soc_data {
 	const struct pinctrl_pin_desc *pins;
@@ -115,6 +127,8 @@
 	const struct msm_pingroup *groups;
 	unsigned ngroups;
 	unsigned ngpios;
+	const struct msm_dir_conn *dir_conn;
+	unsigned int n_dir_conns;
 };
 
 int msm_pinctrl_probe(struct platform_device *pdev,
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c
index 30c31a8..7d125eb 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm845.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c
@@ -2377,6 +2377,84 @@
 	UFS_RESET(ufs_reset, 0x99f000),
 };
 
+static const struct msm_dir_conn sdm845_dir_conn[] = {
+	{1, 510},
+	{3, 511},
+	{5, 512},
+	{10, 513},
+	{11, 514},
+	{20, 515},
+	{22, 516},
+	{24, 517},
+	{26, 518},
+	{30, 519},
+	{31, 639},
+	{32, 521},
+	{34, 522},
+	{36, 523},
+	{37, 524},
+	{38, 525},
+	{39, 526},
+	{40, 527},
+	{41, 637},
+	{43, 529},
+	{44, 530},
+	{46, 531},
+	{48, 532},
+	{49, 640},
+	{52, 534},
+	{53, 535},
+	{54, 536},
+	{56, 537},
+	{57, 538},
+	{58, 539},
+	{59, 540},
+	{60, 541},
+	{61, 542},
+	{62, 543},
+	{63, 544},
+	{64, 545},
+	{66, 546},
+	{68, 547},
+	{71, 548},
+	{73, 549},
+	{77, 550},
+	{78, 551},
+	{79, 552},
+	{80, 553},
+	{84, 554},
+	{85, 555},
+	{86, 556},
+	{88, 557},
+	{89, 638},
+	{91, 559},
+	{92, 560},
+	{95, 561},
+	{96, 562},
+	{97, 563},
+	{101, 564},
+	{103, 565},
+	{104, 566},
+	{115, 570},
+	{116, 571},
+	{117, 572},
+	{118, 573},
+	{119, 609},
+	{120, 610},
+	{121, 611},
+	{122, 612},
+	{123, 613},
+	{124, 614},
+	{125, 615},
+	{127, 617},
+	{128, 618},
+	{129, 619},
+	{130, 620},
+	{132, 621},
+	{133, 622},
+	{145, 623},
+};
+
 static const struct msm_pinctrl_soc_data sdm845_pinctrl = {
 	.pins = sdm845_pins,
 	.npins = ARRAY_SIZE(sdm845_pins),
@@ -2385,6 +2463,8 @@
 	.groups = sdm845_groups,
 	.ngroups = ARRAY_SIZE(sdm845_groups),
 	.ngpios = 150,
+	.dir_conn = sdm845_dir_conn,
+	.n_dir_conns = ARRAY_SIZE(sdm845_dir_conn),
 };
 
 static int sdm845_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 6c597f0..38264d9 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -101,76 +101,76 @@
 
 const char *ipa_clients_strings[IPA_CLIENT_MAX] = {
 	__stringify(IPA_CLIENT_HSIC1_PROD),
-	__stringify(IPA_CLIENT_WLAN1_PROD),
-	__stringify(IPA_CLIENT_HSIC2_PROD),
-	__stringify(IPA_CLIENT_USB2_PROD),
-	__stringify(IPA_CLIENT_HSIC3_PROD),
-	__stringify(IPA_CLIENT_USB3_PROD),
-	__stringify(IPA_CLIENT_HSIC4_PROD),
-	__stringify(IPA_CLIENT_USB4_PROD),
-	__stringify(IPA_CLIENT_HSIC5_PROD),
-	__stringify(IPA_CLIENT_USB_PROD),
-	__stringify(IPA_CLIENT_A5_WLAN_AMPDU_PROD),
-	__stringify(IPA_CLIENT_A2_EMBEDDED_PROD),
-	__stringify(IPA_CLIENT_A2_TETHERED_PROD),
-	__stringify(IPA_CLIENT_APPS_LAN_PROD),
-	__stringify(IPA_CLIENT_APPS_WAN_PROD),
-	__stringify(IPA_CLIENT_APPS_CMD_PROD),
-	__stringify(IPA_CLIENT_ODU_PROD),
-	__stringify(IPA_CLIENT_MHI_PROD),
-	__stringify(IPA_CLIENT_Q6_LAN_PROD),
-	__stringify(IPA_CLIENT_Q6_WAN_PROD),
-	__stringify(IPA_CLIENT_Q6_CMD_PROD),
-	__stringify(IPA_CLIENT_MEMCPY_DMA_SYNC_PROD),
-	__stringify(IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD),
-	__stringify(IPA_CLIENT_Q6_DECOMP_PROD),
-	__stringify(IPA_CLIENT_Q6_DECOMP2_PROD),
-	__stringify(IPA_CLIENT_UC_USB_PROD),
-	__stringify(IPA_CLIENT_ETHERNET_PROD),
-
-	/* Below PROD client type is only for test purpose */
-	__stringify(IPA_CLIENT_TEST_PROD),
-	__stringify(IPA_CLIENT_TEST1_PROD),
-	__stringify(IPA_CLIENT_TEST2_PROD),
-	__stringify(IPA_CLIENT_TEST3_PROD),
-	__stringify(IPA_CLIENT_TEST4_PROD),
-
 	__stringify(IPA_CLIENT_HSIC1_CONS),
-	__stringify(IPA_CLIENT_WLAN1_CONS),
+	__stringify(IPA_CLIENT_HSIC2_PROD),
 	__stringify(IPA_CLIENT_HSIC2_CONS),
-	__stringify(IPA_CLIENT_USB2_CONS),
-	__stringify(IPA_CLIENT_WLAN2_CONS),
+	__stringify(IPA_CLIENT_HSIC3_PROD),
 	__stringify(IPA_CLIENT_HSIC3_CONS),
-	__stringify(IPA_CLIENT_USB3_CONS),
-	__stringify(IPA_CLIENT_WLAN3_CONS),
+	__stringify(IPA_CLIENT_HSIC4_PROD),
 	__stringify(IPA_CLIENT_HSIC4_CONS),
-	__stringify(IPA_CLIENT_USB4_CONS),
-	__stringify(IPA_CLIENT_WLAN4_CONS),
+	__stringify(IPA_CLIENT_HSIC5_PROD),
 	__stringify(IPA_CLIENT_HSIC5_CONS),
+	__stringify(IPA_CLIENT_WLAN1_PROD),
+	__stringify(IPA_CLIENT_WLAN1_CONS),
+	__stringify(IPA_CLIENT_A5_WLAN_AMPDU_PROD),
+	__stringify(IPA_CLIENT_WLAN2_CONS),
+	__stringify(RESERVERD_PROD_14),
+	__stringify(IPA_CLIENT_WLAN3_CONS),
+	__stringify(RESERVERD_PROD_16),
+	__stringify(IPA_CLIENT_WLAN4_CONS),
+	__stringify(IPA_CLIENT_USB_PROD),
 	__stringify(IPA_CLIENT_USB_CONS),
+	__stringify(IPA_CLIENT_USB2_PROD),
+	__stringify(IPA_CLIENT_USB2_CONS),
+	__stringify(IPA_CLIENT_USB3_PROD),
+	__stringify(IPA_CLIENT_USB3_CONS),
+	__stringify(IPA_CLIENT_USB4_PROD),
+	__stringify(IPA_CLIENT_USB4_CONS),
+	__stringify(IPA_CLIENT_UC_USB_PROD),
 	__stringify(IPA_CLIENT_USB_DPL_CONS),
+	__stringify(IPA_CLIENT_A2_EMBEDDED_PROD),
 	__stringify(IPA_CLIENT_A2_EMBEDDED_CONS),
+	__stringify(IPA_CLIENT_A2_TETHERED_PROD),
 	__stringify(IPA_CLIENT_A2_TETHERED_CONS),
-	__stringify(IPA_CLIENT_A5_LAN_WAN_CONS),
+	__stringify(IPA_CLIENT_APPS_LAN_PROD),
 	__stringify(IPA_CLIENT_APPS_LAN_CONS),
+	__stringify(IPA_CLIENT_APPS_WAN_PROD),
 	__stringify(IPA_CLIENT_APPS_WAN_CONS),
+	__stringify(IPA_CLIENT_APPS_CMD_PROD),
+	__stringify(IPA_CLIENT_A5_LAN_WAN_CONS),
+	__stringify(IPA_CLIENT_ODU_PROD),
 	__stringify(IPA_CLIENT_ODU_EMB_CONS),
+	__stringify(RESERVERD_PROD_40),
 	__stringify(IPA_CLIENT_ODU_TETH_CONS),
+	__stringify(IPA_CLIENT_MHI_PROD),
 	__stringify(IPA_CLIENT_MHI_CONS),
-	__stringify(IPA_CLIENT_Q6_LAN_CONS),
-	__stringify(IPA_CLIENT_Q6_WAN_CONS),
-	__stringify(IPA_CLIENT_Q6_DUN_CONS),
+	__stringify(IPA_CLIENT_MEMCPY_DMA_SYNC_PROD),
 	__stringify(IPA_CLIENT_MEMCPY_DMA_SYNC_CONS),
+	__stringify(IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD),
 	__stringify(IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS),
-	__stringify(IPA_CLIENT_Q6_DECOMP_CONS),
-	__stringify(IPA_CLIENT_Q6_DECOMP2_CONS),
-	__stringify(IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS),
+	__stringify(IPA_CLIENT_ETHERNET_PROD),
 	__stringify(IPA_CLIENT_ETHERNET_CONS),
-	/* Below CONS client type is only for test purpose */
+	__stringify(IPA_CLIENT_Q6_LAN_PROD),
+	__stringify(IPA_CLIENT_Q6_LAN_CONS),
+	__stringify(IPA_CLIENT_Q6_WAN_PROD),
+	__stringify(IPA_CLIENT_Q6_WAN_CONS),
+	__stringify(IPA_CLIENT_Q6_CMD_PROD),
+	__stringify(IPA_CLIENT_Q6_DUN_CONS),
+	__stringify(IPA_CLIENT_Q6_DECOMP_PROD),
+	__stringify(IPA_CLIENT_Q6_DECOMP_CONS),
+	__stringify(IPA_CLIENT_Q6_DECOMP2_PROD),
+	__stringify(IPA_CLIENT_Q6_DECOMP2_CONS),
+	__stringify(RESERVERD_PROD_60),
+	__stringify(IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS),
+	__stringify(IPA_CLIENT_TEST_PROD),
 	__stringify(IPA_CLIENT_TEST_CONS),
+	__stringify(IPA_CLIENT_TEST1_PROD),
 	__stringify(IPA_CLIENT_TEST1_CONS),
+	__stringify(IPA_CLIENT_TEST2_PROD),
 	__stringify(IPA_CLIENT_TEST2_CONS),
+	__stringify(IPA_CLIENT_TEST3_PROD),
 	__stringify(IPA_CLIENT_TEST3_CONS),
+	__stringify(IPA_CLIENT_TEST4_PROD),
 	__stringify(IPA_CLIENT_TEST4_CONS),
 };
 
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index 981129e..50804ee 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -108,8 +108,10 @@
 		ipa_assert();\
 } while (0)
 
-#define IPA_CLIENT_IS_PROD(x) (x >= IPA_CLIENT_PROD && x < IPA_CLIENT_CONS)
-#define IPA_CLIENT_IS_CONS(x) (x >= IPA_CLIENT_CONS && x < IPA_CLIENT_MAX)
+#define IPA_CLIENT_IS_PROD(x) \
+	(x < IPA_CLIENT_MAX && (x & 0x1) == 0)
+#define IPA_CLIENT_IS_CONS(x) \
+	(x < IPA_CLIENT_MAX && (x & 0x1) == 1)
 
 #define IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC (1000)
 #define IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC (2000)
diff --git a/drivers/platform/msm/ipa/ipa_rm.c b/drivers/platform/msm/ipa/ipa_rm.c
index ea91b13..914028c 100644
--- a/drivers/platform/msm/ipa/ipa_rm.c
+++ b/drivers/platform/msm/ipa/ipa_rm.c
@@ -19,32 +19,33 @@
 
 static const char *resource_name_to_str[IPA_RM_RESOURCE_MAX] = {
 	__stringify(IPA_RM_RESOURCE_Q6_PROD),
-	__stringify(IPA_RM_RESOURCE_USB_PROD),
-	__stringify(IPA_RM_RESOURCE_USB_DPL_DUMMY_PROD),
-	__stringify(IPA_RM_RESOURCE_HSIC_PROD),
-	__stringify(IPA_RM_RESOURCE_STD_ECM_PROD),
-	__stringify(IPA_RM_RESOURCE_RNDIS_PROD),
-	__stringify(IPA_RM_RESOURCE_WWAN_0_PROD),
-	__stringify(IPA_RM_RESOURCE_WLAN_PROD),
-	__stringify(IPA_RM_RESOURCE_ODU_ADAPT_PROD),
-	__stringify(IPA_RM_RESOURCE_MHI_PROD),
-	__stringify(IPA_RM_RESOURCE_ETHERNET_PROD),
 	__stringify(IPA_RM_RESOURCE_Q6_CONS),
+	__stringify(IPA_RM_RESOURCE_USB_PROD),
 	__stringify(IPA_RM_RESOURCE_USB_CONS),
+	__stringify(IPA_RM_RESOURCE_USB_DPL_DUMMY_PROD),
 	__stringify(IPA_RM_RESOURCE_USB_DPL_CONS),
+	__stringify(IPA_RM_RESOURCE_HSIC_PROD),
 	__stringify(IPA_RM_RESOURCE_HSIC_CONS),
-	__stringify(IPA_RM_RESOURCE_WLAN_CONS),
+	__stringify(IPA_RM_RESOURCE_STD_ECM_PROD),
 	__stringify(IPA_RM_RESOURCE_APPS_CONS),
+	__stringify(IPA_RM_RESOURCE_RNDIS_PROD),
+	__stringify(RESERVED_CONS_11),
+	__stringify(IPA_RM_RESOURCE_WWAN_0_PROD),
+	__stringify(RESERVED_CONS_13),
+	__stringify(IPA_RM_RESOURCE_WLAN_PROD),
+	__stringify(IPA_RM_RESOURCE_WLAN_CONS),
+	__stringify(IPA_RM_RESOURCE_ODU_ADAPT_PROD),
 	__stringify(IPA_RM_RESOURCE_ODU_ADAPT_CONS),
+	__stringify(IPA_RM_RESOURCE_MHI_PROD),
 	__stringify(IPA_RM_RESOURCE_MHI_CONS),
+	__stringify(IPA_RM_RESOURCE_ETHERNET_PROD),
 	__stringify(IPA_RM_RESOURCE_ETHERNET_CONS),
 };
 
 struct ipa_rm_profile_vote_type {
 	enum ipa_voltage_level volt[IPA_RM_RESOURCE_MAX];
 	enum ipa_voltage_level curr_volt;
-	u32 bw_prods[IPA_RM_RESOURCE_PROD_MAX];
-	u32 bw_cons[IPA_RM_RESOURCE_CONS_MAX];
+	u32 bw_resources[IPA_RM_RESOURCE_MAX];
 	u32 curr_bw;
 };
 
@@ -999,7 +1000,9 @@
 		return result;
 
 	spin_lock_irqsave(&ipa_rm_ctx->ipa_rm_lock, flags);
-	for (i = 0; i < IPA_RM_RESOURCE_PROD_MAX; ++i) {
+	for (i = 0; i < IPA_RM_RESOURCE_MAX; ++i) {
+		if (!IPA_RM_RESORCE_IS_PROD(i))
+			continue;
 		result = ipa_rm_dep_graph_get_resource(
 				ipa_rm_ctx->dep_graph,
 				i,
@@ -1014,11 +1017,12 @@
 		}
 	}
 
-	for (i = 0; i < IPA_RM_RESOURCE_PROD_MAX; i++)
-		sum_bw_prod += ipa_rm_ctx->prof_vote.bw_prods[i];
-
-	for (i = 0; i < IPA_RM_RESOURCE_CONS_MAX; i++)
-		sum_bw_cons += ipa_rm_ctx->prof_vote.bw_cons[i];
+	for (i = 0; i < IPA_RM_RESOURCE_MAX; i++) {
+		if (IPA_RM_RESORCE_IS_PROD(i))
+			sum_bw_prod += ipa_rm_ctx->prof_vote.bw_resources[i];
+		else
+			sum_bw_cons += ipa_rm_ctx->prof_vote.bw_resources[i];
+	}
 
 	result = scnprintf(buf + cnt, size - cnt,
 		"All prod bandwidth: %d, All cons bandwidth: %d\n",
@@ -1118,15 +1122,7 @@
 	old_volt = ipa_rm_ctx->prof_vote.curr_volt;
 	old_bw = ipa_rm_ctx->prof_vote.curr_bw;
 
-	if (IPA_RM_RESORCE_IS_PROD(resource_name)) {
-		bw_ptr = &ipa_rm_ctx->prof_vote.bw_prods[resource_name];
-	} else if (IPA_RM_RESORCE_IS_CONS(resource_name)) {
-		bw_ptr = &ipa_rm_ctx->prof_vote.bw_cons[
-				resource_name - IPA_RM_RESOURCE_PROD_MAX];
-	} else {
-		IPA_RM_ERR("Invalid resource_name\n");
-		return;
-	}
+	bw_ptr = &ipa_rm_ctx->prof_vote.bw_resources[resource_name];
 
 	switch (resource->state) {
 	case IPA_RM_GRANTED:
@@ -1161,11 +1157,12 @@
 		}
 	}
 
-	for (i = 0; i < IPA_RM_RESOURCE_PROD_MAX; i++)
-		sum_bw_prod += ipa_rm_ctx->prof_vote.bw_prods[i];
-
-	for (i = 0; i < IPA_RM_RESOURCE_CONS_MAX; i++)
-		sum_bw_cons += ipa_rm_ctx->prof_vote.bw_cons[i];
+	for (i = 0; i < IPA_RM_RESOURCE_MAX; i++) {
+		if (IPA_RM_RESORCE_IS_PROD(i))
+			sum_bw_prod += ipa_rm_ctx->prof_vote.bw_resources[i];
+		else
+			sum_bw_cons += ipa_rm_ctx->prof_vote.bw_resources[i];
+	}
 
 	IPA_RM_DBG_LOW("all prod bandwidth: %d all cons bandwidth: %d\n",
 		sum_bw_prod, sum_bw_cons);
diff --git a/drivers/platform/msm/ipa/ipa_rm_i.h b/drivers/platform/msm/ipa/ipa_rm_i.h
index 1610bb1..c0e3ce2 100644
--- a/drivers/platform/msm/ipa/ipa_rm_i.h
+++ b/drivers/platform/msm/ipa/ipa_rm_i.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -47,12 +47,10 @@
 			IPA_RM_DRV_NAME " %s:%d " fmt, ## args); \
 	} while (0)
 
-#define IPA_RM_RESOURCE_CONS_MAX \
-	(IPA_RM_RESOURCE_MAX - IPA_RM_RESOURCE_PROD_MAX)
 #define IPA_RM_RESORCE_IS_PROD(x) \
-	(x >= IPA_RM_RESOURCE_PROD && x < IPA_RM_RESOURCE_PROD_MAX)
+	(x < IPA_RM_RESOURCE_MAX && (x & 0x1) == 0)
 #define IPA_RM_RESORCE_IS_CONS(x) \
-	(x >= IPA_RM_RESOURCE_PROD_MAX && x < IPA_RM_RESOURCE_MAX)
+	(x < IPA_RM_RESOURCE_MAX && (x & 0x1) == 1)
 #define IPA_RM_INDEX_INVALID	(-1)
 #define IPA_RM_RELEASE_DELAY_IN_MSEC 1000
 
diff --git a/drivers/platform/msm/ipa/ipa_rm_peers_list.c b/drivers/platform/msm/ipa/ipa_rm_peers_list.c
index fe8e781..8365120 100644
--- a/drivers/platform/msm/ipa/ipa_rm_peers_list.c
+++ b/drivers/platform/msm/ipa/ipa_rm_peers_list.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -32,9 +32,6 @@
 		resource_index = ipa_rm_prod_index(resource_name);
 	else if (IPA_RM_RESORCE_IS_CONS(resource_name)) {
 		resource_index = ipa_rm_cons_index(resource_name);
-		if (resource_index != IPA_RM_INDEX_INVALID)
-			resource_index =
-				resource_index - IPA_RM_RESOURCE_PROD_MAX;
 	}
 
 	return resource_index;
diff --git a/drivers/platform/msm/ipa/ipa_rm_resource.c b/drivers/platform/msm/ipa/ipa_rm_resource.c
index 9e74a3f..991208f 100644
--- a/drivers/platform/msm/ipa/ipa_rm_resource.c
+++ b/drivers/platform/msm/ipa/ipa_rm_resource.c
@@ -328,7 +328,7 @@
 
 	(*resource) = (struct ipa_rm_resource *) (*producer);
 	(*resource)->type = IPA_RM_PRODUCER;
-	*max_peers = IPA_RM_RESOURCE_CONS_MAX;
+	*max_peers = IPA_RM_RESOURCE_MAX;
 	goto bail;
 register_fail:
 	kfree(*producer);
@@ -371,7 +371,7 @@
 	(*resource) = (struct ipa_rm_resource *) (*consumer);
 	(*resource)->type = IPA_RM_CONSUMER;
 	init_completion(&((*consumer)->request_consumer_in_progress));
-	*max_peers = IPA_RM_RESOURCE_PROD_MAX;
+	*max_peers = IPA_RM_RESOURCE_MAX;
 bail:
 	return result;
 }
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index f5d8227..947a54c 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -3713,7 +3713,7 @@
 				resource = ipa2_get_rm_resource_from_ep(i);
 				res = ipa_rm_request_resource_with_timer(
 					resource);
-				if (res == -EPERM &&
+				if ((res == -EPERM) &&
 				    IPA_CLIENT_IS_CONS(
 					ipa_ctx->ep[i].client)) {
 					holb_cfg.en = 1;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
index a822f66..0196815 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
@@ -953,7 +953,7 @@
 
 	IPADBG("\n");
 
-	for (client_num = IPA_CLIENT_CONS;
+	for (client_num = 0;
 		client_num < IPA_CLIENT_MAX; client_num++) {
 		if (!IPA_CLIENT_IS_APPS_CONS(client_num))
 			continue;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index a50665c..da62b77 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -72,209 +72,124 @@
 
 #define INVALID_EP_MAPPING_INDEX (-1)
 
-static const int ep_mapping[3][IPA_CLIENT_MAX] = {
-	[IPA_1_1][IPA_CLIENT_HSIC1_PROD]         = 19,
-	[IPA_1_1][IPA_CLIENT_WLAN1_PROD]         = -1,
-	[IPA_1_1][IPA_CLIENT_HSIC2_PROD]         = 12,
-	[IPA_1_1][IPA_CLIENT_USB2_PROD]          = 12,
-	[IPA_1_1][IPA_CLIENT_HSIC3_PROD]         = 13,
-	[IPA_1_1][IPA_CLIENT_USB3_PROD]          = 13,
-	[IPA_1_1][IPA_CLIENT_HSIC4_PROD]         =  0,
-	[IPA_1_1][IPA_CLIENT_USB4_PROD]          =  0,
-	[IPA_1_1][IPA_CLIENT_HSIC5_PROD]         = -1,
-	[IPA_1_1][IPA_CLIENT_USB_PROD]           = 11,
-	[IPA_1_1][IPA_CLIENT_A5_WLAN_AMPDU_PROD] = 15,
-	[IPA_1_1][IPA_CLIENT_A2_EMBEDDED_PROD]   =  8,
-	[IPA_1_1][IPA_CLIENT_A2_TETHERED_PROD]   =  6,
-	[IPA_1_1][IPA_CLIENT_APPS_LAN_PROD]      = -1,
-	[IPA_1_1][IPA_CLIENT_APPS_LAN_WAN_PROD]  =  2,
-	[IPA_1_1][IPA_CLIENT_APPS_CMD_PROD]      =  1,
-	[IPA_1_1][IPA_CLIENT_ODU_PROD]           = -1,
-	[IPA_1_1][IPA_CLIENT_MHI_PROD]           = -1,
-	[IPA_1_1][IPA_CLIENT_Q6_LAN_PROD]        =  5,
-	[IPA_1_1][IPA_CLIENT_Q6_WAN_PROD]        = -1,
-	[IPA_1_1][IPA_CLIENT_Q6_CMD_PROD]        = -1,
-	[IPA_1_1][IPA_CLIENT_ETHERNET_PROD]      = -1,
+struct ipa_ep_confing {
+	bool valid;
+	int pipe_num;
+};
 
-	[IPA_1_1][IPA_CLIENT_HSIC1_CONS]         = 14,
-	[IPA_1_1][IPA_CLIENT_WLAN1_CONS]         = -1,
-	[IPA_1_1][IPA_CLIENT_HSIC2_CONS]         = 16,
-	[IPA_1_1][IPA_CLIENT_USB2_CONS]          = 16,
-	[IPA_1_1][IPA_CLIENT_WLAN2_CONS]         = -1,
-	[IPA_1_1][IPA_CLIENT_HSIC3_CONS]         = 17,
-	[IPA_1_1][IPA_CLIENT_USB3_CONS]          = 17,
-	[IPA_1_1][IPA_CLIENT_WLAN3_CONS]         = -1,
-	[IPA_1_1][IPA_CLIENT_HSIC4_CONS]         = 18,
-	[IPA_1_1][IPA_CLIENT_USB4_CONS]          = 18,
-	[IPA_1_1][IPA_CLIENT_WLAN4_CONS]         = -1,
-	[IPA_1_1][IPA_CLIENT_HSIC5_CONS]         = -1,
-	[IPA_1_1][IPA_CLIENT_USB_CONS]           = 10,
-	[IPA_1_1][IPA_CLIENT_USB_DPL_CONS]       = -1,
-	[IPA_1_1][IPA_CLIENT_A2_EMBEDDED_CONS]   =  9,
-	[IPA_1_1][IPA_CLIENT_A2_TETHERED_CONS]   =  7,
-	[IPA_1_1][IPA_CLIENT_A5_LAN_WAN_CONS]    =  3,
-	[IPA_1_1][IPA_CLIENT_APPS_LAN_CONS]      = -1,
-	[IPA_1_1][IPA_CLIENT_APPS_WAN_CONS]      = -1,
-	[IPA_1_1][IPA_CLIENT_ODU_EMB_CONS]       = -1,
-	[IPA_1_1][IPA_CLIENT_ODU_TETH_CONS]      = -1,
-	[IPA_1_1][IPA_CLIENT_MHI_CONS]           = -1,
-	[IPA_1_1][IPA_CLIENT_Q6_LAN_CONS]        =  4,
-	[IPA_1_1][IPA_CLIENT_Q6_WAN_CONS]        = -1,
-	[IPA_1_1][IPA_CLIENT_ETHERNET_CONS]      = -1,
+static const struct ipa_ep_confing ep_mapping[3][IPA_CLIENT_MAX] = {
+	[IPA_1_1][IPA_CLIENT_HSIC1_PROD]         = {true, 19},
+	[IPA_1_1][IPA_CLIENT_HSIC2_PROD]         = {true, 12},
+	[IPA_1_1][IPA_CLIENT_USB2_PROD]          = {true, 12},
+	[IPA_1_1][IPA_CLIENT_HSIC3_PROD]         = {true, 13},
+	[IPA_1_1][IPA_CLIENT_USB3_PROD]          = {true, 13},
+	[IPA_1_1][IPA_CLIENT_HSIC4_PROD]         = {true,  0},
+	[IPA_1_1][IPA_CLIENT_USB4_PROD]          = {true,  0},
+	[IPA_1_1][IPA_CLIENT_USB_PROD]           = {true, 11},
+	[IPA_1_1][IPA_CLIENT_A5_WLAN_AMPDU_PROD] = {true, 15},
+	[IPA_1_1][IPA_CLIENT_A2_EMBEDDED_PROD]   = {true,  8},
+	[IPA_1_1][IPA_CLIENT_A2_TETHERED_PROD]   = {true,  6},
+	[IPA_1_1][IPA_CLIENT_APPS_LAN_WAN_PROD]  = {true,  2},
+	[IPA_1_1][IPA_CLIENT_APPS_CMD_PROD]      = {true,  1},
+	[IPA_1_1][IPA_CLIENT_Q6_LAN_PROD]        = {true,  5},
+
+	[IPA_1_1][IPA_CLIENT_HSIC1_CONS]         = {true, 14},
+	[IPA_1_1][IPA_CLIENT_HSIC2_CONS]         = {true, 16},
+	[IPA_1_1][IPA_CLIENT_USB2_CONS]          = {true, 16},
+	[IPA_1_1][IPA_CLIENT_HSIC3_CONS]         = {true, 17},
+	[IPA_1_1][IPA_CLIENT_USB3_CONS]          = {true, 17},
+	[IPA_1_1][IPA_CLIENT_HSIC4_CONS]         = {true, 18},
+	[IPA_1_1][IPA_CLIENT_USB4_CONS]          = {true, 18},
+	[IPA_1_1][IPA_CLIENT_USB_CONS]           = {true, 10},
+	[IPA_1_1][IPA_CLIENT_A2_EMBEDDED_CONS]   = {true,  9},
+	[IPA_1_1][IPA_CLIENT_A2_TETHERED_CONS]   = {true,  7},
+	[IPA_1_1][IPA_CLIENT_A5_LAN_WAN_CONS]    = {true,  3},
+	[IPA_1_1][IPA_CLIENT_Q6_LAN_CONS]        = {true,  4},
 
 
-	[IPA_2_0][IPA_CLIENT_HSIC1_PROD]         = 12,
-	[IPA_2_0][IPA_CLIENT_WLAN1_PROD]         = 18,
-	[IPA_2_0][IPA_CLIENT_HSIC2_PROD]         = -1,
-	[IPA_2_0][IPA_CLIENT_USB2_PROD]          = 12,
-	[IPA_2_0][IPA_CLIENT_HSIC3_PROD]         = -1,
-	[IPA_2_0][IPA_CLIENT_USB3_PROD]          = 13,
-	[IPA_2_0][IPA_CLIENT_HSIC4_PROD]         = -1,
-	[IPA_2_0][IPA_CLIENT_USB4_PROD]          =  0,
-	[IPA_2_0][IPA_CLIENT_HSIC5_PROD]         = -1,
-	[IPA_2_0][IPA_CLIENT_USB_PROD]           = 11,
-	[IPA_2_0][IPA_CLIENT_A5_WLAN_AMPDU_PROD] = -1,
-	[IPA_2_0][IPA_CLIENT_A2_EMBEDDED_PROD]   = -1,
-	[IPA_2_0][IPA_CLIENT_A2_TETHERED_PROD]   = -1,
-	[IPA_2_0][IPA_CLIENT_APPS_LAN_PROD]      = -1,
-	[IPA_2_0][IPA_CLIENT_APPS_LAN_WAN_PROD]  =  4,
-	[IPA_2_0][IPA_CLIENT_APPS_CMD_PROD]      =  3,
-	[IPA_2_0][IPA_CLIENT_ODU_PROD]           = 12,
-	[IPA_2_0][IPA_CLIENT_MHI_PROD]           = 18,
-	[IPA_2_0][IPA_CLIENT_Q6_LAN_PROD]        =  6,
-	[IPA_2_0][IPA_CLIENT_Q6_WAN_PROD]	 = -1,
-	[IPA_2_0][IPA_CLIENT_Q6_CMD_PROD]        =  7,
-	[IPA_2_0][IPA_CLIENT_Q6_DECOMP_PROD]     = -1,
-	[IPA_2_0][IPA_CLIENT_Q6_DECOMP2_PROD]    = -1,
+	[IPA_2_0][IPA_CLIENT_HSIC1_PROD]         = {true, 12},
+	[IPA_2_0][IPA_CLIENT_WLAN1_PROD]         = {true, 18},
+	[IPA_2_0][IPA_CLIENT_USB2_PROD]          = {true, 12},
+	[IPA_2_0][IPA_CLIENT_USB3_PROD]          = {true, 13},
+	[IPA_2_0][IPA_CLIENT_USB4_PROD]          = {true,  0},
+	[IPA_2_0][IPA_CLIENT_USB_PROD]           = {true, 11},
+	[IPA_2_0][IPA_CLIENT_APPS_LAN_WAN_PROD]  = {true,  4},
+	[IPA_2_0][IPA_CLIENT_APPS_CMD_PROD]      = {true,  3},
+	[IPA_2_0][IPA_CLIENT_ODU_PROD]           = {true, 12},
+	[IPA_2_0][IPA_CLIENT_MHI_PROD]           = {true, 18},
+	[IPA_2_0][IPA_CLIENT_Q6_LAN_PROD]        = {true,  6},
+	[IPA_2_0][IPA_CLIENT_Q6_CMD_PROD]        = {true,  7},
 	[IPA_2_0][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD]
-						 =  12,
+						 = {true, 12},
 	[IPA_2_0][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD]
-						 =  19,
-	[IPA_2_0][IPA_CLIENT_ETHERNET_PROD]      = 12,
+						 = {true, 19},
+	[IPA_2_0][IPA_CLIENT_ETHERNET_PROD]      = {true, 12},
 	/* Only for test purpose */
-	[IPA_2_0][IPA_CLIENT_TEST_PROD]          = 19,
-	[IPA_2_0][IPA_CLIENT_TEST1_PROD]         = 19,
-	[IPA_2_0][IPA_CLIENT_TEST2_PROD]         = 12,
-	[IPA_2_0][IPA_CLIENT_TEST3_PROD]         = 11,
-	[IPA_2_0][IPA_CLIENT_TEST4_PROD]         =  0,
+	[IPA_2_0][IPA_CLIENT_TEST_PROD]          = {true, 19},
+	[IPA_2_0][IPA_CLIENT_TEST1_PROD]         = {true, 19},
+	[IPA_2_0][IPA_CLIENT_TEST2_PROD]         = {true, 12},
+	[IPA_2_0][IPA_CLIENT_TEST3_PROD]         = {true, 11},
+	[IPA_2_0][IPA_CLIENT_TEST4_PROD]         = {true,  0},
 
-	[IPA_2_0][IPA_CLIENT_HSIC1_CONS]         = 13,
-	[IPA_2_0][IPA_CLIENT_WLAN1_CONS]         = 17,
-	[IPA_2_0][IPA_CLIENT_HSIC2_CONS]         = -1,
-	[IPA_2_0][IPA_CLIENT_USB2_CONS]          = -1,
-	[IPA_2_0][IPA_CLIENT_WLAN2_CONS]         = 16,
-	[IPA_2_0][IPA_CLIENT_HSIC3_CONS]         = -1,
-	[IPA_2_0][IPA_CLIENT_USB3_CONS]          = -1,
-	[IPA_2_0][IPA_CLIENT_WLAN3_CONS]         = 14,
-	[IPA_2_0][IPA_CLIENT_HSIC4_CONS]         = -1,
-	[IPA_2_0][IPA_CLIENT_USB4_CONS]          = -1,
-	[IPA_2_0][IPA_CLIENT_WLAN4_CONS]         = 19,
-	[IPA_2_0][IPA_CLIENT_HSIC5_CONS]         = -1,
-	[IPA_2_0][IPA_CLIENT_USB_CONS]           = 15,
-	[IPA_2_0][IPA_CLIENT_USB_DPL_CONS]       =  0,
-	[IPA_2_0][IPA_CLIENT_A2_EMBEDDED_CONS]   = -1,
-	[IPA_2_0][IPA_CLIENT_A2_TETHERED_CONS]   = -1,
-	[IPA_2_0][IPA_CLIENT_A5_LAN_WAN_CONS]    = -1,
-	[IPA_2_0][IPA_CLIENT_APPS_LAN_CONS]      =  2,
-	[IPA_2_0][IPA_CLIENT_APPS_WAN_CONS]      =  5,
-	[IPA_2_0][IPA_CLIENT_ODU_EMB_CONS]       = 13,
-	[IPA_2_0][IPA_CLIENT_ODU_TETH_CONS]      =  1,
-	[IPA_2_0][IPA_CLIENT_MHI_CONS]           = 17,
-	[IPA_2_0][IPA_CLIENT_Q6_LAN_CONS]        =  8,
-	[IPA_2_0][IPA_CLIENT_Q6_WAN_CONS]        =  9,
-	[IPA_2_0][IPA_CLIENT_Q6_DUN_CONS]        = -1,
-	[IPA_2_0][IPA_CLIENT_Q6_DECOMP_CONS]     = -1,
-	[IPA_2_0][IPA_CLIENT_Q6_DECOMP2_CONS]    = -1,
+	[IPA_2_0][IPA_CLIENT_HSIC1_CONS]         = {true, 13},
+	[IPA_2_0][IPA_CLIENT_WLAN1_CONS]         = {true, 17},
+	[IPA_2_0][IPA_CLIENT_WLAN2_CONS]         = {true, 16},
+	[IPA_2_0][IPA_CLIENT_WLAN3_CONS]         = {true, 14},
+	[IPA_2_0][IPA_CLIENT_WLAN4_CONS]         = {true, 19},
+	[IPA_2_0][IPA_CLIENT_USB_CONS]           = {true, 15},
+	[IPA_2_0][IPA_CLIENT_USB_DPL_CONS]       = {true,  0},
+	[IPA_2_0][IPA_CLIENT_APPS_LAN_CONS]      = {true,  2},
+	[IPA_2_0][IPA_CLIENT_APPS_WAN_CONS]      = {true,  5},
+	[IPA_2_0][IPA_CLIENT_ODU_EMB_CONS]       = {true, 13},
+	[IPA_2_0][IPA_CLIENT_ODU_TETH_CONS]      = {true,  1},
+	[IPA_2_0][IPA_CLIENT_MHI_CONS]           = {true, 17},
+	[IPA_2_0][IPA_CLIENT_Q6_LAN_CONS]        = {true,  8},
+	[IPA_2_0][IPA_CLIENT_Q6_WAN_CONS]        = {true,  9},
 	[IPA_2_0][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS]
-						 =  13,
+						 = {true, 13},
 	[IPA_2_0][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS]
-						 =  16,
+						 = {true, 16},
 	[IPA_2_0][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS]
-						 =  10,
-	[IPA_2_0][IPA_CLIENT_ETHERNET_CONS]      = 1,
+						 = {true, 10},
+	[IPA_2_0][IPA_CLIENT_ETHERNET_CONS]      = {true,  1},
+
 	/* Only for test purpose */
-	[IPA_2_0][IPA_CLIENT_TEST_CONS]          = 1,
-	[IPA_2_0][IPA_CLIENT_TEST1_CONS]         = 1,
-	[IPA_2_0][IPA_CLIENT_TEST2_CONS]         = 16,
-	[IPA_2_0][IPA_CLIENT_TEST3_CONS]         = 13,
-	[IPA_2_0][IPA_CLIENT_TEST4_CONS]         = 15,
+	[IPA_2_0][IPA_CLIENT_TEST_CONS]          = {true,  1},
+	[IPA_2_0][IPA_CLIENT_TEST1_CONS]         = {true,  1},
+	[IPA_2_0][IPA_CLIENT_TEST2_CONS]         = {true, 16},
+	[IPA_2_0][IPA_CLIENT_TEST3_CONS]         = {true, 13},
+	[IPA_2_0][IPA_CLIENT_TEST4_CONS]         = {true, 15},
 
 
-	[IPA_2_6L][IPA_CLIENT_HSIC1_PROD]         = -1,
-	[IPA_2_6L][IPA_CLIENT_WLAN1_PROD]         = -1,
-	[IPA_2_6L][IPA_CLIENT_HSIC2_PROD]         = -1,
-	[IPA_2_6L][IPA_CLIENT_USB2_PROD]          = -1,
-	[IPA_2_6L][IPA_CLIENT_HSIC3_PROD]         = -1,
-	[IPA_2_6L][IPA_CLIENT_USB3_PROD]          = -1,
-	[IPA_2_6L][IPA_CLIENT_HSIC4_PROD]         = -1,
-	[IPA_2_6L][IPA_CLIENT_USB4_PROD]          = -1,
-	[IPA_2_6L][IPA_CLIENT_HSIC5_PROD]         = -1,
-	[IPA_2_6L][IPA_CLIENT_USB_PROD]           =  1,
-	[IPA_2_6L][IPA_CLIENT_A5_WLAN_AMPDU_PROD] = -1,
-	[IPA_2_6L][IPA_CLIENT_A2_EMBEDDED_PROD]   = -1,
-	[IPA_2_6L][IPA_CLIENT_A2_TETHERED_PROD]   = -1,
-	[IPA_2_6L][IPA_CLIENT_APPS_LAN_PROD]      = -1,
-	[IPA_2_6L][IPA_CLIENT_APPS_LAN_WAN_PROD]  =  4,
-	[IPA_2_6L][IPA_CLIENT_APPS_CMD_PROD]      =  3,
-	[IPA_2_6L][IPA_CLIENT_ODU_PROD]           = -1,
-	[IPA_2_6L][IPA_CLIENT_MHI_PROD]           = -1,
-	[IPA_2_6L][IPA_CLIENT_Q6_LAN_PROD]        =  6,
-	[IPA_2_6L][IPA_CLIENT_Q6_WAN_PROD]	  = -1,
-	[IPA_2_6L][IPA_CLIENT_Q6_CMD_PROD]        =  7,
-	[IPA_2_6L][IPA_CLIENT_Q6_DECOMP_PROD]     = 11,
-	[IPA_2_6L][IPA_CLIENT_Q6_DECOMP2_PROD]    = 13,
-	[IPA_2_6L][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD]
-						 =  -1,
-	[IPA_2_6L][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD]
-						 =  -1,
-	[IPA_2_6L][IPA_CLIENT_ETHERNET_PROD]      = -1,
-	/* Only for test purpose */
-	[IPA_2_6L][IPA_CLIENT_TEST_PROD]          = 11,
-	[IPA_2_6L][IPA_CLIENT_TEST1_PROD]         = 11,
-	[IPA_2_6L][IPA_CLIENT_TEST2_PROD]         = 12,
-	[IPA_2_6L][IPA_CLIENT_TEST3_PROD]         = 13,
-	[IPA_2_6L][IPA_CLIENT_TEST4_PROD]         = 14,
+	[IPA_2_6L][IPA_CLIENT_APPS_LAN_WAN_PROD]  = {true,  4},
+	[IPA_2_6L][IPA_CLIENT_APPS_CMD_PROD]      = {true,  3},
+	[IPA_2_6L][IPA_CLIENT_Q6_LAN_PROD]        = {true,  6},
+	[IPA_2_6L][IPA_CLIENT_Q6_CMD_PROD]        = {true,  7},
+	[IPA_2_6L][IPA_CLIENT_Q6_DECOMP_PROD]     = {true, 11},
+	[IPA_2_6L][IPA_CLIENT_Q6_DECOMP2_PROD]    = {true, 13},
 
-	[IPA_2_6L][IPA_CLIENT_HSIC1_CONS]         = -1,
-	[IPA_2_6L][IPA_CLIENT_WLAN1_CONS]         = -1,
-	[IPA_2_6L][IPA_CLIENT_HSIC2_CONS]         = -1,
-	[IPA_2_6L][IPA_CLIENT_USB2_CONS]          = -1,
-	[IPA_2_6L][IPA_CLIENT_WLAN2_CONS]         = -1,
-	[IPA_2_6L][IPA_CLIENT_HSIC3_CONS]         = -1,
-	[IPA_2_6L][IPA_CLIENT_USB3_CONS]          = -1,
-	[IPA_2_6L][IPA_CLIENT_WLAN3_CONS]         = -1,
-	[IPA_2_6L][IPA_CLIENT_HSIC4_CONS]         = -1,
-	[IPA_2_6L][IPA_CLIENT_USB4_CONS]          = -1,
-	[IPA_2_6L][IPA_CLIENT_WLAN4_CONS]         = -1,
-	[IPA_2_6L][IPA_CLIENT_HSIC5_CONS]         = -1,
-	[IPA_2_6L][IPA_CLIENT_USB_CONS]           =  0,
-	[IPA_2_6L][IPA_CLIENT_USB_DPL_CONS]       = 10,
-	[IPA_2_6L][IPA_CLIENT_A2_EMBEDDED_CONS]   = -1,
-	[IPA_2_6L][IPA_CLIENT_A2_TETHERED_CONS]   = -1,
-	[IPA_2_6L][IPA_CLIENT_A5_LAN_WAN_CONS]    = -1,
-	[IPA_2_6L][IPA_CLIENT_APPS_LAN_CONS]      =  2,
-	[IPA_2_6L][IPA_CLIENT_APPS_WAN_CONS]      =  5,
-	[IPA_2_6L][IPA_CLIENT_ODU_EMB_CONS]       = -1,
-	[IPA_2_6L][IPA_CLIENT_ODU_TETH_CONS]      = -1,
-	[IPA_2_6L][IPA_CLIENT_MHI_CONS]           = -1,
-	[IPA_2_6L][IPA_CLIENT_Q6_LAN_CONS]        =  8,
-	[IPA_2_6L][IPA_CLIENT_Q6_WAN_CONS]        =  9,
-	[IPA_2_6L][IPA_CLIENT_Q6_DUN_CONS]        = -1,
-	[IPA_2_6L][IPA_CLIENT_Q6_DECOMP_CONS]     = 12,
-	[IPA_2_6L][IPA_CLIENT_Q6_DECOMP2_CONS]    = 14,
-	[IPA_2_6L][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS]
-						 =  -1,
-	[IPA_2_6L][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS]
-						 =  -1,
-	[IPA_2_6L][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS]
-						 =  -1,
-	[IPA_2_6L][IPA_CLIENT_ETHERNET_CONS]      = -1,
 	/* Only for test purpose */
-	[IPA_2_6L][IPA_CLIENT_TEST_CONS]          = 15,
-	[IPA_2_6L][IPA_CLIENT_TEST1_CONS]         = 15,
-	[IPA_2_6L][IPA_CLIENT_TEST2_CONS]         = 0,
-	[IPA_2_6L][IPA_CLIENT_TEST3_CONS]         = 1,
-	[IPA_2_6L][IPA_CLIENT_TEST4_CONS]         = 10,
+	[IPA_2_6L][IPA_CLIENT_TEST_PROD]          = {true, 11},
+	[IPA_2_6L][IPA_CLIENT_TEST1_PROD]         = {true, 11},
+	[IPA_2_6L][IPA_CLIENT_TEST2_PROD]         = {true, 12},
+	[IPA_2_6L][IPA_CLIENT_TEST3_PROD]         = {true, 13},
+	[IPA_2_6L][IPA_CLIENT_TEST4_PROD]         = {true, 14},
+
+	[IPA_2_6L][IPA_CLIENT_USB_CONS]           = {true,  0},
+	[IPA_2_6L][IPA_CLIENT_USB_DPL_CONS]       = {true, 10},
+	[IPA_2_6L][IPA_CLIENT_APPS_LAN_CONS]      = {true,  2},
+	[IPA_2_6L][IPA_CLIENT_APPS_WAN_CONS]      = {true,  5},
+	[IPA_2_6L][IPA_CLIENT_Q6_LAN_CONS]        = {true,  8},
+	[IPA_2_6L][IPA_CLIENT_Q6_WAN_CONS]        = {true,  9},
+	[IPA_2_6L][IPA_CLIENT_Q6_DECOMP_CONS]     = {true, 12},
+	[IPA_2_6L][IPA_CLIENT_Q6_DECOMP2_CONS]    = {true, 14},
+
+	/* Only for test purpose */
+	[IPA_2_6L][IPA_CLIENT_TEST_CONS]          = {true, 15},
+	[IPA_2_6L][IPA_CLIENT_TEST1_CONS]         = {true, 15},
+	[IPA_2_6L][IPA_CLIENT_TEST2_CONS]         = {true,  0},
+	[IPA_2_6L][IPA_CLIENT_TEST3_CONS]         = {true,  1},
+	[IPA_2_6L][IPA_CLIENT_TEST4_CONS]         = {true, 10},
 };
 
 static struct msm_bus_vectors ipa_init_vectors_v1_1[]  = {
@@ -949,7 +864,10 @@
 		break;
 	}
 
-	return ep_mapping[hw_type_index][client];
+	if (!ep_mapping[hw_type_index][client].valid)
+		return INVALID_EP_MAPPING_INDEX;
+
+	return ep_mapping[hw_type_index][client].pipe_num;
 }
 
 /* ipa2_set_client() - provide client mapping
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index bf13ac5..04d807f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -3659,7 +3659,6 @@
 	struct ipa_mem_buffer mem_info = {0};
 	static int total_cnt;
 
-	IPADBG("\n");
 	if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
 		ipa3_ctx->ep[clnt_hdl].valid == 0) {
 		IPAERR("bad parm 0x%x\n", clnt_hdl);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 73a405f..86442b1 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -139,9 +139,6 @@
 #define IPA_LAN_RX_HDR_NAME "ipa_lan_hdr"
 #define IPA_INVALID_L4_PROTOCOL 0xFF
 
-#define IPA_CLIENT_IS_PROD(x) (x >= IPA_CLIENT_PROD && x < IPA_CLIENT_CONS)
-#define IPA_CLIENT_IS_CONS(x) (x >= IPA_CLIENT_CONS && x < IPA_CLIENT_MAX)
-
 #define IPA_HDR_PROC_CTX_TABLE_ALIGNMENT_BYTE 8
 #define IPA_HDR_PROC_CTX_TABLE_ALIGNMENT(start_ofst) \
 	(((start_ofst) + IPA_HDR_PROC_CTX_TABLE_ALIGNMENT_BYTE - 1) & \
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index f8b4d7d..23c8241 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -93,11 +93,6 @@
 #define QMB_MASTER_SELECT_DDR  (0)
 #define QMB_MASTER_SELECT_PCIE (1)
 
-#define IPA_CLIENT_NOT_USED \
-	{ IPA_EP_NOT_ALLOCATED, IPA_EP_NOT_ALLOCATED, false, \
-	IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, \
-		{ -1, -1, -1, -1, -1 } }
-
 /* Resource Group index*/
 #define IPA_v3_0_GROUP_UL		(0)
 #define IPA_v3_0_GROUP_DL		(1)
@@ -406,7 +401,7 @@
 };
 
 struct ipa_ep_configuration {
-	int pipe_num;
+	bool valid;
 	int group_num;
 	bool support_flt;
 	int sequencer_type;
@@ -414,506 +409,424 @@
 	struct ipa_gsi_ep_config ipa_gsi_ep_info;
 };
 
+/* clients not included in the list below are considered as invalid */
 static const struct ipa_ep_configuration ipa3_ep_mapping
 					[IPA_VER_MAX][IPA_CLIENT_MAX] = {
-	[IPA_3_0][IPA_CLIENT_HSIC1_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_WLAN1_PROD]          = {
-			10, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 10, 1, 8, 16, IPA_EE_UC } },
-	[IPA_3_0][IPA_CLIENT_HSIC2_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_USB2_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_HSIC3_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_USB3_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_HSIC4_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_USB4_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_HSIC5_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_USB_PROD]            = {
-			1, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 1, 3, 8, 16, IPA_EE_AP } },
-	[IPA_3_0][IPA_CLIENT_UC_USB_PROD]         = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_A5_WLAN_AMPDU_PROD]  = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_A2_EMBEDDED_PROD]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_A2_TETHERED_PROD]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_APPS_LAN_PROD] = {
-			14, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 14, 11, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_APPS_WAN_PROD] = {
-			3, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 3, 5, 16, 32, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_APPS_CMD_PROD]	  = {
-			22, IPA_v3_0_GROUP_IMM_CMD, false,
+			true, IPA_v3_0_GROUP_IMM_CMD, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 22, 6, 18, 28, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_ODU_PROD]            = {
-			12, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 12, 9, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_MHI_PROD]            = {
-			0, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_PCIE,
 			{ 0, 0, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_Q6_LAN_PROD]         = {
-			9, IPA_v3_0_GROUP_UL, false,
+			true, IPA_v3_0_GROUP_UL, false,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 9, 4, 8, 12, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_WAN_PROD]         = {
-			5, IPA_v3_0_GROUP_DL, true,
+			true, IPA_v3_0_GROUP_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 5, 0, 16, 32, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_CMD_PROD] = {
-			6, IPA_v3_0_GROUP_IMM_CMD, false,
+			true, IPA_v3_0_GROUP_IMM_CMD, false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 6, 1, 18, 28, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_DECOMP_PROD]      = {
-			7, IPA_v3_0_GROUP_Q6ZIP,
+			true, IPA_v3_0_GROUP_Q6ZIP,
 			false, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 7, 2, 0, 0, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_DECOMP2_PROD]     = {
-			8, IPA_v3_0_GROUP_Q6ZIP,
+			true, IPA_v3_0_GROUP_Q6ZIP,
 			false, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 3, 0, 0, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD] = {
-			12, IPA_v3_0_GROUP_DMA, false,
+			true, IPA_v3_0_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_PCIE,
 			{ 12, 9, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD] = {
-			13, IPA_v3_0_GROUP_DMA, false,
+			true, IPA_v3_0_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_PCIE,
 			{ 13, 10, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_ETHERNET_PROD]          = {
-			2, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{2, 0, 8, 16, IPA_EE_UC} },
 	/* Only for test purpose */
 	[IPA_3_0][IPA_CLIENT_TEST_PROD]           = {
-			1, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 1, 3, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST1_PROD]          = {
-			1, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 1, 3, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST2_PROD]          = {
-			3, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 3, 5, 16, 32, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST3_PROD]          = {
-			12, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 12, 9, 8, 16, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST4_PROD]          = {
-			13, IPA_v3_0_GROUP_UL, true,
+			true, IPA_v3_0_GROUP_UL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 13, 10, 8, 16, IPA_EE_AP } },
 
-	[IPA_3_0][IPA_CLIENT_HSIC1_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_WLAN1_CONS]          = {
-			25, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 25, 4, 8, 8, IPA_EE_UC } },
-	[IPA_3_0][IPA_CLIENT_HSIC2_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_USB2_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_WLAN2_CONS]          = {
-			27, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 27, 4, 8, 8, IPA_EE_AP } },
-	[IPA_3_0][IPA_CLIENT_HSIC3_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_USB3_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_WLAN3_CONS]          = {
-			28, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 28, 13, 8, 8, IPA_EE_AP } },
-	[IPA_3_0][IPA_CLIENT_HSIC4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_USB4_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_WLAN4_CONS]          = {
-			29, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 29, 14, 8, 8, IPA_EE_AP } },
-	[IPA_3_0][IPA_CLIENT_HSIC5_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_USB_CONS]            = {
-			26, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 26, 12, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_USB_DPL_CONS]        = {
-			17, IPA_v3_0_GROUP_DPL, false,
+			true, IPA_v3_0_GROUP_DPL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 17, 2, 8, 12, IPA_EE_AP } },
-	[IPA_3_0][IPA_CLIENT_A2_EMBEDDED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_A2_TETHERED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_0][IPA_CLIENT_A5_LAN_WAN_CONS]     = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_APPS_LAN_CONS]       = {
-			15, IPA_v3_0_GROUP_UL, false,
+			true, IPA_v3_0_GROUP_UL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 15, 7, 8, 12, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_APPS_WAN_CONS]       = {
-			16, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 16, 8, 8, 12, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_ODU_EMB_CONS]        = {
-			23, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 23, 1, 8, 8, IPA_EE_AP } },
-	[IPA_3_0][IPA_CLIENT_ODU_TETH_CONS]       = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_MHI_CONS]            = {
-			23, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 23, 1, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_Q6_LAN_CONS]         = {
-			19, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 19, 6, 8, 12, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_WAN_CONS]         = {
-			18, IPA_v3_0_GROUP_UL, false,
+			true, IPA_v3_0_GROUP_UL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 18, 5, 8, 12, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_DUN_CONS]         = {
-			30, IPA_v3_0_GROUP_DIAG, false,
+			true, IPA_v3_0_GROUP_DIAG, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 30, 7, 4, 4, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_DECOMP_CONS] = {
-			21, IPA_v3_0_GROUP_Q6ZIP, false,
+			true, IPA_v3_0_GROUP_Q6ZIP, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 21, 8, 4, 4, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_Q6_DECOMP2_CONS] = {
-			4, IPA_v3_0_GROUP_Q6ZIP, false,
+			true, IPA_v3_0_GROUP_Q6ZIP, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 4, 9, 4, 4, IPA_EE_Q6 } },
 	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS] = {
-			28, IPA_v3_0_GROUP_DMA, false,
+			true, IPA_v3_0_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 28, 13, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS] = {
-			29, IPA_v3_0_GROUP_DMA, false,
+			true, IPA_v3_0_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 29, 14, 8, 8, IPA_EE_AP } },
-	[IPA_3_0][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS]     = IPA_CLIENT_NOT_USED,
 	[IPA_3_0][IPA_CLIENT_ETHERNET_CONS]          = {
-			24, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{24, 3, 8, 8, IPA_EE_UC} },
 	/* Only for test purpose */
 	[IPA_3_0][IPA_CLIENT_TEST_CONS]           = {
-			26, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 26, 12, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST1_CONS]          = {
-			26, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 26, 12, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST2_CONS]          = {
-			27, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 27, 4, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST3_CONS]          = {
-			28, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 28, 13, 8, 8, IPA_EE_AP } },
 	[IPA_3_0][IPA_CLIENT_TEST4_CONS]          = {
-			29, IPA_v3_0_GROUP_DL, false,
+			true, IPA_v3_0_GROUP_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 29, 14, 8, 8, IPA_EE_AP } },
 
 
 	/* IPA_3_5 */
-	[IPA_3_5][IPA_CLIENT_HSIC1_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_WLAN1_PROD]          = {
-			6, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 6, 1, 8, 16, IPA_EE_UC } },
-	[IPA_3_5][IPA_CLIENT_HSIC2_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_USB2_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_HSIC3_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_USB3_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_HSIC4_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_USB4_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_HSIC5_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_USB_PROD]            = {
-			0, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 0, 7, 8, 16, IPA_EE_AP } },
-	[IPA_3_5][IPA_CLIENT_UC_USB_PROD]         = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_A5_WLAN_AMPDU_PROD]  = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_A2_EMBEDDED_PROD]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_A2_TETHERED_PROD]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_APPS_LAN_PROD]   = {
-			8, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 9, 8, 16, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_APPS_WAN_PROD] = {
-			2, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 2, 3, 16, 32, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_APPS_CMD_PROD]	  = {
-			5, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 5, 4, 20, 23, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_ODU_PROD]            = {
-			1, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_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_UC } },
-	[IPA_3_5][IPA_CLIENT_MHI_PROD]            = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_Q6_LAN_PROD]         = {
-			3, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 3, 0, 16, 32, IPA_EE_Q6 } },
-	[IPA_3_5][IPA_CLIENT_Q6_WAN_PROD]         = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_Q6_CMD_PROD]	  = {
-			4, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 4, 1, 20, 23, IPA_EE_Q6 } },
-	[IPA_3_5][IPA_CLIENT_Q6_DECOMP_PROD]      = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_Q6_DECOMP2_PROD]     = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD] = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD] = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_ETHERNET_PROD]         = IPA_CLIENT_NOT_USED,
 	/* Only for test purpose */
 	[IPA_3_5][IPA_CLIENT_TEST_PROD]           = {
-			0, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{0, 7, 8, 16, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_TEST1_PROD]          = {
-			0, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{0, 7, 8, 16, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_TEST2_PROD]          = {
-			1, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_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_3_5][IPA_CLIENT_TEST3_PROD]          = {
-			7, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{7, 8, 8, 16, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_TEST4_PROD]          = {
-			8, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 9, 8, 16, IPA_EE_AP } },
 
-	[IPA_3_5][IPA_CLIENT_HSIC1_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_WLAN1_CONS]          = {
-			16, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 16, 3, 8, 8, IPA_EE_UC } },
-	[IPA_3_5][IPA_CLIENT_HSIC2_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_USB2_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_WLAN2_CONS]          = {
-			18, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 18, 12, 8, 8, IPA_EE_AP } },
-	[IPA_3_5][IPA_CLIENT_HSIC3_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_USB3_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_WLAN3_CONS]          = {
-			19, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 19, 13, 8, 8, IPA_EE_AP } },
-	[IPA_3_5][IPA_CLIENT_HSIC4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_USB4_CONS]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_WLAN4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_HSIC5_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_USB_CONS]            = {
-			17, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 17, 11, 8, 8, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_USB_DPL_CONS]        = {
-			14, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 14, 10, 4, 6, IPA_EE_AP } },
-	[IPA_3_5][IPA_CLIENT_A2_EMBEDDED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_A2_TETHERED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_A5_LAN_WAN_CONS]     = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_APPS_LAN_CONS]       = {
-			9, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 9, 5, 8, 12, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_APPS_WAN_CONS]       = {
-			10, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 10, 6, 8, 12, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_ODU_EMB_CONS]        = {
-			15, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 15, 1, 8, 8, IPA_EE_AP } },
-	[IPA_3_5][IPA_CLIENT_ODU_TETH_CONS]       = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_MHI_CONS]            = IPA_CLIENT_NOT_USED,
 	[IPA_3_5][IPA_CLIENT_Q6_LAN_CONS]         = {
-			13, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 13, 3, 8, 12, IPA_EE_Q6 } },
 	[IPA_3_5][IPA_CLIENT_Q6_WAN_CONS]         = {
-			12, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 12, 2, 8, 12, IPA_EE_Q6 } },
-	[IPA_3_5][IPA_CLIENT_Q6_DUN_CONS]         = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_Q6_DECOMP_CONS]	  = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_Q6_DECOMP2_CONS]	  = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS] = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS] = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS]     = IPA_CLIENT_NOT_USED,
-	[IPA_3_5][IPA_CLIENT_ETHERNET_CONS]	  = IPA_CLIENT_NOT_USED,
 	/* Only for test purpose */
 	/* MBIM aggregation test pipes should have the same QMB as USB_CONS */
 	[IPA_3_5][IPA_CLIENT_TEST_CONS]           = {
-			15, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 15, 1, 8, 8, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_TEST1_CONS]           = {
-			15, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 15, 1, 8, 8, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_TEST2_CONS]          = {
-			17, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 17, 11, 8, 8, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_TEST3_CONS]          = {
-			18, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 18, 12, 8, 8, IPA_EE_AP } },
 	[IPA_3_5][IPA_CLIENT_TEST4_CONS]          = {
-			19, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 19, 13, 8, 8, IPA_EE_AP } },
 
 	/* IPA_3_5_MHI */
-	[IPA_3_5_MHI][IPA_CLIENT_HSIC1_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_WLAN1_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_HSIC2_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_USB2_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_HSIC3_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_USB3_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_HSIC4_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_USB4_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_HSIC5_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_MHI][IPA_CLIENT_USB_PROD]            = {
-			0, IPA_v3_5_MHI_GROUP_DDR, true,
+			true, IPA_v3_5_MHI_GROUP_DDR, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 0, 7, 8, 16, IPA_EE_AP } },
-	[IPA_3_5_MHI][IPA_CLIENT_UC_USB_PROD]         = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_A5_WLAN_AMPDU_PROD]  = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_A2_EMBEDDED_PROD]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_A2_TETHERED_PROD]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_APPS_LAN_PROD] = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_MHI][IPA_CLIENT_APPS_WAN_PROD]   = {
-			2, IPA_v3_5_MHI_GROUP_DDR, true,
+			true, IPA_v3_5_MHI_GROUP_DDR, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 2, 3, 16, 32, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_APPS_CMD_PROD]	  = {
-			5, IPA_v3_5_MHI_GROUP_DDR, false,
+			true, IPA_v3_5_MHI_GROUP_DDR, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 5, 4, 20, 23, IPA_EE_AP } },
-	[IPA_3_5_MHI][IPA_CLIENT_ODU_PROD]            = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_MHI][IPA_CLIENT_MHI_PROD]            = {
-			1, IPA_v3_5_MHI_GROUP_PCIE, true,
+			true, IPA_v3_5_MHI_GROUP_PCIE, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_PCIE,
 			{ 1, 0, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_Q6_LAN_PROD]         = {
-			3, IPA_v3_5_MHI_GROUP_DDR, true,
+			true, IPA_v3_5_MHI_GROUP_DDR, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 3, 0, 16, 32, IPA_EE_Q6 } },
 	[IPA_3_5_MHI][IPA_CLIENT_Q6_WAN_PROD]         = {
-			6, IPA_v3_5_MHI_GROUP_DDR, true,
+			true, IPA_v3_5_MHI_GROUP_DDR, true,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 6, 4, 10, 30, IPA_EE_Q6 } },
 	[IPA_3_5_MHI][IPA_CLIENT_Q6_CMD_PROD]	  = {
-			4, IPA_v3_5_MHI_GROUP_PCIE, false,
+			true, IPA_v3_5_MHI_GROUP_PCIE, false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 4, 1, 20, 23, IPA_EE_Q6 } },
-	[IPA_3_5_MHI][IPA_CLIENT_Q6_DECOMP_PROD]      = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_Q6_DECOMP2_PROD]     = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_MHI][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD] = {
-			7, IPA_v3_5_MHI_GROUP_DMA, false,
+			true, IPA_v3_5_MHI_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 7, 8, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD] = {
-			8, IPA_v3_5_MHI_GROUP_DMA, false,
+			true, IPA_v3_5_MHI_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 9, 8, 16, IPA_EE_AP } },
-	[IPA_3_5_MHI][IPA_CLIENT_ETHERNET_PROD]       = IPA_CLIENT_NOT_USED,
 	/* Only for test purpose */
 	[IPA_3_5_MHI][IPA_CLIENT_TEST_PROD]           = {
-			0, IPA_v3_5_MHI_GROUP_DDR, true,
+			true, IPA_v3_5_MHI_GROUP_DDR, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{0, 7, 8, 16, IPA_EE_AP } },
@@ -923,300 +836,238 @@
 			QMB_MASTER_SELECT_DDR,
 			{0, 7, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_TEST2_PROD]          = {
-			1, IPA_v3_5_MHI_GROUP_PCIE, true,
+			true, IPA_v3_5_MHI_GROUP_PCIE, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_PCIE,
 			{ 1, 0, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_TEST3_PROD]          = {
-			7, IPA_v3_5_MHI_GROUP_DMA, true,
+			true, IPA_v3_5_MHI_GROUP_DMA, true,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{7, 8, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_TEST4_PROD]          = {
-			8, IPA_v3_5_MHI_GROUP_DMA, true,
+			true, IPA_v3_5_MHI_GROUP_DMA, true,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 9, 8, 16, IPA_EE_AP } },
 
-	[IPA_3_5_MHI][IPA_CLIENT_HSIC1_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_MHI][IPA_CLIENT_WLAN1_CONS]          = {
-			16, IPA_v3_5_MHI_GROUP_DDR, false,
+			true, IPA_v3_5_MHI_GROUP_DDR, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 16, 3, 8, 8, IPA_EE_UC } },
-	[IPA_3_5_MHI][IPA_CLIENT_HSIC2_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_USB2_CONS]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_WLAN2_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_HSIC3_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_USB3_CONS]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_WLAN3_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_HSIC4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_USB4_CONS]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_WLAN4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_HSIC5_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_MHI][IPA_CLIENT_USB_CONS]            = {
-			17, IPA_v3_5_MHI_GROUP_DDR, false,
+			true, IPA_v3_5_MHI_GROUP_DDR, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 17, 11, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_USB_DPL_CONS]        = {
-			14, IPA_v3_5_MHI_GROUP_DDR, false,
+			true, IPA_v3_5_MHI_GROUP_DDR, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 14, 10, 4, 6, IPA_EE_AP } },
-	[IPA_3_5_MHI][IPA_CLIENT_A2_EMBEDDED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_A2_TETHERED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_A5_LAN_WAN_CONS]     = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_MHI][IPA_CLIENT_APPS_LAN_CONS]       = {
-			9, IPA_v3_5_MHI_GROUP_DDR, false,
+			true, IPA_v3_5_MHI_GROUP_DDR, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 9, 5, 8, 12, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_APPS_WAN_CONS]       = {
-			10, IPA_v3_5_MHI_GROUP_DDR, false,
+			true, IPA_v3_5_MHI_GROUP_DDR, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 10, 6, 8, 12, IPA_EE_AP } },
-	[IPA_3_5_MHI][IPA_CLIENT_ODU_EMB_CONS]        = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_ODU_TETH_CONS]       = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_MHI][IPA_CLIENT_MHI_CONS]            = {
-			15, IPA_v3_5_MHI_GROUP_PCIE, false,
+			true, IPA_v3_5_MHI_GROUP_PCIE, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 15, 1, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_Q6_LAN_CONS]         = {
-			13, IPA_v3_5_MHI_GROUP_DDR, false,
+			true, IPA_v3_5_MHI_GROUP_DDR, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 13, 3, 8, 12, IPA_EE_Q6 } },
 	[IPA_3_5_MHI][IPA_CLIENT_Q6_WAN_CONS]         = {
-			12, IPA_v3_5_MHI_GROUP_DDR, false,
+			true, IPA_v3_5_MHI_GROUP_DDR, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 12, 2, 8, 12, IPA_EE_Q6 } },
-	[IPA_3_5_MHI][IPA_CLIENT_Q6_DUN_CONS]		= IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_Q6_DECOMP_CONS]	= IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_Q6_DECOMP2_CONS]	= IPA_CLIENT_NOT_USED,
 	[IPA_3_5_MHI][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS] = {
-			18, IPA_v3_5_MHI_GROUP_DMA, false,
+			true, IPA_v3_5_MHI_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 18, 12, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS] = {
-			19, IPA_v3_5_MHI_GROUP_DMA, false,
+			true, IPA_v3_5_MHI_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 19, 13, 8, 8, IPA_EE_AP } },
-	[IPA_3_5_MHI][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS]	= IPA_CLIENT_NOT_USED,
-	[IPA_3_5_MHI][IPA_CLIENT_ETHERNET_CONS]       = IPA_CLIENT_NOT_USED,
 	/* Only for test purpose */
 	[IPA_3_5_MHI][IPA_CLIENT_TEST_CONS]           = {
-			15, IPA_v3_5_MHI_GROUP_PCIE, false,
+			true, IPA_v3_5_MHI_GROUP_PCIE, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 15, 1, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_TEST1_CONS]           = {
-			15, IPA_v3_5_MHI_GROUP_PCIE, false,
+			true, IPA_v3_5_MHI_GROUP_PCIE, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 15, 1, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_TEST2_CONS]          = {
-			17, IPA_v3_5_MHI_GROUP_DDR, false,
+			true, IPA_v3_5_MHI_GROUP_DDR, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 17, 11, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_TEST3_CONS]          = {
-			18, IPA_v3_5_MHI_GROUP_DMA, false,
+			true, IPA_v3_5_MHI_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 18, 12, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_MHI][IPA_CLIENT_TEST4_CONS]          = {
-			19, IPA_v3_5_MHI_GROUP_DMA, false,
+			true, IPA_v3_5_MHI_GROUP_DMA, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 19, 13, 8, 8, IPA_EE_AP } },
 
 	/* IPA_3_5_1 */
-	[IPA_3_5_1][IPA_CLIENT_HSIC1_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_WLAN1_PROD]          = {
-			7, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 7, 1, 8, 16, IPA_EE_UC } },
-	[IPA_3_5_1][IPA_CLIENT_HSIC2_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_USB2_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_HSIC3_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_USB3_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_HSIC4_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_USB4_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_HSIC5_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_USB_PROD]            = {
-			0, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 0, 0, 8, 16, IPA_EE_AP } },
-	[IPA_3_5_1][IPA_CLIENT_UC_USB_PROD]         = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_A5_WLAN_AMPDU_PROD]  = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_A2_EMBEDDED_PROD]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_A2_TETHERED_PROD]    = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_APPS_LAN_PROD] = {
-			8, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 7, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_APPS_WAN_PROD] = {
-			2, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 2, 3, 16, 32, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_APPS_CMD_PROD]		= {
-			5, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 5, 4, 20, 23, IPA_EE_AP } },
-	[IPA_3_5_1][IPA_CLIENT_ODU_PROD]            = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_MHI_PROD]            = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_Q6_LAN_PROD]         = {
-			3, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 3, 0, 16, 32, IPA_EE_Q6 } },
 	[IPA_3_5_1][IPA_CLIENT_Q6_WAN_PROD]         = {
-			6, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 6, 4, 12, 30, IPA_EE_Q6 } },
 	[IPA_3_5_1][IPA_CLIENT_Q6_CMD_PROD]	    = {
-			4, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 4, 1, 20, 23, IPA_EE_Q6 } },
-	[IPA_3_5_1][IPA_CLIENT_Q6_DECOMP_PROD]      = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_Q6_DECOMP2_PROD]     = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD] = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD] = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_ETHERNET_PROD]       = IPA_CLIENT_NOT_USED,
 	/* Only for test purpose */
 	[IPA_3_5_1][IPA_CLIENT_TEST_PROD]           = {
-			0, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 0, 0, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST1_PROD]          = {
-			0, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 0, 0, 8, 16, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST2_PROD]          = {
-			2, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 2, 3, 16, 32, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST3_PROD]          = {
-			4, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_5_GROUP_UL_DL, true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 4, 1, 20, 23, IPA_EE_Q6 } },
 	[IPA_3_5_1][IPA_CLIENT_TEST4_PROD]          = {
-			1, IPA_v3_5_GROUP_UL_DL, true,
+			true, IPA_v3_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_UC } },
 
-	[IPA_3_5_1][IPA_CLIENT_HSIC1_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_WLAN1_CONS]          = {
-			16, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 16, 3, 8, 8, IPA_EE_UC } },
-	[IPA_3_5_1][IPA_CLIENT_HSIC2_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_USB2_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_WLAN2_CONS]          =  {
-			18, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 18, 9, 8, 8, IPA_EE_AP } },
-	[IPA_3_5_1][IPA_CLIENT_HSIC3_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_USB3_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_WLAN3_CONS]          =  {
-			19, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 19, 10, 8, 8, IPA_EE_AP } },
-	[IPA_3_5_1][IPA_CLIENT_HSIC4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_USB4_CONS]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_WLAN4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_HSIC5_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_USB_CONS]            = {
-			17, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 17, 8, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_USB_DPL_CONS]        = {
-			11, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 11, 2, 4, 6, IPA_EE_AP } },
-	[IPA_3_5_1][IPA_CLIENT_A2_EMBEDDED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_A2_TETHERED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_A5_LAN_WAN_CONS]     = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_APPS_LAN_CONS]       = {
-			9, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 9, 5, 8, 12, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_APPS_WAN_CONS]       = {
-			10, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 10, 6, 8, 12, IPA_EE_AP } },
-	[IPA_3_5_1][IPA_CLIENT_ODU_EMB_CONS]        = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_ODU_TETH_CONS]       = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_MHI_CONS]            = IPA_CLIENT_NOT_USED,
 	[IPA_3_5_1][IPA_CLIENT_Q6_LAN_CONS]         = {
-			13, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 13, 3, 8, 12, IPA_EE_Q6 } },
 	[IPA_3_5_1][IPA_CLIENT_Q6_WAN_CONS]         = {
-			12, IPA_v3_5_GROUP_UL_DL, false,
+			true, IPA_v3_5_GROUP_UL_DL, false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 12, 2, 8, 12, IPA_EE_Q6 } },
-	[IPA_3_5_1][IPA_CLIENT_Q6_DUN_CONS]           = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_Q6_DECOMP_CONS]	      = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_Q6_DECOMP2_CONS]	      = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS]  = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS] = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS] = IPA_CLIENT_NOT_USED,
-	[IPA_3_5_1][IPA_CLIENT_ETHERNET_CONS]       = IPA_CLIENT_NOT_USED,
 	/* Only for test purpose */
 	[IPA_3_5_1][IPA_CLIENT_TEST_CONS]           = {
-			17, IPA_v3_5_GROUP_UL_DL,
+			true, IPA_v3_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 17, 8, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST1_CONS]          = {
-			17, IPA_v3_5_GROUP_UL_DL,
+			true, IPA_v3_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 17, 8, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST2_CONS]          = {
-			18, IPA_v3_5_GROUP_UL_DL,
+			true, IPA_v3_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 18, 9, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST3_CONS]          = {
-			19, IPA_v3_5_GROUP_UL_DL,
+			true, IPA_v3_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 19, 10, 8, 8, IPA_EE_AP } },
 	[IPA_3_5_1][IPA_CLIENT_TEST4_CONS]          = {
-			11, IPA_v3_5_GROUP_UL_DL,
+			true, IPA_v3_5_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
@@ -1224,391 +1075,379 @@
 
 
 	/* IPA_4_0 */
-	[IPA_4_0][IPA_CLIENT_HSIC1_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_WLAN1_PROD]          = {
-			7, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 7, 9, 8, 16, IPA_EE_AP } },
-	[IPA_4_0][IPA_CLIENT_HSIC2_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_USB2_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_HSIC3_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_USB3_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_HSIC4_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_USB4_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_HSIC5_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_USB_PROD]            = {
-			0, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 0, 8, 8, 16, IPA_EE_AP } },
-	[IPA_4_0][IPA_CLIENT_UC_USB_PROD]         = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_A5_WLAN_AMPDU_PROD]  = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_A2_EMBEDDED_PROD]    = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_A2_TETHERED_PROD]    = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_APPS_LAN_PROD]   = {
-			8, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 10, 8, 16, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_APPS_WAN_PROD] = {
-			2, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 2, 3, 16, 32, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_APPS_CMD_PROD]	  = {
-			5, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 5, 4, 20, 24, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_ODU_PROD]            = {
-			0, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 0, 1, 8, 16, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_ETHERNET_PROD]	  = {
-			9, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 9, 0, 8, 16, IPA_EE_UC } },
-	[IPA_4_0][IPA_CLIENT_MHI_PROD]            = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_Q6_LAN_PROD]         = {
-			6, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 6, 2, 12, 24, IPA_EE_Q6 } },
 	[IPA_4_0][IPA_CLIENT_Q6_WAN_PROD]         = {
-			3, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 3, 0, 16, 32, IPA_EE_Q6 } },
 	[IPA_4_0][IPA_CLIENT_Q6_CMD_PROD]	  = {
-			4, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 4, 1, 20, 24, IPA_EE_Q6 } },
-	[IPA_4_0][IPA_CLIENT_Q6_DECOMP_PROD]      = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_Q6_DECOMP2_PROD]     = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD] = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD] = IPA_CLIENT_NOT_USED,
 	/* Only for test purpose */
 	[IPA_4_0][IPA_CLIENT_TEST_PROD]           = {
-			0, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{0, 8, 8, 16, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_TEST1_PROD]          = {
-			0, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{0, 8, 8, 16, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_TEST2_PROD]          = {
-			1, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_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_0][IPA_CLIENT_TEST3_PROD]          = {
-			7, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{7, 9, 8, 16, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_TEST4_PROD]          = {
-			8, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 10, 8, 16, IPA_EE_AP } },
 
 
-	[IPA_4_0][IPA_CLIENT_HSIC1_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_WLAN1_CONS]          = {
-			18, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 18, 12, 6, 9, IPA_EE_AP } },
-	[IPA_4_0][IPA_CLIENT_HSIC2_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_USB2_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_WLAN2_CONS]          = {
-			20, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 20, 14, 9, 9, IPA_EE_AP } },
-	[IPA_4_0][IPA_CLIENT_HSIC3_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_USB3_CONS]           = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_WLAN3_CONS]          = {
-			21, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 21, 15, 9, 9, IPA_EE_AP } },
-	[IPA_4_0][IPA_CLIENT_HSIC4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_USB4_CONS]           = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_WLAN4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_HSIC5_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_USB_CONS]            = {
-			19, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 19, 13, 9, 9, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_USB_DPL_CONS]        = {
-			15, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 15, 7, 5, 5, IPA_EE_AP } },
-	[IPA_4_0][IPA_CLIENT_A2_EMBEDDED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_A2_TETHERED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_A5_LAN_WAN_CONS]     = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_APPS_LAN_CONS]       = {
-			10, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 10, 5, 9, 9, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_APPS_WAN_CONS]       = {
-			11, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 11, 6, 9, 9, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_ODU_EMB_CONS]        = {
-			17, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 17, 1, 17, 17, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_ETHERNET_CONS]	  = {
-			22, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 22, 1, 17, 17, IPA_EE_UC } },
-	[IPA_4_0][IPA_CLIENT_ODU_TETH_CONS]       = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_MHI_CONS]            = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_Q6_LAN_CONS]         = {
-			14, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 14, 4, 9, 9, IPA_EE_Q6 } },
 	[IPA_4_0][IPA_CLIENT_Q6_WAN_CONS]         = {
-			13, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 13, 3, 9, 9, IPA_EE_Q6 } },
-	[IPA_4_0][IPA_CLIENT_Q6_DUN_CONS]         = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_Q6_DECOMP_CONS]	  = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_Q6_DECOMP2_CONS]	  = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS] = IPA_CLIENT_NOT_USED,
-	[IPA_4_0][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS] = IPA_CLIENT_NOT_USED,
 	[IPA_4_0][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS] = {
-			16, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 16, 5, 9, 9, IPA_EE_Q6 } },
 	/* Only for test purpose */
 	/* MBIM aggregation test pipes should have the same QMB as USB_CONS */
 	[IPA_4_0][IPA_CLIENT_TEST_CONS]           = {
-			12, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 12, 2, 5, 5, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_TEST1_CONS]           = {
-			12, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 12, 2, 5, 5, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_TEST2_CONS]          = {
-			18, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 18, 12, 6, 9, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_TEST3_CONS]          = {
-			20, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 20, 14, 9, 9, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_TEST4_CONS]          = {
-			21, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 21, 15, 9, 9, IPA_EE_AP } },
 
 	/* IPA_4_0_MHI */
-	[IPA_4_0_MHI][IPA_CLIENT_HSIC1_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_WLAN1_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_HSIC2_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_USB2_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_HSIC3_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_USB3_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_HSIC4_PROD]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_USB4_PROD]           = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_HSIC5_PROD]          = IPA_CLIENT_NOT_USED,
 	[IPA_4_0_MHI][IPA_CLIENT_USB_PROD]            = {
-			0, IPA_v4_0_MHI_GROUP_DDR, true,
+			true, IPA_v4_0_MHI_GROUP_DDR,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 0, 8, 8, 16, IPA_EE_AP } },
-	[IPA_4_0_MHI][IPA_CLIENT_UC_USB_PROD]         = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_A5_WLAN_AMPDU_PROD]  = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_A2_EMBEDDED_PROD]    = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_A2_TETHERED_PROD]    = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_APPS_LAN_PROD] = IPA_CLIENT_NOT_USED,
 	[IPA_4_0_MHI][IPA_CLIENT_APPS_WAN_PROD]   = {
-			2, IPA_v4_0_MHI_GROUP_DDR, true,
+			true, IPA_v4_0_MHI_GROUP_DDR,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 2, 3, 16, 32, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_APPS_CMD_PROD]	  = {
-			5, IPA_v4_0_MHI_GROUP_DDR, false,
+			true, IPA_v4_0_MHI_GROUP_DDR,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 5, 4, 20, 24, IPA_EE_AP } },
-	[IPA_4_0_MHI][IPA_CLIENT_ODU_PROD]            = IPA_CLIENT_NOT_USED,
 	[IPA_4_0_MHI][IPA_CLIENT_MHI_PROD]            = {
-			1, IPA_v4_0_MHI_GROUP_PCIE, true,
+			true, IPA_v4_0_MHI_GROUP_PCIE,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_PCIE,
 			{ 1, 0, 8, 16, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_LAN_PROD]         = {
-			3, IPA_v4_0_MHI_GROUP_DDR, true,
+			true, IPA_v4_0_MHI_GROUP_DDR,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 3, 0, 16, 32, IPA_EE_Q6 } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_WAN_PROD]         = {
-			6, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 6, 2, 12, 24, IPA_EE_Q6 } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_CMD_PROD]	  = {
-			4, IPA_v4_0_MHI_GROUP_PCIE, false,
+			true, IPA_v4_0_MHI_GROUP_PCIE,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 4, 1, 20, 24, IPA_EE_Q6 } },
-	[IPA_4_0_MHI][IPA_CLIENT_Q6_DECOMP_PROD]      = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_Q6_DECOMP2_PROD]     = IPA_CLIENT_NOT_USED,
 	[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD] = {
-			7, IPA_v4_0_MHI_GROUP_DMA, false,
+			true, IPA_v4_0_MHI_GROUP_DMA,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 7, 9, 8, 16, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD] = {
-			8, IPA_v4_0_MHI_GROUP_DMA, false,
+			true, IPA_v4_0_MHI_GROUP_DMA,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 10, 8, 16, IPA_EE_AP } },
 	/* Only for test purpose */
 	[IPA_4_0_MHI][IPA_CLIENT_TEST_PROD]           = {
-			0, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{0, 8, 8, 16, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_TEST1_PROD]          = {
-			0, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{0, 8, 8, 16, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST2_PROD]          = {
-			1, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_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_0_MHI][IPA_CLIENT_TEST3_PROD]          = {
-			7, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{7, 9, 8, 16, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST4_PROD]          = {
-			8, IPA_v4_0_GROUP_UL_DL, true,
+			true, IPA_v4_0_GROUP_UL_DL,
+			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
 			{ 8, 10, 8, 16, IPA_EE_AP } },
 
-	[IPA_4_0_MHI][IPA_CLIENT_HSIC1_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_WLAN1_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_HSIC2_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_USB2_CONS]           = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_WLAN2_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_HSIC3_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_USB3_CONS]           = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_WLAN3_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_HSIC4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_USB4_CONS]           = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_WLAN4_CONS]          = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_HSIC5_CONS]          = IPA_CLIENT_NOT_USED,
 	[IPA_4_0_MHI][IPA_CLIENT_USB_CONS]            = {
-			19, IPA_v4_0_MHI_GROUP_DDR, false,
+			true, IPA_v4_0_MHI_GROUP_DDR,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 19, 13, 9, 9, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_USB_DPL_CONS]        = {
-			15, IPA_v4_0_MHI_GROUP_DDR, false,
+			true, IPA_v4_0_MHI_GROUP_DDR,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 15, 7, 5, 5, IPA_EE_AP } },
-	[IPA_4_0_MHI][IPA_CLIENT_A2_EMBEDDED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_A2_TETHERED_CONS]    = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_A5_LAN_WAN_CONS]     = IPA_CLIENT_NOT_USED,
 	[IPA_4_0_MHI][IPA_CLIENT_APPS_LAN_CONS]       = {
-			10, IPA_v4_0_MHI_GROUP_DDR, false,
+			true, IPA_v4_0_MHI_GROUP_DDR,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 10, 5, 9, 9, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_APPS_WAN_CONS]       = {
-			11, IPA_v4_0_MHI_GROUP_DDR, false,
+			true, IPA_v4_0_MHI_GROUP_DDR,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 11, 6, 9, 9, IPA_EE_AP } },
-	[IPA_4_0_MHI][IPA_CLIENT_ODU_EMB_CONS]        = IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_ODU_TETH_CONS]       = IPA_CLIENT_NOT_USED,
 	[IPA_4_0_MHI][IPA_CLIENT_MHI_CONS]            = {
-			17, IPA_v4_0_MHI_GROUP_PCIE, false,
+			true, IPA_v4_0_MHI_GROUP_PCIE,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 17, 1, 17, 17, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_LAN_CONS]         = {
-			14, IPA_v4_0_MHI_GROUP_DDR, false,
+			true, IPA_v4_0_MHI_GROUP_DDR,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 14, 4, 9, 9, IPA_EE_Q6 } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_WAN_CONS]         = {
-			13, IPA_v4_0_MHI_GROUP_DDR, false,
+			true, IPA_v4_0_MHI_GROUP_DDR,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 13, 3, 9, 9, IPA_EE_Q6 } },
-	[IPA_4_0_MHI][IPA_CLIENT_Q6_DUN_CONS]		= IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_Q6_DECOMP_CONS]	= IPA_CLIENT_NOT_USED,
-	[IPA_4_0_MHI][IPA_CLIENT_Q6_DECOMP2_CONS]	= IPA_CLIENT_NOT_USED,
 	[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS] = {
-			20, IPA_v4_0_MHI_GROUP_DMA, false,
+			true, IPA_v4_0_MHI_GROUP_DMA,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 20, 14, 9, 9, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS] = {
-			21, IPA_v4_0_MHI_GROUP_DMA, false,
+			true, IPA_v4_0_MHI_GROUP_DMA,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 21, 15, 9, 9, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS] = {
-			16, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 16, 5, 9, 9, IPA_EE_Q6 } },
 	/* Only for test purpose */
 	[IPA_4_0_MHI][IPA_CLIENT_TEST_CONS]           = {
-			12, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 12, 2, 5, 5, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST1_CONS]           = {
-			12, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 12, 2, 5, 5, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST2_CONS]          = {
-			18, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 18, 12, 6, 9, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST3_CONS]          = {
-			20, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 20, 14, 9, 9, IPA_EE_AP } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST4_CONS]          = {
-			21, IPA_v4_0_GROUP_UL_DL, false,
+			true, IPA_v4_0_GROUP_UL_DL,
+			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
 			{ 21, 15, 9, 9, IPA_EE_AP } },
@@ -2204,7 +2043,11 @@
 		return IPA_EP_NOT_ALLOCATED;
 	}
 
-	ipa_ep_idx = ipa3_ep_mapping[ipa3_get_hw_type_index()][client].pipe_num;
+	if (!ipa3_ep_mapping[ipa3_get_hw_type_index()][client].valid)
+		return IPA_EP_NOT_ALLOCATED;
+
+	ipa_ep_idx = ipa3_ep_mapping[ipa3_get_hw_type_index()][client].
+		ipa_gsi_ep_info.ipa_ep_num;
 	if (ipa_ep_idx < 0 || ipa_ep_idx >= IPA3_MAX_NUM_PIPES)
 		return IPA_EP_NOT_ALLOCATED;
 
@@ -2226,6 +2069,9 @@
 	if (ep_idx == IPA_EP_NOT_ALLOCATED)
 		return NULL;
 
+	if (!ipa3_ep_mapping[ipa3_get_hw_type_index()][client].valid)
+		return NULL;
+
 	return &(ipa3_ep_mapping[ipa3_get_hw_type_index()]
 		[client].ipa_gsi_ep_info);
 }
@@ -2243,6 +2089,9 @@
 		return -EINVAL;
 	}
 
+	if (!ipa3_ep_mapping[ipa3_get_hw_type_index()][client].valid)
+		return -EINVAL;
+
 	return ipa3_ep_mapping[ipa3_get_hw_type_index()][client].group_num;
 }
 
@@ -2259,6 +2108,9 @@
 		return -EINVAL;
 	}
 
+	if (!ipa3_ep_mapping[ipa3_get_hw_type_index()][client].valid)
+		return -EINVAL;
+
 	return ipa3_ep_mapping[ipa3_get_hw_type_index()]
 		[client].qmb_master_sel;
 }
@@ -2404,6 +2256,7 @@
 	enum ipa_client_type cl;
 	u8 hw_type_idx = ipa3_get_hw_type_index();
 	u32 bitmap;
+	u32 pipe_num;
 
 	bitmap = 0;
 
@@ -2411,8 +2264,9 @@
 
 	for (cl = 0; cl < IPA_CLIENT_MAX ; cl++) {
 		if (ipa3_ep_mapping[hw_type_idx][cl].support_flt) {
-			bitmap |=
-				(1U<<ipa3_ep_mapping[hw_type_idx][cl].pipe_num);
+			pipe_num = ipa3_ep_mapping[hw_type_idx][cl].
+				ipa_gsi_ep_info.ipa_ep_num;
+			bitmap |= (1U << pipe_num);
 			if (bitmap != ipa3_ctx->ep_flt_bitmap) {
 				ipa3_ctx->ep_flt_bitmap = bitmap;
 				ipa3_ctx->ep_flt_num++;
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 46dc148..cd76ca2 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -119,7 +119,8 @@
 	else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL)
 		return scnprintf(buf, PAGE_SIZE, "%s\n",
 				capacity_level_text[value.intval]);
-	else if (off == POWER_SUPPLY_PROP_TYPE)
+	else if (off == POWER_SUPPLY_PROP_TYPE ||
+			off == POWER_SUPPLY_PROP_REAL_TYPE)
 		return scnprintf(buf, PAGE_SIZE, "%s\n",
 				type_text[value.intval]);
 	else if (off == POWER_SUPPLY_PROP_SCOPE)
@@ -308,6 +309,7 @@
 	POWER_SUPPLY_ATTR(connector_health),
 	POWER_SUPPLY_ATTR(ctm_current_max),
 	POWER_SUPPLY_ATTR(hw_current_max),
+	POWER_SUPPLY_ATTR(real_type),
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_ATTR(charge_counter_ext),
 	/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index 54bef52..4ecf9a5 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -26,6 +26,7 @@
 #include <linux/pm_wakeup.h>
 #include <linux/slab.h>
 #include <linux/pmic-voter.h>
+#include "battery.h"
 
 #define DRV_MAJOR_VERSION	1
 #define DRV_MINOR_VERSION	0
@@ -410,19 +411,6 @@
 	if (!chip->main_psy)
 		return 0;
 
-	if (chip->batt_psy) {
-		rc = power_supply_get_property(chip->batt_psy,
-			POWER_SUPPLY_PROP_CURRENT_QNOVO,
-			&pval);
-		if (rc < 0) {
-			pr_err("Couldn't get qnovo fcc, rc=%d\n", rc);
-			return rc;
-		}
-
-		if (pval.intval != -EINVAL)
-			total_fcc_ua = pval.intval;
-	}
-
 	if (chip->pl_mode == POWER_SUPPLY_PL_NONE
 	    || get_effective_result_locked(chip->pl_disable_votable)) {
 		pval.intval = total_fcc_ua;
@@ -473,7 +461,6 @@
 	struct pl_data *chip = data;
 	union power_supply_propval pval = {0, };
 	int rc = 0;
-	int effective_fv_uv = fv_uv;
 
 	if (fv_uv < 0)
 		return 0;
@@ -481,20 +468,7 @@
 	if (!chip->main_psy)
 		return 0;
 
-	if (chip->batt_psy) {
-		rc = power_supply_get_property(chip->batt_psy,
-			POWER_SUPPLY_PROP_VOLTAGE_QNOVO,
-			&pval);
-		if (rc < 0) {
-			pr_err("Couldn't get qnovo fv, rc=%d\n", rc);
-			return rc;
-		}
-
-		if (pval.intval != -EINVAL)
-			effective_fv_uv = pval.intval;
-	}
-
-	pval.intval = effective_fv_uv;
+	pval.intval = fv_uv;
 
 	rc = power_supply_set_property(chip->main_psy,
 			POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval);
@@ -930,11 +904,17 @@
 }
 
 #define DEFAULT_RESTRICTED_CURRENT_UA	1000000
-static int pl_init(void)
+int qcom_batt_init(void)
 {
 	struct pl_data *chip;
 	int rc = 0;
 
+	/* initialize just once */
+	if (the_chip) {
+		pr_err("was initialized earlier. Failing now\n");
+		return -EINVAL;
+	}
+
 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
@@ -1014,7 +994,9 @@
 		goto unreg_notifier;
 	}
 
-	return rc;
+	the_chip = chip;
+
+	return 0;
 
 unreg_notifier:
 	power_supply_unreg_notifier(&chip->nb);
@@ -1031,21 +1013,23 @@
 	return rc;
 }
 
-static void pl_deinit(void)
+void qcom_batt_deinit(void)
 {
 	struct pl_data *chip = the_chip;
 
+	if (chip == NULL)
+		return;
+
+	cancel_work_sync(&chip->status_change_work);
+	cancel_delayed_work_sync(&chip->pl_taper_work);
+	cancel_work_sync(&chip->pl_disable_forever_work);
+
 	power_supply_unreg_notifier(&chip->nb);
 	destroy_votable(chip->pl_awake_votable);
 	destroy_votable(chip->pl_disable_votable);
 	destroy_votable(chip->fv_votable);
 	destroy_votable(chip->fcc_votable);
 	wakeup_source_unregister(chip->pl_ws);
+	the_chip = NULL;
 	kfree(chip);
 }
-
-module_init(pl_init);
-module_exit(pl_deinit)
-
-MODULE_DESCRIPTION("");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/supply/qcom/battery.h b/drivers/power/supply/qcom/battery.h
new file mode 100644
index 0000000..38626e7
--- /dev/null
+++ b/drivers/power/supply/qcom/battery.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __BATTERY_H
+#define __BATTERY_H
+int qcom_batt_init(void);
+void qcom_batt_deinit(void);
+#endif /* __BATTERY_H */
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index f8a7555..2266a2a 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -238,11 +238,9 @@
 
 #define STEP_CHARGING_MAX_STEPS	5
 struct smb_dt_props {
-	int	fcc_ua;
 	int	usb_icl_ua;
 	int	dc_icl_ua;
 	int	boost_threshold_ua;
-	int	fv_uv;
 	int	wipower_max_uw;
 	int	min_freq_khz;
 	int	max_freq_khz;
@@ -310,14 +308,14 @@
 						"qcom,external-vconn");
 
 	rc = of_property_read_u32(node,
-				"qcom,fcc-max-ua", &chip->dt.fcc_ua);
+				"qcom,fcc-max-ua", &chg->batt_profile_fcc_ua);
 	if (rc < 0)
-		chip->dt.fcc_ua = -EINVAL;
+		chg->batt_profile_fcc_ua = -EINVAL;
 
 	rc = of_property_read_u32(node,
-				"qcom,fv-max-uv", &chip->dt.fv_uv);
+				"qcom,fv-max-uv", &chg->batt_profile_fv_uv);
 	if (rc < 0)
-		chip->dt.fv_uv = -EINVAL;
+		chg->batt_profile_fv_uv = -EINVAL;
 
 	rc = of_property_read_u32(node,
 				"qcom,usb-icl-ua", &chip->dt.usb_icl_ua);
@@ -429,6 +427,7 @@
 	POWER_SUPPLY_PROP_PE_START,
 	POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
 	POWER_SUPPLY_PROP_HW_CURRENT_MAX,
+	POWER_SUPPLY_PROP_REAL_TYPE,
 };
 
 static int smb2_usb_get_prop(struct power_supply *psy,
@@ -448,6 +447,16 @@
 		break;
 	case POWER_SUPPLY_PROP_ONLINE:
 		rc = smblib_get_prop_usb_online(chg, val);
+		if (!val->intval)
+			break;
+
+		rc = smblib_get_prop_typec_mode(chg, val);
+		if ((val->intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
+			chg->micro_usb_mode) &&
+			chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
+			val->intval = 0;
+		else
+			val->intval = 1;
 		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 		val->intval = chg->voltage_min_uv;
@@ -465,10 +474,13 @@
 		rc = smblib_get_prop_usb_current_max(chg, val);
 		break;
 	case POWER_SUPPLY_PROP_TYPE:
+		val->intval = POWER_SUPPLY_TYPE_USB_PD;
+		break;
+	case POWER_SUPPLY_PROP_REAL_TYPE:
 		if (chip->bad_part)
-			val->intval = POWER_SUPPLY_TYPE_USB;
+			val->intval = POWER_SUPPLY_TYPE_USB_PD;
 		else
-			val->intval = chg->usb_psy_desc.type;
+			val->intval = chg->real_charger_type;
 		break;
 	case POWER_SUPPLY_PROP_TYPEC_MODE:
 		if (chg->micro_usb_mode)
@@ -610,7 +622,7 @@
 	struct smb_charger *chg = &chip->chg;
 
 	chg->usb_psy_desc.name			= "usb";
-	chg->usb_psy_desc.type			= POWER_SUPPLY_TYPE_UNKNOWN;
+	chg->usb_psy_desc.type			= POWER_SUPPLY_TYPE_USB_PD;
 	chg->usb_psy_desc.properties		= smb2_usb_props;
 	chg->usb_psy_desc.num_properties	= ARRAY_SIZE(smb2_usb_props);
 	chg->usb_psy_desc.get_property		= smb2_usb_get_prop;
@@ -619,7 +631,7 @@
 
 	usb_cfg.drv_data = chip;
 	usb_cfg.of_node = chg->dev->of_node;
-	chg->usb_psy = devm_power_supply_register(chg->dev,
+	chg->usb_psy = power_supply_register(chg->dev,
 						  &chg->usb_psy_desc,
 						  &usb_cfg);
 	if (IS_ERR(chg->usb_psy)) {
@@ -630,6 +642,97 @@
 	return 0;
 }
 
+/********************************
+ * USB PC_PORT PSY REGISTRATION *
+ ********************************/
+static enum power_supply_property smb2_usb_port_props[] = {
+	POWER_SUPPLY_PROP_TYPE,
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static int smb2_usb_port_get_prop(struct power_supply *psy,
+		enum power_supply_property psp,
+		union power_supply_propval *val)
+{
+	struct smb2 *chip = power_supply_get_drvdata(psy);
+	struct smb_charger *chg = &chip->chg;
+	int rc = 0;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_TYPE:
+		val->intval = POWER_SUPPLY_TYPE_USB;
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		rc = smblib_get_prop_usb_online(chg, val);
+		if (!val->intval)
+			break;
+
+		rc = smblib_get_prop_typec_mode(chg, val);
+		if ((val->intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
+			chg->micro_usb_mode) &&
+			chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
+			val->intval = 1;
+		else
+			val->intval = 0;
+		break;
+	default:
+		pr_err_ratelimited("Get prop %d is not supported in pc_port\n",
+				psp);
+		return -EINVAL;
+	}
+
+	if (rc < 0) {
+		pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
+		return -ENODATA;
+	}
+
+	return 0;
+}
+
+static int smb2_usb_port_set_prop(struct power_supply *psy,
+		enum power_supply_property psp,
+		const union power_supply_propval *val)
+{
+	int rc = 0;
+
+	switch (psp) {
+	default:
+		pr_err_ratelimited("Set prop %d is not supported in pc_port\n",
+				psp);
+		rc = -EINVAL;
+		break;
+	}
+
+	return rc;
+}
+
+static const struct power_supply_desc usb_port_psy_desc = {
+	.name		= "pc_port",
+	.type		= POWER_SUPPLY_TYPE_USB,
+	.properties	= smb2_usb_port_props,
+	.num_properties	= ARRAY_SIZE(smb2_usb_port_props),
+	.get_property	= smb2_usb_port_get_prop,
+	.set_property	= smb2_usb_port_set_prop,
+};
+
+static int smb2_init_usb_port_psy(struct smb2 *chip)
+{
+	struct power_supply_config usb_port_cfg = {};
+	struct smb_charger *chg = &chip->chg;
+
+	usb_port_cfg.drv_data = chip;
+	usb_port_cfg.of_node = chg->dev->of_node;
+	chg->usb_port_psy = power_supply_register(chg->dev,
+						  &usb_port_psy_desc,
+						  &usb_port_cfg);
+	if (IS_ERR(chg->usb_port_psy)) {
+		pr_err("Couldn't register USB pc_port power supply\n");
+		return PTR_ERR(chg->usb_port_psy);
+	}
+
+	return 0;
+}
+
 /*****************************
  * USB MAIN PSY REGISTRATION *
  *****************************/
@@ -677,7 +780,7 @@
 		rc = smblib_get_prop_fcc_delta(chg, val);
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		val->intval = get_effective_result(chg->usb_icl_votable);
+		rc = smblib_get_icl_current(chg, &val->intval);
 		break;
 	default:
 		pr_debug("get prop %d is not supported in usb-main\n", psp);
@@ -734,7 +837,7 @@
 
 	usb_main_cfg.drv_data = chip;
 	usb_main_cfg.of_node = chg->dev->of_node;
-	chg->usb_main_psy = devm_power_supply_register(chg->dev,
+	chg->usb_main_psy = power_supply_register(chg->dev,
 						  &usb_main_psy_desc,
 						  &usb_main_cfg);
 	if (IS_ERR(chg->usb_main_psy)) {
@@ -836,7 +939,7 @@
 
 	dc_cfg.drv_data = chip;
 	dc_cfg.of_node = chg->dev->of_node;
-	chg->dc_psy = devm_power_supply_register(chg->dev,
+	chg->dc_psy = power_supply_register(chg->dev,
 						  &dc_psy_desc,
 						  &dc_cfg);
 	if (IS_ERR(chg->dc_psy)) {
@@ -946,13 +1049,15 @@
 		rc = smblib_get_prop_charge_qnovo_enable(chg, val);
 		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_QNOVO:
-		val->intval = chg->qnovo_fv_uv;
+		val->intval = get_client_vote_locked(chg->fv_votable,
+				QNOVO_VOTER);
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 		rc = smblib_get_prop_batt_current_now(chg, val);
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_QNOVO:
-		val->intval = chg->qnovo_fcc_ua;
+		val->intval = get_client_vote_locked(chg->fcc_votable,
+				QNOVO_VOTER);
 		break;
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
 		val->intval = get_client_vote(chg->fcc_votable,
@@ -1018,23 +1123,37 @@
 		vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
 		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
-		vote(chg->fv_votable, DEFAULT_VOTER, true, val->intval);
+		chg->batt_profile_fv_uv = val->intval;
+		vote(chg->fv_votable, BATT_PROFILE_VOTER, true, val->intval);
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE:
 		rc = smblib_set_prop_charge_qnovo_enable(chg, val);
 		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_QNOVO:
-		chg->qnovo_fv_uv = val->intval;
-		rc = rerun_election(chg->fv_votable);
+		if (val->intval == -EINVAL) {
+			vote(chg->fv_votable, BATT_PROFILE_VOTER,
+					true, chg->batt_profile_fv_uv);
+			vote(chg->fv_votable, QNOVO_VOTER, false, 0);
+		} else {
+			vote(chg->fv_votable, QNOVO_VOTER, true, val->intval);
+			vote(chg->fv_votable, BATT_PROFILE_VOTER, false, 0);
+		}
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_QNOVO:
-		chg->qnovo_fcc_ua = val->intval;
 		vote(chg->pl_disable_votable, PL_QNOVO_VOTER,
 			val->intval != -EINVAL && val->intval < 2000000, 0);
-		rc = rerun_election(chg->fcc_votable);
+		if (val->intval == -EINVAL) {
+			vote(chg->fcc_votable, BATT_PROFILE_VOTER,
+					true, chg->batt_profile_fcc_ua);
+			vote(chg->fcc_votable, QNOVO_VOTER, false, 0);
+		} else {
+			vote(chg->fcc_votable, QNOVO_VOTER, true, val->intval);
+			vote(chg->fcc_votable, BATT_PROFILE_VOTER, false, 0);
+		}
 		break;
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
-		vote(chg->fcc_votable, DEFAULT_VOTER, true, val->intval);
+		chg->batt_profile_fcc_ua = val->intval;
+		vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval);
 		break;
 	case POWER_SUPPLY_PROP_SET_SHIP_MODE:
 		/* Not in ship mode as long as the device is active */
@@ -1051,6 +1170,9 @@
 	case POWER_SUPPLY_PROP_DP_DM:
 		rc = smblib_dp_dm(chg, val->intval);
 		break;
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
+		rc = smblib_set_prop_input_current_limited(chg, val);
+		break;
 	default:
 		rc = -EINVAL;
 	}
@@ -1068,6 +1190,7 @@
 	case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
 	case POWER_SUPPLY_PROP_DP_DM:
 	case POWER_SUPPLY_PROP_RERUN_AICL:
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
 		return 1;
 	default:
 		break;
@@ -1094,7 +1217,7 @@
 
 	batt_cfg.drv_data = chg;
 	batt_cfg.of_node = chg->dev->of_node;
-	chg->batt_psy = devm_power_supply_register(chg->dev,
+	chg->batt_psy = power_supply_register(chg->dev,
 						   &batt_psy_desc,
 						   &batt_cfg);
 	if (IS_ERR(chg->batt_psy)) {
@@ -1451,11 +1574,13 @@
 	if (chip->dt.no_battery)
 		chg->fake_capacity = 50;
 
-	if (chip->dt.fcc_ua < 0)
-		smblib_get_charge_param(chg, &chg->param.fcc, &chip->dt.fcc_ua);
+	if (chg->batt_profile_fcc_ua < 0)
+		smblib_get_charge_param(chg, &chg->param.fcc,
+				&chg->batt_profile_fcc_ua);
 
-	if (chip->dt.fv_uv < 0)
-		smblib_get_charge_param(chg, &chg->param.fv, &chip->dt.fv_uv);
+	if (chg->batt_profile_fv_uv < 0)
+		smblib_get_charge_param(chg, &chg->param.fv,
+				&chg->batt_profile_fv_uv);
 
 	smblib_get_charge_param(chg, &chg->param.usb_icl,
 				&chg->default_icl_ua);
@@ -1516,9 +1641,9 @@
 	vote(chg->dc_suspend_votable,
 		DEFAULT_VOTER, chip->dt.no_battery, 0);
 	vote(chg->fcc_votable,
-		DEFAULT_VOTER, true, chip->dt.fcc_ua);
+		BATT_PROFILE_VOTER, true, chg->batt_profile_fcc_ua);
 	vote(chg->fv_votable,
-		DEFAULT_VOTER, true, chip->dt.fv_uv);
+		BATT_PROFILE_VOTER, true, chg->batt_profile_fv_uv);
 	vote(chg->dc_icl_votable,
 		DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
 	vote(chg->hvdcp_disable_votable_indirect, PD_INACTIVE_VOTER,
@@ -2062,6 +2187,21 @@
 	return rc;
 }
 
+static void smb2_free_interrupts(struct smb_charger *chg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(smb2_irqs); i++) {
+		if (smb2_irqs[i].irq > 0) {
+			if (smb2_irqs[i].wake)
+				disable_irq_wake(smb2_irqs[i].irq);
+
+			devm_free_irq(chg->dev, smb2_irqs[i].irq,
+					smb2_irqs[i].irq_data);
+		}
+	}
+}
+
 static void smb2_disable_interrupts(struct smb_charger *chg)
 {
 	int i;
@@ -2239,7 +2379,13 @@
 
 	rc = smb2_init_usb_main_psy(chip);
 	if (rc < 0) {
-		pr_err("Couldn't initialize usb psy rc=%d\n", rc);
+		pr_err("Couldn't initialize usb main psy rc=%d\n", rc);
+		goto cleanup;
+	}
+
+	rc = smb2_init_usb_port_psy(chip);
+	if (rc < 0) {
+		pr_err("Couldn't initialize usb pc_port psy rc=%d\n", rc);
 		goto cleanup;
 	}
 
@@ -2297,20 +2443,29 @@
 	device_init_wakeup(chg->dev, true);
 
 	pr_info("QPNP SMB2 probed successfully usb:present=%d type=%d batt:present = %d health = %d charge = %d\n",
-		usb_present, chg->usb_psy_desc.type,
+		usb_present, chg->real_charger_type,
 		batt_present, batt_health, batt_charge_type);
 	return rc;
 
 cleanup:
-	smblib_deinit(chg);
-	if (chg->usb_psy)
-		power_supply_unregister(chg->usb_psy);
+	smb2_free_interrupts(chg);
 	if (chg->batt_psy)
 		power_supply_unregister(chg->batt_psy);
+	if (chg->usb_main_psy)
+		power_supply_unregister(chg->usb_main_psy);
+	if (chg->usb_psy)
+		power_supply_unregister(chg->usb_psy);
+	if (chg->usb_port_psy)
+		power_supply_unregister(chg->usb_port_psy);
+	if (chg->dc_psy)
+		power_supply_unregister(chg->dc_psy);
 	if (chg->vconn_vreg && chg->vconn_vreg->rdev)
-		regulator_unregister(chg->vconn_vreg->rdev);
+		devm_regulator_unregister(chg->dev, chg->vconn_vreg->rdev);
 	if (chg->vbus_vreg && chg->vbus_vreg->rdev)
-		regulator_unregister(chg->vbus_vreg->rdev);
+		devm_regulator_unregister(chg->dev, chg->vbus_vreg->rdev);
+
+	smblib_deinit(chg);
+
 	platform_set_drvdata(pdev, NULL);
 	return rc;
 }
@@ -2322,6 +2477,7 @@
 
 	power_supply_unregister(chg->batt_psy);
 	power_supply_unregister(chg->usb_psy);
+	power_supply_unregister(chg->usb_port_psy);
 	regulator_unregister(chg->vconn_vreg->rdev);
 	regulator_unregister(chg->vbus_vreg->rdev);
 
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index f4ae415..b1070e8 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -18,10 +18,11 @@
 #include <linux/regulator/driver.h>
 #include <linux/qpnp/qpnp-revid.h>
 #include <linux/irq.h>
+#include <linux/pmic-voter.h>
 #include "smb-lib.h"
 #include "smb-reg.h"
+#include "battery.h"
 #include "storm-watch.h"
-#include <linux/pmic-voter.h>
 
 #define smblib_err(chg, fmt, ...)		\
 	pr_err("%s: %s: " fmt, chg->name,	\
@@ -548,9 +549,9 @@
 
 	/* if PD is active, APSD is disabled so won't have a valid result */
 	if (chg->pd_active)
-		chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
+		chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD;
 	else
-		chg->usb_psy_desc.type = apsd_result->pst;
+		chg->real_charger_type = apsd_result->pst;
 
 	smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n",
 					apsd_result->name, chg->pd_active);
@@ -812,6 +813,28 @@
 	return rc;
 }
 
+static int get_sdp_current(struct smb_charger *chg, int *icl_ua)
+{
+	int rc;
+	u8 icl_options;
+	bool usb3 = false;
+
+	rc = smblib_read(chg, USBIN_ICL_OPTIONS_REG, &icl_options);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't get ICL options rc=%d\n", rc);
+		return rc;
+	}
+
+	usb3 = (icl_options & CFG_USB3P0_SEL_BIT);
+
+	if (icl_options & USB51_MODE_BIT)
+		*icl_ua = usb3 ? USBIN_900MA : USBIN_500MA;
+	else
+		*icl_ua = usb3 ? USBIN_150MA : USBIN_100MA;
+
+	return rc;
+}
+
 int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
 {
 	int rc = 0;
@@ -834,7 +857,7 @@
 
 	/* configure current */
 	if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
-		&& (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) {
+		&& (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)) {
 		rc = set_sdp_current(chg, icl_ua);
 		if (rc < 0) {
 			smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc);
@@ -855,10 +878,10 @@
 		/* remove override if no voters - hw defaults is desired */
 		override = false;
 	} else if (pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
-		if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)
+		if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
 			/* For std cable with type = SDP never override */
 			override = false;
-		else if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_CDP
+		else if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_CDP
 			&& icl_ua == 1500000)
 			/*
 			 * For std cable with type = CDP override only if
@@ -889,6 +912,48 @@
 	return rc;
 }
 
+int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua)
+{
+	int rc = 0;
+	u8 load_cfg;
+	bool override;
+	union power_supply_propval pval;
+
+	rc = smblib_get_prop_typec_mode(chg, &pval);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't get typeC mode rc = %d\n", rc);
+		return rc;
+	}
+
+	if ((pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
+		|| chg->micro_usb_mode)
+		&& (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) {
+		rc = get_sdp_current(chg, icl_ua);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't get SDP ICL rc=%d\n", rc);
+			return rc;
+		}
+	} else {
+		rc = smblib_read(chg, USBIN_LOAD_CFG_REG, &load_cfg);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't get load cfg rc=%d\n", rc);
+			return rc;
+		}
+		override = load_cfg & ICL_OVERRIDE_AFTER_APSD_BIT;
+		if (!override)
+			return INT_MAX;
+
+		/* override is set */
+		rc = smblib_get_charge_param(chg, &chg->param.usb_icl, icl_ua);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't get HC ICL rc=%d\n", rc);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
 /*********************
  * VOTABLE CALLBACKS *
  *********************/
@@ -1648,6 +1713,11 @@
 	u8 stat;
 	int rc;
 
+	if (chg->fake_input_current_limited >= 0) {
+		val->intval = chg->fake_input_current_limited;
+		return 0;
+	}
+
 	rc = smblib_read(chg, AICL_STATUS_REG, &stat);
 	if (rc < 0) {
 		smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n", rc);
@@ -1839,6 +1909,13 @@
 	return rc;
 }
 
+int smblib_set_prop_input_current_limited(struct smb_charger *chg,
+				const union power_supply_propval *val)
+{
+	chg->fake_input_current_limited = val->intval;
+	return 0;
+}
+
 int smblib_rerun_aicl(struct smb_charger *chg)
 {
 	int rc, settled_icl_ua;
@@ -2822,7 +2899,7 @@
 int smblib_get_charge_current(struct smb_charger *chg,
 				int *total_current_ua)
 {
-	const struct apsd_result *apsd_result = smblib_update_usb_type(chg);
+	const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
 	union power_supply_propval val = {0, };
 	int rc = 0, typec_source_rd, current_ua;
 	bool non_compliant;
@@ -3094,12 +3171,28 @@
 	}
 }
 
-static void smblib_typec_usb_plugin(struct smb_charger *chg, bool vbus_rising)
+void smblib_usb_plugin_hard_reset_locked(struct smb_charger *chg)
 {
+	int rc;
+	u8 stat;
+	bool vbus_rising;
+
+	rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
+		return;
+	}
+
+	vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
+
 	if (vbus_rising)
 		smblib_cc2_sink_removal_exit(chg);
 	else
 		smblib_cc2_sink_removal_enter(chg);
+
+	power_supply_changed(chg->usb_psy);
+	smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
+					vbus_rising ? "attached" : "detached");
 }
 
 #define PL_DELAY_MS			30000
@@ -3158,8 +3251,6 @@
 
 	if (chg->micro_usb_mode)
 		smblib_micro_usb_plugin(chg, vbus_rising);
-	else
-		smblib_typec_usb_plugin(chg, vbus_rising);
 
 	power_supply_changed(chg->usb_psy);
 	smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
@@ -3172,7 +3263,10 @@
 	struct smb_charger *chg = irq_data->parent_data;
 
 	mutex_lock(&chg->lock);
-	smblib_usb_plugin_locked(chg);
+	if (chg->pd_hard_reset)
+		smblib_usb_plugin_hard_reset_locked(chg);
+	else
+		smblib_usb_plugin_locked(chg);
 	mutex_unlock(&chg->lock);
 	return IRQ_HANDLED;
 }
@@ -3238,7 +3332,7 @@
 	int pulses;
 
 	power_supply_changed(chg->usb_main_psy);
-	if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP) {
+	if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP) {
 		rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat);
 		if (rc < 0) {
 			smblib_err(chg,
@@ -3266,7 +3360,7 @@
 		}
 	}
 
-	if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
+	if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
 		rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
 		if (rc < 0) {
 			smblib_err(chg,
@@ -3336,7 +3430,7 @@
 static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
 					      bool rising, bool qc_charger)
 {
-	const struct apsd_result *apsd_result = smblib_update_usb_type(chg);
+	const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
 
 	/* Hold off PD only until hvdcp 2.0 detection timeout */
 	if (rising) {
@@ -4197,26 +4291,30 @@
 	int rc = 0;
 
 	chg->fcc_votable = find_votable("FCC");
-	if (!chg->fcc_votable) {
-		rc = -EPROBE_DEFER;
+	if (chg->fcc_votable == NULL) {
+		rc = -EINVAL;
+		smblib_err(chg, "Couldn't find FCC votable rc=%d\n", rc);
 		return rc;
 	}
 
 	chg->fv_votable = find_votable("FV");
-	if (!chg->fv_votable) {
-		rc = -EPROBE_DEFER;
+	if (chg->fv_votable == NULL) {
+		rc = -EINVAL;
+		smblib_err(chg, "Couldn't find FV votable rc=%d\n", rc);
 		return rc;
 	}
 
 	chg->usb_icl_votable = find_votable("USB_ICL");
 	if (!chg->usb_icl_votable) {
-		rc = -EPROBE_DEFER;
+		rc = -EINVAL;
+		smblib_err(chg, "Couldn't find USB_ICL votable rc=%d\n", rc);
 		return rc;
 	}
 
 	chg->pl_disable_votable = find_votable("PL_DISABLE");
-	if (!chg->pl_disable_votable) {
-		rc = -EPROBE_DEFER;
+	if (chg->pl_disable_votable == NULL) {
+		rc = -EINVAL;
+		smblib_err(chg, "Couldn't find votable PL_DISABLE rc=%d\n", rc);
 		return rc;
 	}
 	vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0);
@@ -4395,11 +4493,17 @@
 	INIT_DELAYED_WORK(&chg->pl_enable_work, smblib_pl_enable_work);
 	INIT_WORK(&chg->legacy_detection_work, smblib_legacy_detection_work);
 	chg->fake_capacity = -EINVAL;
+	chg->fake_input_current_limited = -EINVAL;
 
 	switch (chg->mode) {
 	case PARALLEL_MASTER:
-		chg->qnovo_fcc_ua = -EINVAL;
-		chg->qnovo_fv_uv = -EINVAL;
+		rc = qcom_batt_init();
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't init qcom_batt_init rc=%d\n",
+				rc);
+			return rc;
+		}
+
 		rc = smblib_create_votables(chg);
 		if (rc < 0) {
 			smblib_err(chg, "Couldn't create votables rc=%d\n",
@@ -4431,8 +4535,20 @@
 {
 	switch (chg->mode) {
 	case PARALLEL_MASTER:
+		cancel_work_sync(&chg->bms_update_work);
+		cancel_work_sync(&chg->rdstd_cc2_detach_work);
+		cancel_delayed_work_sync(&chg->hvdcp_detect_work);
+		cancel_delayed_work_sync(&chg->step_soc_req_work);
+		cancel_delayed_work_sync(&chg->clear_hdc_work);
+		cancel_work_sync(&chg->otg_oc_work);
+		cancel_work_sync(&chg->vconn_oc_work);
+		cancel_delayed_work_sync(&chg->otg_ss_done_work);
+		cancel_delayed_work_sync(&chg->icl_change_work);
+		cancel_delayed_work_sync(&chg->pl_enable_work);
+		cancel_work_sync(&chg->legacy_detection_work);
 		power_supply_unreg_notifier(&chg->nb);
 		smblib_destroy_votables(chg);
+		qcom_batt_deinit();
 		break;
 	case PARALLEL_SLAVE:
 		break;
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 5409166..42b357e 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -62,6 +62,8 @@
 #define AICL_RERUN_VOTER		"AICL_RERUN_VOTER"
 #define LEGACY_UNKNOWN_VOTER		"LEGACY_UNKNOWN_VOTER"
 #define CC2_WA_VOTER			"CC2_WA_VOTER"
+#define QNOVO_VOTER			"QNOVO_VOTER"
+#define BATT_PROFILE_VOTER		"BATT_PROFILE_VOTER"
 
 #define VCONN_MAX_ATTEMPTS	3
 #define OTG_MAX_ATTEMPTS	3
@@ -242,6 +244,8 @@
 	struct power_supply		*bms_psy;
 	struct power_supply_desc	usb_psy_desc;
 	struct power_supply		*usb_main_psy;
+	struct power_supply		*usb_port_psy;
+	enum power_supply_type		real_charger_type;
 
 	/* notifiers */
 	struct notifier_block	nb;
@@ -314,6 +318,7 @@
 	bool			typec_present;
 	u8			typec_status[5];
 	bool			typec_legacy_valid;
+	int			fake_input_current_limited;
 
 	/* workaround flag */
 	u32			wa_flags;
@@ -325,9 +330,11 @@
 	/* extcon for VBUS / ID notification to USB for uUSB */
 	struct extcon_dev	*extcon;
 
+	/* battery profile */
+	int			batt_profile_fcc_ua;
+	int			batt_profile_fv_uv;
+
 	/* qnovo */
-	int			qnovo_fcc_ua;
-	int			qnovo_fv_uv;
 	int			usb_icl_delta_ua;
 	int			pulse_cnt;
 };
@@ -417,6 +424,8 @@
 				const union power_supply_propval *val);
 int smblib_set_prop_system_temp_level(struct smb_charger *chg,
 				const union power_supply_propval *val);
+int smblib_set_prop_input_current_limited(struct smb_charger *chg,
+				const union power_supply_propval *val);
 
 int smblib_get_prop_dc_present(struct smb_charger *chg,
 				union power_supply_propval *val);
@@ -495,6 +504,7 @@
 int smblib_dp_dm(struct smb_charger *chg, int val);
 int smblib_rerun_aicl(struct smb_charger *chg);
 int smblib_set_icl_current(struct smb_charger *chg, int icl_ua);
+int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua);
 int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua);
 
 int smblib_init(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h
index 3f260a4..167666a 100644
--- a/drivers/power/supply/qcom/smb-reg.h
+++ b/drivers/power/supply/qcom/smb-reg.h
@@ -1025,14 +1025,4 @@
 /* CHGR FREQ Peripheral registers */
 #define FREQ_CLK_DIV_REG			(CHGR_FREQ_BASE + 0x50)
 
-/* SMB1355 specific registers */
-#define SMB1355_TEMP_COMP_STATUS_REG		(MISC_BASE + 0x07)
-#define SKIN_TEMP_RST_HOT_BIT			BIT(6)
-#define SKIN_TEMP_UB_HOT_BIT			BIT(5)
-#define SKIN_TEMP_LB_HOT_BIT			BIT(4)
-#define DIE_TEMP_TSD_HOT_BIT			BIT(3)
-#define DIE_TEMP_RST_HOT_BIT			BIT(2)
-#define DIE_TEMP_UB_HOT_BIT			BIT(1)
-#define DIE_TEMP_LB_HOT_BIT			BIT(0)
-
 #endif /* __SMB2_CHARGER_REG_H */
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index a29871b..83374bb 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -104,8 +104,6 @@
 	struct smb_dt_props	dt;
 	struct power_supply	*parallel_psy;
 	u32			wa_flags;
-	struct pmic_revid_data	*pmic_rev_id;
-	char			*name;
 };
 
 static int __debug_mask;
@@ -169,14 +167,6 @@
 	if (rc < 0)
 		chip->dt.pl_mode = POWER_SUPPLY_PL_USBMID_USBMID;
 
-	/* check that smb1355 is configured to run in mid-mid mode */
-	if (chip->pmic_rev_id->pmic_subtype == SMB1355_SUBTYPE
-		&& chip->dt.pl_mode != POWER_SUPPLY_PL_USBMID_USBMID) {
-		pr_err("Smb1355 can only run in MID-MID mode, saw = %d mode\n",
-				chip->dt.pl_mode);
-		return -EINVAL;
-	}
-
 	chip->dt.suspend_input = of_property_read_bool(node,
 				"qcom,suspend-input");
 
@@ -489,30 +479,6 @@
  * PARALLEL PSY REGISTRATION *
  *****************************/
 
-static int smb1355_get_prop_connector_health(struct smb138x *chip)
-{
-	struct smb_charger *chg = &chip->chg;
-	u8 temp;
-	int rc;
-
-	rc = smblib_read(chg, SMB1355_TEMP_COMP_STATUS_REG, &temp);
-	if (rc < 0) {
-		pr_err("Couldn't read comp stat reg rc = %d\n", rc);
-		return POWER_SUPPLY_HEALTH_UNKNOWN;
-	}
-
-	if (temp & SKIN_TEMP_RST_HOT_BIT)
-		return POWER_SUPPLY_HEALTH_OVERHEAT;
-
-	if (temp & SKIN_TEMP_UB_HOT_BIT)
-		return POWER_SUPPLY_HEALTH_HOT;
-
-	if (temp & SKIN_TEMP_LB_HOT_BIT)
-		return POWER_SUPPLY_HEALTH_WARM;
-
-	return POWER_SUPPLY_HEALTH_COOL;
-}
-
 static int smb138x_get_prop_connector_health(struct smb138x *chip)
 {
 	struct smb_charger *chg = &chip->chg;
@@ -570,32 +536,16 @@
 	POWER_SUPPLY_PROP_PIN_ENABLED,
 	POWER_SUPPLY_PROP_INPUT_SUSPEND,
 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
-	POWER_SUPPLY_PROP_VOLTAGE_MAX,
-	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
-	POWER_SUPPLY_PROP_MODEL_NAME,
-	POWER_SUPPLY_PROP_PARALLEL_MODE,
-	POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
-	POWER_SUPPLY_PROP_SET_SHIP_MODE,
-	POWER_SUPPLY_PROP_CHARGER_TEMP,
-	POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
-	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
-};
-
-static enum power_supply_property smb1355_parallel_props[] = {
-	POWER_SUPPLY_PROP_CHARGE_TYPE,
-	POWER_SUPPLY_PROP_CHARGING_ENABLED,
-	POWER_SUPPLY_PROP_PIN_ENABLED,
-	POWER_SUPPLY_PROP_INPUT_SUSPEND,
-	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
 	POWER_SUPPLY_PROP_VOLTAGE_MAX,
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CHARGER_TEMP,
+	POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
 	POWER_SUPPLY_PROP_MODEL_NAME,
 	POWER_SUPPLY_PROP_PARALLEL_MODE,
 	POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
 	POWER_SUPPLY_PROP_SET_SHIP_MODE,
-	POWER_SUPPLY_PROP_CHARGER_TEMP,
-	POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
 };
 
 static int smb138x_parallel_get_prop(struct power_supply *psy,
@@ -633,6 +583,14 @@
 		else
 			val->intval = 0;
 		break;
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
+		|| (chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))
+			rc = smblib_get_charge_param(chg, &chg->param.usb_icl,
+				&val->intval);
+		else
+			val->intval = 0;
+		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
 		rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
 		break;
@@ -640,46 +598,28 @@
 		rc = smblib_get_charge_param(chg, &chg->param.fcc,
 					     &val->intval);
 		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		rc = smblib_get_prop_slave_current_now(chg, val);
+		break;
+	case POWER_SUPPLY_PROP_CHARGER_TEMP:
+		rc = smb138x_get_prop_charger_temp(chip, val);
+		break;
+	case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
+		rc = smblib_get_prop_charger_temp_max(chg, val);
+		break;
 	case POWER_SUPPLY_PROP_MODEL_NAME:
-		val->strval = chip->name;
+		val->strval = "smb138x";
 		break;
 	case POWER_SUPPLY_PROP_PARALLEL_MODE:
 		val->intval = chip->dt.pl_mode;
 		break;
 	case POWER_SUPPLY_PROP_CONNECTOR_HEALTH:
-		if (chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
-			val->intval = smb138x_get_prop_connector_health(chip);
-		else
-			val->intval = smb1355_get_prop_connector_health(chip);
+		val->intval = smb138x_get_prop_connector_health(chip);
 		break;
 	case POWER_SUPPLY_PROP_SET_SHIP_MODE:
 		/* Not in ship mode as long as device is active */
 		val->intval = 0;
 		break;
-	case POWER_SUPPLY_PROP_CHARGER_TEMP:
-		if (chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
-			rc = smb138x_get_prop_charger_temp(chip, val);
-		else
-			rc = smblib_get_prop_charger_temp(chg, val);
-		break;
-	case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
-		rc = smblib_get_prop_charger_temp_max(chg, val);
-		break;
-	case POWER_SUPPLY_PROP_CURRENT_NOW:
-		if (chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
-			rc = smblib_get_prop_slave_current_now(chg, val);
-		else
-			rc = -ENODATA;
-		break;
-	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		if ((chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
-		  && ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
-		  || (chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT)))
-			rc = smblib_get_charge_param(chg, &chg->param.usb_icl,
-				&val->intval);
-		else
-			rc = -ENODATA;
-		break;
 	default:
 		pr_err("parallel power supply get prop %d not supported\n",
 			prop);
@@ -763,7 +703,7 @@
 	return 0;
 }
 
-static struct power_supply_desc parallel_psy_desc = {
+static const struct power_supply_desc parallel_psy_desc = {
 	.name			= "parallel",
 	.type			= POWER_SUPPLY_TYPE_PARALLEL,
 	.properties		= smb138x_parallel_props,
@@ -791,28 +731,6 @@
 	return 0;
 }
 
-static int smb1355_init_parallel_psy(struct smb138x *chip)
-{
-	struct power_supply_config parallel_cfg = {};
-	struct smb_charger *chg = &chip->chg;
-
-	parallel_cfg.drv_data = chip;
-	parallel_cfg.of_node = chg->dev->of_node;
-
-	/* change to smb1355's property list */
-	parallel_psy_desc.properties = smb1355_parallel_props;
-	parallel_psy_desc.num_properties = ARRAY_SIZE(smb1355_parallel_props);
-	chip->parallel_psy = devm_power_supply_register(chg->dev,
-						   &parallel_psy_desc,
-						   &parallel_cfg);
-	if (IS_ERR(chip->parallel_psy)) {
-		pr_err("Couldn't register parallel power supply\n");
-		return PTR_ERR(chip->parallel_psy);
-	}
-
-	return 0;
-}
-
 /******************************
  * VBUS REGULATOR REGISTRATION *
  ******************************/
@@ -1132,6 +1050,7 @@
 
 static int smb138x_setup_wa_flags(struct smb138x *chip)
 {
+	struct pmic_revid_data *pmic_rev_id;
 	struct device_node *revid_dev_node;
 
 	revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
@@ -1141,8 +1060,8 @@
 		return -EINVAL;
 	}
 
-	chip->pmic_rev_id = get_revid_data(revid_dev_node);
-	if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
+	pmic_rev_id = get_revid_data(revid_dev_node);
+	if (IS_ERR_OR_NULL(pmic_rev_id)) {
 		/*
 		 * the revid peripheral must be registered, any failure
 		 * here only indicates that the rev-id module has not
@@ -1151,14 +1070,14 @@
 		return -EPROBE_DEFER;
 	}
 
-	switch (chip->pmic_rev_id->pmic_subtype) {
+	switch (pmic_rev_id->pmic_subtype) {
 	case SMB1381_SUBTYPE:
-		if (chip->pmic_rev_id->rev4 < 2) /* SMB1381 rev 1.0 */
+		if (pmic_rev_id->rev4 < 2) /* SMB1381 rev 1.0 */
 			chip->wa_flags |= OOB_COMP_WA_BIT;
 		break;
 	default:
 		pr_err("PMIC subtype %d not supported\n",
-				chip->pmic_rev_id->pmic_subtype);
+				pmic_rev_id->pmic_subtype);
 		return -EINVAL;
 	}
 
@@ -1456,7 +1375,6 @@
 
 	chg->param = v1_params;
 
-	chip->name = "smb1381";
 	rc = smblib_init(chg);
 	if (rc < 0) {
 		pr_err("Couldn't initialize smblib rc=%d\n", rc);
@@ -1517,7 +1435,7 @@
 	return rc;
 }
 
-static int smb1355_slave_probe(struct smb138x *chip)
+static int smb138x_slave_probe(struct smb138x *chip)
 {
 	struct smb_charger *chg = &chip->chg;
 	int rc = 0;
@@ -1530,55 +1448,6 @@
 		goto cleanup;
 	}
 
-	rc = smb138x_parse_dt(chip);
-	if (rc < 0) {
-		pr_err("Couldn't parse device tree rc=%d\n", rc);
-		goto cleanup;
-	}
-
-	rc = smb138x_init_slave_hw(chip);
-	if (rc < 0) {
-		pr_err("Couldn't initialize hardware rc=%d\n", rc);
-		goto cleanup;
-	}
-
-	rc = smb1355_init_parallel_psy(chip);
-	if (rc < 0) {
-		pr_err("Couldn't initialize parallel psy rc=%d\n", rc);
-		goto cleanup;
-	}
-
-	rc = smb138x_determine_initial_slave_status(chip);
-	if (rc < 0) {
-		pr_err("Couldn't determine initial status rc=%d\n", rc);
-		goto cleanup;
-	}
-
-	rc = smb138x_request_interrupts(chip);
-	if (rc < 0) {
-		pr_err("Couldn't request interrupts rc=%d\n", rc);
-		goto cleanup;
-	}
-
-	return 0;
-
-cleanup:
-	smblib_deinit(chg);
-	return rc;
-}
-
-static int smb1381_slave_probe(struct smb138x *chip)
-{
-	struct smb_charger *chg = &chip->chg;
-	int rc = 0;
-
-	chg->param = v1_params;
-
-	rc = smblib_init(chg);
-	if (rc < 0) {
-		pr_err("Couldn't initialize smblib rc=%d\n", rc);
-		goto cleanup;
-	}
 	chg->iio.temp_max_chan = iio_channel_get(chg->dev, "charger_temp_max");
 	if (IS_ERR(chg->iio.temp_max_chan)) {
 		rc = PTR_ERR(chg->iio.temp_max_chan);
@@ -1646,71 +1515,25 @@
 		goto cleanup;
 	}
 
-	return 0;
+	return rc;
 
 cleanup:
 	smblib_deinit(chg);
+	if (chip->parallel_psy)
+		power_supply_unregister(chip->parallel_psy);
+	if (chg->vbus_vreg && chg->vbus_vreg->rdev)
+		regulator_unregister(chg->vbus_vreg->rdev);
 	return rc;
 }
 
-static int slave_probe(struct smb138x *chip)
-{
-	struct device_node *revid_dev_node;
-	int rc = 0;
-
-	revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
-					"qcom,pmic-revid", 0);
-	if (!revid_dev_node) {
-		pr_err("Missing qcom,pmic-revid property\n");
-		return -EINVAL;
-	}
-
-	chip->pmic_rev_id = get_revid_data(revid_dev_node);
-	if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
-		/*
-		 * the revid peripheral must be registered, any failure
-		 * here only indicates that the rev-id module has not
-		 * probed yet.
-		 */
-		return -EPROBE_DEFER;
-	}
-
-	switch (chip->pmic_rev_id->pmic_subtype) {
-	case SMB1355_SUBTYPE:
-		chip->name = "smb1355";
-		rc = smb1355_slave_probe(chip);
-		break;
-	case SMB1381_SUBTYPE:
-		chip->name = "smb1381";
-		rc = smb1381_slave_probe(chip);
-		break;
-	default:
-		pr_err("Unsupported pmic subtype = 0x%02x\n",
-				chip->pmic_rev_id->pmic_subtype);
-		rc = -EINVAL;
-	}
-
-	if (rc < 0) {
-		if (rc != -EPROBE_DEFER)
-			pr_err("Couldn't probe SMB138X rc=%d\n", rc);
-		return rc;
-	}
-
-	return 0;
-}
-
 static const struct of_device_id match_table[] = {
 	{
-		.compatible	= "qcom,smb138x-charger",
-		.data		= (void *) PARALLEL_MASTER,
+		.compatible = "qcom,smb138x-charger",
+		.data = (void *) PARALLEL_MASTER
 	},
 	{
-		.compatible	= "qcom,smb138x-parallel-slave",
-		.data		= (void *) PARALLEL_SLAVE,
-	},
-	{
-		.compatible	= "qcom,smb1355-parallel-slave",
-		.data		= (void *) PARALLEL_SLAVE,
+		.compatible = "qcom,smb138x-parallel-slave",
+		.data = (void *) PARALLEL_SLAVE
 	},
 	{ },
 };
@@ -1757,7 +1580,7 @@
 		rc = smb138x_master_probe(chip);
 		break;
 	case PARALLEL_SLAVE:
-		rc = slave_probe(chip);
+		rc = smb138x_slave_probe(chip);
 		break;
 	default:
 		pr_err("Couldn't find a matching mode %d\n", chip->chg.mode);
@@ -1771,8 +1594,7 @@
 		goto cleanup;
 	}
 
-	pr_info("%s probed successfully mode=%d pl_mode = %d\n",
-		chip->name, chip->chg.mode, chip->dt.pl_mode);
+	pr_info("SMB138X probed successfully mode=%d\n", chip->chg.mode);
 	return rc;
 
 cleanup:
diff --git a/drivers/regulator/cprh-kbss-regulator.c b/drivers/regulator/cprh-kbss-regulator.c
index cf7c35d..deb0ce5 100644
--- a/drivers/regulator/cprh-kbss-regulator.c
+++ b/drivers/regulator/cprh-kbss-regulator.c
@@ -86,7 +86,7 @@
  */
 #define CPRH_MSM8998_KBSS_FUSE_COMBO_COUNT	32
 #define CPRH_SDM660_KBSS_FUSE_COMBO_COUNT	16
-#define CPRH_SDM845_KBSS_FUSE_COMBO_COUNT	16
+#define CPRH_SDM845_KBSS_FUSE_COMBO_COUNT	24
 
 /*
  * Constants which define the name of each fuse corner.
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index dc74484..2f6cd95 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -10054,7 +10054,8 @@
 	mb();
 
 	/* IRQ registration */
-	err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
+	err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED,
+				dev_name(dev), hba);
 	if (err) {
 		dev_err(hba->dev, "request irq failed\n");
 		goto exit_gating;
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 0bdcc99..a50e901 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -616,6 +616,15 @@
 	  This enables bare minimum support of power management at platform level.
 	  i.e WFI
 
+config MSM_QBT1000
+	bool "QBT1000 Ultrasonic Fingerprint Sensor"
+	help
+	  This driver provides services for configuring the fingerprint
+	  sensor hardware and for communicating with the trusted app which
+	  uses it. It enables clocks and provides commands for loading
+	  trusted apps, unloading them and marshalling buffers to the
+	  trusted fingerprint app.
+
 config APSS_CORE_EA
 	depends on CPU_FREQ && PM_OPP
 	bool "Qualcomm Technology Inc specific power aware driver"
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 9d175cd..9a7262e 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -65,6 +65,7 @@
        obj-y += ramdump.o
 endif
 obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+obj-$(CONFIG_MSM_QBT1000) += qbt1000.o
 obj-$(CONFIG_WCD_DSP_GLINK) += wcd-dsp-glink.o
 obj-$(CONFIG_MSM_EVENT_TIMER) += event_timer.o
 obj-$(CONFIG_MSM_IDLE_STATS)	+= lpm-stats.o
diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c
index 4d2f54d..42f146d 100644
--- a/drivers/soc/qcom/dcc_v2.c
+++ b/drivers/soc/qcom/dcc_v2.c
@@ -74,6 +74,12 @@
 #define DCC_RD_MOD_WR_DESCRIPTOR	(BIT(31))
 #define DCC_LINK_DESCRIPTOR		(BIT(31) | BIT(30))
 
+#define DCC_READ_IND			0x00
+#define DCC_WRITE_IND			(BIT(28))
+
+#define DCC_AHB_IND			0x00
+#define DCC_APB_IND			BIT(29)
+
 #define DCC_MAX_LINK_LIST		5
 #define DCC_INVALID_LINK_LIST		0xFF
 
@@ -92,6 +98,13 @@
 	DCC_DATA_SINK_ATB
 };
 
+enum dcc_descriptor_type {
+	DCC_ADDR_TYPE,
+	DCC_LOOP_TYPE,
+	DCC_READ_WRITE_TYPE,
+	DCC_WRITE_TYPE
+};
+
 static const char * const str_dcc_data_sink[] = {
 	[DCC_DATA_SINK_SRAM]		= "sram",
 	[DCC_DATA_SINK_ATB]		= "atb",
@@ -103,15 +116,16 @@
 };
 
 struct dcc_config_entry {
-	uint32_t		base;
-	uint32_t		offset;
-	uint32_t		len;
-	uint32_t		index;
-	uint32_t		loop_cnt;
-	uint32_t		rd_mod_wr;
-	uint32_t		mask;
-	bool			rd_wr_entry;
-	struct list_head	list;
+	uint32_t			base;
+	uint32_t			offset;
+	uint32_t			len;
+	uint32_t			index;
+	uint32_t			loop_cnt;
+	uint32_t			write_val;
+	uint32_t			mask;
+	bool				apb_bus;
+	enum dcc_descriptor_type	desc_type;
+	struct list_head		list;
 };
 
 struct dcc_drvdata {
@@ -140,6 +154,7 @@
 	void			*sram_buf;
 	struct msm_dump_data	sram_data;
 	uint8_t			curr_list;
+	uint8_t			cti_trig;
 };
 
 static bool dcc_ready(struct dcc_drvdata *drvdata)
@@ -189,7 +204,7 @@
 	mutex_lock(&drvdata->mutex);
 
 	if (!dcc_ready(drvdata)) {
-		dev_err(drvdata->dev, "DCC is not ready!\n");
+		dev_err(drvdata->dev, "DCC is not ready\n");
 		ret = -EBUSY;
 		goto err;
 	}
@@ -224,7 +239,7 @@
 	uint32_t loop_off = 0;
 	uint32_t link;
 	uint32_t pos, total_len = 0, loop_len = 0;
-	uint32_t loop, loop_cnt;
+	uint32_t loop, loop_cnt = 0;
 	bool loop_start = false;
 	struct dcc_config_entry *entry;
 
@@ -233,7 +248,9 @@
 	link = 0;
 
 	list_for_each_entry(entry, &drvdata->cfg_head[curr_list], list) {
-		if (entry->rd_wr_entry) {
+		switch (entry->desc_type) {
+		case DCC_READ_WRITE_TYPE:
+		{
 			if (link) {
 				/* write new offset = 1 to continue
 				 * processing the list
@@ -255,12 +272,14 @@
 			dcc_sram_writel(drvdata, entry->mask, sram_offset);
 				sram_offset += 4;
 
-			dcc_sram_writel(drvdata, entry->rd_mod_wr, sram_offset);
+			dcc_sram_writel(drvdata, entry->write_val, sram_offset);
 				sram_offset += 4;
-			continue;
+			addr = 0;
+			break;
 		}
 
-		if (entry->loop_cnt) {
+		case DCC_LOOP_TYPE:
+		{
 			/* Check if we need to write link of prev entry */
 			if (link) {
 				dcc_sram_writel(drvdata, link, sram_offset);
@@ -292,73 +311,130 @@
 			prev_off = 0;
 			prev_addr = addr;
 
-			continue;
+			break;
 		}
 
-		/* Address type */
-		addr = (entry->base >> 4) & BM(0, 27);
-		addr |= DCC_ADDR_DESCRIPTOR;
-		off = entry->offset/4;
-		total_len += entry->len * 4;
-
-		if (!prev_addr || prev_addr != addr || prev_off > off) {
-			/* Check if we need to write link of prev entry */
+		case DCC_WRITE_TYPE:
+		{
 			if (link) {
+				/* write new offset = 1 to continue
+				 * processing the list
+				 */
+				link |= ((0x1 << 8) & BM(8, 14));
 				dcc_sram_writel(drvdata, link, sram_offset);
 				sram_offset += 4;
+				/* Reset link and prev_off */
+				addr = 0x00;
+				prev_off = 0;
+				prev_addr = addr;
 			}
-			dev_err(drvdata->dev,
-				"DCC: sram address.%d\n", sram_offset);
 
-			/* Write address */
+			off = entry->offset/4;
+			/* write new offset-length pair to correct position */
+			link |= ((off & BM(0, 7)) | BIT(15) |
+				 ((entry->len << 8) & BM(8, 14)));
+			link |= DCC_LINK_DESCRIPTOR;
+
+			/* Address type */
+			addr = (entry->base >> 4) & BM(0, 27);
+			if (entry->apb_bus)
+				addr |= DCC_ADDR_DESCRIPTOR | DCC_WRITE_IND
+					| DCC_APB_IND;
+			else
+				addr |= DCC_ADDR_DESCRIPTOR | DCC_WRITE_IND
+					| DCC_AHB_IND;
+
 			dcc_sram_writel(drvdata, addr, sram_offset);
-			sram_offset += 4;
+				sram_offset += 4;
 
-			/* Reset link and prev_off */
-			link = 0;
-			prev_off = 0;
-		}
-
-		if ((off - prev_off) > 0xFF || entry->len > MAX_DCC_LEN) {
-			dev_err(drvdata->dev,
-				"DCC: Progamming error! Base: 0x%x, offset 0x%x.\n",
-				entry->base, entry->offset);
-			ret = -EINVAL;
-			goto err;
-		}
-
-		if (link) {
-			/*
-			 * link already has one offset-length so new
-			 * offset-length needs to be placed at bits [29:15]
-			 */
-			pos = 15;
-
-			/* Clear bits [31:16] */
-			link &= BM(0, 14);
-		} else {
-			/*
-			 * link is empty, so new offset-length needs to be
-			 * placed at bits [15:0]
-			 */
-			pos = 0;
-			link = 1 << 15;
-		}
-
-		/* write new offset-length pair to correct position */
-		link |= (((off-prev_off) & BM(0, 7)) |
-			 ((entry->len << 8) & BM(8, 14))) << pos;
-
-		link |= DCC_LINK_DESCRIPTOR;
-
-		if (pos) {
 			dcc_sram_writel(drvdata, link, sram_offset);
-			sram_offset += 4;
+				sram_offset += 4;
+
+			dcc_sram_writel(drvdata, entry->write_val, sram_offset);
+				sram_offset += 4;
+			addr = 0x00;
 			link = 0;
+			break;
 		}
 
-		prev_off  = off;
-		prev_addr = addr;
+		default:
+		{
+			/* Address type */
+			addr = (entry->base >> 4) & BM(0, 27);
+			if (entry->apb_bus)
+				addr |= DCC_ADDR_DESCRIPTOR | DCC_READ_IND
+					| DCC_APB_IND;
+			else
+				addr |= DCC_ADDR_DESCRIPTOR | DCC_READ_IND
+					| DCC_AHB_IND;
+
+			off = entry->offset/4;
+			total_len += entry->len * 4;
+
+			if (!prev_addr || prev_addr != addr || prev_off > off) {
+				/* Check if we need to write prev link entry */
+				if (link) {
+					dcc_sram_writel(drvdata,
+							link, sram_offset);
+					sram_offset += 4;
+				}
+				dev_dbg(drvdata->dev,
+					"DCC: sram address 0x%x\n",
+					sram_offset);
+
+				/* Write address */
+				dcc_sram_writel(drvdata, addr, sram_offset);
+				sram_offset += 4;
+
+				/* Reset link and prev_off */
+				link = 0;
+				prev_off = 0;
+			}
+
+			if ((off - prev_off) > 0xFF ||
+			    entry->len > MAX_DCC_LEN) {
+				dev_err(drvdata->dev,
+					"DCC: Progamming error Base: 0x%x, offset 0x%x\n",
+					entry->base, entry->offset);
+				ret = -EINVAL;
+				goto err;
+			}
+
+			if (link) {
+				/*
+				 * link already has one offset-length so new
+				 * offset-length needs to be placed at
+				 * bits [29:15]
+				 */
+				pos = 15;
+
+				/* Clear bits [31:16] */
+				link &= BM(0, 14);
+			} else {
+				/*
+				 * link is empty, so new offset-length needs
+				 * to be placed at bits [15:0]
+				 */
+				pos = 0;
+				link = 1 << 15;
+			}
+
+			/* write new offset-length pair to correct position */
+			link |= (((off-prev_off) & BM(0, 7)) |
+				 ((entry->len << 8) & BM(8, 14))) << pos;
+
+			link |= DCC_LINK_DESCRIPTOR;
+
+			if (pos) {
+				dcc_sram_writel(drvdata, link, sram_offset);
+				sram_offset += 4;
+				link = 0;
+			}
+
+			prev_off  = off;
+			prev_addr = addr;
+			}
+		}
 	}
 
 	if (link) {
@@ -368,7 +444,7 @@
 
 	if (loop_start) {
 		dev_err(drvdata->dev,
-			"DCC: Progamming error! Loop unterminated.\n");
+			"DCC: Progamming error: Loop unterminated\n");
 		ret = -EINVAL;
 		goto err;
 	}
@@ -457,7 +533,7 @@
 	 */
 	for (i = 0; i < 2; i++) {
 		if (!dcc_ready(drvdata))
-			dev_err(drvdata->dev, "DCC is not ready!\n");
+			dev_err(drvdata->dev, "DCC is not ready\n");
 
 		dcc_writel(drvdata, 1,
 			   DCC_LL_SW_TRIGGER(drvdata->curr_list));
@@ -476,13 +552,13 @@
 		return -EINVAL;
 
 	if (drvdata->enable[curr_list]) {
-		dev_err(drvdata->dev, "DCC is already enabled!\n");
+		dev_err(drvdata->dev, "DCC is already enabled\n");
 		return -EINVAL;
 	}
 
 	lock_reg = dcc_readl(drvdata, DCC_LL_LOCK(curr_list));
 	if (lock_reg & 0x1) {
-		dev_err(drvdata->dev, "DCC is already enabled!\n");
+		dev_err(drvdata->dev, "DCC is already enabled\n");
 		return -EINVAL;
 	}
 
@@ -525,8 +601,9 @@
 			dcc_writel(drvdata, 0, DCC_LL_TIMEOUT(list));
 		}
 
-		/* 4. Configure data sink and function type */
-		dcc_writel(drvdata, ((drvdata->data_sink << 4) |
+		/* 4. Configure trigger, data sink and function type */
+		dcc_writel(drvdata, BIT(9) | ((drvdata->cti_trig << 8) |
+			   (drvdata->data_sink << 4) |
 			   (drvdata->func_type[list])), DCC_LL_CFG(list));
 
 		/* 5. Clears interrupt status register */
@@ -565,7 +642,7 @@
 	mutex_lock(&drvdata->mutex);
 
 	if (!dcc_ready(drvdata))
-		dev_err(drvdata->dev, "DCC is not ready! Disabling DCC...\n");
+		dev_err(drvdata->dev, "DCC is not ready Disabling DCC...\n");
 
 	for (curr_list = 0; curr_list < DCC_MAX_LINK_LIST; curr_list++) {
 		if (!drvdata->enable[curr_list])
@@ -600,7 +677,7 @@
 	mutex_lock(&drvdata->mutex);
 	lock_reg = dcc_readl(drvdata, DCC_LL_LOCK(val));
 	if (lock_reg & 0x1) {
-		dev_err(drvdata->dev, "DCC linked list is already configured!\n");
+		dev_err(drvdata->dev, "DCC linked list is already configured\n");
 		mutex_unlock(&drvdata->mutex);
 		return -EINVAL;
 	}
@@ -783,25 +860,36 @@
 	mutex_lock(&drvdata->mutex);
 	list_for_each_entry(entry,
 			    &drvdata->cfg_head[drvdata->curr_list], list) {
-		if (entry->rd_wr_entry)
+		switch (entry->desc_type) {
+		case DCC_READ_WRITE_TYPE:
 			len = snprintf(local_buf, 64,
 				       "Index: 0x%x, mask: 0x%x, val: 0x%x\n",
 				       entry->index, entry->mask,
-				       entry->rd_mod_wr);
-		else if (entry->loop_cnt)
+				       entry->write_val);
+			break;
+		case DCC_LOOP_TYPE:
 			len = snprintf(local_buf, 64, "Index: 0x%x, Loop: %d\n",
 				       entry->index, entry->loop_cnt);
-		else
-			len = snprintf(local_buf, 64,
-				       "Index: 0x%x, Base: 0x%x, Offset: 0x%x, len: 0x%x\n",
-				       entry->index, entry->base,
-				       entry->offset, entry->len);
-
-		if ((count + len) > PAGE_SIZE) {
-			dev_err(dev, "DCC: Couldn't write complete config!\n");
 			break;
+		case DCC_WRITE_TYPE:
+			len = snprintf(local_buf, 64,
+				       "Write Index: 0x%x, Base: 0x%x, Offset: 0x%x, len: 0x%x APB: %d\n",
+				       entry->index, entry->base,
+				       entry->offset, entry->len,
+				       entry->apb_bus);
+			break;
+		default:
+			len = snprintf(local_buf, 64,
+				       "Read Index: 0x%x, Base: 0x%x, Offset: 0x%x, len: 0x%x APB: %d\n",
+				       entry->index, entry->base,
+				       entry->offset, entry->len,
+				       entry->apb_bus);
 		}
 
+		if ((count + len) > PAGE_SIZE) {
+			dev_err(dev, "DCC: Couldn't write complete config\n");
+			break;
+		}
 		strlcat(buf, local_buf, PAGE_SIZE);
 		count += len;
 	}
@@ -812,7 +900,7 @@
 }
 
 static int dcc_config_add(struct dcc_drvdata *drvdata, unsigned int addr,
-			  unsigned int len)
+			  unsigned int len, int apb_bus)
 {
 	int ret;
 	struct dcc_config_entry *entry, *pentry;
@@ -821,7 +909,7 @@
 	mutex_lock(&drvdata->mutex);
 
 	if (!len) {
-		dev_err(drvdata->dev, "DCC: Invalid length!\n");
+		dev_err(drvdata->dev, "DCC: Invalid length\n");
 		ret = -EINVAL;
 		goto err;
 	}
@@ -883,6 +971,8 @@
 		entry->offset = offset;
 		entry->len = min_t(uint32_t, len, MAX_DCC_LEN);
 		entry->index = drvdata->nr_config[drvdata->curr_list]++;
+		entry->desc_type = DCC_ADDR_TYPE;
+		entry->apb_bus = apb_bus;
 		INIT_LIST_HEAD(&entry->list);
 		list_add_tail(&entry->list,
 			      &drvdata->cfg_head[drvdata->curr_list]);
@@ -902,24 +992,30 @@
 				struct device_attribute *attr,
 				const char *buf, size_t size)
 {
-	int ret, len;
+	int ret, len, apb_bus;
 	unsigned int base;
 	struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
 	int nval;
 
-	nval = sscanf(buf, "%x %i", &base, &len);
-	if (nval <= 0 || nval > 2)
+	nval = sscanf(buf, "%x %i %d", &base, &len, &apb_bus);
+	if (nval <= 0 || nval > 3)
 		return -EINVAL;
 
-	if (nval == 1)
-		len = 1;
-
 	if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
 		dev_err(dev, "Select link list to program using curr_list\n");
 		return -EINVAL;
 	}
 
-	ret = dcc_config_add(drvdata, base, len);
+	if (nval == 1) {
+		len = 1;
+		apb_bus = 0;
+	} else if (nval == 2) {
+		apb_bus = 0;
+	} else {
+		apb_bus = 1;
+	}
+
+	ret = dcc_config_add(drvdata, base, len, apb_bus);
 	if (ret)
 		return ret;
 
@@ -1087,7 +1183,7 @@
 	}
 
 	if (list_empty(&drvdata->cfg_head[drvdata->curr_list])) {
-		dev_err(drvdata->dev, "DCC: No read address programmed!\n");
+		dev_err(drvdata->dev, "DCC: No read address programmed\n");
 		ret = -EPERM;
 		goto err;
 	}
@@ -1098,9 +1194,9 @@
 		goto err;
 	}
 
-	entry->rd_wr_entry = true;
+	entry->desc_type = DCC_READ_WRITE_TYPE;
 	entry->mask = mask;
-	entry->rd_mod_wr = val;
+	entry->write_val = val;
 	entry->index = drvdata->nr_config[drvdata->curr_list]++;
 	INIT_LIST_HEAD(&entry->list);
 	list_add_tail(&entry->list, &drvdata->cfg_head[drvdata->curr_list]);
@@ -1110,6 +1206,91 @@
 }
 static DEVICE_ATTR(rd_mod_wr, 0200, NULL, dcc_rd_mod_wr);
 
+static ssize_t dcc_write(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	int ret = size;
+	int nval;
+	unsigned int addr, write_val;
+	int apb_bus;
+	struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
+	struct dcc_config_entry *entry;
+
+	mutex_lock(&drvdata->mutex);
+
+	nval = sscanf(buf, "%x %x %d", &addr, &write_val, &apb_bus);
+
+	if (drvdata->curr_list >= DCC_MAX_LINK_LIST) {
+		dev_err(dev, "Select link list to program using curr_list\n");
+		return -EINVAL;
+	}
+
+	if (nval <= 1 || nval > 3) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (nval == 3)
+		entry->apb_bus = true;
+
+	entry->desc_type = DCC_WRITE_TYPE;
+	entry->base = addr & BM(4, 31);
+	entry->offset = addr - entry->base;
+	entry->write_val = write_val;
+	entry->index = drvdata->nr_config[drvdata->curr_list]++;
+	entry->len = 1;
+	INIT_LIST_HEAD(&entry->list);
+	list_add_tail(&entry->list, &drvdata->cfg_head[drvdata->curr_list]);
+err:
+	mutex_unlock(&drvdata->mutex);
+	return ret;
+}
+static DEVICE_ATTR(config_write, 0200, NULL, dcc_write);
+
+static ssize_t dcc_show_cti_trig(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", drvdata->cti_trig);
+}
+
+static ssize_t dcc_store_cti_trig(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	unsigned long val;
+	int ret = 0;
+	struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	mutex_lock(&drvdata->mutex);
+
+	if (drvdata->enable[drvdata->curr_list]) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (val)
+		drvdata->cti_trig = 1;
+	else
+		drvdata->cti_trig = 0;
+out:
+	mutex_unlock(&drvdata->mutex);
+	return ret;
+}
+static DEVICE_ATTR(cti_trig, 0644,
+		   dcc_show_cti_trig, dcc_store_cti_trig);
+
 static const struct device_attribute *dcc_attrs[] = {
 	&dev_attr_func_type,
 	&dev_attr_data_sink,
@@ -1123,6 +1304,8 @@
 	&dev_attr_loop,
 	&dev_attr_rd_mod_wr,
 	&dev_attr_curr_list,
+	&dev_attr_config_write,
+	&dev_attr_cti_trig,
 	NULL,
 };
 
@@ -1134,7 +1317,7 @@
 	for (i = 0; attrs[i] != NULL; i++) {
 		ret = device_create_file(dev, attrs[i]);
 		if (ret) {
-			dev_err(dev, "DCC: Couldn't create sysfs attribute: %s!\n",
+			dev_err(dev, "DCC: Couldn't create sysfs attribute: %s\n",
 				attrs[i]->attr.name);
 			break;
 		}
@@ -1173,7 +1356,7 @@
 
 	if (copy_to_user(data, buf, len)) {
 		dev_err(drvdata->dev,
-			"DCC: Couldn't copy all data to user!\n");
+			"DCC: Couldn't copy all data to user\n");
 		kfree(buf);
 		return -EFAULT;
 	}
@@ -1372,7 +1555,7 @@
 			}
 
 		if (i == ARRAY_SIZE(str_dcc_data_sink)) {
-			dev_err(dev, "Unknown sink type for DCC! Using '%s' as data sink\n",
+			dev_err(dev, "Unknown sink type for DCC Using '%s' as data sink\n",
 				str_dcc_data_sink[drvdata->data_sink]);
 		}
 	}
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
index 0a28ee0..be2b7da 100644
--- a/drivers/soc/qcom/llcc-sdm845.c
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -65,20 +65,15 @@
 	SCT_ENTRY("audio",       6, 6, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("modemhp_grow", 7, 7, 1024, 2, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("modem",       8, 8, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("modemhw",     9, 9, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("compute",     10, 10, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("gpuhtw",      11, 11, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("gpu",         12, 12, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
+	SCT_ENTRY("gpuhtw",      11, 11, 515, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
+	SCT_ENTRY("gpu",         12, 12, 2560, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("mmuhwt",      13, 13, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1),
-	SCT_ENTRY("sensor",      14, 14, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("compute_dma", 15, 15, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("display",     16, 16, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("videofw",     17, 17, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("camerafw",    18, 18, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("mss_tcm",     19, 19, 1024, 0, 0, 0x0,  0xf, 1, 0, 1, 1, 0),
 	SCT_ENTRY("modemhp_fix", 20, 20, 1024, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 	SCT_ENTRY("modem_paging", 21, 21, 1024, 0, 1, 0xF,  0x0, 0, 0, 0, 1, 0),
-	SCT_ENTRY("audiohw",     22, 22, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
+	SCT_ENTRY("audiohw",     22, 22, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
 };
 
 static int sdm845_qcom_llcc_probe(struct platform_device *pdev)
diff --git a/drivers/soc/qcom/memory_dump_v2.c b/drivers/soc/qcom/memory_dump_v2.c
index b9ce417..5ed66bf 100644
--- a/drivers/soc/qcom/memory_dump_v2.c
+++ b/drivers/soc/qcom/memory_dump_v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,9 @@
 #include <linux/of_address.h>
 #include <soc/qcom/memory_dump.h>
 #include <soc/qcom/scm.h>
+#include <linux/of_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
 
 #define MSM_DUMP_TABLE_VERSION		MSM_DUMP_MAKE_VERSION(2, 0)
 
@@ -195,3 +198,84 @@
 }
 early_initcall(init_debug_lar_unlock);
 #endif
+
+static int mem_dump_probe(struct platform_device *pdev)
+{
+	struct device_node *child_node;
+	const struct device_node *node = pdev->dev.of_node;
+	static dma_addr_t dump_addr;
+	static void *dump_vaddr;
+	struct msm_dump_data *dump_data;
+	struct msm_dump_entry dump_entry;
+	int ret;
+	u32 size, id;
+
+	for_each_available_child_of_node(node, child_node) {
+		ret = of_property_read_u32(child_node, "qcom,dump-size", &size);
+		if (ret) {
+			dev_err(&pdev->dev, "Unable to find size for %s\n",
+					child_node->name);
+			continue;
+		}
+
+		ret = of_property_read_u32(child_node, "qcom,dump-id", &id);
+		if (ret) {
+			dev_err(&pdev->dev, "Unable to find id for %s\n",
+					child_node->name);
+			continue;
+		}
+
+		dump_vaddr = (void *) dma_alloc_coherent(&pdev->dev, size,
+						&dump_addr, GFP_KERNEL);
+
+		if (!dump_vaddr) {
+			dev_err(&pdev->dev, "Couldn't get memory for dumping\n");
+			continue;
+		}
+
+		memset(dump_vaddr, 0x0, size);
+
+		dump_data = devm_kzalloc(&pdev->dev,
+				sizeof(struct msm_dump_data), GFP_KERNEL);
+		if (!dump_data) {
+			dma_free_coherent(&pdev->dev, size, dump_vaddr,
+					dump_addr);
+			continue;
+		}
+
+		dump_data->addr = dump_addr;
+		dump_data->len = size;
+		dump_entry.id = id;
+		dump_entry.addr = virt_to_phys(dump_data);
+		ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry);
+		if (ret) {
+			dev_err(&pdev->dev, "Data dump setup failed, id = %d\n",
+				id);
+			dma_free_coherent(&pdev->dev, size, dump_vaddr,
+					dump_addr);
+			devm_kfree(&pdev->dev, dump_data);
+		}
+	}
+	return 0;
+}
+
+static const struct of_device_id mem_dump_match_table[] = {
+	{.compatible = "qcom,mem-dump",},
+	{}
+};
+
+static struct platform_driver mem_dump_driver = {
+	.probe = mem_dump_probe,
+	.driver = {
+		.name = "msm_mem_dump",
+		.owner = THIS_MODULE,
+		.of_match_table = mem_dump_match_table,
+	},
+};
+
+static int __init mem_dump_init(void)
+{
+	return platform_driver_register(&mem_dump_driver);
+}
+
+pure_initcall(mem_dump_init);
diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c
index 11e1b4d..1f28712 100644
--- a/drivers/soc/qcom/peripheral-loader.c
+++ b/drivers/soc/qcom/peripheral-loader.c
@@ -464,6 +464,8 @@
 	if (region == NULL) {
 		pil_err(priv->desc, "Failed to allocate relocatable region of size %zx\n",
 					size);
+		priv->region_start = 0;
+		priv->region_end = 0;
 		return -ENOMEM;
 	}
 
diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c
new file mode 100644
index 0000000..67a5e05
--- /dev/null
+++ b/drivers/soc/qcom/qbt1000.c
@@ -0,0 +1,1207 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#define DEBUG
+#define pr_fmt(fmt) "qbt1000:%s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/pm.h>
+#include <linux/of.h>
+#include <linux/mutex.h>
+#include <linux/atomic.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/input.h>
+#include <linux/kfifo.h>
+#include <linux/poll.h>
+#include <uapi/linux/qbt1000.h>
+#include <soc/qcom/scm.h>
+#include "../../misc/qseecom_kernel.h"
+
+#define QBT1000_DEV "qbt1000"
+#define QBT1000_IN_DEV_NAME "qbt1000_key_input"
+#define QBT1000_IN_DEV_VERSION 0x0100
+#define MAX_FW_EVENTS 128
+#define FP_APP_CMD_RX_IPC 132
+#define FW_MAX_IPC_MSG_DATA_SIZE 0x500
+#define IPC_MSG_ID_CBGE_REQUIRED 29
+
+/*
+ * shared buffer size - init with max value,
+ * user space will provide new value upon tz app load
+ */
+static uint32_t g_app_buf_size = SZ_256K;
+static char const *const FP_APP_NAME = "fingerpr";
+
+struct finger_detect_gpio {
+	int gpio;
+	int active_low;
+	int irq;
+	struct work_struct work;
+	unsigned int key_code;
+	int power_key_enabled;
+	int last_gpio_state;
+	int event_reported;
+};
+
+struct fw_event_desc {
+	enum qbt1000_fw_event ev;
+};
+
+struct fw_ipc_info {
+	int gpio;
+	int irq;
+};
+
+struct qbt1000_drvdata {
+	struct class	*qbt1000_class;
+	struct cdev	qbt1000_cdev;
+	struct device	*dev;
+	char		*qbt1000_node;
+	struct clk	**clocks;
+	unsigned int	clock_count;
+	uint8_t		clock_state;
+	unsigned int	root_clk_idx;
+	unsigned int	frequency;
+	atomic_t	available;
+	struct mutex	mutex;
+	struct mutex	fw_events_mutex;
+	struct input_dev	*in_dev;
+	struct fw_ipc_info	fw_ipc;
+	struct finger_detect_gpio	fd_gpio;
+	DECLARE_KFIFO(fw_events, struct fw_event_desc, MAX_FW_EVENTS);
+	wait_queue_head_t read_wait_queue;
+	struct qseecom_handle *app_handle;
+	struct qseecom_handle *fp_app_handle;
+};
+
+/*
+ * struct fw_ipc_cmd -
+ *      used to store IPC commands to/from firmware
+ * @status - indicates whether sending/getting the IPC message was successful
+ * @msg_type - the type of IPC message
+ * @msg_len - the length of the message data
+ * @resp_needed - whether a response is needed for this message
+ * @msg_data - any extra data associated with the message
+ */
+struct fw_ipc_cmd {
+	uint32_t status;
+	uint32_t numMsgs;
+	uint8_t msg_data[FW_MAX_IPC_MSG_DATA_SIZE];
+};
+
+struct fw_ipc_header {
+	uint32_t msg_type;
+	uint32_t msg_len;
+	uint32_t resp_needed;
+};
+
+/*
+ * struct ipc_msg_type_to_fw_event -
+ *      entry in mapping between an IPC message type to a firmware event
+ * @msg_type - IPC message type, as reported by firmware
+ * @fw_event - corresponding firmware event code to report to driver client
+ */
+struct ipc_msg_type_to_fw_event {
+	uint32_t msg_type;
+	enum qbt1000_fw_event fw_event;
+};
+
+/* mapping between firmware IPC message types to HLOS firmware events */
+struct ipc_msg_type_to_fw_event g_msg_to_event[] = {
+		{IPC_MSG_ID_CBGE_REQUIRED, FW_EVENT_CBGE_REQUIRED}
+};
+
+/**
+ * get_cmd_rsp_buffers() - Function sets cmd & rsp buffer pointers and
+ *                         aligns buffer lengths
+ * @hdl:	index of qseecom_handle
+ * @cmd:	req buffer - set to qseecom_handle.sbuf
+ * @cmd_len:	ptr to req buffer len
+ * @rsp:	rsp buffer - set to qseecom_handle.sbuf + offset
+ * @rsp_len:	ptr to rsp buffer len
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int get_cmd_rsp_buffers(struct qseecom_handle *hdl,
+	void **cmd,
+	uint32_t *cmd_len,
+	void **rsp,
+	uint32_t *rsp_len)
+{
+	/* 64 bytes alignment for QSEECOM */
+	*cmd_len = ALIGN(*cmd_len, 64);
+	*rsp_len = ALIGN(*rsp_len, 64);
+
+	if (((uint64_t)*rsp_len + (uint64_t)*cmd_len)
+			> (uint64_t)g_app_buf_size) {
+		pr_err("buffer too small to hold cmd=%d and rsp=%d\n",
+			*cmd_len, *rsp_len);
+		return -ENOMEM;
+	}
+
+	*cmd = hdl->sbuf;
+	*rsp = hdl->sbuf + *cmd_len;
+	return 0;
+}
+
+/**
+ * send_tz_cmd() - Function sends a command to TZ
+ *
+ * @drvdata: pointer to driver data
+ * @app_handle: handle to tz app
+ * @is_user_space: 1 if the cmd buffer is in user space, 0
+ *          otherwise
+ * @cmd: command buffer to send
+ * @cmd_len: length of the command buffer
+ * @rsp: output, will be set to location of response buffer
+ * @rsp_len: max size of response
+ *
+ * Return: 0 on success.
+ */
+static int send_tz_cmd(struct qbt1000_drvdata *drvdata,
+	struct qseecom_handle *app_handle,
+	int is_user_space,
+	void *cmd, uint32_t cmd_len,
+	void **rsp, uint32_t rsp_len)
+{
+	int rc = 0;
+	void *aligned_cmd;
+	void *aligned_rsp;
+	uint32_t aligned_cmd_len;
+	uint32_t aligned_rsp_len;
+
+	/* init command and response buffers and align lengths */
+	aligned_cmd_len = cmd_len;
+	aligned_rsp_len = rsp_len;
+
+	rc = get_cmd_rsp_buffers(app_handle,
+		(void **)&aligned_cmd,
+		&aligned_cmd_len,
+		(void **)&aligned_rsp,
+		&aligned_rsp_len);
+
+	if (rc != 0)
+		goto end;
+
+	if (!aligned_cmd) {
+		dev_err(drvdata->dev, "%s: Null command buffer\n",
+			__func__);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	if (aligned_cmd - cmd + cmd_len > g_app_buf_size) {
+		rc = -ENOMEM;
+		goto end;
+	}
+
+	if (is_user_space) {
+		rc = copy_from_user(aligned_cmd, (void __user *)cmd,
+				cmd_len);
+		if (rc != 0) {
+			pr_err("failure to copy user space buf %d\n", rc);
+			rc = -EFAULT;
+			goto end;
+		}
+	} else
+		memcpy(aligned_cmd, cmd, cmd_len);
+
+	/* send cmd to TZ */
+	rc = qseecom_send_command(app_handle,
+		aligned_cmd,
+		aligned_cmd_len,
+		aligned_rsp,
+		aligned_rsp_len);
+
+	if (rc != 0) {
+		pr_err("failure to send tz cmd %d\n", rc);
+		goto end;
+	}
+
+	*rsp = aligned_rsp;
+
+end:
+	return rc;
+}
+
+/**
+ * qbt1000_open() - Function called when user space opens device.
+ * Successful if driver not currently open.
+ * @inode:	ptr to inode object
+ * @file:	ptr to file object
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int qbt1000_open(struct inode *inode, struct file *file)
+{
+	int rc = 0;
+
+	struct qbt1000_drvdata *drvdata = container_of(inode->i_cdev,
+						   struct qbt1000_drvdata,
+						   qbt1000_cdev);
+	file->private_data = drvdata;
+
+	pr_debug("qbt1000_open begin\n");
+	/* disallowing concurrent opens */
+	if (!atomic_dec_and_test(&drvdata->available)) {
+		atomic_inc(&drvdata->available);
+		rc = -EBUSY;
+	}
+
+	pr_debug("qbt1000_open end : %d\n", rc);
+	return rc;
+}
+
+/**
+ * qbt1000_release() - Function called when user space closes device.
+
+ * @inode:	ptr to inode object
+ * @file:	ptr to file object
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int qbt1000_release(struct inode *inode, struct file *file)
+{
+	struct qbt1000_drvdata *drvdata;
+
+	if (!file || !file->private_data) {
+		pr_err("qbt1000_release: NULL pointer passed");
+		return -EINVAL;
+	}
+	drvdata = file->private_data;
+	atomic_inc(&drvdata->available);
+	return 0;
+}
+
+/**
+ * qbt1000_ioctl() - Function called when user space calls ioctl.
+ * @file:	struct file - not used
+ * @cmd:	cmd identifier:QBT1000_LOAD_APP,QBT1000_UNLOAD_APP,
+ *              QBT1000_SEND_TZCMD
+ * @arg:	ptr to relevant structe: either qbt1000_app or
+ *              qbt1000_send_tz_cmd depending on which cmd is passed
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static long qbt1000_ioctl(
+		struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int rc = 0;
+	void __user *priv_arg = (void __user *)arg;
+	struct qbt1000_drvdata *drvdata;
+
+	if (!file || !file->private_data) {
+		pr_err("qbt1000_ioctl: NULL pointer passed");
+		return -EINVAL;
+	}
+
+	drvdata = file->private_data;
+
+	mutex_lock(&drvdata->mutex);
+
+	pr_debug("qbt1000_ioctl %d\n", cmd);
+
+	switch (cmd) {
+	case QBT1000_LOAD_APP:
+	{
+		struct qbt1000_app app;
+		struct qseecom_handle *app_handle;
+
+		if (copy_from_user(&app, priv_arg,
+			sizeof(app)) != 0) {
+			rc = -EFAULT;
+			pr_err("failed copy from user space-LOAD\n");
+			goto end;
+		}
+
+		if (!app.app_handle) {
+			dev_err(drvdata->dev, "%s: LOAD app_handle is null\n",
+				__func__);
+			rc = -EINVAL;
+			goto end;
+		}
+
+		if (drvdata->app_handle) {
+			dev_err(drvdata->dev, "%s: LOAD app already loaded, unloading first\n",
+				__func__);
+			drvdata->fp_app_handle = 0;
+			rc = qseecom_shutdown_app(&drvdata->app_handle);
+			if (rc != 0) {
+				dev_err(drvdata->dev, "%s: LOAD current app failed to shutdown\n",
+					  __func__);
+				goto end;
+			}
+		}
+
+		pr_debug("app %s load before\n", app.name);
+
+		/* start the TZ app */
+		rc = qseecom_start_app(
+				&drvdata->app_handle, app.name, app.size);
+		if (rc == 0) {
+			g_app_buf_size = app.size;
+			rc = qseecom_set_bandwidth(drvdata->app_handle,
+				app.high_band_width == 1 ? true : false);
+			if (rc != 0) {
+				/* log error, allow to continue */
+				pr_err("App %s failed to set bw\n", app.name);
+			}
+		} else {
+			pr_err("app %s failed to load\n", app.name);
+			goto end;
+		}
+
+		/* copy a fake app handle to user */
+		app_handle = drvdata->app_handle ?
+				(struct qseecom_handle *)123456 : 0;
+		rc = copy_to_user((void __user *)app.app_handle, &app_handle,
+			sizeof(*app.app_handle));
+
+		if (rc != 0) {
+			dev_err(drvdata->dev,
+				"%s: Failed copy 2us LOAD rc:%d\n",
+				 __func__, rc);
+			rc = -ENOMEM;
+			goto end;
+		}
+
+		pr_debug("app %s load after\n", app.name);
+
+		if (!strcmp(app.name, FP_APP_NAME))
+			drvdata->fp_app_handle = drvdata->app_handle;
+
+		break;
+	}
+	case QBT1000_UNLOAD_APP:
+	{
+		struct qbt1000_app app;
+		struct qseecom_handle *app_handle = 0;
+
+		if (copy_from_user(&app, priv_arg,
+			sizeof(app)) != 0) {
+			rc = -ENOMEM;
+			pr_err("failed copy from user space-UNLOAD\n");
+			goto end;
+		}
+
+		if (!app.app_handle) {
+			dev_err(drvdata->dev, "%s: UNLOAD app_handle is null\n",
+				__func__);
+			rc = -EINVAL;
+			goto end;
+		}
+
+		rc = copy_from_user(&app_handle, app.app_handle,
+			sizeof(app_handle));
+
+		if (rc != 0) {
+			dev_err(drvdata->dev,
+				"%s: Failed copy from user space-UNLOAD handle rc:%d\n",
+				 __func__, rc);
+			rc = -ENOMEM;
+			goto end;
+		}
+
+		/* if the app hasn't been loaded already, return err */
+		if (!drvdata->app_handle) {
+			pr_err("app not loaded\n");
+			rc = -EINVAL;
+			goto end;
+		}
+
+		if (drvdata->fp_app_handle == drvdata->app_handle)
+			drvdata->fp_app_handle = 0;
+
+		/* set bw & shutdown the TZ app */
+		qseecom_set_bandwidth(drvdata->app_handle,
+			app.high_band_width == 1 ? true : false);
+		rc = qseecom_shutdown_app(&drvdata->app_handle);
+		if (rc != 0) {
+			pr_err("app failed to shutdown\n");
+			goto end;
+		}
+
+		/* copy the app handle (should be null) to user */
+		rc = copy_to_user((void __user *)app.app_handle, &app_handle,
+			sizeof(*app.app_handle));
+
+		if (rc != 0) {
+			dev_err(drvdata->dev,
+				"%s: Failed copy 2us UNLOAD rc:%d\n",
+				 __func__, rc);
+			rc = -ENOMEM;
+			goto end;
+		}
+
+		break;
+	}
+	case QBT1000_SEND_TZCMD:
+	{
+		struct qbt1000_send_tz_cmd tzcmd;
+		void *rsp_buf;
+
+		if (copy_from_user(&tzcmd, priv_arg,
+			sizeof(tzcmd))
+				!= 0) {
+			rc = -EFAULT;
+			pr_err("failed copy from user space %d\n", rc);
+			goto end;
+		}
+
+		if (tzcmd.req_buf_len > g_app_buf_size ||
+			tzcmd.rsp_buf_len > g_app_buf_size) {
+			rc = -ENOMEM;
+			pr_err("invalid cmd buf len, req=%d, rsp=%d\n",
+				tzcmd.req_buf_len, tzcmd.rsp_buf_len);
+			goto end;
+		}
+
+		/* if the app hasn't been loaded already, return err */
+		if (!drvdata->app_handle) {
+			pr_err("app not loaded\n");
+			rc = -EINVAL;
+			goto end;
+		}
+
+		rc = send_tz_cmd(drvdata,
+			drvdata->app_handle, 1,
+			tzcmd.req_buf, tzcmd.req_buf_len,
+			&rsp_buf, tzcmd.rsp_buf_len);
+
+		if (rc < 0) {
+			pr_err("failure sending command to tz\n");
+			goto end;
+		}
+
+		/* copy rsp buf back to user space buffer */
+		rc = copy_to_user((void __user *)tzcmd.rsp_buf,
+			 rsp_buf, tzcmd.rsp_buf_len);
+		if (rc != 0) {
+			pr_err("failed copy 2us rc:%d bytes %d:\n",
+				rc, tzcmd.rsp_buf_len);
+			rc = -EFAULT;
+			goto end;
+		}
+
+		break;
+	}
+	case QBT1000_SET_FINGER_DETECT_KEY:
+	{
+		struct qbt1000_set_finger_detect_key set_fd_key;
+
+		if (copy_from_user(&set_fd_key, priv_arg,
+			sizeof(set_fd_key))
+				!= 0) {
+			rc = -EFAULT;
+			pr_err("failed copy from user space %d\n", rc);
+			goto end;
+		}
+
+		drvdata->fd_gpio.key_code = set_fd_key.key_code;
+
+		break;
+	}
+	case QBT1000_CONFIGURE_POWER_KEY:
+	{
+		struct qbt1000_configure_power_key power_key;
+
+		if (copy_from_user(&power_key, priv_arg,
+			sizeof(power_key))
+				!= 0) {
+			rc = -EFAULT;
+			pr_err("failed copy from user space %d\n", rc);
+			goto end;
+		}
+
+		drvdata->fd_gpio.power_key_enabled = power_key.enable;
+
+		break;
+	}
+	default:
+		pr_err("invalid cmd %d\n", cmd);
+		rc = -ENOIOCTLCMD;
+		goto end;
+	}
+
+end:
+	mutex_unlock(&drvdata->mutex);
+	return rc;
+}
+
+static int get_events_fifo_len_locked(struct qbt1000_drvdata *drvdata)
+{
+	int len;
+
+	mutex_lock(&drvdata->fw_events_mutex);
+	len = kfifo_len(&drvdata->fw_events);
+	mutex_unlock(&drvdata->fw_events_mutex);
+
+	return len;
+}
+
+static ssize_t qbt1000_read(struct file *filp, char __user *ubuf,
+		size_t cnt, loff_t *ppos)
+{
+	struct fw_event_desc fw_event;
+	struct qbt1000_drvdata *drvdata = filp->private_data;
+
+	if (cnt < sizeof(fw_event.ev))
+		return -EINVAL;
+
+	mutex_lock(&drvdata->fw_events_mutex);
+
+	while (kfifo_len(&drvdata->fw_events) == 0) {
+		mutex_unlock(&drvdata->fw_events_mutex);
+
+		if (filp->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+
+		pr_debug("fw_events fifo: empty, waiting\n");
+
+		if (wait_event_interruptible(drvdata->read_wait_queue,
+			  (get_events_fifo_len_locked(drvdata) > 0)))
+			return -ERESTARTSYS;
+
+		mutex_lock(&drvdata->fw_events_mutex);
+	}
+
+	if (!kfifo_get(&drvdata->fw_events, &fw_event)) {
+		pr_debug("fw_events fifo: unexpectedly empty\n");
+
+		mutex_unlock(&drvdata->fw_events_mutex);
+		return -EINVAL;
+	}
+
+	mutex_unlock(&drvdata->fw_events_mutex);
+
+	pr_debug("fw_event: %d\n", (int)fw_event.ev);
+	return copy_to_user(ubuf, &fw_event.ev, sizeof(fw_event.ev));
+}
+
+static unsigned int qbt1000_poll(struct file *filp,
+	struct poll_table_struct *wait)
+{
+	struct qbt1000_drvdata *drvdata = filp->private_data;
+	unsigned int mask = 0;
+
+	poll_wait(filp, &drvdata->read_wait_queue, wait);
+
+	if (kfifo_len(&drvdata->fw_events) > 0)
+		mask |= (POLLIN | POLLRDNORM);
+
+	return mask;
+}
+
+static const struct file_operations qbt1000_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = qbt1000_ioctl,
+	.open = qbt1000_open,
+	.release = qbt1000_release,
+	.read = qbt1000_read,
+	.poll = qbt1000_poll
+};
+
+static int qbt1000_dev_register(struct qbt1000_drvdata *drvdata)
+{
+	dev_t dev_no;
+	int ret = 0;
+	size_t node_size;
+	char *node_name = QBT1000_DEV;
+	struct device *dev = drvdata->dev;
+	struct device *device;
+
+	node_size = strlen(node_name) + 1;
+
+	drvdata->qbt1000_node = devm_kzalloc(dev, node_size, GFP_KERNEL);
+	if (!drvdata->qbt1000_node) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	strlcpy(drvdata->qbt1000_node, node_name, node_size);
+
+	ret = alloc_chrdev_region(&dev_no, 0, 1, drvdata->qbt1000_node);
+	if (ret) {
+		pr_err("alloc_chrdev_region failed %d\n", ret);
+		goto err_alloc;
+	}
+
+	cdev_init(&drvdata->qbt1000_cdev, &qbt1000_fops);
+
+	drvdata->qbt1000_cdev.owner = THIS_MODULE;
+	ret = cdev_add(&drvdata->qbt1000_cdev, dev_no, 1);
+	if (ret) {
+		pr_err("cdev_add failed %d\n", ret);
+		goto err_cdev_add;
+	}
+
+	drvdata->qbt1000_class = class_create(THIS_MODULE,
+					   drvdata->qbt1000_node);
+	if (IS_ERR(drvdata->qbt1000_class)) {
+		ret = PTR_ERR(drvdata->qbt1000_class);
+		pr_err("class_create failed %d\n", ret);
+		goto err_class_create;
+	}
+
+	device = device_create(drvdata->qbt1000_class, NULL,
+			       drvdata->qbt1000_cdev.dev, drvdata,
+			       drvdata->qbt1000_node);
+	if (IS_ERR(device)) {
+		ret = PTR_ERR(device);
+		pr_err("device_create failed %d\n", ret);
+		goto err_dev_create;
+	}
+
+	return 0;
+err_dev_create:
+	class_destroy(drvdata->qbt1000_class);
+err_class_create:
+	cdev_del(&drvdata->qbt1000_cdev);
+err_cdev_add:
+	unregister_chrdev_region(drvdata->qbt1000_cdev.dev, 1);
+err_alloc:
+	return ret;
+}
+
+/**
+ * qbt1000_create_input_device() - Function allocates an input
+ * device, configures it for key events and registers it
+ *
+ * @drvdata:	ptr to driver data
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int qbt1000_create_input_device(struct qbt1000_drvdata *drvdata)
+{
+	int rc = 0;
+
+	drvdata->in_dev = input_allocate_device();
+	if (drvdata->in_dev == NULL) {
+		dev_err(drvdata->dev, "%s: input_allocate_device() failed\n",
+			__func__);
+		rc = -ENOMEM;
+		goto end;
+	}
+
+	drvdata->in_dev->name = QBT1000_IN_DEV_NAME;
+	drvdata->in_dev->phys = NULL;
+	drvdata->in_dev->id.bustype = BUS_HOST;
+	drvdata->in_dev->id.vendor  = 0x0001;
+	drvdata->in_dev->id.product = 0x0001;
+	drvdata->in_dev->id.version = QBT1000_IN_DEV_VERSION;
+
+	drvdata->in_dev->evbit[0] = BIT_MASK(EV_KEY) |  BIT_MASK(EV_ABS);
+	drvdata->in_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	drvdata->in_dev->keybit[BIT_WORD(KEY_HOMEPAGE)] |=
+		BIT_MASK(KEY_HOMEPAGE);
+	drvdata->in_dev->keybit[BIT_WORD(KEY_CAMERA)] |=
+		BIT_MASK(KEY_CAMERA);
+	drvdata->in_dev->keybit[BIT_WORD(KEY_VOLUMEDOWN)] |=
+		BIT_MASK(KEY_VOLUMEDOWN);
+	drvdata->in_dev->keybit[BIT_WORD(KEY_POWER)] |=
+		BIT_MASK(KEY_POWER);
+
+	input_set_abs_params(drvdata->in_dev, ABS_X,
+			     0,
+			     1000,
+			     0, 0);
+	input_set_abs_params(drvdata->in_dev, ABS_Y,
+			     0,
+			     1000,
+			     0, 0);
+
+	rc = input_register_device(drvdata->in_dev);
+	if (rc) {
+		dev_err(drvdata->dev, "%s: input_reg_dev() failed %d\n",
+			__func__, rc);
+		goto end;
+	}
+
+end:
+	if (rc)
+		input_free_device(drvdata->in_dev);
+	return rc;
+}
+
+static void purge_finger_events(struct qbt1000_drvdata *drvdata)
+{
+	int i, fifo_len;
+	struct fw_event_desc fw_event;
+
+	fifo_len = kfifo_len(&drvdata->fw_events);
+
+	for (i = 0; i < fifo_len; i++) {
+		if (!kfifo_get(&drvdata->fw_events, &fw_event))
+			pr_err("fw events fifo: could not remove oldest item\n");
+		else if (fw_event.ev != FW_EVENT_FINGER_DOWN
+					&& fw_event.ev != FW_EVENT_FINGER_UP)
+			kfifo_put(&drvdata->fw_events, fw_event);
+	}
+}
+
+static void qbt1000_gpio_report_event(struct qbt1000_drvdata *drvdata)
+{
+	int state;
+	struct fw_event_desc fw_event;
+
+	state = (__gpio_get_value(drvdata->fd_gpio.gpio) ? 1 : 0)
+		^ drvdata->fd_gpio.active_low;
+
+	if (drvdata->fd_gpio.event_reported
+		  && state == drvdata->fd_gpio.last_gpio_state)
+		return;
+
+	pr_debug("gpio %d: report state %d\n", drvdata->fd_gpio.gpio, state);
+
+	drvdata->fd_gpio.event_reported = 1;
+	drvdata->fd_gpio.last_gpio_state = state;
+
+	if (drvdata->fd_gpio.key_code) {
+		input_event(drvdata->in_dev, EV_KEY,
+			drvdata->fd_gpio.key_code, !!state);
+		input_sync(drvdata->in_dev);
+	}
+
+	if (state && drvdata->fd_gpio.power_key_enabled) {
+		input_event(drvdata->in_dev, EV_KEY, KEY_POWER, 1);
+		input_sync(drvdata->in_dev);
+		input_event(drvdata->in_dev, EV_KEY, KEY_POWER, 0);
+		input_sync(drvdata->in_dev);
+	}
+
+	fw_event.ev = (state ? FW_EVENT_FINGER_DOWN : FW_EVENT_FINGER_UP);
+
+	mutex_lock(&drvdata->fw_events_mutex);
+
+	if (kfifo_is_full(&drvdata->fw_events)) {
+		struct fw_event_desc dummy_fw_event;
+
+		pr_warn("fw events fifo: full, dropping oldest item\n");
+		if (!kfifo_get(&drvdata->fw_events, &dummy_fw_event))
+			pr_err("fw events fifo: could not remove oldest item\n");
+	}
+
+	purge_finger_events(drvdata);
+
+	if (!kfifo_put(&drvdata->fw_events, fw_event))
+		pr_err("fw events fifo: error adding item\n");
+
+	mutex_unlock(&drvdata->fw_events_mutex);
+	wake_up_interruptible(&drvdata->read_wait_queue);
+}
+
+static void qbt1000_gpio_work_func(struct work_struct *work)
+{
+	struct qbt1000_drvdata *drvdata =
+		container_of(work, struct qbt1000_drvdata, fd_gpio.work);
+
+	qbt1000_gpio_report_event(drvdata);
+
+	pm_relax(drvdata->dev);
+}
+
+static irqreturn_t qbt1000_gpio_isr(int irq, void *dev_id)
+{
+	struct qbt1000_drvdata *drvdata = dev_id;
+
+	if (irq != drvdata->fd_gpio.irq) {
+		pr_warn("invalid irq %d (expected %d)\n",
+			irq, drvdata->fd_gpio.irq);
+		return IRQ_HANDLED;
+	}
+
+	pm_stay_awake(drvdata->dev);
+	schedule_work(&drvdata->fd_gpio.work);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * qbt1000_ipc_irq_handler() - function processes IPC
+ * interrupts on its own thread
+ * @irq:	the interrupt that occurred
+ * @dev_id: pointer to the qbt1000_drvdata
+ *
+ * Return: IRQ_HANDLED when complete
+ */
+static irqreturn_t qbt1000_ipc_irq_handler(int irq, void *dev_id)
+{
+	uint8_t *msg_buffer;
+	struct fw_ipc_cmd *rx_cmd;
+	struct fw_ipc_header *header;
+	int i, j;
+	uint32_t rxipc = FP_APP_CMD_RX_IPC;
+	struct qbt1000_drvdata *drvdata = (struct qbt1000_drvdata *)dev_id;
+	int rc = 0;
+	uint32_t retry_count = 10;
+
+	pm_stay_awake(drvdata->dev);
+
+	mutex_lock(&drvdata->mutex);
+
+	if (irq != drvdata->fw_ipc.irq) {
+		pr_warn("invalid irq %d (expected %d)\n",
+			irq, drvdata->fw_ipc.irq);
+		goto end;
+	}
+
+	pr_debug("firmware interrupt received (irq %d)\n", irq);
+
+	if (!drvdata->fp_app_handle)
+		goto end;
+
+	while (retry_count > 0) {
+		/*
+		 * send the TZ command to fetch the message from firmware
+		 * TZ will process the message if it can
+		 */
+		rc = send_tz_cmd(drvdata, drvdata->fp_app_handle, 0,
+				&rxipc, sizeof(rxipc),
+				(void *)&rx_cmd, sizeof(*rx_cmd));
+		if (rc < 0) {
+			msleep(50); // sleep for 50ms before retry
+			retry_count -= 1;
+			continue;
+		} else {
+			pr_err("retry_count %d\n", retry_count);
+			break;
+		}
+	}
+
+	if (rc < 0) {
+		pr_err("failure sending tz cmd %d\n", rxipc);
+		goto end;
+	}
+
+	if (rx_cmd->status != 0) {
+		pr_err("tz command failed to complete\n");
+		goto end;
+	}
+
+	msg_buffer = rx_cmd->msg_data;
+
+	for (j = 0; j < rx_cmd->numMsgs; j++) {
+		header = (struct fw_ipc_header *) msg_buffer;
+		/*
+		 * given the IPC message type, search for a corresponding
+		 * event for the driver client. If found, add to the events
+		 * FIFO
+		 */
+		for (i = 0; i < ARRAY_SIZE(g_msg_to_event); i++) {
+			if (g_msg_to_event[i].msg_type == header->msg_type) {
+				enum qbt1000_fw_event ev =
+						g_msg_to_event[i].fw_event;
+				struct fw_event_desc fw_ev_desc;
+
+				mutex_lock(&drvdata->fw_events_mutex);
+				pr_debug("fw events: add %d\n", (int) ev);
+				fw_ev_desc.ev = ev;
+
+				if (!kfifo_put(&drvdata->fw_events, fw_ev_desc))
+					pr_err("fw events: fifo full, drop event %d\n",
+						(int) ev);
+
+				mutex_unlock(&drvdata->fw_events_mutex);
+				break;
+			}
+		}
+		msg_buffer += sizeof(*header) + header->msg_len;
+	}
+	wake_up_interruptible(&drvdata->read_wait_queue);
+end:
+	mutex_unlock(&drvdata->mutex);
+	pm_relax(drvdata->dev);
+	return IRQ_HANDLED;
+}
+
+static int setup_fd_gpio_irq(struct platform_device *pdev,
+	struct qbt1000_drvdata *drvdata)
+{
+	int rc = 0;
+	int irq;
+	const char *desc = "qbt_finger_detect";
+
+	rc = devm_gpio_request_one(&pdev->dev, drvdata->fd_gpio.gpio,
+		GPIOF_IN, desc);
+
+	if (rc < 0) {
+		pr_err("failed to request gpio %d, error %d\n",
+			drvdata->fd_gpio.gpio, rc);
+		goto end;
+	}
+
+	irq = gpio_to_irq(drvdata->fd_gpio.gpio);
+	if (irq < 0) {
+		rc = irq;
+		pr_err("unable to get irq number for gpio %d, error %d\n",
+			drvdata->fd_gpio.gpio, rc);
+		goto end;
+	}
+
+	drvdata->fd_gpio.irq = irq;
+	INIT_WORK(&drvdata->fd_gpio.work, qbt1000_gpio_work_func);
+
+	rc = devm_request_any_context_irq(&pdev->dev, drvdata->fd_gpio.irq,
+		qbt1000_gpio_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		desc, drvdata);
+
+	if (rc < 0) {
+		pr_err("unable to claim irq %d; error %d\n",
+			drvdata->fd_gpio.irq, rc);
+		goto end;
+	}
+
+end:
+	return rc;
+}
+
+static int setup_ipc_irq(struct platform_device *pdev,
+	struct qbt1000_drvdata *drvdata)
+{
+	int rc = 0;
+	const char *desc = "qbt_ipc";
+
+	drvdata->fw_ipc.irq = gpio_to_irq(drvdata->fw_ipc.gpio);
+	pr_debug("\nirq %d gpio %d\n",
+			drvdata->fw_ipc.irq, drvdata->fw_ipc.gpio);
+	if (drvdata->fw_ipc.irq < 0) {
+		rc = drvdata->fw_ipc.irq;
+		pr_err("no irq for gpio %d, error=%d\n",
+		  drvdata->fw_ipc.gpio, rc);
+		goto end;
+	}
+
+	rc = devm_gpio_request_one(&pdev->dev, drvdata->fw_ipc.gpio,
+			GPIOF_IN, desc);
+
+	if (rc < 0) {
+		pr_err("failed to request gpio %d, error %d\n",
+			drvdata->fw_ipc.gpio, rc);
+		goto end;
+	}
+
+	rc = devm_request_threaded_irq(&pdev->dev,
+		drvdata->fw_ipc.irq,
+		NULL,
+		qbt1000_ipc_irq_handler,
+		IRQF_ONESHOT | IRQF_TRIGGER_RISING,
+		desc,
+		drvdata);
+
+	if (rc < 0) {
+		pr_err("failed to register for ipc irq %d, rc = %d\n",
+			drvdata->fw_ipc.irq, rc);
+		goto end;
+	}
+
+end:
+	return rc;
+}
+
+/**
+ * qbt1000_read_device_tree() - Function reads device tree
+ * properties into driver data
+ * @pdev:	ptr to platform device object
+ * @drvdata:	ptr to driver data
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int qbt1000_read_device_tree(struct platform_device *pdev,
+	struct qbt1000_drvdata *drvdata)
+{
+	int rc = 0;
+	uint32_t rate;
+	int gpio;
+	enum of_gpio_flags flags;
+
+	/* read clock frequency */
+	if (of_property_read_u32(pdev->dev.of_node,
+		"clock-frequency", &rate) == 0) {
+		pr_debug("clk frequency %d\n", rate);
+		drvdata->frequency = rate;
+	}
+
+	/* read IPC gpio */
+	drvdata->fw_ipc.gpio = of_get_named_gpio(pdev->dev.of_node,
+		"qcom,ipc-gpio", 0);
+	if (drvdata->fw_ipc.gpio < 0) {
+		rc = drvdata->fw_ipc.gpio;
+		pr_err("ipc gpio not found, error=%d\n", rc);
+		goto end;
+	}
+
+	/**
+	 * TODO: Need to revisit after adding GPIO in DTSI- read
+	 * finger detect GPIO configuration
+	 */
+
+	gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+				"qcom,finger-detect-gpio", 0, &flags);
+	if (gpio < 0) {
+		pr_err("failed to get gpio flags\n");
+		rc = gpio;
+		goto end;
+	}
+
+	drvdata->fd_gpio.gpio = gpio;
+	drvdata->fd_gpio.active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+end:
+	return rc;
+}
+
+/**
+ * qbt1000_probe() - Function loads hardware config from device tree
+ * @pdev:	ptr to platform device object
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int qbt1000_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct qbt1000_drvdata *drvdata;
+	int rc = 0;
+
+	pr_debug("qbt1000_probe begin\n");
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	rc = qbt1000_read_device_tree(pdev, drvdata);
+	if (rc < 0)
+		goto end;
+
+	atomic_set(&drvdata->available, 1);
+
+	mutex_init(&drvdata->mutex);
+	mutex_init(&drvdata->fw_events_mutex);
+
+	rc = qbt1000_dev_register(drvdata);
+	if (rc < 0)
+		goto end;
+
+	INIT_KFIFO(drvdata->fw_events);
+	init_waitqueue_head(&drvdata->read_wait_queue);
+
+	rc = qbt1000_create_input_device(drvdata);
+	if (rc < 0)
+		goto end;
+
+	rc = setup_fd_gpio_irq(pdev, drvdata);
+	if (rc < 0)
+		goto end;
+
+	rc = setup_ipc_irq(pdev, drvdata);
+	if (rc < 0)
+		goto end;
+
+	rc = device_init_wakeup(&pdev->dev, 1);
+	if (rc < 0)
+		goto end;
+
+end:
+	pr_debug("qbt1000_probe end : %d\n", rc);
+	return rc;
+}
+
+static int qbt1000_remove(struct platform_device *pdev)
+{
+	struct qbt1000_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	input_unregister_device(drvdata->in_dev);
+
+	mutex_destroy(&drvdata->mutex);
+	mutex_destroy(&drvdata->fw_events_mutex);
+
+	device_destroy(drvdata->qbt1000_class, drvdata->qbt1000_cdev.dev);
+	class_destroy(drvdata->qbt1000_class);
+	cdev_del(&drvdata->qbt1000_cdev);
+	unregister_chrdev_region(drvdata->qbt1000_cdev.dev, 1);
+
+	device_init_wakeup(&pdev->dev, 0);
+
+	return 0;
+}
+
+static int qbt1000_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	int rc = 0;
+	struct qbt1000_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	/*
+	 * Returning an error code if driver currently making a TZ call.
+	 * Note: The purpose of this driver is to ensure that the clocks are on
+	 * while making a TZ call. Hence the clock check to determine if the
+	 * driver will allow suspend to occur.
+	 */
+	if (!mutex_trylock(&drvdata->mutex))
+		return -EBUSY;
+
+	if (drvdata->clock_state)
+		rc = -EBUSY;
+	else {
+		enable_irq_wake(drvdata->fd_gpio.irq);
+		enable_irq_wake(drvdata->fw_ipc.irq);
+	}
+
+	mutex_unlock(&drvdata->mutex);
+
+	return rc;
+}
+
+static int qbt1000_resume(struct platform_device *pdev)
+{
+	struct qbt1000_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	disable_irq_wake(drvdata->fd_gpio.irq);
+	disable_irq_wake(drvdata->fw_ipc.irq);
+
+	return 0;
+}
+
+static const struct of_device_id qbt1000_match[] = {
+	{ .compatible = "qcom,qbt1000" },
+	{}
+};
+
+static struct platform_driver qbt1000_plat_driver = {
+	.probe = qbt1000_probe,
+	.remove = qbt1000_remove,
+	.suspend = qbt1000_suspend,
+	.resume = qbt1000_resume,
+	.driver = {
+		.name = "qbt1000",
+		.owner = THIS_MODULE,
+		.of_match_table = qbt1000_match,
+	},
+};
+
+module_platform_driver(qbt1000_plat_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. QBT1000 driver");
diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c
index 82718c8..57f38d3 100644
--- a/drivers/soc/qcom/service-locator.c
+++ b/drivers/soc/qcom/service-locator.c
@@ -266,7 +266,6 @@
 			pd->total_domains = resp->total_domains;
 			if (!resp->total_domains) {
 				pr_err("No matching domains found\n");
-				rc = -EIO;
 				goto out;
 			}
 
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index 62e2384..221ae0c 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -373,13 +373,6 @@
 	mutex_unlock(&qmi_client_release_lock);
 	pr_info("Connection established between QMI handle and %d service\n",
 							data->instance_id);
-	/* Register for indication messages about service */
-	rc = qmi_register_ind_cb(data->clnt_handle, root_service_service_ind_cb,
-							(void *)data);
-	if (rc < 0)
-		pr_err("Indication callback register failed(instance-id: %d) rc:%d\n",
-							data->instance_id, rc);
-
 	mutex_lock(&notif_add_lock);
 	mutex_lock(&service_list_lock);
 	list_for_each_entry(service_notif, &service_list, list) {
@@ -402,6 +395,12 @@
 	}
 	mutex_unlock(&service_list_lock);
 	mutex_unlock(&notif_add_lock);
+	/* Register for indication messages about service */
+	rc = qmi_register_ind_cb(data->clnt_handle,
+		root_service_service_ind_cb, (void *)data);
+	if (rc < 0)
+		pr_err("Indication callback register failed(instance-id: %d) rc:%d\n",
+							data->instance_id, rc);
 }
 
 static void root_service_service_exit(struct qmi_client_info *data,
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 119ede3..8aff84c 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -36,6 +36,7 @@
 #include <soc/qcom/boot_stats.h>
 
 #define BUILD_ID_LENGTH 32
+#define CHIP_ID_LENGTH 32
 #define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
 #define SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE 128
 #define SMEM_IMAGE_VERSION_SIZE 4096
@@ -199,6 +200,20 @@
 struct socinfo_v0_13 {
 	struct socinfo_v0_12 v0_12;
 	uint32_t nproduct_id;
+	char chip_name[CHIP_ID_LENGTH];
+};
+
+struct socinfo_v0_14 {
+	struct socinfo_v0_13 v0_13;
+	uint32_t num_clusters;
+	uint32_t ncluster_array_offset;
+	uint32_t num_defective_parts;
+	uint32_t ndefective_parts_array_offset;
+};
+
+struct socinfo_v0_15 {
+	struct socinfo_v0_14 v0_14;
+	uint32_t nmodem_supported;
 };
 
 static union {
@@ -215,10 +230,12 @@
 	struct socinfo_v0_11 v0_11;
 	struct socinfo_v0_12 v0_12;
 	struct socinfo_v0_13 v0_13;
+	struct socinfo_v0_14 v0_14;
+	struct socinfo_v0_15 v0_15;
 } *socinfo;
 
 /* max socinfo format version supported */
-#define MAX_SOCINFO_FORMAT SOCINFO_VERSION(0, 13)
+#define MAX_SOCINFO_FORMAT SOCINFO_VERSION(0, 15)
 
 static struct msm_soc_info cpu_of_id[] = {
 
@@ -705,6 +722,14 @@
 		: 0;
 }
 
+static char *socinfo_get_chip_name(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_VERSION(0, 13) ?
+			socinfo->v0_13.chip_name : "N/A")
+		: "N/A";
+}
+
 static uint32_t socinfo_get_nproduct_id(void)
 {
 	return socinfo ?
@@ -713,6 +738,46 @@
 		: 0;
 }
 
+static uint32_t socinfo_get_num_clusters(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_VERSION(0, 14) ?
+			socinfo->v0_14.num_clusters : 0)
+		: 0;
+}
+
+static uint32_t socinfo_get_ncluster_array_offset(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_VERSION(0, 14) ?
+			socinfo->v0_14.ncluster_array_offset : 0)
+		: 0;
+}
+
+static uint32_t socinfo_get_num_defective_parts(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_VERSION(0, 14) ?
+			socinfo->v0_14.num_defective_parts : 0)
+		: 0;
+}
+
+static uint32_t socinfo_get_ndefective_parts_array_offset(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_VERSION(0, 14) ?
+			socinfo->v0_14.ndefective_parts_array_offset : 0)
+		: 0;
+}
+
+static uint32_t socinfo_get_nmodem_supported(void)
+{
+	return socinfo ?
+		(socinfo_format >= SOCINFO_VERSION(0, 15) ?
+			socinfo->v0_15.nmodem_supported : 0)
+		: 0;
+}
+
 enum pmic_model socinfo_get_pmic_model(void)
 {
 	return socinfo ?
@@ -890,6 +955,15 @@
 }
 
 static ssize_t
+msm_get_chip_name(struct device *dev,
+		   struct device_attribute *attr,
+		   char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+			socinfo_get_chip_name());
+}
+
+static ssize_t
 msm_get_nproduct_id(struct device *dev,
 			struct device_attribute *attr,
 			char *buf)
@@ -899,6 +973,51 @@
 }
 
 static ssize_t
+msm_get_num_clusters(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%x\n",
+		socinfo_get_num_clusters());
+}
+
+static ssize_t
+msm_get_ncluster_array_offset(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%x\n",
+		socinfo_get_ncluster_array_offset());
+}
+
+static ssize_t
+msm_get_num_defective_parts(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%x\n",
+		socinfo_get_num_defective_parts());
+}
+
+static ssize_t
+msm_get_ndefective_parts_array_offset(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%x\n",
+		socinfo_get_ndefective_parts_array_offset());
+}
+
+static ssize_t
+msm_get_nmodem_supported(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0x%x\n",
+		socinfo_get_nmodem_supported());
+}
+
+static ssize_t
 msm_get_pmic_model(struct device *dev,
 			struct device_attribute *attr,
 			char *buf)
@@ -1146,10 +1265,34 @@
 	__ATTR(raw_device_number, S_IRUGO,
 			msm_get_raw_device_number, NULL);
 
+static struct device_attribute msm_soc_attr_chip_name =
+	__ATTR(chip_name, 0444,
+			msm_get_chip_name, NULL);
+
 static struct device_attribute msm_soc_attr_nproduct_id =
 	__ATTR(nproduct_id, 0444,
 			msm_get_nproduct_id, NULL);
 
+static struct device_attribute msm_soc_attr_num_clusters =
+	__ATTR(num_clusters, 0444,
+			msm_get_num_clusters, NULL);
+
+static struct device_attribute msm_soc_attr_ncluster_array_offset =
+	__ATTR(ncluster_array_offset, 0444,
+			msm_get_ncluster_array_offset, NULL);
+
+static struct device_attribute msm_soc_attr_num_defective_parts =
+	__ATTR(num_defective_parts, 0444,
+			msm_get_num_defective_parts, NULL);
+
+static struct device_attribute msm_soc_attr_ndefective_parts_array_offset =
+	__ATTR(ndefective_parts_array_offset, 0444,
+			msm_get_ndefective_parts_array_offset, NULL);
+
+static struct device_attribute msm_soc_attr_nmodem_supported =
+	__ATTR(nmodem_supported, 0444,
+			msm_get_nmodem_supported, NULL);
+
 static struct device_attribute msm_soc_attr_pmic_model =
 	__ATTR(pmic_model, S_IRUGO,
 			msm_get_pmic_model, NULL);
@@ -1280,9 +1423,23 @@
 	device_create_file(msm_soc_device, &images);
 
 	switch (socinfo_format) {
+	case SOCINFO_VERSION(0, 15):
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_nmodem_supported);
+	case SOCINFO_VERSION(0, 14):
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_num_clusters);
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_ncluster_array_offset);
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_num_defective_parts);
+		device_create_file(msm_soc_device,
+				&msm_soc_attr_ndefective_parts_array_offset);
 	case SOCINFO_VERSION(0, 13):
 		 device_create_file(msm_soc_device,
 					&msm_soc_attr_nproduct_id);
+		 device_create_file(msm_soc_device,
+					&msm_soc_attr_chip_name);
 	case SOCINFO_VERSION(0, 12):
 		device_create_file(msm_soc_device,
 					&msm_soc_attr_chip_family);
@@ -1522,6 +1679,53 @@
 			socinfo->v0_13.nproduct_id);
 		break;
 
+	case SOCINFO_VERSION(0, 14):
+		pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u foundry_id=%u serial_number=%u num_pmics=%u chip_family=0x%x raw_device_family=0x%x raw_device_number=0x%x nproduct_id=0x%x num_clusters=0x%x ncluster_array_offset=0x%x num_defective_parts=0x%x ndefective_parts_array_offset=0x%x\n",
+			f_maj, f_min, socinfo->v0_1.id, v_maj, v_min,
+			socinfo->v0_2.raw_id, socinfo->v0_2.raw_version,
+			socinfo->v0_3.hw_platform,
+			socinfo->v0_4.platform_version,
+			socinfo->v0_5.accessory_chip,
+			socinfo->v0_6.hw_platform_subtype,
+			socinfo->v0_7.pmic_model,
+			socinfo->v0_7.pmic_die_revision,
+			socinfo->v0_9.foundry_id,
+			socinfo->v0_10.serial_number,
+			socinfo->v0_11.num_pmics,
+			socinfo->v0_12.chip_family,
+			socinfo->v0_12.raw_device_family,
+			socinfo->v0_12.raw_device_number,
+			socinfo->v0_13.nproduct_id,
+			socinfo->v0_14.num_clusters,
+			socinfo->v0_14.ncluster_array_offset,
+			socinfo->v0_14.num_defective_parts,
+			socinfo->v0_14.ndefective_parts_array_offset);
+		break;
+
+	case SOCINFO_VERSION(0, 15):
+		pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u foundry_id=%u serial_number=%u num_pmics=%u chip_family=0x%x raw_device_family=0x%x raw_device_number=0x%x nproduct_id=0x%x num_clusters=0x%x ncluster_array_offset=0x%x num_defective_parts=0x%x ndefective_parts_array_offset=0x%x nmodem_supported=0x%x\n",
+			f_maj, f_min, socinfo->v0_1.id, v_maj, v_min,
+			socinfo->v0_2.raw_id, socinfo->v0_2.raw_version,
+			socinfo->v0_3.hw_platform,
+			socinfo->v0_4.platform_version,
+			socinfo->v0_5.accessory_chip,
+			socinfo->v0_6.hw_platform_subtype,
+			socinfo->v0_7.pmic_model,
+			socinfo->v0_7.pmic_die_revision,
+			socinfo->v0_9.foundry_id,
+			socinfo->v0_10.serial_number,
+			socinfo->v0_11.num_pmics,
+			socinfo->v0_12.chip_family,
+			socinfo->v0_12.raw_device_family,
+			socinfo->v0_12.raw_device_number,
+			socinfo->v0_13.nproduct_id,
+			socinfo->v0_14.num_clusters,
+			socinfo->v0_14.ncluster_array_offset,
+			socinfo->v0_14.num_defective_parts,
+			socinfo->v0_14.ndefective_parts_array_offset,
+			socinfo->v0_15.nmodem_supported);
+		break;
+
 	default:
 		pr_err("Unknown format found: v%u.%u\n", f_maj, f_min);
 		break;
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 68f0217..9846c51 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -96,6 +96,7 @@
 	int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
 	int other_file = global_node_page_state(NR_FILE_PAGES) -
 				global_node_page_state(NR_SHMEM) -
+				global_node_page_state(NR_UNEVICTABLE) -
 				total_swapcache_pages();
 
 	if (lowmem_adj_size < array_size)
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 70390de..eb0a095 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -611,7 +611,7 @@
 		s = &dev->subdevices[i];
 		spriv = s->private;
 
-		if (now > spriv->next_time_min) {
+		if (time_after_eq(now, spriv->next_time_min)) {
 			struct jr3_pci_poll_delay sub_delay;
 
 			sub_delay = jr3_pci_poll_subdevice(s);
@@ -727,11 +727,12 @@
 		s->insn_read	= jr3_pci_ai_insn_read;
 
 		spriv = jr3_pci_alloc_spriv(dev, s);
-		if (spriv) {
-			/* Channel specific range and maxdata */
-			s->range_table_list	= spriv->range_table_list;
-			s->maxdata_list		= spriv->maxdata_list;
-		}
+		if (!spriv)
+			return -ENOMEM;
+
+		/* Channel specific range and maxdata */
+		s->range_table_list	= spriv->range_table_list;
+		s->maxdata_list		= spriv->maxdata_list;
 	}
 
 	/* Reset DSP card */
diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c
index 4009691..f03e43b 100644
--- a/drivers/staging/gdm724x/gdm_mux.c
+++ b/drivers/staging/gdm724x/gdm_mux.c
@@ -664,9 +664,8 @@
 
 static void __exit gdm_usb_mux_exit(void)
 {
-	unregister_lte_tty_driver();
-
 	usb_deregister(&gdm_mux_driver);
+	unregister_lte_tty_driver();
 }
 
 module_init(gdm_usb_mux_init);
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index e9b6b21..f759aa8 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -47,15 +47,25 @@
 		u16 index, u16 length, u8 *buffer)
 {
 	int status = 0;
+	u8 *usb_buffer;
 
 	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
 		return STATUS_FAILURE;
 
 	mutex_lock(&priv->usb_lock);
 
+	usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
+	if (!usb_buffer) {
+		mutex_unlock(&priv->usb_lock);
+		return -ENOMEM;
+	}
+
 	status = usb_control_msg(priv->usb,
-		usb_sndctrlpipe(priv->usb, 0), request, 0x40, value,
-			index, buffer, length, USB_CTL_WAIT);
+				 usb_sndctrlpipe(priv->usb, 0),
+				 request, 0x40, value,
+				 index, usb_buffer, length, USB_CTL_WAIT);
+
+	kfree(usb_buffer);
 
 	mutex_unlock(&priv->usb_lock);
 
@@ -75,15 +85,28 @@
 		u16 index, u16 length, u8 *buffer)
 {
 	int status;
+	u8 *usb_buffer;
 
 	if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
 		return STATUS_FAILURE;
 
 	mutex_lock(&priv->usb_lock);
 
+	usb_buffer = kmalloc(length, GFP_KERNEL);
+	if (!usb_buffer) {
+		mutex_unlock(&priv->usb_lock);
+		return -ENOMEM;
+	}
+
 	status = usb_control_msg(priv->usb,
-		usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value,
-			index, buffer, length, USB_CTL_WAIT);
+				 usb_rcvctrlpipe(priv->usb, 0),
+				 request, 0xc0, value,
+				 index, usb_buffer, length, USB_CTL_WAIT);
+
+	if (status == length)
+		memcpy(buffer, usb_buffer, length);
+
+	kfree(usb_buffer);
 
 	mutex_unlock(&priv->usb_lock);
 
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index b7d747e..40e50f2 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -4671,6 +4671,7 @@
 			continue;
 		}
 		atomic_set(&sess->session_reinstatement, 1);
+		atomic_set(&sess->session_fall_back_to_erl0, 1);
 		spin_unlock(&sess->conn_lock);
 
 		list_move_tail(&se_sess->sess_list, &free_list);
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index e980e2d..7e70fe8 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -1530,6 +1530,7 @@
 		return;
 	}
 	atomic_set(&sess->session_reinstatement, 1);
+	atomic_set(&sess->session_fall_back_to_erl0, 1);
 	spin_unlock(&sess->conn_lock);
 
 	iscsit_stop_time2retain_timer(sess);
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 15f79a2..96c55bc 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -204,6 +204,7 @@
 			    initiatorname_param->value) &&
 		   (sess_p->sess_ops->SessionType == sessiontype))) {
 			atomic_set(&sess_p->session_reinstatement, 1);
+			atomic_set(&sess_p->session_fall_back_to_erl0, 1);
 			spin_unlock(&sess_p->conn_lock);
 			iscsit_inc_session_usage_count(sess_p);
 			iscsit_stop_time2retain_timer(sess_p);
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index d545993..29f807b 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -594,8 +594,7 @@
 	if (ret < 0)
 		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-	if (ret)
-		target_complete_cmd(cmd, SAM_STAT_GOOD);
+	target_complete_cmd(cmd, SAM_STAT_GOOD);
 	return 0;
 }
 
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index a53fb23..b3b1461 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -506,8 +506,11 @@
 	 * been failed with a non-zero SCSI status.
 	 */
 	if (cmd->scsi_status) {
-		pr_err("compare_and_write_callback: non zero scsi_status:"
+		pr_debug("compare_and_write_callback: non zero scsi_status:"
 			" 0x%02x\n", cmd->scsi_status);
+		*post_ret = 1;
+		if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 		goto out;
 	}
 
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 342160e..04320d8 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -1973,8 +1973,6 @@
 			chip->sensor[sen_idx].thermal_node = true;
 			snprintf(name, sizeof(name), "%s",
 				chip->adc->adc_channels[sen_idx].name);
-			chip->sensor[sen_idx].meas_interval =
-				QPNP_ADC_TM_MEAS_INTERVAL;
 			chip->sensor[sen_idx].low_thr =
 						QPNP_ADC_TM_M0_LOW_THR;
 			chip->sensor[sen_idx].high_thr =
@@ -2027,7 +2025,7 @@
 
 	rc = devm_request_irq(&pdev->dev, chip->adc->adc_irq_eoc,
 			qpnp_adc_tm_rc_thr_isr,
-		IRQF_TRIGGER_RISING, "qpnp_adc_tm_interrupt", chip);
+		IRQF_TRIGGER_HIGH, "qpnp_adc_tm_interrupt", chip);
 	if (rc)
 		dev_err(&pdev->dev, "failed to request adc irq\n");
 	else
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index a23fa5e..2b90738 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -216,16 +216,11 @@
 static void pty_flush_buffer(struct tty_struct *tty)
 {
 	struct tty_struct *to = tty->link;
-	struct tty_ldisc *ld;
 
 	if (!to)
 		return;
 
-	ld = tty_ldisc_ref(to);
-	tty_buffer_flush(to, ld);
-	if (ld)
-		tty_ldisc_deref(ld);
-
+	tty_buffer_flush(to, NULL);
 	if (to->packet) {
 		spin_lock_irq(&tty->ctrl_lock);
 		tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 8108da8..2e12c3f 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -145,6 +145,7 @@
 	void *ipc_log_pwr;
 	void *ipc_log_misc;
 	unsigned int cur_baud;
+	int ioctl_count;
 };
 
 static const struct uart_ops msm_geni_serial_pops;
@@ -161,6 +162,8 @@
 static unsigned int msm_geni_serial_tx_empty(struct uart_port *port);
 static int msm_geni_serial_power_on(struct uart_port *uport);
 static void msm_geni_serial_power_off(struct uart_port *uport);
+static int msm_geni_serial_poll_bit(struct uart_port *uport,
+				int offset, int bit_field, bool set);
 
 static atomic_t uart_line_id = ATOMIC_INIT(0);
 
@@ -218,22 +221,22 @@
 					(unsigned int)addr, size, buf);
 }
 
-static void check_tx_active(struct uart_port *uport)
+static bool check_tx_active(struct uart_port *uport)
 {
-	u32 geni_status = geni_read_reg_nolog(uport->membase,
-					SE_GENI_STATUS);
-
-	while ((geni_status & M_GENI_CMD_ACTIVE)) {
-		cpu_relax();
-		geni_status = geni_read_reg_nolog(uport->membase,
-					SE_GENI_STATUS);
-	}
+	/*
+	 * Poll if the GENI STATUS bit for TX is cleared. If the bit is
+	 * clear (poll condition met), return false, meaning tx isn't active
+	 * else return true. So return not of the poll return.
+	 */
+	return !msm_geni_serial_poll_bit(uport, SE_GENI_STATUS,
+					M_GENI_CMD_ACTIVE, false);
 }
 
 static int vote_clock_on(struct uart_port *uport)
 {
 	int ret = 0;
 	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+	int usage_count = atomic_read(&uport->dev->power.usage_count);
 
 	if (!pm_runtime_enabled(uport->dev)) {
 		dev_err(uport->dev, "RPM not available.Can't enable clocks\n");
@@ -245,8 +248,10 @@
 		dev_err(uport->dev, "Failed to vote clock on\n");
 		return ret;
 	}
+	port->ioctl_count++;
 	__pm_relax(&port->geni_wake);
-	IPC_LOG_MSG(port->ipc_log_pwr, "%s\n", __func__);
+	IPC_LOG_MSG(port->ipc_log_pwr, "%s rpm %d ioctl %d\n",
+				__func__, usage_count, port->ioctl_count);
 	return 0;
 }
 
@@ -254,16 +259,29 @@
 {
 	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
 	int ret = 0;
+	int usage_count = atomic_read(&uport->dev->power.usage_count);
 
 	if (!pm_runtime_enabled(uport->dev)) {
 		dev_err(uport->dev, "RPM not available.Can't enable clocks\n");
 		ret = -EPERM;
 		return ret;
 	}
-	/* Block till any on going Tx goes out.*/
-	check_tx_active(uport);
+	/* Check on going Tx. Don't block on this for now. */
+	if (check_tx_active(uport))
+		dev_warn(uport->dev, "%s: Vote off called during active Tx",
+								__func__);
+	if (!port->ioctl_count) {
+		dev_warn(uport->dev, "%s:Imbalanced vote off ioctl %d\n",
+						 __func__, usage_count);
+		IPC_LOG_MSG(port->ipc_log_pwr,
+				"%s:Imbalanced vote_off from userspace rpm%d",
+				__func__, usage_count);
+		return 0;
+	}
+	port->ioctl_count--;
 	msm_geni_serial_power_off(uport);
-	IPC_LOG_MSG(port->ipc_log_pwr, "%s\n", __func__);
+	IPC_LOG_MSG(port->ipc_log_pwr, "%s rpm %d ioctl %d\n",
+				__func__, usage_count, port->ioctl_count);
 	return 0;
 };
 
@@ -398,20 +416,20 @@
 	bool cond = false;
 	unsigned int baud = 115200;
 	unsigned int fifo_bits = DEF_FIFO_DEPTH_WORDS * DEF_FIFO_WIDTH_BITS;
-	unsigned long total_iter = 0;
+	unsigned long total_iter = 1000;
 
 
-	if (uport->private_data) {
+	if (uport->private_data && !uart_console(uport)) {
 		port = GET_DEV_PORT(uport);
 		baud = (port->cur_baud ? port->cur_baud : 115200);
 		fifo_bits = port->tx_fifo_depth * port->tx_fifo_width;
+		/*
+		 * Total polling iterations based on FIFO worth of bytes to be
+		 * sent at current baud .Add a little fluff to the wait.
+		 */
+		total_iter = ((fifo_bits * USEC_PER_SEC) / baud);
+		total_iter += 50;
 	}
-	/*
-	 * Total polling iterations based on FIFO worth of bytes to be
-	 * sent at current baud .Add a little fluff to the wait.
-	 */
-	total_iter = ((fifo_bits * USEC_PER_SEC) / baud);
-	total_iter += 50;
 
 	while (iter < total_iter) {
 		reg = geni_read_reg_nolog(uport->membase, offset);
@@ -449,17 +467,11 @@
 	done = msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
 						M_CMD_DONE_EN, true);
 	if (!done) {
-		geni_write_reg_nolog(M_GENI_CMD_CANCEL, uport->membase,
-						SE_GENI_S_CMD_CTRL_REG);
-		irq_clear |= M_CMD_CANCEL_EN;
-		if (!msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
-						M_CMD_CANCEL_EN, true)) {
-			geni_write_reg_nolog(M_GENI_CMD_ABORT, uport->membase,
-						SE_GENI_M_CMD_CTRL_REG);
-			irq_clear |= M_CMD_ABORT_EN;
-			msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
+		geni_write_reg_nolog(M_GENI_CMD_ABORT, uport->membase,
+					SE_GENI_M_CMD_CTRL_REG);
+		irq_clear |= M_CMD_ABORT_EN;
+		msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
 							M_CMD_ABORT_EN, true);
-		}
 	}
 	geni_write_reg_nolog(irq_clear, uport->membase, SE_GENI_M_IRQ_CLEAR);
 }
@@ -678,7 +690,6 @@
 	geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN);
 	/* Geni command setup/irq enables should complete before returning.*/
 	mb();
-	IPC_LOG_MSG(msm_port->ipc_log_misc, "%s\n", __func__);
 }
 
 static void msm_geni_serial_stop_tx(struct uart_port *uport)
@@ -1009,6 +1020,7 @@
 	disable_irq(uport->irq);
 	free_irq(uport->irq, msm_port);
 	if (uart_console(uport)) {
+		console_stop(uport->cons);
 		se_geni_resources_off(&msm_port->serial_rsc);
 	} else {
 		if (msm_port->wakeup_irq > 0) {
@@ -1032,23 +1044,33 @@
 	if (!uart_console(uport)) {
 		/* For now only assume FIFO mode. */
 		msm_port->xfer_mode = FIFO_MODE;
-		ret = geni_se_init(uport->membase,
-					msm_port->rx_wm, msm_port->rx_rfr);
-		if (ret) {
-			dev_err(uport->dev, "%s: Fail\n", __func__);
-			goto exit_portsetup;
-		}
-
-		ret = geni_se_select_mode(uport->membase, msm_port->xfer_mode);
-		if (ret)
-			goto exit_portsetup;
-
 		se_get_packing_config(8, 4, false, &cfg0, &cfg1);
 		geni_write_reg_nolog(cfg0, uport->membase,
 						SE_GENI_TX_PACKING_CFG0);
 		geni_write_reg_nolog(cfg1, uport->membase,
 						SE_GENI_TX_PACKING_CFG1);
+	} else {
+		/*
+		 * Make an unconditional cancel on the main sequencer to reset
+		 * it else we could end up in data loss scenarios.
+		 */
+		msm_port->xfer_mode = FIFO_MODE;
+		msm_geni_serial_poll_cancel_tx(uport);
+		se_get_packing_config(8, 1, false, &cfg0, &cfg1);
+		geni_write_reg_nolog(cfg0, uport->membase,
+						SE_GENI_TX_PACKING_CFG0);
+		geni_write_reg_nolog(cfg1, uport->membase,
+						SE_GENI_TX_PACKING_CFG1);
 	}
+	ret = geni_se_init(uport->membase, msm_port->rx_wm, msm_port->rx_rfr);
+	if (ret) {
+		dev_err(uport->dev, "%s: Fail\n", __func__);
+		goto exit_portsetup;
+	}
+
+	ret = geni_se_select_mode(uport->membase, msm_port->xfer_mode);
+	if (ret)
+		goto exit_portsetup;
 
 	msm_port->port_setup = true;
 	/*
@@ -1118,12 +1140,10 @@
 	if (unlikely(get_se_proto(uport->membase) != UART)) {
 		dev_err(uport->dev, "%s: Invalid FW %d loaded.\n",
 				 __func__, get_se_proto(uport->membase));
-		if (unlikely(get_se_proto(uport->membase) != UART)) {
-			ret = -ENXIO;
-			disable_irq(uport->irq);
-			free_irq(uport->irq, msm_port);
-			goto exit_startup;
-		}
+		ret = -ENXIO;
+		disable_irq(uport->irq);
+		free_irq(uport->irq, msm_port);
+		goto exit_startup;
 	}
 
 	if (!msm_port->port_setup) {
@@ -1358,7 +1378,6 @@
 	int parity = 'n';
 	int flow = 'n';
 	int ret = 0;
-	unsigned long cfg0, cfg1;
 
 	if (unlikely(co->index >= GENI_UART_NR_PORTS  || co->index < 0))
 		return -ENXIO;
@@ -1386,14 +1405,6 @@
 	if (!dev_port->port_setup)
 		msm_geni_serial_port_setup(uport);
 
-	/*
-	 * Make an unconditional cancel on the main sequencer to reset
-	 * it else we could end up in data loss scenarios.
-	 */
-	msm_geni_serial_poll_cancel_tx(uport);
-	se_get_packing_config(8, 1, false, &cfg0, &cfg1);
-	geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_TX_PACKING_CFG0);
-	geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_TX_PACKING_CFG1);
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 
@@ -1438,9 +1449,6 @@
 		goto exit_geni_serial_earlyconsetup;
 	}
 
-	geni_se_init(uport->membase, (DEF_FIFO_DEPTH_WORDS >> 1),
-					(DEF_FIFO_DEPTH_WORDS - 2));
-	geni_se_select_mode(uport->membase, FIFO_MODE);
 	/*
 	 * Ignore Flow control.
 	 * Disable Tx Parity.
@@ -1471,7 +1479,11 @@
 	 * it else we could end up in data loss scenarios.
 	 */
 	msm_geni_serial_poll_cancel_tx(uport);
+	msm_geni_serial_abort_rx(uport);
 	se_get_packing_config(8, 1, false, &cfg0, &cfg1);
+	geni_se_init(uport->membase, (DEF_FIFO_DEPTH_WORDS >> 1),
+					(DEF_FIFO_DEPTH_WORDS - 2));
+	geni_se_select_mode(uport->membase, FIFO_MODE);
 	geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_TX_PACKING_CFG0);
 	geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_TX_PACKING_CFG1);
 	geni_write_reg_nolog(tx_trans_cfg, uport->membase,
@@ -1802,8 +1814,7 @@
 	}
 	if (port->wakeup_irq > 0)
 		enable_irq(port->wakeup_irq);
-	IPC_LOG_MSG(port->ipc_log_pwr, "%s: Current usage count %d\n", __func__,
-				atomic_read(&dev->power.usage_count));
+	IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__);
 exit_runtime_suspend:
 	return ret;
 }
@@ -1821,8 +1832,7 @@
 		dev_err(dev, "%s: Error ret %d\n", __func__, ret);
 		goto exit_runtime_resume;
 	}
-	IPC_LOG_MSG(port->ipc_log_pwr, "%s: Current usage count %d\n", __func__,
-				atomic_read(&dev->power.usage_count));
+	IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__);
 exit_runtime_resume:
 	return ret;
 }
@@ -1836,7 +1846,6 @@
 	if (uart_console(uport)) {
 		uart_suspend_port((struct uart_driver *)uport->private_data,
 					uport);
-		se_geni_resources_off(&port->serial_rsc);
 	} else {
 		if (!pm_runtime_status_suspended(dev)) {
 			dev_info(dev, "%s: Is still active\n", __func__);
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index a2a5299..44e5b5b 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1712,7 +1712,8 @@
 	return 0;
 
 err_add_port:
-	pm_runtime_put(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_qos_remove_request(&up->pm_qos_request);
 	device_init_wakeup(up->dev, false);
@@ -1725,9 +1726,13 @@
 {
 	struct uart_omap_port *up = platform_get_drvdata(dev);
 
+	pm_runtime_get_sync(up->dev);
+
+	uart_remove_one_port(&serial_omap_reg, &up->port);
+
+	pm_runtime_dont_use_autosuspend(up->dev);
 	pm_runtime_put_sync(up->dev);
 	pm_runtime_disable(up->dev);
-	uart_remove_one_port(&serial_omap_reg, &up->port);
 	pm_qos_remove_request(&up->pm_qos_request);
 	device_init_wakeup(&dev->dev, false);
 
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 3e2ef4f..d65f92b 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -906,14 +906,13 @@
 		return -ENOMEM;
 	}
 
-	dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf,
+	dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf,
 				dma->rx_size, DMA_FROM_DEVICE);
 
 	spin_lock_irqsave(&p->port.lock, flags);
 
 	/* TX buffer */
-	dma->tx_addr = dma_map_single(dma->tx_chan->device->dev,
-				p->port.state->xmit.buf,
+	dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf,
 				UART_XMIT_SIZE, DMA_TO_DEVICE);
 
 	spin_unlock_irqrestore(&p->port.lock, flags);
@@ -927,7 +926,7 @@
 
 	if (dma->rx_chan) {
 		dmaengine_terminate_all(dma->rx_chan);
-		dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
+		dma_unmap_single(p->port.dev, dma->rx_addr,
 				dma->rx_size, DMA_FROM_DEVICE);
 		kfree(dma->rx_buf);
 		dma_release_channel(dma->rx_chan);
@@ -936,7 +935,7 @@
 
 	if (dma->tx_chan) {
 		dmaengine_terminate_all(dma->tx_chan);
-		dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr,
+		dma_unmap_single(p->port.dev, dma->tx_addr,
 				UART_XMIT_SIZE, DMA_TO_DEVICE);
 		dma_release_channel(dma->tx_chan);
 		dma->tx_chan = NULL;
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 0a63695..0b845e5 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -58,7 +58,6 @@
 #define WDM_SUSPENDING		8
 #define WDM_RESETTING		9
 #define WDM_OVERFLOW		10
-#define WDM_DRAIN_ON_OPEN	11
 
 #define WDM_MAX			16
 
@@ -182,7 +181,7 @@
 				"nonzero urb status received: -ESHUTDOWN\n");
 			goto skip_error;
 		case -EPIPE:
-			dev_dbg(&desc->intf->dev,
+			dev_err(&desc->intf->dev,
 				"nonzero urb status received: -EPIPE\n");
 			break;
 		default:
@@ -210,25 +209,6 @@
 			desc->reslength = length;
 		}
 	}
-
-	/*
-	 * Handling devices with the WDM_DRAIN_ON_OPEN flag set:
-	 * If desc->resp_count is unset, then the urb was submitted
-	 * without a prior notification.  If the device returned any
-	 * data, then this implies that it had messages queued without
-	 * notifying us.  Continue reading until that queue is flushed.
-	 */
-	if (!desc->resp_count) {
-		if (!length) {
-			/* do not propagate the expected -EPIPE */
-			desc->rerr = 0;
-			goto unlock;
-		}
-		dev_dbg(&desc->intf->dev, "got %d bytes without notification\n", length);
-		set_bit(WDM_RESPONDING, &desc->flags);
-		usb_submit_urb(desc->response, GFP_ATOMIC);
-	}
-
 skip_error:
 	set_bit(WDM_READ, &desc->flags);
 	wake_up(&desc->wait);
@@ -243,7 +223,6 @@
 		service_outstanding_interrupt(desc);
 	}
 
-unlock:
 	spin_unlock(&desc->iuspin);
 }
 
@@ -686,17 +665,6 @@
 			dev_err(&desc->intf->dev,
 				"Error submitting int urb - %d\n", rv);
 			rv = usb_translate_errors(rv);
-		} else if (test_bit(WDM_DRAIN_ON_OPEN, &desc->flags)) {
-			/*
-			 * Some devices keep pending messages queued
-			 * without resending notifications.  We must
-			 * flush the message queue before we can
-			 * assume a one-to-one relationship between
-			 * notifications and messages in the queue
-			 */
-			dev_dbg(&desc->intf->dev, "draining queued data\n");
-			set_bit(WDM_RESPONDING, &desc->flags);
-			rv = usb_submit_urb(desc->response, GFP_KERNEL);
 		}
 	} else {
 		rv = 0;
@@ -803,8 +771,7 @@
 /* --- hotplug --- */
 
 static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep,
-		u16 bufsize, int (*manage_power)(struct usb_interface *, int),
-		bool drain_on_open)
+		u16 bufsize, int (*manage_power)(struct usb_interface *, int))
 {
 	int rv = -ENOMEM;
 	struct wdm_device *desc;
@@ -891,68 +858,6 @@
 
 	desc->manage_power = manage_power;
 
-	/*
-	 * "drain_on_open" enables a hack to work around a firmware
-	 * issue observed on network functions, in particular MBIM
-	 * functions.
-	 *
-	 * Quoting section 7 of the CDC-WMC r1.1 specification:
-	 *
-	 *  "The firmware shall interpret GetEncapsulatedResponse as a
-	 *   request to read response bytes. The firmware shall send
-	 *   the next wLength bytes from the response. The firmware
-	 *   shall allow the host to retrieve data using any number of
-	 *   GetEncapsulatedResponse requests. The firmware shall
-	 *   return a zero- length reply if there are no data bytes
-	 *   available.
-	 *
-	 *   The firmware shall send ResponseAvailable notifications
-	 *   periodically, using any appropriate algorithm, to inform
-	 *   the host that there is data available in the reply
-	 *   buffer. The firmware is allowed to send ResponseAvailable
-	 *   notifications even if there is no data available, but
-	 *   this will obviously reduce overall performance."
-	 *
-	 * These requirements, although they make equally sense, are
-	 * often not implemented by network functions. Some firmwares
-	 * will queue data indefinitely, without ever resending a
-	 * notification. The result is that the driver and firmware
-	 * loses "syncronization" if the driver ever fails to respond
-	 * to a single notification, something which easily can happen
-	 * on release(). When this happens, the driver will appear to
-	 * never receive notifications for the most current data. Each
-	 * notification will only cause a single read, which returns
-	 * the oldest data in the firmware's queue.
-	 *
-	 * The "drain_on_open" hack resolves the situation by draining
-	 * data from the firmware until none is returned, without a
-	 * prior notification.
-	 *
-	 * This will inevitably race with the firmware, risking that
-	 * we read data from the device before handling the associated
-	 * notification. To make things worse, some of the devices
-	 * needing the hack do not implement the "return zero if no
-	 * data is available" requirement either. Instead they return
-	 * an error on the subsequent read in this case.  This means
-	 * that "winning" the race can cause an unexpected EIO to
-	 * userspace.
-	 *
-	 * "winning" the race is more likely on resume() than on
-	 * open(), and the unexpected error is more harmful in the
-	 * middle of an open session. The hack is therefore only
-	 * applied on open(), and not on resume() where it logically
-	 * would be equally necessary. So we define open() as the only
-	 * driver <-> device "syncronization point".  Should we happen
-	 * to lose a notification after open(), then syncronization
-	 * will be lost until release()
-	 *
-	 * The hack should not be enabled for CDC WDM devices
-	 * conforming to the CDC-WMC r1.1 specification.  This is
-	 * ensured by setting drain_on_open to false in wdm_probe().
-	 */
-	if (drain_on_open)
-		set_bit(WDM_DRAIN_ON_OPEN, &desc->flags);
-
 	spin_lock(&wdm_device_list_lock);
 	list_add(&desc->device_list, &wdm_device_list);
 	spin_unlock(&wdm_device_list_lock);
@@ -1006,7 +911,7 @@
 		goto err;
 	ep = &iface->endpoint[0].desc;
 
-	rv = wdm_create(intf, ep, maxcom, &wdm_manage_power, false);
+	rv = wdm_create(intf, ep, maxcom, &wdm_manage_power);
 
 err:
 	return rv;
@@ -1038,7 +943,7 @@
 {
 	int rv = -EINVAL;
 
-	rv = wdm_create(intf, ep, bufsize, manage_power, true);
+	rv = wdm_create(intf, ep, bufsize, manage_power);
 	if (rv < 0)
 		goto err;
 
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 26a305f..ee33c0d 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1328,6 +1328,24 @@
 		 */
 		if (udev->parent && !PMSG_IS_AUTO(msg))
 			status = 0;
+
+		/*
+		 * If the device is inaccessible, don't try to resume
+		 * suspended interfaces and just return the error.
+		 */
+		if (status && status != -EBUSY) {
+			int err;
+			u16 devstat;
+
+			err = usb_get_status(udev, USB_RECIP_DEVICE, 0,
+					     &devstat);
+			if (err) {
+				dev_err(&udev->dev,
+					"Failed to suspend device, error %d\n",
+					status);
+				goto done;
+			}
+		}
 	}
 
 	/* If the suspend failed, resume interfaces that did get suspended */
@@ -1772,6 +1790,9 @@
 	int			w, i;
 	struct usb_interface	*intf;
 
+	if (udev->state == USB_STATE_NOTATTACHED)
+		return -ENODEV;
+
 	/* Fail if autosuspend is disabled, or any interfaces are in use, or
 	 * any interface drivers require remote wakeup but it isn't available.
 	 */
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 822ced9..422ce7b 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -27,6 +27,7 @@
 #define MAX_USB_MINORS	256
 static const struct file_operations *usb_minors[MAX_USB_MINORS];
 static DECLARE_RWSEM(minor_rwsem);
+static DEFINE_MUTEX(init_usb_class_mutex);
 
 static int usb_open(struct inode *inode, struct file *file)
 {
@@ -109,8 +110,9 @@
 
 static void destroy_usb_class(void)
 {
-	if (usb_class)
-		kref_put(&usb_class->kref, release_usb_class);
+	mutex_lock(&init_usb_class_mutex);
+	kref_put(&usb_class->kref, release_usb_class);
+	mutex_unlock(&init_usb_class_mutex);
 }
 
 int usb_major_init(void)
@@ -171,7 +173,10 @@
 	if (intf->minor >= 0)
 		return -EADDRINUSE;
 
+	mutex_lock(&init_usb_class_mutex);
 	retval = init_usb_class();
+	mutex_unlock(&init_usb_class_mutex);
+
 	if (retval)
 		return retval;
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index edb7a9a..7388f73 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1075,6 +1075,9 @@
 
 		portstatus = portchange = 0;
 		status = hub_port_status(hub, port1, &portstatus, &portchange);
+		if (status)
+			goto abort;
+
 		if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
 			dev_dbg(&port_dev->dev, "status %04x change %04x\n",
 					portstatus, portchange);
@@ -1207,7 +1210,7 @@
 
 	/* Scan all ports that need attention */
 	kick_hub_wq(hub);
-
+ abort:
 	if (type == HUB_INIT2 || type == HUB_INIT3) {
 		/* Allow autosuspend if it was suppressed */
  disconnected:
@@ -2093,6 +2096,12 @@
 	dev_info(&udev->dev, "USB disconnect, device number %d\n",
 			udev->devnum);
 
+	/*
+	 * Ensure that the pm runtime code knows that the USB device
+	 * is in the process of being disconnected.
+	 */
+	pm_runtime_barrier(&udev->dev);
+
 	usb_lock_device(udev);
 
 	hub_disconnect_children(udev);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index a159011..38614fa 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -3743,7 +3743,8 @@
 		}
 	}
 
-	power_supply_get_property(mdwc->usb_psy, POWER_SUPPLY_PROP_TYPE, &pval);
+	power_supply_get_property(mdwc->usb_psy,
+			POWER_SUPPLY_PROP_REAL_TYPE, &pval);
 	if (pval.intval != POWER_SUPPLY_TYPE_USB)
 		return 0;
 
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index da284fe..b040fdd 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -562,6 +562,7 @@
 choice
 	tristate "USB Gadget Drivers"
 	default USB_ETH
+	optional
 	help
 	  A Linux "Gadget Driver" talks to the USB Peripheral Controller
 	  driver through the abstract "gadget" API.  Some other operating
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index af1bca6..ea17164 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -591,14 +591,10 @@
 	ssize_t r = count;
 	unsigned xfer;
 	int ret = 0;
-	size_t len;
+	size_t len = 0;
 
 	DBG(cdev, "mtp_read(%zu) state:%d\n", count, dev->state);
 
-	len = usb_ep_align_maybe(cdev->gadget, dev->ep_out, count);
-	if (len > MTP_BULK_BUFFER_SIZE)
-		return -EINVAL;
-
 	/* we will block until we're online */
 	DBG(cdev, "mtp_read: waiting for online state\n");
 	ret = wait_event_interruptible(dev->read_wq,
@@ -613,6 +609,14 @@
 		return -EINVAL;
 
 	spin_lock_irq(&dev->lock);
+	if (dev->ep_out->desc) {
+		len = usb_ep_align_maybe(cdev->gadget, dev->ep_out, count);
+		if (len > MTP_BULK_BUFFER_SIZE) {
+			spin_unlock_irq(&dev->lock);
+			return -EINVAL;
+		}
+	}
+
 	if (dev->state == STATE_CANCELED) {
 		/* report cancelation to userspace */
 		dev->state = STATE_READY;
@@ -968,6 +972,10 @@
 				break;
 			}
 
+			if (read_req->status) {
+				r = read_req->status;
+				break;
+			}
 			/* Check if we aligned the size due to MTU constraint */
 			if (count < read_req->length)
 				read_req->actual = (read_req->actual > count ?
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index b59efd2..40504c8 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1494,6 +1494,17 @@
 	 */
 	max_esit_payload = xhci_get_max_esit_payload(udev, ep);
 	interval = xhci_get_endpoint_interval(udev, ep);
+
+	/* Periodic endpoint bInterval limit quirk */
+	if (usb_endpoint_xfer_int(&ep->desc) ||
+	    usb_endpoint_xfer_isoc(&ep->desc)) {
+		if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_7) &&
+		    udev->speed >= USB_SPEED_HIGH &&
+		    interval >= 7) {
+			interval = 6;
+		}
+	}
+
 	mult = xhci_get_endpoint_mult(udev, ep);
 	max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
 	max_burst = xhci_get_endpoint_max_burst(udev, ep);
@@ -2752,7 +2763,7 @@
 		(xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
 		xhci->cmd_ring->cycle_state;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"// Setting command ring address to 0x%x", val);
+			"// Setting command ring address to 0x%016llx", val_64);
 	xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
 	xhci_dbg_cmd_ptrs(xhci);
 
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 954abfd..93f566c 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -199,6 +199,9 @@
 			pdev->device == 0x1042)
 		xhci->quirks |= XHCI_BROKEN_STREAMS;
 
+	if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
+		xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
+
 	if (xhci->quirks & XHCI_RESET_ON_RESUME)
 		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
 				"QUIRK: Resetting on resume");
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 918f659..86d578e 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1667,6 +1667,7 @@
 #define XHCI_MISSING_CAS	(1 << 24)
 /* For controller with a broken Port Disable implementation */
 #define XHCI_BROKEN_PORT_PED	(1 << 25)
+#define XHCI_LIMIT_ENDPOINT_INTERVAL_7	(1 << 26)
 
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 5c8210d..d94927e 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -159,6 +159,7 @@
 			case USB_ENDPOINT_XFER_INT:
 				if (dev->info->intr)
 					goto try_intr;
+				continue;
 			case USB_ENDPOINT_XFER_ISOC:
 				if (dev->info->iso)
 					goto try_iso;
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 3ee2938..d951abb 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -2374,7 +2374,7 @@
 	pd->vbus_present = val.intval;
 
 	ret = power_supply_get_property(pd->usb_psy,
-			POWER_SUPPLY_PROP_TYPE, &val);
+			POWER_SUPPLY_PROP_REAL_TYPE, &val);
 	if (ret) {
 		usbpd_err(&pd->dev, "Unable to read USB TYPE: %d\n", ret);
 		return ret;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index d8d13ee..1dc75db 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -873,6 +873,7 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
 					USB_CLASS_VENDOR_SPEC,
 					USB_SUBCLASS_VENDOR_SPEC, 0x00) },
+	{ USB_DEVICE_INTERFACE_NUMBER(ACTEL_VID, MICROSEMI_ARROW_SF2PLUS_BOARD_PID, 2) },
 	{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
 	{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 48ee04c..71fb9e5 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -873,6 +873,12 @@
 #define	FIC_VID			0x1457
 #define	FIC_NEO1973_DEBUG_PID	0x5118
 
+/*
+ * Actel / Microsemi
+ */
+#define ACTEL_VID				0x1514
+#define MICROSEMI_ARROW_SF2PLUS_BOARD_PID	0x2008
+
 /* Olimex */
 #define OLIMEX_VID			0x15BA
 #define OLIMEX_ARM_USB_OCD_PID		0x0003
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 2ba1942..1d48e62 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -130,57 +130,36 @@
 	rb_erase(&old->node, &iommu->dma_list);
 }
 
-struct vwork {
-	struct mm_struct	*mm;
-	long			npage;
-	struct work_struct	work;
-};
-
-/* delayed decrement/increment for locked_vm */
-static void vfio_lock_acct_bg(struct work_struct *work)
+static int vfio_lock_acct(long npage, bool *lock_cap)
 {
-	struct vwork *vwork = container_of(work, struct vwork, work);
-	struct mm_struct *mm;
+	int ret;
 
-	mm = vwork->mm;
-	down_write(&mm->mmap_sem);
-	mm->locked_vm += vwork->npage;
-	up_write(&mm->mmap_sem);
-	mmput(mm);
-	kfree(vwork);
-}
+	if (!npage)
+		return 0;
 
-static void vfio_lock_acct(long npage)
-{
-	struct vwork *vwork;
-	struct mm_struct *mm;
+	if (!current->mm)
+		return -ESRCH; /* process exited */
 
-	if (!current->mm || !npage)
-		return; /* process exited or nothing to do */
+	ret = down_write_killable(&current->mm->mmap_sem);
+	if (!ret) {
+		if (npage > 0) {
+			if (lock_cap ? !*lock_cap : !capable(CAP_IPC_LOCK)) {
+				unsigned long limit;
 
-	if (down_write_trylock(&current->mm->mmap_sem)) {
-		current->mm->locked_vm += npage;
+				limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+
+				if (current->mm->locked_vm + npage > limit)
+					ret = -ENOMEM;
+			}
+		}
+
+		if (!ret)
+			current->mm->locked_vm += npage;
+
 		up_write(&current->mm->mmap_sem);
-		return;
 	}
 
-	/*
-	 * Couldn't get mmap_sem lock, so must setup to update
-	 * mm->locked_vm later. If locked_vm were atomic, we
-	 * wouldn't need this silliness
-	 */
-	vwork = kmalloc(sizeof(struct vwork), GFP_KERNEL);
-	if (!vwork)
-		return;
-	mm = get_task_mm(current);
-	if (!mm) {
-		kfree(vwork);
-		return;
-	}
-	INIT_WORK(&vwork->work, vfio_lock_acct_bg);
-	vwork->mm = mm;
-	vwork->npage = npage;
-	schedule_work(&vwork->work);
+	return ret;
 }
 
 /*
@@ -262,9 +241,9 @@
 static long vfio_pin_pages(unsigned long vaddr, long npage,
 			   int prot, unsigned long *pfn_base)
 {
-	unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+	unsigned long pfn = 0, limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
 	bool lock_cap = capable(CAP_IPC_LOCK);
-	long ret, i;
+	long ret, i = 1;
 	bool rsvd;
 
 	if (!current->mm)
@@ -283,16 +262,11 @@
 		return -ENOMEM;
 	}
 
-	if (unlikely(disable_hugepages)) {
-		if (!rsvd)
-			vfio_lock_acct(1);
-		return 1;
-	}
+	if (unlikely(disable_hugepages))
+		goto out;
 
 	/* Lock all the consecutive pages from pfn_base */
-	for (i = 1, vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) {
-		unsigned long pfn = 0;
-
+	for (vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) {
 		ret = vaddr_get_pfn(vaddr, prot, &pfn);
 		if (ret)
 			break;
@@ -308,12 +282,24 @@
 			put_pfn(pfn, prot);
 			pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n",
 				__func__, limit << PAGE_SHIFT);
-			break;
+			ret = -ENOMEM;
+			goto unpin_out;
 		}
 	}
 
+out:
 	if (!rsvd)
-		vfio_lock_acct(i);
+		ret = vfio_lock_acct(i, &lock_cap);
+
+unpin_out:
+	if (ret) {
+		if (!rsvd) {
+			for (pfn = *pfn_base ; i ; pfn++, i--)
+				put_pfn(pfn, prot);
+		}
+
+		return ret;
+	}
 
 	return i;
 }
@@ -328,7 +314,7 @@
 		unlocked += put_pfn(pfn++, prot);
 
 	if (do_accounting)
-		vfio_lock_acct(-unlocked);
+		vfio_lock_acct(-unlocked, NULL);
 
 	return unlocked;
 }
@@ -390,7 +376,7 @@
 		cond_resched();
 	}
 
-	vfio_lock_acct(-unlocked);
+	vfio_lock_acct(-unlocked, NULL);
 }
 
 static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 9ad527f..2924bddb 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -102,12 +102,11 @@
 {
 	struct address_space *mapping = bdev->bd_inode->i_mapping;
 
-	if (mapping->nrpages == 0)
-		return;
-
-	invalidate_bh_lrus();
-	lru_add_drain_all();	/* make sure all lru add caches are flushed */
-	invalidate_mapping_pages(mapping, 0, -1);
+	if (mapping->nrpages) {
+		invalidate_bh_lrus();
+		lru_add_drain_all();	/* make sure all lru add caches are flushed */
+		invalidate_mapping_pages(mapping, 0, -1);
+	}
 	/* 99% of the time, we don't need to flush the cleancache on the bdev.
 	 * But, for the strange corners, lets be cautious
 	 */
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index febc28f..75267cd 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -392,6 +392,7 @@
 
 	if (update_xattr) {
 		int err = 0;
+
 		if (xattr && (flags & XATTR_CREATE))
 			err = -EEXIST;
 		else if (!xattr && (flags & XATTR_REPLACE))
@@ -399,12 +400,14 @@
 		if (err) {
 			kfree(name);
 			kfree(val);
+			kfree(*newxattr);
 			return err;
 		}
 		if (update_xattr < 0) {
 			if (xattr)
 				__remove_xattr(ci, xattr);
 			kfree(name);
+			kfree(*newxattr);
 			return 0;
 		}
 	}
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 02b071bf..a0b3e7d 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -83,6 +83,9 @@
 	case SFM_COLON:
 		*target = ':';
 		break;
+	case SFM_DOUBLEQUOTE:
+		*target = '"';
+		break;
 	case SFM_ASTERISK:
 		*target = '*';
 		break;
@@ -418,6 +421,9 @@
 	case ':':
 		dest_char = cpu_to_le16(SFM_COLON);
 		break;
+	case '"':
+		dest_char = cpu_to_le16(SFM_DOUBLEQUOTE);
+		break;
 	case '*':
 		dest_char = cpu_to_le16(SFM_ASTERISK);
 		break;
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index 479bc0a..07ade70 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -57,6 +57,7 @@
  * not conflict (although almost does) with the mapping above.
  */
 
+#define SFM_DOUBLEQUOTE ((__u16) 0xF020)
 #define SFM_ASTERISK    ((__u16) 0xF021)
 #define SFM_QUESTION    ((__u16) 0xF025)
 #define SFM_COLON       ((__u16) 0xF022)
@@ -64,8 +65,8 @@
 #define SFM_LESSTHAN    ((__u16) 0xF023)
 #define SFM_PIPE        ((__u16) 0xF027)
 #define SFM_SLASH       ((__u16) 0xF026)
-#define SFM_PERIOD	((__u16) 0xF028)
-#define SFM_SPACE	((__u16) 0xF029)
+#define SFM_SPACE	((__u16) 0xF028)
+#define SFM_PERIOD	((__u16) 0xF029)
 
 /*
  * Mapping mechanism to use when one of the seven reserved characters is
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 15261ba..c0c2530 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -87,6 +87,7 @@
 extern mempool_t *cifs_mid_poolp;
 
 struct workqueue_struct	*cifsiod_wq;
+struct workqueue_struct	*cifsoplockd_wq;
 __u32 cifs_lock_secret;
 
 /*
@@ -1283,9 +1284,16 @@
 		goto out_clean_proc;
 	}
 
+	cifsoplockd_wq = alloc_workqueue("cifsoplockd",
+					 WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+	if (!cifsoplockd_wq) {
+		rc = -ENOMEM;
+		goto out_destroy_cifsiod_wq;
+	}
+
 	rc = cifs_fscache_register();
 	if (rc)
-		goto out_destroy_wq;
+		goto out_destroy_cifsoplockd_wq;
 
 	rc = cifs_init_inodecache();
 	if (rc)
@@ -1333,7 +1341,9 @@
 	cifs_destroy_inodecache();
 out_unreg_fscache:
 	cifs_fscache_unregister();
-out_destroy_wq:
+out_destroy_cifsoplockd_wq:
+	destroy_workqueue(cifsoplockd_wq);
+out_destroy_cifsiod_wq:
 	destroy_workqueue(cifsiod_wq);
 out_clean_proc:
 	cifs_proc_clean();
@@ -1356,6 +1366,7 @@
 	cifs_destroy_mids();
 	cifs_destroy_inodecache();
 	cifs_fscache_unregister();
+	destroy_workqueue(cifsoplockd_wq);
 	destroy_workqueue(cifsiod_wq);
 	cifs_proc_clean();
 }
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index b3830f7..48ef401 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1651,6 +1651,7 @@
 
 extern const struct slow_work_ops cifs_oplock_break_ops;
 extern struct workqueue_struct *cifsiod_wq;
+extern struct workqueue_struct *cifsoplockd_wq;
 extern __u32 cifs_lock_secret;
 
 extern mempool_t *cifs_mid_poolp;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 586fdac..1f91c9d 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -717,6 +717,9 @@
 	if (rc)
 		return rc;
 
+	if (server->capabilities & CAP_UNICODE)
+		smb->hdr.Flags2 |= SMBFLG2_UNICODE;
+
 	/* set up echo request */
 	smb->hdr.Tid = 0xffff;
 	smb->hdr.WordCount = 1;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index b8015de..1a54569 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2839,16 +2839,14 @@
 {
 	struct cifs_sb_info *old = CIFS_SB(sb);
 	struct cifs_sb_info *new = mnt_data->cifs_sb;
+	bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
+	bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
 
-	if (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) {
-		if (!(new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH))
-			return 0;
-		/* The prepath should be null terminated strings */
-		if (strcmp(new->prepath, old->prepath))
-			return 0;
-
+	if (old_set && new_set && !strcmp(new->prepath, old->prepath))
 		return 1;
-	}
+	else if (!old_set && !new_set)
+		return 1;
+
 	return 0;
 }
 
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 0015287..bdba9e7 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -264,10 +264,14 @@
 				rc = -EOPNOTSUPP;
 			break;
 		case CIFS_IOC_GET_MNT_INFO:
+			if (pSMBFile == NULL)
+				break;
 			tcon = tlink_tcon(pSMBFile->tlink);
 			rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg);
 			break;
 		case CIFS_ENUMERATE_SNAPSHOTS:
+			if (pSMBFile == NULL)
+				break;
 			if (arg == 0) {
 				rc = -EINVAL;
 				goto cifs_ioc_exit;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index c672915..5419afe 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -492,7 +492,7 @@
 					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
 					   &pCifsInode->flags);
 
-				queue_work(cifsiod_wq,
+				queue_work(cifsoplockd_wq,
 					   &netfile->oplock_break);
 				netfile->oplock_break_cancelled = false;
 
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 9730780..967dfe6 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -494,7 +494,7 @@
 		else
 			cfile->oplock_break_cancelled = true;
 
-		queue_work(cifsiod_wq, &cfile->oplock_break);
+		queue_work(cifsoplockd_wq, &cfile->oplock_break);
 		kfree(lw);
 		return true;
 	}
@@ -638,7 +638,8 @@
 					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
 					   &cinode->flags);
 				spin_unlock(&cfile->file_info_lock);
-				queue_work(cifsiod_wq, &cfile->oplock_break);
+				queue_work(cifsoplockd_wq,
+					   &cfile->oplock_break);
 
 				spin_unlock(&tcon->open_file_lock);
 				spin_unlock(&cifs_tcp_ses_lock);
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 007abf7..36334fe 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -924,6 +924,7 @@
 		}
 		if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) {
 			rc = -ERANGE;
+			kfree(retbuf);
 			return rc;
 		}
 
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 8021853..7c1c6c3 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -569,8 +569,12 @@
 	}
 
 	if (rsplen != sizeof(struct validate_negotiate_info_rsp)) {
-		cifs_dbg(VFS, "invalid size of protocol negotiate response\n");
-		return -EIO;
+		cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n",
+			 rsplen);
+
+		/* relax check since Mac returns max bufsize allowed on ioctl */
+		if (rsplen > CIFSMaxBufSize)
+			return -EIO;
 	}
 
 	/* check validate negotiate info response matches what we got earlier */
@@ -1670,8 +1674,12 @@
 	 * than one credit. Windows typically sets this smaller, but for some
 	 * ioctls it may be useful to allow server to send more. No point
 	 * limiting what the server can send as long as fits in one credit
+	 * Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE
+	 * (by default, note that it can be overridden to make max larger)
+	 * in responses (except for read responses which can be bigger.
+	 * We may want to bump this limit up
 	 */
-	req->MaxOutputResponse = cpu_to_le32(0xFF00); /* < 64K uses 1 credit */
+	req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize);
 
 	if (is_fsctl)
 		req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);
diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
index abc1884..bb4e209 100644
--- a/fs/crypto/policy.c
+++ b/fs/crypto/policy.c
@@ -161,27 +161,61 @@
 }
 EXPORT_SYMBOL(fscrypt_get_policy);
 
+/**
+ * fscrypt_has_permitted_context() - is a file's encryption policy permitted
+ *				     within its directory?
+ *
+ * @parent: inode for parent directory
+ * @child: inode for file being looked up, opened, or linked into @parent
+ *
+ * Filesystems must call this before permitting access to an inode in a
+ * situation where the parent directory is encrypted (either before allowing
+ * ->lookup() to succeed, or for a regular file before allowing it to be opened)
+ * and before any operation that involves linking an inode into an encrypted
+ * directory, including link, rename, and cross rename.  It enforces the
+ * constraint that within a given encrypted directory tree, all files use the
+ * same encryption policy.  The pre-access check is needed to detect potentially
+ * malicious offline violations of this constraint, while the link and rename
+ * checks are needed to prevent online violations of this constraint.
+ *
+ * Return: 1 if permitted, 0 if forbidden.  If forbidden, the caller must fail
+ * the filesystem operation with EPERM.
+ */
 int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
 {
-	struct fscrypt_info *parent_ci, *child_ci;
+	const struct fscrypt_operations *cops = parent->i_sb->s_cop;
+	const struct fscrypt_info *parent_ci, *child_ci;
+	struct fscrypt_context parent_ctx, child_ctx;
 	int res;
 
-	if ((parent == NULL) || (child == NULL)) {
-		printk(KERN_ERR	"parent %p child %p\n", parent, child);
-		BUG_ON(1);
-	}
-
 	/* No restrictions on file types which are never encrypted */
 	if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) &&
 	    !S_ISLNK(child->i_mode))
 		return 1;
 
-	/* no restrictions if the parent directory is not encrypted */
-	if (!parent->i_sb->s_cop->is_encrypted(parent))
+	/* No restrictions if the parent directory is unencrypted */
+	if (!cops->is_encrypted(parent))
 		return 1;
-	/* if the child directory is not encrypted, this is always a problem */
-	if (!parent->i_sb->s_cop->is_encrypted(child))
+
+	/* Encrypted directories must not contain unencrypted files */
+	if (!cops->is_encrypted(child))
 		return 0;
+
+	/*
+	 * Both parent and child are encrypted, so verify they use the same
+	 * encryption policy.  Compare the fscrypt_info structs if the keys are
+	 * available, otherwise retrieve and compare the fscrypt_contexts.
+	 *
+	 * Note that the fscrypt_context retrieval will be required frequently
+	 * when accessing an encrypted directory tree without the key.
+	 * Performance-wise this is not a big deal because we already don't
+	 * really optimize for file access without the key (to the extent that
+	 * such access is even possible), given that any attempted access
+	 * already causes a fscrypt_context retrieval and keyring search.
+	 *
+	 * In any case, if an unexpected error occurs, fall back to "forbidden".
+	 */
+
 	res = fscrypt_get_encryption_info(parent);
 	if (res)
 		return 0;
@@ -190,17 +224,32 @@
 		return 0;
 	parent_ci = parent->i_crypt_info;
 	child_ci = child->i_crypt_info;
-	if (!parent_ci && !child_ci)
-		return 1;
-	if (!parent_ci || !child_ci)
+
+	if (parent_ci && child_ci) {
+		return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key,
+			      FS_KEY_DESCRIPTOR_SIZE) == 0 &&
+			(parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
+			(parent_ci->ci_filename_mode ==
+			 child_ci->ci_filename_mode) &&
+			(parent_ci->ci_flags == child_ci->ci_flags);
+	}
+
+	res = cops->get_context(parent, &parent_ctx, sizeof(parent_ctx));
+	if (res != sizeof(parent_ctx))
 		return 0;
 
-	return (memcmp(parent_ci->ci_master_key,
-			child_ci->ci_master_key,
-			FS_KEY_DESCRIPTOR_SIZE) == 0 &&
-		(parent_ci->ci_data_mode == child_ci->ci_data_mode) &&
-		(parent_ci->ci_filename_mode == child_ci->ci_filename_mode) &&
-		(parent_ci->ci_flags == child_ci->ci_flags));
+	res = cops->get_context(child, &child_ctx, sizeof(child_ctx));
+	if (res != sizeof(child_ctx))
+		return 0;
+
+	return memcmp(parent_ctx.master_key_descriptor,
+		      child_ctx.master_key_descriptor,
+		      FS_KEY_DESCRIPTOR_SIZE) == 0 &&
+		(parent_ctx.contents_encryption_mode ==
+		 child_ctx.contents_encryption_mode) &&
+		(parent_ctx.filenames_encryption_mode ==
+		 child_ctx.filenames_encryption_mode) &&
+		(parent_ctx.flags == child_ctx.flags);
 }
 EXPORT_SYMBOL(fscrypt_has_permitted_context);
 
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 3cb7fa2..42723b2 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5741,6 +5741,11 @@
 	file_update_time(vma->vm_file);
 
 	down_read(&EXT4_I(inode)->i_mmap_sem);
+
+	ret = ext4_convert_inline_data(inode);
+	if (ret)
+		goto out_ret;
+
 	/* Delalloc case is easy... */
 	if (test_opt(inode->i_sb, DELALLOC) &&
 	    !ext4_should_journal_data(inode) &&
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index ef3b4eb..08ecdee 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -223,8 +223,7 @@
 	if (ret)
 		goto out;
 
-	if ((iattr->ia_valid & ATTR_SIZE) &&
-	    iattr->ia_size != i_size_read(inode)) {
+	if (iattr->ia_valid & ATTR_SIZE) {
 		ret = orangefs_setattr_size(inode, iattr);
 		if (ret)
 			goto out;
diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c
index a290ff6..7c31593 100644
--- a/fs/orangefs/namei.c
+++ b/fs/orangefs/namei.c
@@ -193,8 +193,6 @@
 		goto out;
 	}
 
-	ORANGEFS_I(inode)->getattr_time = jiffies - 1;
-
 	gossip_debug(GOSSIP_NAME_DEBUG,
 		     "%s:%s:%d "
 		     "Found good inode [%lu] with count [%d]\n",
diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c
index 74a81b1..237c9c0 100644
--- a/fs/orangefs/xattr.c
+++ b/fs/orangefs/xattr.c
@@ -76,11 +76,8 @@
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
 
-	if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) {
-		gossip_err("Invalid key length (%d)\n",
-			   (int)strlen(name));
+	if (strlen(name) > ORANGEFS_MAX_XATTR_NAMELEN)
 		return -EINVAL;
-	}
 
 	fsuid = from_kuid(&init_user_ns, current_fsuid());
 	fsgid = from_kgid(&init_user_ns, current_fsgid());
@@ -172,6 +169,9 @@
 	struct orangefs_kernel_op_s *new_op = NULL;
 	int ret = -ENOMEM;
 
+	if (strlen(name) > ORANGEFS_MAX_XATTR_NAMELEN)
+		return -EINVAL;
+
 	down_write(&orangefs_inode->xattr_sem);
 	new_op = op_alloc(ORANGEFS_VFS_OP_REMOVEXATTR);
 	if (!new_op)
@@ -231,23 +231,13 @@
 		     "%s: name %s, buffer_size %zd\n",
 		     __func__, name, size);
 
-	if (size >= ORANGEFS_MAX_XATTR_VALUELEN ||
-	    flags < 0) {
-		gossip_err("orangefs_inode_setxattr: bogus values of size(%d), flags(%d)\n",
-			   (int)size,
-			   flags);
+	if (size > ORANGEFS_MAX_XATTR_VALUELEN)
 		return -EINVAL;
-	}
+	if (strlen(name) > ORANGEFS_MAX_XATTR_NAMELEN)
+		return -EINVAL;
 
 	internal_flag = convert_to_internal_xattr_flags(flags);
 
-	if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) {
-		gossip_err
-		    ("orangefs_inode_setxattr: bogus key size (%d)\n",
-		     (int)(strlen(name)));
-		return -EINVAL;
-	}
-
 	/* This is equivalent to a removexattr */
 	if (size == 0 && value == NULL) {
 		gossip_debug(GOSSIP_XATTR_DEBUG,
@@ -358,7 +348,7 @@
 
 	returned_count = new_op->downcall.resp.listxattr.returned_count;
 	if (returned_count < 0 ||
-	    returned_count >= ORANGEFS_MAX_XATTR_LISTLEN) {
+	    returned_count > ORANGEFS_MAX_XATTR_LISTLEN) {
 		gossip_err("%s: impossible value for returned_count:%d:\n",
 		__func__,
 		returned_count);
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 14984d9..43033a3 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -704,6 +704,7 @@
 	if (psi->flags & PSTORE_FLAGS_PMSG)
 		pstore_register_pmsg();
 
+	/* Start watching for new records, if desired. */
 	if (pstore_update_ms >= 0) {
 		pstore_timer.expires = jiffies +
 			msecs_to_jiffies(pstore_update_ms);
@@ -726,6 +727,11 @@
 
 void pstore_unregister(struct pstore_info *psi)
 {
+	/* Stop timer and make sure all work has finished. */
+	pstore_update_ms = -1;
+	del_timer_sync(&pstore_timer);
+	flush_work(&pstore_work);
+
 	if (psi->flags & PSTORE_FLAGS_PMSG)
 		pstore_unregister_pmsg();
 	if (psi->flags & PSTORE_FLAGS_FTRACE)
@@ -825,7 +831,9 @@
 		schedule_work(&pstore_work);
 	}
 
-	mod_timer(&pstore_timer, jiffies + msecs_to_jiffies(pstore_update_ms));
+	if (pstore_update_ms >= 0)
+		mod_timer(&pstore_timer,
+			  jiffies + msecs_to_jiffies(pstore_update_ms));
 }
 
 module_param(backend, charp, 0444);
diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c
index ae2b4ba..a231681 100644
--- a/fs/sdcardfs/dentry.c
+++ b/fs/sdcardfs/dentry.c
@@ -34,6 +34,8 @@
 	struct dentry *parent_lower_dentry = NULL;
 	struct dentry *lower_cur_parent_dentry = NULL;
 	struct dentry *lower_dentry = NULL;
+	struct inode *inode;
+	struct sdcardfs_inode_data *data;
 
 	if (flags & LOOKUP_RCU)
 		return -ECHILD;
@@ -103,6 +105,19 @@
 		spin_unlock(&dentry->d_lock);
 		spin_unlock(&lower_dentry->d_lock);
 	}
+	if (!err)
+		goto out;
+
+	/* If our top's inode is gone, we may be out of date */
+	inode = d_inode(dentry);
+	if (inode) {
+		data = top_data_get(SDCARDFS_I(inode));
+		if (data->abandoned) {
+			d_drop(dentry);
+			err = 0;
+		}
+		data_put(data);
+	}
 
 out:
 	dput(parent_dentry);
diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c
index 5a0ef38..1239d1c 100644
--- a/fs/sdcardfs/derived_perm.c
+++ b/fs/sdcardfs/derived_perm.c
@@ -26,28 +26,28 @@
 	struct sdcardfs_inode_info *pi = SDCARDFS_I(parent);
 	struct sdcardfs_inode_info *ci = SDCARDFS_I(child);
 
-	ci->perm = PERM_INHERIT;
-	ci->userid = pi->userid;
-	ci->d_uid = pi->d_uid;
-	ci->under_android = pi->under_android;
-	ci->under_cache = pi->under_cache;
-	ci->under_obb = pi->under_obb;
-	set_top(ci, pi->top);
+	ci->data->perm = PERM_INHERIT;
+	ci->data->userid = pi->data->userid;
+	ci->data->d_uid = pi->data->d_uid;
+	ci->data->under_android = pi->data->under_android;
+	ci->data->under_cache = pi->data->under_cache;
+	ci->data->under_obb = pi->data->under_obb;
+	set_top(ci, pi->top_data);
 }
 
 /* helper function for derived state */
 void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid,
-						uid_t uid, bool under_android,
-						struct inode *top)
+					uid_t uid, bool under_android,
+					struct sdcardfs_inode_data *top)
 {
 	struct sdcardfs_inode_info *info = SDCARDFS_I(inode);
 
-	info->perm = perm;
-	info->userid = userid;
-	info->d_uid = uid;
-	info->under_android = under_android;
-	info->under_cache = false;
-	info->under_obb = false;
+	info->data->perm = perm;
+	info->data->userid = userid;
+	info->data->d_uid = uid;
+	info->data->under_android = under_android;
+	info->data->under_cache = false;
+	info->data->under_obb = false;
 	set_top(info, top);
 }
 
@@ -58,7 +58,8 @@
 				const struct qstr *name)
 {
 	struct sdcardfs_inode_info *info = SDCARDFS_I(d_inode(dentry));
-	struct sdcardfs_inode_info *parent_info = SDCARDFS_I(d_inode(parent));
+	struct sdcardfs_inode_data *parent_data =
+			SDCARDFS_I(d_inode(parent))->data;
 	appid_t appid;
 	unsigned long user_num;
 	int err;
@@ -82,60 +83,61 @@
 	if (!S_ISDIR(d_inode(dentry)->i_mode))
 		return;
 	/* Derive custom permissions based on parent and current node */
-	switch (parent_info->perm) {
+	switch (parent_data->perm) {
 	case PERM_INHERIT:
 	case PERM_ANDROID_PACKAGE_CACHE:
 		/* Already inherited above */
 		break;
 	case PERM_PRE_ROOT:
 		/* Legacy internal layout places users at top level */
-		info->perm = PERM_ROOT;
+		info->data->perm = PERM_ROOT;
 		err = kstrtoul(name->name, 10, &user_num);
 		if (err)
-			info->userid = 0;
+			info->data->userid = 0;
 		else
-			info->userid = user_num;
-		set_top(info, &info->vfs_inode);
+			info->data->userid = user_num;
+		set_top(info, info->data);
 		break;
 	case PERM_ROOT:
 		/* Assume masked off by default. */
 		if (qstr_case_eq(name, &q_Android)) {
 			/* App-specific directories inside; let anyone traverse */
-			info->perm = PERM_ANDROID;
-			info->under_android = true;
-			set_top(info, &info->vfs_inode);
+			info->data->perm = PERM_ANDROID;
+			info->data->under_android = true;
+			set_top(info, info->data);
 		}
 		break;
 	case PERM_ANDROID:
 		if (qstr_case_eq(name, &q_data)) {
 			/* App-specific directories inside; let anyone traverse */
-			info->perm = PERM_ANDROID_DATA;
-			set_top(info, &info->vfs_inode);
+			info->data->perm = PERM_ANDROID_DATA;
+			set_top(info, info->data);
 		} else if (qstr_case_eq(name, &q_obb)) {
 			/* App-specific directories inside; let anyone traverse */
-			info->perm = PERM_ANDROID_OBB;
-			info->under_obb = true;
-			set_top(info, &info->vfs_inode);
+			info->data->perm = PERM_ANDROID_OBB;
+			info->data->under_obb = true;
+			set_top(info, info->data);
 			/* Single OBB directory is always shared */
 		} else if (qstr_case_eq(name, &q_media)) {
 			/* App-specific directories inside; let anyone traverse */
-			info->perm = PERM_ANDROID_MEDIA;
-			set_top(info, &info->vfs_inode);
+			info->data->perm = PERM_ANDROID_MEDIA;
+			set_top(info, info->data);
 		}
 		break;
 	case PERM_ANDROID_OBB:
 	case PERM_ANDROID_DATA:
 	case PERM_ANDROID_MEDIA:
-		info->perm = PERM_ANDROID_PACKAGE;
+		info->data->perm = PERM_ANDROID_PACKAGE;
 		appid = get_appid(name->name);
-		if (appid != 0 && !is_excluded(name->name, parent_info->userid))
-			info->d_uid = multiuser_get_uid(parent_info->userid, appid);
-		set_top(info, &info->vfs_inode);
+		if (appid != 0 && !is_excluded(name->name, parent_data->userid))
+			info->data->d_uid =
+				multiuser_get_uid(parent_data->userid, appid);
+		set_top(info, info->data);
 		break;
 	case PERM_ANDROID_PACKAGE:
 		if (qstr_case_eq(name, &q_cache)) {
-			info->perm = PERM_ANDROID_PACKAGE_CACHE;
-			info->under_cache = true;
+			info->data->perm = PERM_ANDROID_PACKAGE_CACHE;
+			info->data->under_cache = true;
 		}
 		break;
 	}
@@ -166,7 +168,8 @@
 	struct inode *delegated_inode = NULL;
 	int error;
 	struct sdcardfs_inode_info *info;
-	struct sdcardfs_inode_info *info_top;
+	struct sdcardfs_inode_data *info_d;
+	struct sdcardfs_inode_data *info_top;
 	perm_t perm;
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
 	uid_t uid = sbi->options.fs_low_uid;
@@ -174,15 +177,16 @@
 	struct iattr newattrs;
 
 	info = SDCARDFS_I(d_inode(dentry));
-	perm = info->perm;
-	if (info->under_obb) {
+	info_d = info->data;
+	perm = info_d->perm;
+	if (info_d->under_obb) {
 		perm = PERM_ANDROID_OBB;
-	} else if (info->under_cache) {
+	} else if (info_d->under_cache) {
 		perm = PERM_ANDROID_PACKAGE_CACHE;
 	} else if (perm == PERM_INHERIT) {
-		info_top = SDCARDFS_I(grab_top(info));
+		info_top = top_data_get(info);
 		perm = info_top->perm;
-		release_top(info);
+		data_put(info_top);
 	}
 
 	switch (perm) {
@@ -192,7 +196,7 @@
 	case PERM_ANDROID_MEDIA:
 	case PERM_ANDROID_PACKAGE:
 	case PERM_ANDROID_PACKAGE_CACHE:
-		uid = multiuser_get_uid(info->userid, uid);
+		uid = multiuser_get_uid(info_d->userid, uid);
 		break;
 	case PERM_ANDROID_OBB:
 		uid = AID_MEDIA_OBB;
@@ -207,24 +211,24 @@
 	case PERM_ANDROID_DATA:
 	case PERM_ANDROID_MEDIA:
 		if (S_ISDIR(d_inode(dentry)->i_mode))
-			gid = multiuser_get_uid(info->userid, AID_MEDIA_RW);
+			gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW);
 		else
-			gid = multiuser_get_uid(info->userid, get_type(name));
+			gid = multiuser_get_uid(info_d->userid, get_type(name));
 		break;
 	case PERM_ANDROID_OBB:
 		gid = AID_MEDIA_OBB;
 		break;
 	case PERM_ANDROID_PACKAGE:
-		if (uid_is_app(info->d_uid))
-			gid = multiuser_get_ext_gid(info->d_uid);
+		if (uid_is_app(info_d->d_uid))
+			gid = multiuser_get_ext_gid(info_d->d_uid);
 		else
-			gid = multiuser_get_uid(info->userid, AID_MEDIA_RW);
+			gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW);
 		break;
 	case PERM_ANDROID_PACKAGE_CACHE:
-		if (uid_is_app(info->d_uid))
-			gid = multiuser_get_ext_cache_gid(info->d_uid);
+		if (uid_is_app(info_d->d_uid))
+			gid = multiuser_get_ext_cache_gid(info_d->d_uid);
 		else
-			gid = multiuser_get_uid(info->userid, AID_MEDIA_RW);
+			gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW);
 		break;
 	case PERM_PRE_ROOT:
 	default:
@@ -257,11 +261,13 @@
 	sdcardfs_put_lower_path(dentry, &path);
 }
 
-static int descendant_may_need_fixup(struct sdcardfs_inode_info *info, struct limit_search *limit)
+static int descendant_may_need_fixup(struct sdcardfs_inode_data *data,
+		struct limit_search *limit)
 {
-	if (info->perm == PERM_ROOT)
-		return (limit->flags & BY_USERID)?info->userid == limit->userid:1;
-	if (info->perm == PERM_PRE_ROOT || info->perm == PERM_ANDROID)
+	if (data->perm == PERM_ROOT)
+		return (limit->flags & BY_USERID) ?
+				data->userid == limit->userid : 1;
+	if (data->perm == PERM_PRE_ROOT || data->perm == PERM_ANDROID)
 		return 1;
 	return 0;
 }
@@ -292,7 +298,7 @@
 	}
 	info = SDCARDFS_I(d_inode(dentry));
 
-	if (needs_fixup(info->perm)) {
+	if (needs_fixup(info->data->perm)) {
 		list_for_each_entry(child, &dentry->d_subdirs, d_child) {
 			spin_lock_nested(&child->d_lock, depth + 1);
 			if (!(limit->flags & BY_NAME) || qstr_case_eq(&child->d_name, &limit->name)) {
@@ -305,7 +311,7 @@
 			}
 			spin_unlock(&child->d_lock);
 		}
-	} else if (descendant_may_need_fixup(info, limit)) {
+	} else if (descendant_may_need_fixup(info->data, limit)) {
 		list_for_each_entry(child, &dentry->d_subdirs, d_child) {
 			__fixup_perms_recursive(child, limit, depth + 1);
 		}
@@ -349,12 +355,12 @@
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
 	struct qstr obb = QSTR_LITERAL("obb");
 
-	if (parent_info->perm == PERM_ANDROID &&
+	if (parent_info->data->perm == PERM_ANDROID &&
 			qstr_case_eq(&dentry->d_name, &obb)) {
 
 		/* /Android/obb is the base obbpath of DERIVED_UNIFIED */
 		if (!(sbi->options.multiuser == false
-				&& parent_info->userid == 0)) {
+				&& parent_info->data->userid == 0)) {
 			ret = 1;
 		}
 	}
@@ -415,11 +421,11 @@
 
 	spin_lock(&SDCARDFS_D(dentry)->lock);
 	if (sbi->options.multiuser) {
-		if (parent_info->perm == PERM_PRE_ROOT &&
+		if (parent_info->data->perm == PERM_PRE_ROOT &&
 				qstr_case_eq(&dentry->d_name, &q_obb)) {
 			ret = 1;
 		}
-	} else  if (parent_info->perm == PERM_ANDROID &&
+	} else  if (parent_info->data->perm == PERM_ANDROID &&
 			qstr_case_eq(&dentry->d_name, &q_obb)) {
 		ret = 1;
 	}
diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c
index 4d558b8..d48da41 100644
--- a/fs/sdcardfs/inode.c
+++ b/fs/sdcardfs/inode.c
@@ -23,7 +23,8 @@
 #include <linux/ratelimit.h>
 
 /* Do not directly use this function. Use OVERRIDE_CRED() instead. */
-const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, struct sdcardfs_inode_info *info)
+const struct cred *override_fsids(struct sdcardfs_sb_info *sbi,
+		struct sdcardfs_inode_data *data)
 {
 	struct cred *cred;
 	const struct cred *old_cred;
@@ -33,10 +34,10 @@
 	if (!cred)
 		return NULL;
 
-	if (info->under_obb)
+	if (data->under_obb)
 		uid = AID_MEDIA_OBB;
 	else
-		uid = multiuser_get_uid(info->userid, sbi->options.fs_low_uid);
+		uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid);
 	cred->fsuid = make_kuid(&init_user_ns, uid);
 	cred->fsgid = make_kgid(&init_user_ns, sbi->options.fs_low_gid);
 
@@ -96,7 +97,8 @@
 	if (err)
 		goto out;
 
-	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, SDCARDFS_I(dir)->userid);
+	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path,
+			SDCARDFS_I(dir)->data->userid);
 	if (err)
 		goto out;
 	fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
@@ -267,7 +269,7 @@
 	struct path lower_path;
 	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
 	const struct cred *saved_cred = NULL;
-	struct sdcardfs_inode_info *pi = SDCARDFS_I(dir);
+	struct sdcardfs_inode_data *pd = SDCARDFS_I(dir)->data;
 	int touch_err = 0;
 	struct fs_struct *saved_fs;
 	struct fs_struct *copied_fs;
@@ -336,7 +338,7 @@
 			make_nomedia_in_obb = 1;
 	}
 
-	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pi->userid);
+	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pd->userid);
 	if (err) {
 		unlock_dir(lower_parent_dentry);
 		goto out;
@@ -349,12 +351,13 @@
 	fixup_lower_ownership(dentry, dentry->d_name.name);
 	unlock_dir(lower_parent_dentry);
 	if ((!sbi->options.multiuser) && (qstr_case_eq(&dentry->d_name, &q_obb))
-		&& (pi->perm == PERM_ANDROID) && (pi->userid == 0))
+		&& (pd->perm == PERM_ANDROID) && (pd->userid == 0))
 		make_nomedia_in_obb = 1;
 
 	/* When creating /Android/data and /Android/obb, mark them as .nomedia */
 	if (make_nomedia_in_obb ||
-		((pi->perm == PERM_ANDROID) && (qstr_case_eq(&dentry->d_name, &q_data)))) {
+		((pd->perm == PERM_ANDROID)
+				&& (qstr_case_eq(&dentry->d_name, &q_data)))) {
 		REVERT_CRED(saved_cred);
 		OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(d_inode(dentry)));
 		set_fs_pwd(current->fs, &lower_path);
@@ -620,7 +623,7 @@
 {
 	int err;
 	struct inode tmp;
-	struct inode *top = grab_top(SDCARDFS_I(inode));
+	struct sdcardfs_inode_data *top = top_data_get(SDCARDFS_I(inode));
 
 	if (!top)
 		return -EINVAL;
@@ -637,10 +640,11 @@
 	 * locks must be dealt with to avoid undefined behavior.
 	 */
 	copy_attrs(&tmp, inode);
-	tmp.i_uid = make_kuid(&init_user_ns, SDCARDFS_I(top)->d_uid);
-	tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, SDCARDFS_I(top)));
-	tmp.i_mode = (inode->i_mode & S_IFMT) | get_mode(mnt, SDCARDFS_I(top));
-	release_top(SDCARDFS_I(inode));
+	tmp.i_uid = make_kuid(&init_user_ns, top->d_uid);
+	tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, top));
+	tmp.i_mode = (inode->i_mode & S_IFMT)
+			| get_mode(mnt, SDCARDFS_I(inode), top);
+	data_put(top);
 	tmp.i_sb = inode->i_sb;
 	if (IS_POSIXACL(inode))
 		pr_warn("%s: This may be undefined behavior...\n", __func__);
@@ -692,11 +696,12 @@
 	struct dentry *parent;
 	struct inode tmp;
 	struct dentry tmp_d;
-	struct inode *top;
+	struct sdcardfs_inode_data *top;
+
 	const struct cred *saved_cred = NULL;
 
 	inode = d_inode(dentry);
-	top = grab_top(SDCARDFS_I(inode));
+	top = top_data_get(SDCARDFS_I(inode));
 
 	if (!top)
 		return -EINVAL;
@@ -714,11 +719,12 @@
 	 *
 	 */
 	copy_attrs(&tmp, inode);
-	tmp.i_uid = make_kuid(&init_user_ns, SDCARDFS_I(top)->d_uid);
-	tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, SDCARDFS_I(top)));
-	tmp.i_mode = (inode->i_mode & S_IFMT) | get_mode(mnt, SDCARDFS_I(top));
+	tmp.i_uid = make_kuid(&init_user_ns, top->d_uid);
+	tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, top));
+	tmp.i_mode = (inode->i_mode & S_IFMT)
+			| get_mode(mnt, SDCARDFS_I(inode), top);
 	tmp.i_size = i_size_read(inode);
-	release_top(SDCARDFS_I(inode));
+	data_put(top);
 	tmp.i_sb = inode->i_sb;
 	tmp_d.d_inode = &tmp;
 
@@ -821,17 +827,17 @@
 				struct inode *inode, struct kstat *stat)
 {
 	struct sdcardfs_inode_info *info = SDCARDFS_I(inode);
-	struct inode *top = grab_top(info);
+	struct sdcardfs_inode_data *top = top_data_get(info);
 
 	if (!top)
 		return -EINVAL;
 
 	stat->dev = inode->i_sb->s_dev;
 	stat->ino = inode->i_ino;
-	stat->mode = (inode->i_mode  & S_IFMT) | get_mode(mnt, SDCARDFS_I(top));
+	stat->mode = (inode->i_mode  & S_IFMT) | get_mode(mnt, info, top);
 	stat->nlink = inode->i_nlink;
-	stat->uid = make_kuid(&init_user_ns, SDCARDFS_I(top)->d_uid);
-	stat->gid = make_kgid(&init_user_ns, get_gid(mnt, SDCARDFS_I(top)));
+	stat->uid = make_kuid(&init_user_ns, top->d_uid);
+	stat->gid = make_kgid(&init_user_ns, get_gid(mnt, top));
 	stat->rdev = inode->i_rdev;
 	stat->size = i_size_read(inode);
 	stat->atime = inode->i_atime;
@@ -839,7 +845,7 @@
 	stat->ctime = inode->i_ctime;
 	stat->blksize = (1 << inode->i_blkbits);
 	stat->blocks = inode->i_blocks;
-	release_top(info);
+	data_put(top);
 	return 0;
 }
 
diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c
index 706329d..17761c5 100644
--- a/fs/sdcardfs/lookup.c
+++ b/fs/sdcardfs/lookup.c
@@ -71,7 +71,7 @@
 static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/)
 {
 	struct inode *current_lower_inode = sdcardfs_lower_inode(inode);
-	userid_t current_userid = SDCARDFS_I(inode)->userid;
+	userid_t current_userid = SDCARDFS_I(inode)->data->userid;
 
 	if (current_lower_inode == ((struct inode_data *)candidate_data)->lower_inode &&
 			current_userid == ((struct inode_data *)candidate_data)->id)
@@ -438,7 +438,8 @@
 		goto out;
 	}
 
-	ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path, SDCARDFS_I(dir)->userid);
+	ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path,
+				SDCARDFS_I(dir)->data->userid);
 	if (IS_ERR(ret))
 		goto out;
 	if (ret)
diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c
index 953d215..3c5b51d 100644
--- a/fs/sdcardfs/main.c
+++ b/fs/sdcardfs/main.c
@@ -327,13 +327,13 @@
 	mutex_lock(&sdcardfs_super_list_lock);
 	if (sb_info->options.multiuser) {
 		setup_derived_state(d_inode(sb->s_root), PERM_PRE_ROOT,
-					sb_info->options.fs_user_id, AID_ROOT,
-					false, d_inode(sb->s_root));
+				sb_info->options.fs_user_id, AID_ROOT,
+				false, SDCARDFS_I(d_inode(sb->s_root))->data);
 		snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name);
 	} else {
 		setup_derived_state(d_inode(sb->s_root), PERM_ROOT,
-					sb_info->options.fs_user_id, AID_ROOT,
-					false, d_inode(sb->s_root));
+				sb_info->options.fs_user_id, AID_ROOT,
+				false, SDCARDFS_I(d_inode(sb->s_root))->data);
 		snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name);
 	}
 	fixup_tmp_permissions(d_inode(sb->s_root));
diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c
index 5ea6469..00a0f65 100644
--- a/fs/sdcardfs/packagelist.c
+++ b/fs/sdcardfs/packagelist.c
@@ -156,7 +156,7 @@
 	struct qstr q_android_secure = QSTR_LITERAL("android_secure");
 
 	/* Always block security-sensitive files at root */
-	if (parent_node && SDCARDFS_I(parent_node)->perm == PERM_ROOT) {
+	if (parent_node && SDCARDFS_I(parent_node)->data->perm == PERM_ROOT) {
 		if (qstr_case_eq(name, &q_autorun)
 			|| qstr_case_eq(name, &q__android_secure)
 			|| qstr_case_eq(name, &q_android_secure)) {
diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h
index 380982b..3687b22 100644
--- a/fs/sdcardfs/sdcardfs.h
+++ b/fs/sdcardfs/sdcardfs.h
@@ -30,6 +30,7 @@
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/aio.h>
+#include <linux/kref.h>
 #include <linux/mm.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
@@ -81,7 +82,8 @@
  */
 #define fixup_tmp_permissions(x)	\
 	do {						\
-		(x)->i_uid = make_kuid(&init_user_ns, SDCARDFS_I(x)->d_uid);	\
+		(x)->i_uid = make_kuid(&init_user_ns,	\
+				SDCARDFS_I(x)->data->d_uid);	\
 		(x)->i_gid = make_kgid(&init_user_ns, AID_SDCARD_RW);	\
 		(x)->i_mode = ((x)->i_mode & S_IFMT) | 0775;\
 	} while (0)
@@ -97,14 +99,14 @@
  */
 #define OVERRIDE_CRED(sdcardfs_sbi, saved_cred, info)		\
 	do {	\
-		saved_cred = override_fsids(sdcardfs_sbi, info);	\
+		saved_cred = override_fsids(sdcardfs_sbi, info->data);	\
 		if (!saved_cred)	\
 			return -ENOMEM;	\
 	} while (0)
 
 #define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred, info)	\
 	do {	\
-		saved_cred = override_fsids(sdcardfs_sbi, info);	\
+		saved_cred = override_fsids(sdcardfs_sbi, info->data);	\
 		if (!saved_cred)	\
 			return ERR_PTR(-ENOMEM);	\
 	} while (0)
@@ -142,9 +144,11 @@
 struct sdcardfs_sb_info;
 struct sdcardfs_mount_options;
 struct sdcardfs_inode_info;
+struct sdcardfs_inode_data;
 
 /* Do not directly use this function. Use OVERRIDE_CRED() instead. */
-const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, struct sdcardfs_inode_info *info);
+const struct cred *override_fsids(struct sdcardfs_sb_info *sbi,
+			struct sdcardfs_inode_data *data);
 /* Do not directly use this function, use REVERT_CRED() instead. */
 void revert_fsids(const struct cred *old_cred);
 
@@ -178,18 +182,26 @@
 	const struct vm_operations_struct *lower_vm_ops;
 };
 
-/* sdcardfs inode data in memory */
-struct sdcardfs_inode_info {
-	struct inode *lower_inode;
-	/* state derived based on current position in hierachy */
+struct sdcardfs_inode_data {
+	struct kref refcount;
+	bool abandoned;
+
 	perm_t perm;
 	userid_t userid;
 	uid_t d_uid;
 	bool under_android;
 	bool under_cache;
 	bool under_obb;
+};
+
+/* sdcardfs inode data in memory */
+struct sdcardfs_inode_info {
+	struct inode *lower_inode;
+	/* state derived based on current position in hierarchy */
+	struct sdcardfs_inode_data *data;
+
 	/* top folder for ownership */
-	struct inode *top;
+	struct sdcardfs_inode_data *top_data;
 
 	struct inode vfs_inode;
 };
@@ -351,39 +363,56 @@
 
 static inline bool sbinfo_has_sdcard_magic(struct sdcardfs_sb_info *sbinfo)
 {
-	return sbinfo && sbinfo->sb && sbinfo->sb->s_magic == SDCARDFS_SUPER_MAGIC;
+	return sbinfo && sbinfo->sb
+			&& sbinfo->sb->s_magic == SDCARDFS_SUPER_MAGIC;
 }
 
-/* grab a refererence if we aren't linking to ourself */
-static inline void set_top(struct sdcardfs_inode_info *info, struct inode *top)
+static inline struct sdcardfs_inode_data *data_get(
+		struct sdcardfs_inode_data *data)
 {
-	struct inode *old_top = NULL;
-
-	BUG_ON(IS_ERR_OR_NULL(top));
-	if (info->top && info->top != &info->vfs_inode)
-		old_top = info->top;
-	if (top != &info->vfs_inode)
-		igrab(top);
-	info->top = top;
-	iput(old_top);
+	if (data)
+		kref_get(&data->refcount);
+	return data;
 }
 
-static inline struct inode *grab_top(struct sdcardfs_inode_info *info)
+static inline struct sdcardfs_inode_data *top_data_get(
+		struct sdcardfs_inode_info *info)
 {
-	struct inode *top = info->top;
+	return data_get(info->top_data);
+}
+
+extern void data_release(struct kref *ref);
+
+static inline void data_put(struct sdcardfs_inode_data *data)
+{
+	kref_put(&data->refcount, data_release);
+}
+
+static inline void release_own_data(struct sdcardfs_inode_info *info)
+{
+	/*
+	 * This happens exactly once per inode. At this point, the inode that
+	 * originally held this data is about to be freed, and all references
+	 * to it are held as a top value, and will likely be released soon.
+	 */
+	info->data->abandoned = true;
+	data_put(info->data);
+}
+
+static inline void set_top(struct sdcardfs_inode_info *info,
+			struct sdcardfs_inode_data *top)
+{
+	struct sdcardfs_inode_data *old_top = info->top_data;
 
 	if (top)
-		return igrab(top);
-	else
-		return NULL;
+		data_get(top);
+	info->top_data = top;
+	if (old_top)
+		data_put(old_top);
 }
 
-static inline void release_top(struct sdcardfs_inode_info *info)
-{
-	iput(info->top);
-}
-
-static inline int get_gid(struct vfsmount *mnt, struct sdcardfs_inode_info *info)
+static inline int get_gid(struct vfsmount *mnt,
+		struct sdcardfs_inode_data *data)
 {
 	struct sdcardfs_vfsmount_options *opts = mnt->data;
 
@@ -396,10 +425,12 @@
 		 */
 		return AID_SDCARD_RW;
 	else
-		return multiuser_get_uid(info->userid, opts->gid);
+		return multiuser_get_uid(data->userid, opts->gid);
 }
 
-static inline int get_mode(struct vfsmount *mnt, struct sdcardfs_inode_info *info)
+static inline int get_mode(struct vfsmount *mnt,
+		struct sdcardfs_inode_info *info,
+		struct sdcardfs_inode_data *data)
 {
 	int owner_mode;
 	int filtered_mode;
@@ -407,12 +438,12 @@
 	int visible_mode = 0775 & ~opts->mask;
 
 
-	if (info->perm == PERM_PRE_ROOT) {
+	if (data->perm == PERM_PRE_ROOT) {
 		/* Top of multi-user view should always be visible to ensure
 		* secondary users can traverse inside.
 		*/
 		visible_mode = 0711;
-	} else if (info->under_android) {
+	} else if (data->under_android) {
 		/* Block "other" access to Android directories, since only apps
 		* belonging to a specific user should be in there; we still
 		* leave +x open for the default view.
@@ -481,8 +512,9 @@
 	userid_t userid;
 };
 
-extern void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid,
-			uid_t uid, bool under_android, struct inode *top);
+extern void setup_derived_state(struct inode *inode, perm_t perm,
+		userid_t userid, uid_t uid, bool under_android,
+		struct sdcardfs_inode_data *top);
 extern void get_derived_permission(struct dentry *parent, struct dentry *dentry);
 extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const struct qstr *name);
 extern void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit);
@@ -601,7 +633,7 @@
 {
 	dest->i_mode = (src->i_mode  & S_IFMT) | S_IRWXU | S_IRWXG |
 			S_IROTH | S_IXOTH; /* 0775 */
-	dest->i_uid = make_kuid(&init_user_ns, SDCARDFS_I(dest)->d_uid);
+	dest->i_uid = make_kuid(&init_user_ns, SDCARDFS_I(dest)->data->d_uid);
 	dest->i_gid = make_kgid(&init_user_ns, AID_SDCARD_RW);
 	dest->i_rdev = src->i_rdev;
 	dest->i_atime = src->i_atime;
diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c
index 8a9c9c7..7f4539b 100644
--- a/fs/sdcardfs/super.c
+++ b/fs/sdcardfs/super.c
@@ -26,6 +26,23 @@
  */
 static struct kmem_cache *sdcardfs_inode_cachep;
 
+/*
+ * To support the top references, we must track some data separately.
+ * An sdcardfs_inode_info always has a reference to its data, and once set up,
+ * also has a reference to its top. The top may be itself, in which case it
+ * holds two references to its data. When top is changed, it takes a ref to the
+ * new data and then drops the ref to the old data.
+ */
+static struct kmem_cache *sdcardfs_inode_data_cachep;
+
+void data_release(struct kref *ref)
+{
+	struct sdcardfs_inode_data *data =
+		container_of(ref, struct sdcardfs_inode_data, refcount);
+
+	kmem_cache_free(sdcardfs_inode_data_cachep, data);
+}
+
 /* final actions when unmounting a file system */
 static void sdcardfs_put_super(struct super_block *sb)
 {
@@ -166,6 +183,7 @@
 	struct inode *lower_inode;
 
 	truncate_inode_pages(&inode->i_data, 0);
+	set_top(SDCARDFS_I(inode), NULL);
 	clear_inode(inode);
 	/*
 	 * Decrement a reference to a lower_inode, which was incremented
@@ -173,13 +191,13 @@
 	 */
 	lower_inode = sdcardfs_lower_inode(inode);
 	sdcardfs_set_lower_inode(inode, NULL);
-	set_top(SDCARDFS_I(inode), inode);
 	iput(lower_inode);
 }
 
 static struct inode *sdcardfs_alloc_inode(struct super_block *sb)
 {
 	struct sdcardfs_inode_info *i;
+	struct sdcardfs_inode_data *d;
 
 	i = kmem_cache_alloc(sdcardfs_inode_cachep, GFP_KERNEL);
 	if (!i)
@@ -188,6 +206,16 @@
 	/* memset everything up to the inode to 0 */
 	memset(i, 0, offsetof(struct sdcardfs_inode_info, vfs_inode));
 
+	d = kmem_cache_alloc(sdcardfs_inode_data_cachep,
+					GFP_KERNEL | __GFP_ZERO);
+	if (!d) {
+		kmem_cache_free(sdcardfs_inode_cachep, i);
+		return NULL;
+	}
+
+	i->data = d;
+	kref_init(&d->refcount);
+
 	i->vfs_inode.i_version = 1;
 	return &i->vfs_inode;
 }
@@ -196,6 +224,7 @@
 {
 	struct inode *inode = container_of(head, struct inode, i_rcu);
 
+	release_own_data(SDCARDFS_I(inode));
 	kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode));
 }
 
@@ -214,20 +243,30 @@
 
 int sdcardfs_init_inode_cache(void)
 {
-	int err = 0;
-
 	sdcardfs_inode_cachep =
 		kmem_cache_create("sdcardfs_inode_cache",
 				  sizeof(struct sdcardfs_inode_info), 0,
 				  SLAB_RECLAIM_ACCOUNT, init_once);
+
 	if (!sdcardfs_inode_cachep)
-		err = -ENOMEM;
-	return err;
+		return -ENOMEM;
+
+	sdcardfs_inode_data_cachep =
+		kmem_cache_create("sdcardfs_inode_data_cache",
+				  sizeof(struct sdcardfs_inode_data), 0,
+				  SLAB_RECLAIM_ACCOUNT, NULL);
+	if (!sdcardfs_inode_data_cachep) {
+		kmem_cache_destroy(sdcardfs_inode_cachep);
+		return -ENOMEM;
+	}
+
+	return 0;
 }
 
 /* sdcardfs inode cache destructor */
 void sdcardfs_destroy_inode_cache(void)
 {
+	kmem_cache_destroy(sdcardfs_inode_data_cachep);
 	kmem_cache_destroy(sdcardfs_inode_cachep);
 }
 
diff --git a/fs/xattr.c b/fs/xattr.c
index 2d13b4e..ed8c374 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -530,7 +530,7 @@
 			size = XATTR_SIZE_MAX;
 		kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
 		if (!kvalue) {
-			kvalue = vmalloc(size);
+			kvalue = vzalloc(size);
 			if (!kvalue)
 				return -ENOMEM;
 		}
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm845.h b/include/dt-bindings/clock/qcom,gcc-sdm845.h
index a95d494..115b62f 100644
--- a/include/dt-bindings/clock/qcom,gcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,gcc-sdm845.h
@@ -185,19 +185,17 @@
 #define GPLL0							167
 #define GPLL0_OUT_EVEN						168
 #define GPLL0_OUT_MAIN						169
-#define GPLL1							170
-#define GPLL1_OUT_MAIN						171
-#define GCC_UFS_CARD_AXI_HW_CTL_CLK				172
-#define GCC_UFS_PHY_AXI_HW_CTL_CLK				173
-#define GCC_UFS_CARD_UNIPRO_CORE_HW_CTL_CLK			174
-#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK			175
-#define GCC_UFS_CARD_ICE_CORE_HW_CTL_CLK			176
-#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK				177
-#define GCC_AGGRE_UFS_CARD_AXI_HW_CTL_CLK			178
-#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK			179
-#define GCC_UFS_CARD_PHY_AUX_HW_CTL_CLK				180
-#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK				181
-#define GCC_GPU_IREF_CLK					182
+#define GCC_UFS_CARD_AXI_HW_CTL_CLK				170
+#define GCC_UFS_PHY_AXI_HW_CTL_CLK				171
+#define GCC_UFS_CARD_UNIPRO_CORE_HW_CTL_CLK			172
+#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK			173
+#define GCC_UFS_CARD_ICE_CORE_HW_CTL_CLK			174
+#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK				175
+#define GCC_AGGRE_UFS_CARD_AXI_HW_CTL_CLK			176
+#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK			177
+#define GCC_UFS_CARD_PHY_AUX_HW_CTL_CLK				178
+#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK				179
+#define GCC_GPU_IREF_CLK					180
 
 /* GCC reset clocks */
 #define GCC_GPU_BCR						0
diff --git a/include/dt-bindings/clock/qcom,gpucc-sdm845.h b/include/dt-bindings/clock/qcom,gpucc-sdm845.h
index c43a9f8..323beaf 100644
--- a/include/dt-bindings/clock/qcom,gpucc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,gpucc-sdm845.h
@@ -40,13 +40,10 @@
 #define GPU_CC_PLL1_OUT_ODD					22
 #define GPU_CC_PLL1_OUT_TEST					23
 #define GPU_CC_PLL_TEST_CLK					24
-#define GPU_CC_RBCPR_AHB_CLK					25
-#define GPU_CC_RBCPR_CLK					26
-#define GPU_CC_RBCPR_CLK_SRC					27
-#define GPU_CC_SLEEP_CLK					28
-#define GPU_CC_GMU_CLK_SRC					29
-#define GPU_CC_CX_GFX3D_CLK					30
-#define GPU_CC_CX_GFX3D_SLV_CLK					31
+#define GPU_CC_SLEEP_CLK					25
+#define GPU_CC_GMU_CLK_SRC					26
+#define GPU_CC_CX_GFX3D_CLK					27
+#define GPU_CC_CX_GFX3D_SLV_CLK					28
 
 /* GPUCC reset clock registers */
 #define GPUCC_GPU_CC_ACD_BCR					0
@@ -54,9 +51,8 @@
 #define GPUCC_GPU_CC_GFX3D_AON_BCR				2
 #define GPUCC_GPU_CC_GMU_BCR					3
 #define GPUCC_GPU_CC_GX_BCR					4
-#define GPUCC_GPU_CC_RBCPR_BCR					5
-#define GPUCC_GPU_CC_SPDM_BCR					6
-#define GPUCC_GPU_CC_XO_BCR					7
+#define GPUCC_GPU_CC_SPDM_BCR					5
+#define GPUCC_GPU_CC_XO_BCR					6
 
 /* GFX3D clock registers */
 #define GPU_CC_PLL0						0
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 32c5890..7f7e9a7 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -61,6 +61,10 @@
 		enum dma_data_direction dir, unsigned long attrs);
 void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
 		enum dma_data_direction dir, unsigned long attrs);
+dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
+		size_t size, enum dma_data_direction dir, unsigned long attrs);
+void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir, unsigned long attrs);
 int iommu_dma_supported(struct device *dev, u64 mask);
 int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
 
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 77912a1..72f9211 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -247,6 +247,7 @@
 	POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
 	POWER_SUPPLY_PROP_CTM_CURRENT_MAX,
 	POWER_SUPPLY_PROP_HW_CURRENT_MAX,
+	POWER_SUPPLY_PROP_REAL_TYPE,
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
 	/* Properties of type `const char *' */
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index 657ac07..5947107 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -308,6 +308,22 @@
 #define SE_DMA_RX_MAX_BURST	(0xD5C)
 #define SE_DMA_RX_FLUSH		(0xD60)
 
+/* SE_DMA_TX_IRQ_STAT Register fields */
+#define TX_DMA_DONE		(BIT(0))
+#define TX_EOT			(BIT(1))
+#define TX_SBE			(BIT(2))
+#define TX_RESET_DONE		(BIT(3))
+
+/* SE_DMA_RX_IRQ_STAT Register fields */
+#define RX_DMA_DONE		(BIT(0))
+#define RX_EOT			(BIT(1))
+#define RX_SBE			(BIT(2))
+#define RX_RESET_DONE		(BIT(3))
+#define RX_FLUSH_DONE		(BIT(4))
+#define RX_GENI_GP_IRQ		(GENMASK(10, 5))
+#define RX_GENI_CANCEL_IRQ	(BIT(11))
+#define RX_GENI_GP_IRQ_EXT	(GENMASK(13, 12))
+
 #define DEFAULT_BUS_WIDTH	(4)
 #define DEFAULT_SE_CLK		(19200000)
 
diff --git a/include/trace/events/pdc.h b/include/trace/events/pdc.h
new file mode 100644
index 0000000..400e959
--- /dev/null
+++ b/include/trace/events/pdc.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM pdc
+
+#if !defined(_TRACE_PDC_) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_PDC_H_
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(irq_pin_config,
+
+	TP_PROTO(char *func, u32 pin, u32 hwirq, u32 type, u32 enable),
+
+	TP_ARGS(func, pin, hwirq, type, enable),
+
+	TP_STRUCT__entry(
+		__field(char *, func)
+		__field(u32, pin)
+		__field(u32, hwirq)
+		__field(u32, type)
+		__field(u32, enable)
+	),
+
+	TP_fast_assign(
+		__entry->pin = pin;
+		__entry->func = func;
+		__entry->hwirq = hwirq;
+		__entry->type = type;
+		__entry->enable = enable;
+	),
+
+	TP_printk("%s hwirq:%u pin:%u type:%u enable:%u",
+		__entry->func, __entry->pin, __entry->hwirq, __entry->type,
+		__entry->enable)
+);
+
+#endif
+#define TRACE_INCLUDE_FILE pdc
+#include <trace/define_trace.h>
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index eb18389..ab38f9e 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -321,6 +321,8 @@
 /* sde custom events */
 #define DRM_EVENT_HISTOGRAM 0x80000000
 #define DRM_EVENT_AD_BACKLIGHT 0x80000001
+#define DRM_EVENT_CRTC_POWER 0x80000002
+#define DRM_EVENT_SYS_BACKLIGHT 0x80000003
 
 #define DRM_IOCTL_MSM_GET_PARAM        DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param)
 #define DRM_IOCTL_MSM_GEM_NEW          DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new)
diff --git a/include/uapi/drm/msm_drm_pp.h b/include/uapi/drm/msm_drm_pp.h
index e809c03..d9155a9 100644
--- a/include/uapi/drm/msm_drm_pp.h
+++ b/include/uapi/drm/msm_drm_pp.h
@@ -96,8 +96,8 @@
  * @c2_c1: Holds c2/c1 values
  */
 struct drm_msm_3d_col {
-	__u32 c0;
 	__u32 c2_c1;
+	__u32 c0;
 };
 /**
  * struct drm_msm_3d_gamut - 3d gamut feature structure
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 7c1899e..7cf7779 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -382,6 +382,7 @@
 header-y += psci.h
 header-y += ptp_clock.h
 header-y += ptrace.h
+header-y += qbt1000.h
 header-y += qcedev.h
 header-y += qcota.h
 header-y += qnx4_fs.h
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index ea68202..57c2ca4 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -130,89 +130,123 @@
  * enum ipa_client_type - names for the various IPA "clients"
  * these are from the perspective of the clients, for e.g.
  * HSIC1_PROD means HSIC client is the producer and IPA is the
- * consumer
+ * consumer.
+ * PROD clients are always even, and CONS clients are always odd.
+ * Add new clients in the end of the list and update IPA_CLIENT_MAX
  */
 enum ipa_client_type {
-	IPA_CLIENT_PROD,
-	IPA_CLIENT_HSIC1_PROD = IPA_CLIENT_PROD,
-	IPA_CLIENT_WLAN1_PROD,
-	IPA_CLIENT_HSIC2_PROD,
-	IPA_CLIENT_USB2_PROD,
-	IPA_CLIENT_HSIC3_PROD,
-	IPA_CLIENT_USB3_PROD,
-	IPA_CLIENT_HSIC4_PROD,
-	IPA_CLIENT_USB4_PROD,
-	IPA_CLIENT_HSIC5_PROD,
-	IPA_CLIENT_USB_PROD,
-	IPA_CLIENT_A5_WLAN_AMPDU_PROD,
-	IPA_CLIENT_A2_EMBEDDED_PROD,
-	IPA_CLIENT_A2_TETHERED_PROD,
-	IPA_CLIENT_APPS_LAN_PROD,
-	IPA_CLIENT_APPS_WAN_PROD,
+	IPA_CLIENT_HSIC1_PROD			= 0,
+	IPA_CLIENT_HSIC1_CONS			= 1,
+
+	IPA_CLIENT_HSIC2_PROD			= 2,
+	IPA_CLIENT_HSIC2_CONS			= 3,
+
+	IPA_CLIENT_HSIC3_PROD			= 4,
+	IPA_CLIENT_HSIC3_CONS			= 5,
+
+	IPA_CLIENT_HSIC4_PROD			= 6,
+	IPA_CLIENT_HSIC4_CONS			= 7,
+
+	IPA_CLIENT_HSIC5_PROD			= 8,
+	IPA_CLIENT_HSIC5_CONS			= 9,
+
+	IPA_CLIENT_WLAN1_PROD			= 10,
+	IPA_CLIENT_WLAN1_CONS			= 11,
+
+	IPA_CLIENT_A5_WLAN_AMPDU_PROD		= 12,
+	IPA_CLIENT_WLAN2_CONS			= 13,
+
+	/* RESERVERD PROD			= 14, */
+	IPA_CLIENT_WLAN3_CONS			= 15,
+
+	/* RESERVERD PROD			= 16, */
+	IPA_CLIENT_WLAN4_CONS			= 17,
+
+	IPA_CLIENT_USB_PROD			= 18,
+	IPA_CLIENT_USB_CONS			= 19,
+
+	IPA_CLIENT_USB2_PROD			= 20,
+	IPA_CLIENT_USB2_CONS			= 21,
+
+	IPA_CLIENT_USB3_PROD			= 22,
+	IPA_CLIENT_USB3_CONS			= 23,
+
+	IPA_CLIENT_USB4_PROD			= 24,
+	IPA_CLIENT_USB4_CONS			= 25,
+
+	IPA_CLIENT_UC_USB_PROD			= 26,
+	IPA_CLIENT_USB_DPL_CONS			= 27,
+
+	IPA_CLIENT_A2_EMBEDDED_PROD		= 28,
+	IPA_CLIENT_A2_EMBEDDED_CONS		= 29,
+
+	IPA_CLIENT_A2_TETHERED_PROD		= 30,
+	IPA_CLIENT_A2_TETHERED_CONS		= 31,
+
+	IPA_CLIENT_APPS_LAN_PROD		= 32,
+	IPA_CLIENT_APPS_LAN_CONS		= 33,
+
+	IPA_CLIENT_APPS_WAN_PROD		= 34,
 	IPA_CLIENT_APPS_LAN_WAN_PROD = IPA_CLIENT_APPS_WAN_PROD,
-	IPA_CLIENT_APPS_CMD_PROD,
-	IPA_CLIENT_ODU_PROD,
-	IPA_CLIENT_MHI_PROD,
-	IPA_CLIENT_Q6_LAN_PROD,
-	IPA_CLIENT_Q6_WAN_PROD,
-	IPA_CLIENT_Q6_CMD_PROD,
-	IPA_CLIENT_MEMCPY_DMA_SYNC_PROD,
-	IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD,
-	IPA_CLIENT_Q6_DECOMP_PROD,
-	IPA_CLIENT_Q6_DECOMP2_PROD,
-	IPA_CLIENT_UC_USB_PROD,
-	IPA_CLIENT_ETHERNET_PROD,
+	IPA_CLIENT_APPS_WAN_CONS		= 35,
 
-	/* Below PROD client type is only for test purpose */
-	IPA_CLIENT_TEST_PROD,
-	IPA_CLIENT_TEST1_PROD,
-	IPA_CLIENT_TEST2_PROD,
-	IPA_CLIENT_TEST3_PROD,
-	IPA_CLIENT_TEST4_PROD,
+	IPA_CLIENT_APPS_CMD_PROD		= 36,
+	IPA_CLIENT_A5_LAN_WAN_CONS		= 37,
 
-	IPA_CLIENT_CONS,
-	IPA_CLIENT_HSIC1_CONS = IPA_CLIENT_CONS,
-	IPA_CLIENT_WLAN1_CONS,
-	IPA_CLIENT_HSIC2_CONS,
-	IPA_CLIENT_USB2_CONS,
-	IPA_CLIENT_WLAN2_CONS,
-	IPA_CLIENT_HSIC3_CONS,
-	IPA_CLIENT_USB3_CONS,
-	IPA_CLIENT_WLAN3_CONS,
-	IPA_CLIENT_HSIC4_CONS,
-	IPA_CLIENT_USB4_CONS,
-	IPA_CLIENT_WLAN4_CONS,
-	IPA_CLIENT_HSIC5_CONS,
-	IPA_CLIENT_USB_CONS,
-	IPA_CLIENT_USB_DPL_CONS,
-	IPA_CLIENT_A2_EMBEDDED_CONS,
-	IPA_CLIENT_A2_TETHERED_CONS,
-	IPA_CLIENT_A5_LAN_WAN_CONS,
-	IPA_CLIENT_APPS_LAN_CONS,
-	IPA_CLIENT_APPS_WAN_CONS,
-	IPA_CLIENT_ODU_EMB_CONS,
-	IPA_CLIENT_ODU_TETH_CONS,
-	IPA_CLIENT_MHI_CONS,
-	IPA_CLIENT_Q6_LAN_CONS,
-	IPA_CLIENT_Q6_WAN_CONS,
-	IPA_CLIENT_Q6_DUN_CONS,
-	IPA_CLIENT_MEMCPY_DMA_SYNC_CONS,
-	IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS,
-	IPA_CLIENT_Q6_DECOMP_CONS,
-	IPA_CLIENT_Q6_DECOMP2_CONS,
-	IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS,
-	IPA_CLIENT_ETHERNET_CONS,
+	IPA_CLIENT_ODU_PROD			= 38,
+	IPA_CLIENT_ODU_EMB_CONS			= 39,
 
-	/* Below CONS client type is only for test purpose */
-	IPA_CLIENT_TEST_CONS,
-	IPA_CLIENT_TEST1_CONS,
-	IPA_CLIENT_TEST2_CONS,
-	IPA_CLIENT_TEST3_CONS,
-	IPA_CLIENT_TEST4_CONS,
+	/* RESERVERD PROD			= 40, */
+	IPA_CLIENT_ODU_TETH_CONS		= 41,
 
-	IPA_CLIENT_MAX,
+	IPA_CLIENT_MHI_PROD			= 42,
+	IPA_CLIENT_MHI_CONS			= 43,
+
+	IPA_CLIENT_MEMCPY_DMA_SYNC_PROD		= 44,
+	IPA_CLIENT_MEMCPY_DMA_SYNC_CONS		= 45,
+
+	IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD	= 46,
+	IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS	= 47,
+
+	IPA_CLIENT_ETHERNET_PROD		= 48,
+	IPA_CLIENT_ETHERNET_CONS		= 49,
+
+	IPA_CLIENT_Q6_LAN_PROD			= 50,
+	IPA_CLIENT_Q6_LAN_CONS			= 51,
+
+	IPA_CLIENT_Q6_WAN_PROD			= 52,
+	IPA_CLIENT_Q6_WAN_CONS			= 53,
+
+	IPA_CLIENT_Q6_CMD_PROD			= 54,
+	IPA_CLIENT_Q6_DUN_CONS			= 55,
+
+	IPA_CLIENT_Q6_DECOMP_PROD		= 56,
+	IPA_CLIENT_Q6_DECOMP_CONS		= 57,
+
+	IPA_CLIENT_Q6_DECOMP2_PROD		= 58,
+	IPA_CLIENT_Q6_DECOMP2_CONS		= 59,
+
+	/* RESERVERD PROD			= 60, */
+	IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS	= 61,
+
+	IPA_CLIENT_TEST_PROD			= 62,
+	IPA_CLIENT_TEST_CONS			= 63,
+
+	IPA_CLIENT_TEST1_PROD			= 64,
+	IPA_CLIENT_TEST1_CONS			= 65,
+
+	IPA_CLIENT_TEST2_PROD			= 66,
+	IPA_CLIENT_TEST2_CONS			= 67,
+
+	IPA_CLIENT_TEST3_PROD			= 68,
+	IPA_CLIENT_TEST3_CONS			= 69,
+
+	IPA_CLIENT_TEST4_PROD			= 70,
+	IPA_CLIENT_TEST4_CONS			= 71,
 };
 
+#define IPA_CLIENT_MAX (IPA_CLIENT_TEST4_CONS + 1)
+
 #define IPA_CLIENT_IS_APPS_CONS(client) \
 	((client) == IPA_CLIENT_APPS_LAN_CONS || \
 	(client) == IPA_CLIENT_APPS_WAN_CONS)
@@ -317,8 +351,8 @@
 enum ipa_rule_type {
 	IPA_RULE_HASHABLE,
 	IPA_RULE_NON_HASHABLE,
-	IPA_RULE_TYPE_MAX
 };
+#define IPA_RULE_TYPE_MAX (IPA_RULE_NON_HASHABLE + 1)
 
 /**
  * enum ipa_flt_action - action field of filtering rule
@@ -405,35 +439,44 @@
 /**
  * enum ipa_rm_resource_name - IPA RM clients identification names
  *
- * Add new mapping to ipa_rm_prod_index() / ipa_rm_cons_index()
- * when adding new entry to this enum.
+ * PROD resources are always even, and CONS resources are always odd.
+ * Add new clients in the end of the list and update IPA_RM_RESOURCE_MAX
  */
 enum ipa_rm_resource_name {
-	IPA_RM_RESOURCE_PROD = 0,
-	IPA_RM_RESOURCE_Q6_PROD = IPA_RM_RESOURCE_PROD,
-	IPA_RM_RESOURCE_USB_PROD,
-	IPA_RM_RESOURCE_USB_DPL_DUMMY_PROD,
-	IPA_RM_RESOURCE_HSIC_PROD,
-	IPA_RM_RESOURCE_STD_ECM_PROD,
-	IPA_RM_RESOURCE_RNDIS_PROD,
-	IPA_RM_RESOURCE_WWAN_0_PROD,
-	IPA_RM_RESOURCE_WLAN_PROD,
-	IPA_RM_RESOURCE_ODU_ADAPT_PROD,
-	IPA_RM_RESOURCE_MHI_PROD,
-	IPA_RM_RESOURCE_ETHERNET_PROD,
-	IPA_RM_RESOURCE_PROD_MAX,
+	IPA_RM_RESOURCE_Q6_PROD				= 0,
+	IPA_RM_RESOURCE_Q6_CONS				= 1,
 
-	IPA_RM_RESOURCE_Q6_CONS = IPA_RM_RESOURCE_PROD_MAX,
-	IPA_RM_RESOURCE_USB_CONS,
-	IPA_RM_RESOURCE_USB_DPL_CONS,
-	IPA_RM_RESOURCE_HSIC_CONS,
-	IPA_RM_RESOURCE_WLAN_CONS,
-	IPA_RM_RESOURCE_APPS_CONS,
-	IPA_RM_RESOURCE_ODU_ADAPT_CONS,
-	IPA_RM_RESOURCE_MHI_CONS,
-	IPA_RM_RESOURCE_ETHERNET_CONS,
-	IPA_RM_RESOURCE_MAX
+	IPA_RM_RESOURCE_USB_PROD			= 2,
+	IPA_RM_RESOURCE_USB_CONS			= 3,
+
+	IPA_RM_RESOURCE_USB_DPL_DUMMY_PROD		= 4,
+	IPA_RM_RESOURCE_USB_DPL_CONS			= 5,
+
+	IPA_RM_RESOURCE_HSIC_PROD			= 6,
+	IPA_RM_RESOURCE_HSIC_CONS			= 7,
+
+	IPA_RM_RESOURCE_STD_ECM_PROD			= 8,
+	IPA_RM_RESOURCE_APPS_CONS			= 9,
+
+	IPA_RM_RESOURCE_RNDIS_PROD			= 10,
+	/* RESERVED CONS				= 11, */
+
+	IPA_RM_RESOURCE_WWAN_0_PROD			= 12,
+	/* RESERVED CONS				= 13, */
+
+	IPA_RM_RESOURCE_WLAN_PROD			= 14,
+	IPA_RM_RESOURCE_WLAN_CONS			= 15,
+
+	IPA_RM_RESOURCE_ODU_ADAPT_PROD			= 16,
+	IPA_RM_RESOURCE_ODU_ADAPT_CONS			= 17,
+
+	IPA_RM_RESOURCE_MHI_PROD			= 18,
+	IPA_RM_RESOURCE_MHI_CONS			= 19,
+
+	IPA_RM_RESOURCE_ETHERNET_PROD			= 20,
+	IPA_RM_RESOURCE_ETHERNET_CONS			= 21,
 };
+#define IPA_RM_RESOURCE_MAX (IPA_RM_RESOURCE_ETHERNET_CONS + 1)
 
 /**
  * enum ipa_hw_type - IPA hardware version type
@@ -465,8 +508,8 @@
 	IPA_HW_v3_5 = 12,
 	IPA_HW_v3_5_1 = 13,
 	IPA_HW_v4_0 = 14,
-	IPA_HW_MAX
 };
+#define IPA_HW_MAX (IPA_HW_v4_0 + 1)
 
 #define IPA_HW_v4_0 IPA_HW_v4_0
 
@@ -700,8 +743,8 @@
 	IPA_HDR_L2_NONE,
 	IPA_HDR_L2_ETHERNET_II,
 	IPA_HDR_L2_802_3,
-	IPA_HDR_L2_MAX,
 };
+#define IPA_HDR_L2_MAX (IPA_HDR_L2_802_3 + 1)
 
 /**
  * enum ipa_hdr_l2_type - Processing context type
@@ -717,8 +760,8 @@
 	IPA_HDR_PROC_ETHII_TO_802_3,
 	IPA_HDR_PROC_802_3_TO_ETHII,
 	IPA_HDR_PROC_802_3_TO_802_3,
-	IPA_HDR_PROC_MAX,
 };
+#define IPA_HDR_PROC_MAX (IPA_HDR_PROC_802_3_TO_802_3 + 1)
 
 /**
  * struct ipa_rt_rule - attributes of a routing rule
diff --git a/include/uapi/linux/qbt1000.h b/include/uapi/linux/qbt1000.h
new file mode 100644
index 0000000..a4f0dca
--- /dev/null
+++ b/include/uapi/linux/qbt1000.h
@@ -0,0 +1,99 @@
+#ifndef _UAPI_QBT1000_H_
+#define _UAPI_QBT1000_H_
+
+#define MAX_NAME_SIZE					 32
+
+/*
+ * enum qbt1000_commands -
+ *      enumeration of command options
+ * @QBT1000_LOAD_APP - cmd loads TZ app
+ * @QBT1000_UNLOAD_APP - cmd unloads TZ app
+ * @QBT1000_SEND_TZCMD - sends cmd to TZ app
+ * @QBT1000_SET_FINGER_DETECT_KEY - sets the input key to send on finger detect
+ * @QBT1000_CONFIGURE_POWER_KEY - enables/disables sending the power key on
+	finger down events
+*/
+enum qbt1000_commands {
+	QBT1000_LOAD_APP = 100,
+	QBT1000_UNLOAD_APP = 101,
+	QBT1000_SEND_TZCMD = 102,
+	QBT1000_SET_FINGER_DETECT_KEY = 103,
+	QBT1000_CONFIGURE_POWER_KEY = 104
+};
+
+/*
+ * enum qbt1000_fw_event -
+ *      enumeration of firmware events
+ * @FW_EVENT_FINGER_DOWN - finger down detected
+ * @FW_EVENT_FINGER_UP - finger up detected
+ * @FW_EVENT_INDICATION - an indication IPC from the firmware is pending
+ */
+enum qbt1000_fw_event {
+	FW_EVENT_FINGER_DOWN = 1,
+	FW_EVENT_FINGER_UP = 2,
+	FW_EVENT_CBGE_REQUIRED = 3,
+};
+
+/*
+ * struct qbt1000_app -
+ *      used to load and unload apps in TZ
+ * @app_handle - qseecom handle for clients
+ * @name - Name of secure app to load
+ * @size - Size of requested buffer of secure app
+ * @high_band_width - 1 - for high bandwidth usage
+ *                    0 - for normal bandwidth usage
+ */
+struct qbt1000_app {
+	struct qseecom_handle **app_handle;
+	char name[MAX_NAME_SIZE];
+	uint32_t size;
+	uint8_t high_band_width;
+};
+
+/*
+ * struct qbt1000_send_tz_cmd -
+ *      used to cmds to TZ App
+ * @app_handle - qseecom handle for clients
+ * @req_buf - Buffer containing request for secure app
+ * @req_buf_len - Length of request buffer
+ * @rsp_buf - Buffer containing response from secure app
+ * @rsp_buf_len - Length of response buffer
+ */
+struct qbt1000_send_tz_cmd {
+	struct qseecom_handle *app_handle;
+	uint8_t *req_buf;
+	uint32_t req_buf_len;
+	uint8_t *rsp_buf;
+	uint32_t rsp_buf_len;
+};
+
+/*
+ * struct qbt1000_erie_event -
+ *      used to receive events from Erie
+ * @buf - Buffer containing event from Erie
+ * @buf_len - Length of buffer
+ */
+struct qbt1000_erie_event {
+	uint8_t *buf;
+	uint32_t buf_len;
+};
+
+/*
+ * struct qbt1000_set_finger_detect_key -
+ *      used to configure the input key which is sent on finger down/up event
+ * @key_code - Key code to send on finger down/up. 0 disables sending key events
+ */
+struct qbt1000_set_finger_detect_key {
+	unsigned int key_code;
+};
+
+/*
+ * struct qbt1000_configure_power_key -
+ *      used to configure whether the power key is sent on finger down
+ * @enable - if non-zero, power key is sent on finger down
+ */
+struct qbt1000_configure_power_key {
+	unsigned int enable;
+};
+
+#endif /* _UAPI_QBT1000_H_ */
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index a70b90d..c61c56f 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/debug_locks.h>
 #include <linux/osq_lock.h>
+#include <linux/delay.h>
 
 /*
  * In the DEBUG case we are using the "NULL fastpath" for mutexes,
@@ -378,6 +379,17 @@
 		 * values at the cost of a few extra spins.
 		 */
 		cpu_relax_lowlatency();
+
+		/*
+		 * On arm systems, we must slow down the waiter's repeated
+		 * aquisition of spin_mlock and atomics on the lock count, or
+		 * we risk starving out a thread attempting to release the
+		 * mutex. The mutex slowpath release must take spin lock
+		 * wait_lock. This spin lock can share a monitor with the
+		 * other waiter atomics in the mutex data structure, so must
+		 * take care to rate limit the waiters.
+		 */
+		udelay(1);
 	}
 
 	osq_unlock(&lock->osq);
diff --git a/kernel/padata.c b/kernel/padata.c
index b4a3c0a..e4a8f8d 100644
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -358,7 +358,7 @@
 
 	cpumask_and(pd->cpumask.pcpu, pcpumask, cpu_online_mask);
 	if (!alloc_cpumask_var(&pd->cpumask.cbcpu, GFP_KERNEL)) {
-		free_cpumask_var(pd->cpumask.cbcpu);
+		free_cpumask_var(pd->cpumask.pcpu);
 		return -ENOMEM;
 	}
 
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index ccb2321..b6fb796 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3327,33 +3327,6 @@
 static inline void sched_freq_tick(int cpu) { }
 #endif /* CONFIG_CPU_FREQ_GOV_SCHED */
 
-#ifdef CONFIG_SCHED_WALT
-static atomic64_t walt_irq_work_lastq_ws;
-
-static inline u64 walt_window_start_of(struct rq *rq)
-{
-	return rq->window_start;
-}
-
-static inline void run_walt_irq_work(u64 window_start, struct rq *rq)
-{
-	/* No HMP since that uses sched_get_cpus_busy */
-	if (rq->window_start != window_start &&
-		atomic_cmpxchg(&walt_irq_work_lastq_ws, window_start,
-			   rq->window_start) == window_start)
-		irq_work_queue(&rq->irq_work);
-}
-#else
-static inline u64 walt_window_start_of(struct rq *rq)
-{
-	return 0;
-}
-
-static inline void run_walt_irq_work(u64 window_start, struct rq *rq)
-{
-}
-#endif
-
 /*
  * This function gets called by the timer code, with HZ frequency.
  * We call it with interrupts disabled.
@@ -3367,22 +3340,14 @@
 	bool early_notif;
 	u32 old_load;
 	struct related_thread_group *grp;
-	u64 window_start;
 
 	sched_clock_tick();
 
 	raw_spin_lock(&rq->lock);
 
-	/*
-	 * Record current window_start. If after utra() below the window
-	 * has rolled over, schedule a load-reporting irq-work
-	 */
-	window_start = walt_window_start_of(rq);
-
 	old_load = task_load(curr);
 	set_window_start(rq);
 
-
 	wallclock = sched_ktime_clock();
 	update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
 
@@ -3392,8 +3357,6 @@
 	calc_global_load_tick(rq);
 	cpufreq_update_util(rq, 0);
 
-	run_walt_irq_work(window_start, rq);
-
 	early_notif = early_detection_notify(rq, wallclock);
 
 	raw_spin_unlock(&rq->lock);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 82e6490..6ccd3a7 100755
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -12319,7 +12319,7 @@
 			return;
 
 		new_cpu = energy_aware_wake_cpu(p, cpu, 0);
-		if (new_cpu != cpu) {
+		if (capacity_orig_of(new_cpu) > capacity_orig_of(cpu)) {
 			active_balance = kick_active_balance(rq, p, new_cpu);
 			if (active_balance) {
 				mark_reserved(new_cpu);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 29b6e3d..5220511 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1816,6 +1816,7 @@
 
 			walt_load->prev_window_util = util;
 			walt_load->nl = nl;
+			walt_load->pl = 0;
 		}
 	}
 #endif
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index 58854b0..b89abbd 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -47,6 +47,7 @@
 static struct cpu_cycle_counter_cb cpu_cycle_counter_cb;
 static bool use_cycle_counter;
 DEFINE_MUTEX(cluster_lock);
+static atomic64_t walt_irq_work_lastq_ws;
 
 u64 sched_ktime_clock(void)
 {
@@ -298,11 +299,12 @@
  */
 __read_mostly int sched_freq_aggregate_threshold;
 
-static void
+static u64
 update_window_start(struct rq *rq, u64 wallclock, int event)
 {
 	s64 delta;
 	int nr_windows;
+	u64 old_window_start = rq->window_start;
 
 	delta = wallclock - rq->window_start;
 	/* If the MPM global timer is cleared, set delta as 0 to avoid kernel BUG happening */
@@ -312,7 +314,7 @@
 	}
 
 	if (delta < sched_ravg_window)
-		return;
+		return old_window_start;
 
 	nr_windows = div64_u64(delta, sched_ravg_window);
 	rq->window_start += (u64)nr_windows * (u64)sched_ravg_window;
@@ -320,6 +322,8 @@
 	rq->cum_window_demand = rq->hmp_stats.cumulative_runnable_avg;
 	if (event == PUT_PREV_TASK)
 		rq->cum_window_demand += rq->curr->ravg.demand;
+
+	return old_window_start;
 }
 
 int register_cpu_cycle_counter_cb(struct cpu_cycle_counter_cb *cb)
@@ -913,12 +917,13 @@
 {
 	static int sync_cpu_available;
 
-	if (rq->window_start)
+	if (likely(rq->window_start))
 		return;
 
 	if (!sync_cpu_available) {
-		rq->window_start = sched_ktime_clock();
+		rq->window_start = 1;
 		sync_cpu_available = 1;
+		atomic_set(&walt_irq_work_lastq_ws, rq->window_start);
 	} else {
 		struct rq *sync_rq = cpu_rq(cpumask_any(cpu_online_mask));
 
@@ -1904,11 +1909,24 @@
 	trace_sched_get_task_cpu_cycles(cpu, event, rq->cc.cycles, rq->cc.time);
 }
 
+static inline void run_walt_irq_work(u64 old_window_start, struct rq *rq)
+{
+	u64 result;
+
+	if (old_window_start == rq->window_start)
+		return;
+
+	result = atomic_cmpxchg(&walt_irq_work_lastq_ws, old_window_start,
+				   rq->window_start);
+	if (result == old_window_start)
+		irq_work_queue(&rq->irq_work);
+}
+
 /* Reflect task activity on its demand and cpu's busy time statistics */
 void update_task_ravg(struct task_struct *p, struct rq *rq, int event,
 						u64 wallclock, u64 irqtime)
 {
-	u64 runtime;
+	u64 runtime, old_window_start;
 
 	if (!rq->window_start || sched_disable_window_stats ||
 	    p->ravg.mark_start == wallclock)
@@ -1916,7 +1934,7 @@
 
 	lockdep_assert_held(&rq->lock);
 
-	update_window_start(rq, wallclock, event);
+	old_window_start = update_window_start(rq, wallclock, event);
 
 	if (!p->ravg.mark_start) {
 		update_task_cpu_cycles(p, cpu_of(rq));
@@ -1936,6 +1954,8 @@
 				rq->cc.cycles, rq->cc.time, &rq->grp_time);
 
 	p->ravg.mark_start = wallclock;
+
+	run_walt_irq_work(old_window_start, rq);
 }
 
 u32 sched_get_init_task_load(struct task_struct *p)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 8e57301..0ca9565 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3152,6 +3152,7 @@
 		enum compact_priority prio, enum compact_result *compact_result)
 {
 	struct page *page;
+	unsigned int noreclaim_flag = current->flags & PF_MEMALLOC;
 
 	if (!order)
 		return NULL;
@@ -3159,7 +3160,7 @@
 	current->flags |= PF_MEMALLOC;
 	*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
 									prio);
-	current->flags &= ~PF_MEMALLOC;
+	current->flags = (current->flags & ~PF_MEMALLOC) | noreclaim_flag;
 
 	if (*compact_result <= COMPACT_INACTIVE)
 		return NULL;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 48f9471..c88a600 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -1680,7 +1680,8 @@
 	if (msg->msg_flags & MSG_OOB)
 		return -EOPNOTSUPP;
 
-	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
+	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE|
+			       MSG_CMSG_COMPAT))
 		return -EINVAL;
 
 	if (len < 4 || len > HCI_MAX_FRAME_SIZE)
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 963732e..58dfa23 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -740,7 +740,7 @@
 
 	if (msg_data_left(msg) < chunk) {
 		if (__skb_checksum_complete(skb))
-			goto csum_error;
+			return -EINVAL;
 		if (skb_copy_datagram_msg(skb, hlen, msg, chunk))
 			goto fault;
 	} else {
@@ -748,15 +748,16 @@
 		if (skb_copy_and_csum_datagram(skb, hlen, &msg->msg_iter,
 					       chunk, &csum))
 			goto fault;
-		if (csum_fold(csum))
-			goto csum_error;
+
+		if (csum_fold(csum)) {
+			iov_iter_revert(&msg->msg_iter, chunk);
+			return -EINVAL;
+		}
+
 		if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
 			netdev_rx_csum_fault(skb->dev);
 	}
 	return 0;
-csum_error:
-	iov_iter_revert(&msg->msg_iter, chunk);
-	return -EINVAL;
 fault:
 	return -EFAULT;
 }
diff --git a/sound/soc/codecs/wcd9330.c b/sound/soc/codecs/wcd9330.c
index 0b07393..4278e36 100644
--- a/sound/soc/codecs/wcd9330.c
+++ b/sound/soc/codecs/wcd9330.c
@@ -1536,6 +1536,13 @@
 	tomtom_mad_input = ucontrol->value.integer.value[0];
 	micb_4_int_reg = tomtom->resmgr.reg_addr->micb_4_int_rbias;
 
+	if (tomtom_mad_input >= ARRAY_SIZE(tomtom_conn_mad_text)) {
+		dev_err(codec->dev,
+			"%s: tomtom_mad_input = %d out of bounds\n",
+			__func__, tomtom_mad_input);
+		return -EINVAL;
+	}
+
 	pr_debug("%s: tomtom_mad_input = %s\n", __func__,
 			tomtom_conn_mad_text[tomtom_mad_input]);
 
diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile
index d4db55f..36382ba 100644
--- a/sound/soc/msm/qdsp6v2/Makefile
+++ b/sound/soc/msm/qdsp6v2/Makefile
@@ -1,5 +1,5 @@
-snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o \
-			msm-compress-q6-v2.o msm-compr-q6-v2.o \
+snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o \
+			msm-pcm-routing-v2.o msm-compress-q6-v2.o \
 			msm-pcm-afe-v2.o msm-pcm-voip-v2.o \
 			msm-pcm-voice-v2.o msm-dai-q6-hdmi-v2.o \
 			msm-lsm-client.o msm-pcm-host-voice-v2.o \
diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c
index 5d4a0ba..820aa1b 100644
--- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c
+++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c
@@ -646,7 +646,9 @@
 	return cal_block;
 err:
 	kfree(cal_block->cal_info);
+	cal_block->cal_info = NULL;
 	kfree(cal_block->client_info);
+	cal_block->client_info = NULL;
 	kfree(cal_block);
 	cal_block = NULL;
 	return cal_block;
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
deleted file mode 100644
index 449325c..0000000
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ /dev/null
@@ -1,1714 +0,0 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-#include <sound/control.h>
-#include <sound/q6asm-v2.h>
-#include <sound/pcm_params.h>
-#include <asm/dma.h>
-#include <linux/dma-mapping.h>
-#include <linux/msm_audio_ion.h>
-
-#include <sound/timer.h>
-
-#include "msm-compr-q6-v2.h"
-#include "msm-pcm-routing-v2.h"
-#include <sound/tlv.h>
-
-#define COMPRE_CAPTURE_NUM_PERIODS	16
-/* Allocate the worst case frame size for compressed audio */
-#define COMPRE_CAPTURE_HEADER_SIZE	(sizeof(struct snd_compr_audio_info))
-/* Changing period size to 4032. 4032 will make sure COMPRE_CAPTURE_PERIOD_SIZE
- * is 4096 with meta data size of 64 and MAX_NUM_FRAMES_PER_BUFFER 1
- */
-#define COMPRE_CAPTURE_MAX_FRAME_SIZE	(4032)
-#define COMPRE_CAPTURE_PERIOD_SIZE	((COMPRE_CAPTURE_MAX_FRAME_SIZE + \
-					  COMPRE_CAPTURE_HEADER_SIZE) * \
-					  MAX_NUM_FRAMES_PER_BUFFER)
-#define COMPRE_OUTPUT_METADATA_SIZE	(sizeof(struct output_meta_data_st))
-#define COMPRESSED_LR_VOL_MAX_STEPS	0x20002000
-
-#define MAX_AC3_PARAM_SIZE		(18*2*sizeof(int))
-#define AMR_WB_BAND_MODE 8
-#define AMR_WB_DTX_MODE 0
-
-
-const DECLARE_TLV_DB_LINEAR(compr_rx_vol_gain, 0,
-			    COMPRESSED_LR_VOL_MAX_STEPS);
-
-static struct audio_locks the_locks;
-
-static struct snd_pcm_hardware msm_compr_hardware_capture = {
-	.info =		 (SNDRV_PCM_INFO_MMAP |
-				SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				SNDRV_PCM_INFO_MMAP_VALID |
-				SNDRV_PCM_INFO_INTERLEAVED |
-				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
-	.formats =	      SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =		SNDRV_PCM_RATE_8000_48000,
-	.rate_min =	     8000,
-	.rate_max =	     48000,
-	.channels_min =	 1,
-	.channels_max =	 8,
-	.buffer_bytes_max =
-		COMPRE_CAPTURE_PERIOD_SIZE * COMPRE_CAPTURE_NUM_PERIODS,
-	.period_bytes_min =	COMPRE_CAPTURE_PERIOD_SIZE,
-	.period_bytes_max = COMPRE_CAPTURE_PERIOD_SIZE,
-	.periods_min =	  COMPRE_CAPTURE_NUM_PERIODS,
-	.periods_max =	  COMPRE_CAPTURE_NUM_PERIODS,
-	.fifo_size =	    0,
-};
-
-static struct snd_pcm_hardware msm_compr_hardware_playback = {
-	.info =		 (SNDRV_PCM_INFO_MMAP |
-				SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				SNDRV_PCM_INFO_MMAP_VALID |
-				SNDRV_PCM_INFO_INTERLEAVED |
-				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
-	.formats =	      SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
-	.rates =		SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
-	.rate_min =	     8000,
-	.rate_max =	     48000,
-	.channels_min =	 1,
-	.channels_max =	 8,
-	.buffer_bytes_max =     1024 * 1024,
-	.period_bytes_min =	128 * 1024,
-	.period_bytes_max =     256 * 1024,
-	.periods_min =	  4,
-	.periods_max =	  8,
-	.fifo_size =	    0,
-};
-
-/* Conventional and unconventional sample rate supported */
-static unsigned int supported_sample_rates[] = {
-	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
-};
-
-/* Add supported codecs for compress capture path */
-static uint32_t supported_compr_capture_codecs[] = {
-	SND_AUDIOCODEC_AMRWB
-};
-
-static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
-	.count = ARRAY_SIZE(supported_sample_rates),
-	.list = supported_sample_rates,
-	.mask = 0,
-};
-
-static bool msm_compr_capture_codecs(uint32_t req_codec)
-{
-	int i;
-
-	pr_debug("%s req_codec:%d\n", __func__, req_codec);
-	if (req_codec == 0)
-		return false;
-	for (i = 0; i < ARRAY_SIZE(supported_compr_capture_codecs); i++) {
-		if (req_codec == supported_compr_capture_codecs[i])
-			return true;
-	}
-	return false;
-}
-
-static void compr_event_handler(uint32_t opcode,
-		uint32_t token, uint32_t *payload, void *priv)
-{
-	struct compr_audio *compr = priv;
-	struct msm_audio *prtd = &compr->prtd;
-	struct snd_pcm_substream *substream = prtd->substream;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct audio_aio_write_param param;
-	struct audio_aio_read_param read_param;
-	struct audio_buffer *buf = NULL;
-	phys_addr_t temp;
-	struct output_meta_data_st output_meta_data;
-	uint32_t *ptrmem = (uint32_t *)payload;
-	int i = 0;
-	int time_stamp_flag = 0;
-	int buffer_length = 0;
-	int stop_playback = 0;
-
-	pr_debug("%s opcode =%08x\n", __func__, opcode);
-	switch (opcode) {
-	case ASM_DATA_EVENT_WRITE_DONE_V2: {
-		uint32_t *ptrmem = (uint32_t *)&param;
-
-		pr_debug("ASM_DATA_EVENT_WRITE_DONE\n");
-		pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
-		prtd->pcm_irq_pos += prtd->pcm_count;
-		if (atomic_read(&prtd->start))
-			snd_pcm_period_elapsed(substream);
-		else
-			if (substream->timer_running)
-				snd_timer_interrupt(substream->timer, 1);
-		atomic_inc(&prtd->out_count);
-		wake_up(&the_locks.write_wait);
-		if (!atomic_read(&prtd->start)) {
-			atomic_set(&prtd->pending_buffer, 1);
-			break;
-		}
-		atomic_set(&prtd->pending_buffer, 0);
-
-		/*
-		 * check for underrun
-		 */
-		snd_pcm_stream_lock_irq(substream);
-		if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
-			runtime->render_flag |= SNDRV_RENDER_STOPPED;
-			stop_playback = 1;
-		}
-		snd_pcm_stream_unlock_irq(substream);
-
-		if (stop_playback) {
-			pr_err("underrun! render stopped\n");
-			break;
-		}
-
-		buf = prtd->audio_client->port[IN].buf;
-		pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n",
-				__func__, prtd->pcm_count, prtd->out_head);
-		temp = buf[0].phys + (prtd->out_head * prtd->pcm_count);
-		pr_debug("%s:writing buffer[%d] from 0x%pK\n",
-			__func__, prtd->out_head, &temp);
-
-		if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
-			time_stamp_flag = SET_TIMESTAMP;
-		else
-			time_stamp_flag = NO_TIMESTAMP;
-		memcpy(&output_meta_data, (char *)(buf->data +
-			prtd->out_head * prtd->pcm_count),
-			COMPRE_OUTPUT_METADATA_SIZE);
-
-		buffer_length = output_meta_data.frame_size;
-		pr_debug("meta_data_length: %d, frame_length: %d\n",
-			 output_meta_data.meta_data_length,
-			 output_meta_data.frame_size);
-		pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n",
-			 output_meta_data.timestamp_msw,
-			 output_meta_data.timestamp_lsw);
-		if (buffer_length == 0) {
-			pr_debug("Received a zero length buffer-break out");
-			break;
-		}
-		param.paddr = temp + output_meta_data.meta_data_length;
-		param.len = buffer_length;
-		param.msw_ts = output_meta_data.timestamp_msw;
-		param.lsw_ts = output_meta_data.timestamp_lsw;
-		param.flags = time_stamp_flag;
-		param.uid = prtd->session_id;
-		for (i = 0; i < sizeof(struct audio_aio_write_param)/4;
-					i++, ++ptrmem)
-			pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
-		if (q6asm_async_write(prtd->audio_client,
-					&param) < 0)
-			pr_err("%s:q6asm_async_write failed\n",
-				__func__);
-		else
-			prtd->out_head =
-				(prtd->out_head + 1) & (runtime->periods - 1);
-		break;
-	}
-	case ASM_DATA_EVENT_RENDERED_EOS:
-		pr_debug("ASM_DATA_CMDRSP_EOS\n");
-		if (atomic_read(&prtd->eos)) {
-			pr_debug("ASM_DATA_CMDRSP_EOS wake up\n");
-			prtd->cmd_ack = 1;
-			wake_up(&the_locks.eos_wait);
-			atomic_set(&prtd->eos, 0);
-		}
-		break;
-	case ASM_DATA_EVENT_READ_DONE_V2: {
-		pr_debug("ASM_DATA_EVENT_READ_DONE\n");
-		pr_debug("buf = %pK, data = 0x%X, *data = %pK,\n"
-			 "prtd->pcm_irq_pos = %d\n",
-				prtd->audio_client->port[OUT].buf,
-			 *(uint32_t *)prtd->audio_client->port[OUT].buf->data,
-				prtd->audio_client->port[OUT].buf->data,
-				prtd->pcm_irq_pos);
-
-		memcpy(prtd->audio_client->port[OUT].buf->data +
-			   prtd->pcm_irq_pos, (ptrmem + READDONE_IDX_SIZE),
-			   COMPRE_CAPTURE_HEADER_SIZE);
-		pr_debug("buf = %pK, updated data = 0x%X, *data = %pK\n",
-				prtd->audio_client->port[OUT].buf,
-			*(uint32_t *)(prtd->audio_client->port[OUT].buf->data +
-				prtd->pcm_irq_pos),
-				prtd->audio_client->port[OUT].buf->data);
-		if (!atomic_read(&prtd->start))
-			break;
-		pr_debug("frame size=%d, buffer = 0x%X\n",
-				ptrmem[READDONE_IDX_SIZE],
-				ptrmem[READDONE_IDX_BUFADD_LSW]);
-		if (ptrmem[READDONE_IDX_SIZE] > COMPRE_CAPTURE_MAX_FRAME_SIZE) {
-			pr_err("Frame length exceeded the max length");
-			break;
-		}
-		buf = prtd->audio_client->port[OUT].buf;
-
-		pr_debug("pcm_irq_pos=%d, buf[0].phys = 0x%pK\n",
-				prtd->pcm_irq_pos, &buf[0].phys);
-		read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE;
-		read_param.paddr = buf[0].phys +
-			prtd->pcm_irq_pos + COMPRE_CAPTURE_HEADER_SIZE;
-		prtd->pcm_irq_pos += prtd->pcm_count;
-
-		if (atomic_read(&prtd->start))
-			snd_pcm_period_elapsed(substream);
-
-		q6asm_async_read(prtd->audio_client, &read_param);
-		break;
-	}
-	case APR_BASIC_RSP_RESULT: {
-		switch (payload[0]) {
-		case ASM_SESSION_CMD_RUN_V2: {
-			if (substream->stream
-				!= SNDRV_PCM_STREAM_PLAYBACK) {
-				atomic_set(&prtd->start, 1);
-				break;
-			}
-			if (!atomic_read(&prtd->pending_buffer))
-				break;
-			pr_debug("%s: writing %d bytes of buffer[%d] to dsp\n",
-				__func__, prtd->pcm_count, prtd->out_head);
-			buf = prtd->audio_client->port[IN].buf;
-			pr_debug("%s: writing buffer[%d] from 0x%pK head %d count %d\n",
-				__func__, prtd->out_head, &buf[0].phys,
-				prtd->pcm_count, prtd->out_head);
-			if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
-				time_stamp_flag = SET_TIMESTAMP;
-			else
-				time_stamp_flag = NO_TIMESTAMP;
-			memcpy(&output_meta_data, (char *)(buf->data +
-				prtd->out_head * prtd->pcm_count),
-				COMPRE_OUTPUT_METADATA_SIZE);
-			buffer_length = output_meta_data.frame_size;
-			pr_debug("meta_data_length: %d, frame_length: %d\n",
-				 output_meta_data.meta_data_length,
-				 output_meta_data.frame_size);
-			pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n",
-				 output_meta_data.timestamp_msw,
-				 output_meta_data.timestamp_lsw);
-			param.paddr = buf[prtd->out_head].phys
-					+ output_meta_data.meta_data_length;
-			param.len = buffer_length;
-			param.msw_ts = output_meta_data.timestamp_msw;
-			param.lsw_ts = output_meta_data.timestamp_lsw;
-			param.flags = time_stamp_flag;
-			param.uid = prtd->session_id;
-			param.metadata_len = COMPRE_OUTPUT_METADATA_SIZE;
-			if (q6asm_async_write(prtd->audio_client,
-						&param) < 0)
-				pr_err("%s:q6asm_async_write failed\n",
-					__func__);
-			else
-				prtd->out_head =
-					(prtd->out_head + 1)
-					& (runtime->periods - 1);
-			atomic_set(&prtd->pending_buffer, 0);
-		}
-			break;
-		case ASM_STREAM_CMD_FLUSH:
-			pr_debug("ASM_STREAM_CMD_FLUSH\n");
-			prtd->cmd_ack = 1;
-			wake_up(&the_locks.flush_wait);
-			break;
-		default:
-			break;
-		}
-		break;
-	}
-	default:
-		pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
-		break;
-	}
-}
-
-static int msm_compr_send_ddp_cfg(struct audio_client *ac,
-					struct snd_dec_ddp *ddp)
-{
-	int i, rc;
-
-	pr_debug("%s\n", __func__);
-
-	if (ddp->params_length / 2 > SND_DEC_DDP_MAX_PARAMS) {
-		pr_err("%s: Invalid number of params %u, max allowed %u\n",
-			__func__, ddp->params_length / 2,
-			SND_DEC_DDP_MAX_PARAMS);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < ddp->params_length/2; i++) {
-		rc = q6asm_ds1_set_endp_params(ac, ddp->params_id[i],
-						ddp->params_value[i]);
-		if (rc) {
-			pr_err("sending params_id: %d failed\n",
-				ddp->params_id[i]);
-			return rc;
-		}
-	}
-	return 0;
-}
-
-static int msm_compr_playback_prepare(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct compr_audio *compr = runtime->private_data;
-	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
-	struct msm_audio *prtd = &compr->prtd;
-	struct snd_pcm_hw_params *params;
-	struct asm_aac_cfg aac_cfg;
-	uint16_t bits_per_sample = 16;
-	int ret;
-
-	struct asm_softpause_params softpause = {
-		.enable = SOFT_PAUSE_ENABLE,
-		.period = SOFT_PAUSE_PERIOD,
-		.step = SOFT_PAUSE_STEP,
-		.rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
-	};
-	struct asm_softvolume_params softvol = {
-		.period = SOFT_VOLUME_PERIOD,
-		.step = SOFT_VOLUME_STEP,
-		.rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
-	};
-
-	pr_debug("%s\n", __func__);
-
-	params = &soc_prtd->dpcm[substream->stream].hw_params;
-	if (runtime->format == SNDRV_PCM_FORMAT_S24_LE)
-		bits_per_sample = 24;
-
-	ret = q6asm_open_write_v2(prtd->audio_client,
-			compr->codec, bits_per_sample);
-	if (ret < 0) {
-		pr_err("%s: Session out open failed\n",
-				__func__);
-		return -ENOMEM;
-	}
-	msm_pcm_routing_reg_phy_stream(
-			soc_prtd->dai_link->id,
-			prtd->audio_client->perf_mode,
-			prtd->session_id,
-			substream->stream);
-	/*
-	 * the number of channels are required to call volume api
-	 * accoridngly. So, get channels from hw params
-	 */
-	if ((params_channels(params) > 0) &&
-			(params_periods(params) <= runtime->hw.channels_max))
-		prtd->channel_mode = params_channels(params);
-
-	ret = q6asm_set_softpause(prtd->audio_client, &softpause);
-	if (ret < 0)
-		pr_err("%s: Send SoftPause Param failed ret=%d\n",
-				__func__, ret);
-	ret = q6asm_set_softvolume(prtd->audio_client, &softvol);
-	if (ret < 0)
-		pr_err("%s: Send SoftVolume Param failed ret=%d\n",
-				__func__, ret);
-
-	ret = q6asm_set_io_mode(prtd->audio_client,
-			(COMPRESSED_IO | ASYNC_IO_MODE));
-	if (ret < 0) {
-		pr_err("%s: Set IO mode failed\n", __func__);
-		return -ENOMEM;
-	}
-
-	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
-	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
-	prtd->pcm_irq_pos = 0;
-	/* rate and channels are sent to audio driver */
-	prtd->samp_rate = runtime->rate;
-	prtd->channel_mode = runtime->channels;
-	prtd->out_head = 0;
-	atomic_set(&prtd->out_count, runtime->periods);
-
-	if (prtd->enabled)
-		return 0;
-
-	switch (compr->info.codec_param.codec.id) {
-	case SND_AUDIOCODEC_MP3:
-		/* No media format block for mp3 */
-		break;
-	case SND_AUDIOCODEC_AAC:
-		pr_debug("%s: SND_AUDIOCODEC_AAC\n", __func__);
-		memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
-		aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
-		aac_cfg.format = 0x03;
-		aac_cfg.ch_cfg = runtime->channels;
-		aac_cfg.sample_rate =  runtime->rate;
-		ret = q6asm_media_format_block_aac(prtd->audio_client,
-					&aac_cfg);
-		if (ret < 0)
-			pr_err("%s: CMD Format block failed\n", __func__);
-		break;
-	case SND_AUDIOCODEC_AC3: {
-		struct snd_dec_ddp *ddp =
-				&compr->info.codec_param.codec.options.ddp;
-		pr_debug("%s: SND_AUDIOCODEC_AC3\n", __func__);
-		ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp);
-		if (ret < 0)
-			pr_err("%s: DDP CMD CFG failed\n", __func__);
-		break;
-	}
-	case SND_AUDIOCODEC_EAC3: {
-		struct snd_dec_ddp *ddp =
-				&compr->info.codec_param.codec.options.ddp;
-		pr_debug("%s: SND_AUDIOCODEC_EAC3\n", __func__);
-		ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp);
-		if (ret < 0)
-			pr_err("%s: DDP CMD CFG failed\n", __func__);
-		break;
-	}
-	default:
-		return -EINVAL;
-	}
-
-	prtd->enabled = 1;
-	prtd->cmd_ack = 0;
-	prtd->cmd_interrupt = 0;
-
-	return 0;
-}
-
-static int msm_compr_capture_prepare(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct compr_audio *compr = runtime->private_data;
-	struct msm_audio *prtd = &compr->prtd;
-	struct audio_buffer *buf = prtd->audio_client->port[OUT].buf;
-	struct snd_codec *codec = &compr->info.codec_param.codec;
-	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
-	struct audio_aio_read_param read_param;
-	uint16_t bits_per_sample = 16;
-	int ret = 0;
-	int i;
-
-	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
-	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
-	prtd->pcm_irq_pos = 0;
-
-	if (runtime->format == SNDRV_PCM_FORMAT_S24_LE)
-		bits_per_sample = 24;
-
-	if (!msm_compr_capture_codecs(
-				compr->info.codec_param.codec.id)) {
-		/*
-		 * request codec invalid or not supported,
-		 * use default compress format
-		 */
-		compr->info.codec_param.codec.id =
-			SND_AUDIOCODEC_AMRWB;
-	}
-	switch (compr->info.codec_param.codec.id) {
-	case SND_AUDIOCODEC_AMRWB:
-		pr_debug("q6asm_open_read(FORMAT_AMRWB)\n");
-		ret = q6asm_open_read(prtd->audio_client,
-				FORMAT_AMRWB);
-		if (ret < 0) {
-			pr_err("%s: compressed Session out open failed\n",
-					__func__);
-			return -ENOMEM;
-		}
-		pr_debug("msm_pcm_routing_reg_phy_stream\n");
-		msm_pcm_routing_reg_phy_stream(
-				soc_prtd->dai_link->id,
-				prtd->audio_client->perf_mode,
-				prtd->session_id, substream->stream);
-		break;
-	default:
-		pr_debug("q6asm_open_read_compressed(COMPRESSED_META_DATA_MODE)\n");
-		/*
-		 * ret = q6asm_open_read_compressed(prtd->audio_client,
-		 * MAX_NUM_FRAMES_PER_BUFFER,
-		 * COMPRESSED_META_DATA_MODE);
-		 */
-			ret = -EINVAL;
-			break;
-	}
-
-	if (ret < 0) {
-		pr_err("%s: compressed Session out open failed\n",
-				__func__);
-		return -ENOMEM;
-	}
-
-	ret = q6asm_set_io_mode(prtd->audio_client,
-		(COMPRESSED_IO | ASYNC_IO_MODE));
-		if (ret < 0) {
-			pr_err("%s: Set IO mode failed\n", __func__);
-				return -ENOMEM;
-		}
-
-	if (!msm_compr_capture_codecs(codec->id)) {
-		/*
-		 * request codec invalid or not supported,
-		 * use default compress format
-		 */
-		codec->id = SND_AUDIOCODEC_AMRWB;
-	}
-	/* rate and channels are sent to audio driver */
-	prtd->samp_rate = runtime->rate;
-	prtd->channel_mode = runtime->channels;
-
-	if (prtd->enabled)
-		return ret;
-	read_param.len = prtd->pcm_count;
-
-	switch (codec->id) {
-	case SND_AUDIOCODEC_AMRWB:
-		pr_debug("SND_AUDIOCODEC_AMRWB\n");
-		ret = q6asm_enc_cfg_blk_amrwb(prtd->audio_client,
-			MAX_NUM_FRAMES_PER_BUFFER,
-			/*
-			 * use fixed band mode and dtx mode
-			 * band mode - 23.85 kbps
-			 */
-			AMR_WB_BAND_MODE,
-			/* dtx mode - disable */
-			AMR_WB_DTX_MODE);
-		if (ret < 0)
-			pr_err("%s: CMD Format block failed: %d\n",
-				__func__, ret);
-		break;
-	default:
-		pr_debug("No config for codec %d\n", codec->id);
-	}
-	pr_debug("%s: Samp_rate = %d, Channel = %d, pcm_size = %d,\n"
-			 "pcm_count = %d, periods = %d\n",
-			 __func__, prtd->samp_rate, prtd->channel_mode,
-			 prtd->pcm_size, prtd->pcm_count, runtime->periods);
-
-	for (i = 0; i < runtime->periods; i++) {
-		read_param.uid = i;
-		switch (codec->id) {
-		case SND_AUDIOCODEC_AMRWB:
-			read_param.len = prtd->pcm_count
-					- COMPRE_CAPTURE_HEADER_SIZE;
-			read_param.paddr = buf[i].phys
-					+ COMPRE_CAPTURE_HEADER_SIZE;
-			pr_debug("Push buffer [%d] to DSP, paddr: %pK, vaddr: %pK\n",
-					i, &read_param.paddr,
-					buf[i].data);
-			q6asm_async_read(prtd->audio_client, &read_param);
-			break;
-		default:
-			read_param.paddr = buf[i].phys;
-			/* q6asm_async_read_compressed(prtd->audio_client,
-			 * &read_param);
-			 */
-			pr_debug("%s: To add support for read compressed\n",
-								__func__);
-			ret = -EINVAL;
-			break;
-		}
-	}
-	prtd->periods = runtime->periods;
-
-	prtd->enabled = 1;
-
-	return ret;
-}
-
-static int msm_compr_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	int ret = 0;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
-	struct compr_audio *compr = runtime->private_data;
-	struct msm_audio *prtd = &compr->prtd;
-
-	pr_debug("%s\n", __func__);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		prtd->pcm_irq_pos = 0;
-
-		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-			if (!msm_compr_capture_codecs(
-				compr->info.codec_param.codec.id)) {
-				/*
-				 * request codec invalid or not supported,
-				 * use default compress format
-				 */
-				compr->info.codec_param.codec.id =
-				SND_AUDIOCODEC_AMRWB;
-			}
-			switch (compr->info.codec_param.codec.id) {
-			case SND_AUDIOCODEC_AMRWB:
-				break;
-			default:
-				msm_pcm_routing_reg_psthr_stream(
-					soc_prtd->dai_link->id,
-					prtd->session_id, substream->stream);
-				break;
-			}
-		}
-		atomic_set(&prtd->pending_buffer, 1);
-		/* fallthrough */
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		pr_debug("%s: Trigger start\n", __func__);
-		q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
-		atomic_set(&prtd->start, 1);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-		pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
-		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-			switch (compr->info.codec_param.codec.id) {
-			case SND_AUDIOCODEC_AMRWB:
-				break;
-			default:
-				msm_pcm_routing_reg_psthr_stream(
-					soc_prtd->dai_link->id,
-					prtd->session_id, substream->stream);
-				break;
-			}
-		}
-		atomic_set(&prtd->start, 0);
-		runtime->render_flag &= ~SNDRV_RENDER_STOPPED;
-		break;
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
-		q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
-		atomic_set(&prtd->start, 0);
-		runtime->render_flag &= ~SNDRV_RENDER_STOPPED;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static void populate_codec_list(struct compr_audio *compr,
-		struct snd_pcm_runtime *runtime)
-{
-	pr_debug("%s\n", __func__);
-	/* MP3 Block */
-	compr->info.compr_cap.num_codecs = 5;
-	compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
-	compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
-	compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
-	compr->info.compr_cap.max_fragments = runtime->hw.periods_max;
-	compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
-	compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
-	compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
-	compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
-	compr->info.compr_cap.codecs[4] = SND_AUDIOCODEC_AMRWB;
-	/* Add new codecs here */
-}
-
-static int msm_compr_open(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct compr_audio *compr;
-	struct msm_audio *prtd;
-	int ret = 0;
-
-	pr_debug("%s\n", __func__);
-	compr = kzalloc(sizeof(struct compr_audio), GFP_KERNEL);
-	if (compr == NULL) {
-		pr_err("Failed to allocate memory for msm_audio\n");
-		return -ENOMEM;
-	}
-	prtd = &compr->prtd;
-	prtd->substream = substream;
-	runtime->render_flag = SNDRV_DMA_MODE;
-	prtd->audio_client = q6asm_audio_client_alloc(
-				(app_cb)compr_event_handler, compr);
-	if (!prtd->audio_client) {
-		pr_info("%s: Could not allocate memory\n", __func__);
-		kfree(prtd);
-		return -ENOMEM;
-	}
-
-	prtd->audio_client->perf_mode = false;
-	pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session);
-
-	prtd->session_id = prtd->audio_client->session;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		runtime->hw = msm_compr_hardware_playback;
-		prtd->cmd_ack = 1;
-	} else {
-		runtime->hw = msm_compr_hardware_capture;
-	}
-
-
-	ret = snd_pcm_hw_constraint_list(runtime, 0,
-			SNDRV_PCM_HW_PARAM_RATE,
-			&constraints_sample_rates);
-	if (ret < 0)
-		pr_info("snd_pcm_hw_constraint_list failed\n");
-	/* Ensure that buffer size is a multiple of period size */
-	ret = snd_pcm_hw_constraint_integer(runtime,
-			    SNDRV_PCM_HW_PARAM_PERIODS);
-	if (ret < 0)
-		pr_info("snd_pcm_hw_constraint_integer failed\n");
-
-	prtd->dsp_cnt = 0;
-	atomic_set(&prtd->pending_buffer, 1);
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		compr->codec = FORMAT_MP3;
-	populate_codec_list(compr, runtime);
-	runtime->private_data = compr;
-	atomic_set(&prtd->eos, 0);
-	return 0;
-}
-
-static int compressed_set_volume(struct msm_audio *prtd, uint32_t volume)
-{
-	int rc = 0;
-	int avg_vol = 0;
-	int lgain = (volume >> 16) & 0xFFFF;
-	int rgain = volume & 0xFFFF;
-
-	if (prtd && prtd->audio_client) {
-		pr_debug("%s: channels %d volume 0x%x\n", __func__,
-			prtd->channel_mode, volume);
-		if ((prtd->channel_mode == 2) &&
-			(lgain != rgain)) {
-			pr_debug("%s: call q6asm_set_lrgain\n", __func__);
-			rc = q6asm_set_lrgain(prtd->audio_client, lgain, rgain);
-		} else {
-			avg_vol = (lgain + rgain)/2;
-			pr_debug("%s: call q6asm_set_volume\n", __func__);
-			rc = q6asm_set_volume(prtd->audio_client, avg_vol);
-		}
-		if (rc < 0) {
-			pr_err("%s: Send Volume command failed rc=%d\n",
-				__func__, rc);
-		}
-	}
-	return rc;
-}
-
-static int msm_compr_playback_close(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
-	struct compr_audio *compr = runtime->private_data;
-	struct msm_audio *prtd = &compr->prtd;
-	int dir = 0;
-
-	pr_debug("%s\n", __func__);
-
-	dir = IN;
-	atomic_set(&prtd->pending_buffer, 0);
-
-	prtd->pcm_irq_pos = 0;
-	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
-	q6asm_audio_client_buf_free_contiguous(dir,
-				prtd->audio_client);
-		msm_pcm_routing_dereg_phy_stream(
-			soc_prtd->dai_link->id,
-			SNDRV_PCM_STREAM_PLAYBACK);
-	q6asm_audio_client_free(prtd->audio_client);
-	kfree(prtd);
-	return 0;
-}
-
-static int msm_compr_capture_close(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
-	struct compr_audio *compr = runtime->private_data;
-	struct msm_audio *prtd = &compr->prtd;
-	int dir = OUT;
-
-	pr_debug("%s\n", __func__);
-	atomic_set(&prtd->pending_buffer, 0);
-	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
-	q6asm_audio_client_buf_free_contiguous(dir,
-				prtd->audio_client);
-	msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
-				SNDRV_PCM_STREAM_CAPTURE);
-	q6asm_audio_client_free(prtd->audio_client);
-	kfree(prtd);
-	return 0;
-}
-
-static int msm_compr_close(struct snd_pcm_substream *substream)
-{
-	int ret = 0;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		ret = msm_compr_playback_close(substream);
-	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-		ret = msm_compr_capture_close(substream);
-	return ret;
-}
-
-static int msm_compr_prepare(struct snd_pcm_substream *substream)
-{
-	int ret = 0;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		ret = msm_compr_playback_prepare(substream);
-	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-		ret = msm_compr_capture_prepare(substream);
-	return ret;
-}
-
-static snd_pcm_uframes_t msm_compr_pointer(struct snd_pcm_substream *substream)
-{
-
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct compr_audio *compr = runtime->private_data;
-	struct msm_audio *prtd = &compr->prtd;
-
-	if (prtd->pcm_irq_pos >= prtd->pcm_size)
-		prtd->pcm_irq_pos = 0;
-
-	pr_debug("%s: pcm_irq_pos = %d, pcm_size = %d, sample_bits = %d,\n"
-			 "frame_bits = %d\n", __func__, prtd->pcm_irq_pos,
-			 prtd->pcm_size, runtime->sample_bits,
-			 runtime->frame_bits);
-	return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
-}
-
-static int msm_compr_mmap(struct snd_pcm_substream *substream,
-				struct vm_area_struct *vma)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct msm_audio *prtd = runtime->private_data;
-	struct audio_client *ac = prtd->audio_client;
-	struct audio_port_data *apd = ac->port;
-	struct audio_buffer *ab;
-	int dir = -1;
-
-	prtd->mmap_flag = 1;
-	runtime->render_flag = SNDRV_NON_DMA_MODE;
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		dir = IN;
-	else
-		dir = OUT;
-	ab = &(apd[dir].buf[0]);
-
-	return msm_audio_ion_mmap(ab, vma);
-}
-
-static int msm_compr_hw_params(struct snd_pcm_substream *substream,
-				struct snd_pcm_hw_params *params)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct compr_audio *compr = runtime->private_data;
-	struct msm_audio *prtd = &compr->prtd;
-	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
-	struct audio_buffer *buf;
-	int dir, ret;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		dir = IN;
-	else
-		dir = OUT;
-	/* Modifying kernel hardware params based on userspace config */
-	if (params_periods(params) > 0 &&
-		(params_periods(params) != runtime->hw.periods_max)) {
-		runtime->hw.periods_max = params_periods(params);
-	}
-	if (params_period_bytes(params) > 0 &&
-		(params_period_bytes(params) != runtime->hw.period_bytes_min)) {
-		runtime->hw.period_bytes_min = params_period_bytes(params);
-	}
-	runtime->hw.buffer_bytes_max =
-			runtime->hw.period_bytes_min * runtime->hw.periods_max;
-	pr_debug("allocate %zd buffers each of size %d\n",
-		runtime->hw.period_bytes_min,
-		runtime->hw.periods_max);
-	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
-			prtd->audio_client,
-			runtime->hw.period_bytes_min,
-			runtime->hw.periods_max);
-	if (ret < 0) {
-		pr_err("Audio Start: Buffer Allocation failed rc = %d\n",
-						ret);
-		return -ENOMEM;
-	}
-	buf = prtd->audio_client->port[dir].buf;
-
-	dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
-	dma_buf->dev.dev = substream->pcm->card->dev;
-	dma_buf->private_data = NULL;
-	dma_buf->area = buf[0].data;
-	dma_buf->addr =  buf[0].phys;
-	dma_buf->bytes = runtime->hw.buffer_bytes_max;
-
-	pr_debug("%s: buf[%pK]dma_buf->area[%pK]dma_buf->addr[%pK]\n"
-		 "dma_buf->bytes[%zd]\n", __func__,
-		 (void *)buf, (void *)dma_buf->area,
-		 &dma_buf->addr, dma_buf->bytes);
-	if (!dma_buf->area)
-		return -ENOMEM;
-
-	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-	return 0;
-}
-
-static int msm_compr_ioctl_shared(struct snd_pcm_substream *substream,
-		unsigned int cmd, void *arg)
-{
-	int rc = 0;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct compr_audio *compr = runtime->private_data;
-	struct msm_audio *prtd = &compr->prtd;
-	uint64_t timestamp;
-	uint64_t temp;
-
-	switch (cmd) {
-	case SNDRV_COMPRESS_TSTAMP: {
-		struct snd_compr_tstamp *tstamp;
-
-		pr_debug("SNDRV_COMPRESS_TSTAMP\n");
-		tstamp = arg;
-		memset(tstamp, 0x0, sizeof(*tstamp));
-		rc = q6asm_get_session_time(prtd->audio_client, &timestamp);
-		if (rc < 0) {
-			pr_err("%s: Get Session Time return value =%lld\n",
-				__func__, timestamp);
-			return -EAGAIN;
-		}
-		temp = (timestamp * 2 * runtime->channels);
-		temp = temp * (runtime->rate/1000);
-		temp = div_u64(temp, 1000);
-		tstamp->sampling_rate = runtime->rate;
-		tstamp->timestamp = timestamp;
-		pr_debug("%s: bytes_consumed:,timestamp = %lld,\n",
-						__func__,
-			tstamp->timestamp);
-		return 0;
-	}
-	case SNDRV_COMPRESS_GET_CAPS: {
-		struct snd_compr_caps *caps;
-
-		caps = arg;
-		memset(caps, 0, sizeof(*caps));
-		pr_debug("SNDRV_COMPRESS_GET_CAPS\n");
-		memcpy(caps, &compr->info.compr_cap, sizeof(*caps));
-		return 0;
-	}
-	case SNDRV_COMPRESS_SET_PARAMS:
-		pr_debug("SNDRV_COMPRESS_SET_PARAMS:\n");
-		memcpy(&compr->info.codec_param, (void *) arg,
-			sizeof(struct snd_compr_params));
-		switch (compr->info.codec_param.codec.id) {
-		case SND_AUDIOCODEC_MP3:
-			/* For MP3 we dont need any other parameter */
-			pr_debug("SND_AUDIOCODEC_MP3\n");
-			compr->codec = FORMAT_MP3;
-			break;
-		case SND_AUDIOCODEC_AAC:
-			pr_debug("SND_AUDIOCODEC_AAC\n");
-			compr->codec = FORMAT_MPEG4_AAC;
-			break;
-		case SND_AUDIOCODEC_AC3: {
-			char params_value[MAX_AC3_PARAM_SIZE];
-			int *params_value_data = (int *)params_value;
-			/* 36 is the max param length for ddp */
-			int i;
-			struct snd_dec_ddp *ddp =
-				&compr->info.codec_param.codec.options.ddp;
-			uint32_t params_length = 0;
-
-			memset(params_value, 0, MAX_AC3_PARAM_SIZE);
-			/* check integer overflow */
-			if (ddp->params_length > UINT_MAX/sizeof(int)) {
-				pr_err("%s: Integer overflow ddp->params_length %d\n",
-				__func__, ddp->params_length);
-				return -EINVAL;
-			}
-			params_length = ddp->params_length*sizeof(int);
-			if (params_length > MAX_AC3_PARAM_SIZE) {
-				/*MAX is 36*sizeof(int) this should not happen*/
-				pr_err("%s: params_length(%d) is greater than %zd\n",
-				__func__, params_length, MAX_AC3_PARAM_SIZE);
-				return -EINVAL;
-			}
-			pr_debug("SND_AUDIOCODEC_AC3\n");
-			compr->codec = FORMAT_AC3;
-			pr_debug("params_length: %d\n", ddp->params_length);
-			for (i = 0; i < params_length/sizeof(int); i++)
-				pr_debug("params_value[%d]: %x\n", i,
-					params_value_data[i]);
-			for (i = 0; i < ddp->params_length/2; i++) {
-				ddp->params_id[i] = params_value_data[2*i];
-				ddp->params_value[i] = params_value_data[2*i+1];
-			}
-			if (atomic_read(&prtd->start)) {
-				rc = msm_compr_send_ddp_cfg(prtd->audio_client,
-								ddp);
-				if (rc < 0)
-					pr_err("%s: DDP CMD CFG failed\n",
-						__func__);
-			}
-			break;
-		}
-		case SND_AUDIOCODEC_EAC3: {
-			char params_value[MAX_AC3_PARAM_SIZE];
-			int *params_value_data = (int *)params_value;
-			/* 36 is the max param length for ddp */
-			int i;
-			struct snd_dec_ddp *ddp =
-				&compr->info.codec_param.codec.options.ddp;
-			uint32_t params_length = 0;
-
-			memset(params_value, 0, MAX_AC3_PARAM_SIZE);
-			/* check integer overflow */
-			if (ddp->params_length > UINT_MAX/sizeof(int)) {
-				pr_err("%s: Integer overflow ddp->params_length %d\n",
-				__func__, ddp->params_length);
-				return -EINVAL;
-			}
-			params_length = ddp->params_length*sizeof(int);
-			if (params_length > MAX_AC3_PARAM_SIZE) {
-				/*MAX is 36*sizeof(int) this should not happen*/
-				pr_err("%s: params_length(%d) is greater than %zd\n",
-				__func__, params_length, MAX_AC3_PARAM_SIZE);
-				return -EINVAL;
-			}
-			pr_debug("SND_AUDIOCODEC_EAC3\n");
-			compr->codec = FORMAT_EAC3;
-			pr_debug("params_length: %d\n", ddp->params_length);
-			for (i = 0; i < ddp->params_length; i++)
-				pr_debug("params_value[%d]: %x\n", i,
-					params_value_data[i]);
-			for (i = 0; i < ddp->params_length/2; i++) {
-				ddp->params_id[i] = params_value_data[2*i];
-				ddp->params_value[i] = params_value_data[2*i+1];
-			}
-			if (atomic_read(&prtd->start)) {
-				rc = msm_compr_send_ddp_cfg(prtd->audio_client,
-								ddp);
-				if (rc < 0)
-					pr_err("%s: DDP CMD CFG failed\n",
-						__func__);
-			}
-			break;
-		}
-		default:
-			pr_debug("FORMAT_LINEAR_PCM\n");
-			compr->codec = FORMAT_LINEAR_PCM;
-			break;
-		}
-		return 0;
-	case SNDRV_PCM_IOCTL1_RESET:
-		pr_debug("SNDRV_PCM_IOCTL1_RESET\n");
-		/* Flush only when session is started during CAPTURE,
-		 * while PLAYBACK has no such restriction.
-		 */
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
-			  (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
-						atomic_read(&prtd->start))) {
-			if (atomic_read(&prtd->eos)) {
-				prtd->cmd_interrupt = 1;
-				wake_up(&the_locks.eos_wait);
-				atomic_set(&prtd->eos, 0);
-			}
-
-			/* A unlikely race condition possible with FLUSH
-			 * DRAIN if ack is set by flush and reset by drain
-			 */
-			prtd->cmd_ack = 0;
-			rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH);
-			if (rc < 0) {
-				pr_err("%s: flush cmd failed rc=%d\n",
-					__func__, rc);
-				return rc;
-			}
-			rc = wait_event_timeout(the_locks.flush_wait,
-				prtd->cmd_ack, 5 * HZ);
-			if (!rc)
-				pr_err("Flush cmd timeout\n");
-			prtd->pcm_irq_pos = 0;
-		}
-		break;
-	case SNDRV_COMPRESS_DRAIN:
-		pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
-		if (atomic_read(&prtd->pending_buffer)) {
-			pr_debug("%s: no pending writes, drain would block\n",
-			 __func__);
-			return -EWOULDBLOCK;
-		}
-
-		atomic_set(&prtd->eos, 1);
-		atomic_set(&prtd->pending_buffer, 0);
-		prtd->cmd_ack = 0;
-		q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
-		/* Wait indefinitely for  DRAIN. Flush can also signal this*/
-		rc = wait_event_interruptible(the_locks.eos_wait,
-			(prtd->cmd_ack || prtd->cmd_interrupt));
-
-		if (rc < 0)
-			pr_err("EOS cmd interrupted\n");
-		pr_debug("%s: SNDRV_COMPRESS_DRAIN  out of wait\n", __func__);
-
-		if (prtd->cmd_interrupt)
-			rc = -EINTR;
-
-		prtd->cmd_interrupt = 0;
-		return rc;
-	default:
-		break;
-	}
-	return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-#ifdef CONFIG_COMPAT
-struct snd_enc_wma32 {
-	u32 super_block_align; /* WMA Type-specific data */
-	u32 encodeopt1;
-	u32 encodeopt2;
-};
-
-struct snd_enc_vorbis32 {
-	s32 quality;
-	u32 managed;
-	u32 max_bit_rate;
-	u32 min_bit_rate;
-	u32 downmix;
-};
-
-struct snd_enc_real32 {
-	u32 quant_bits;
-	u32 start_region;
-	u32 num_regions;
-};
-
-struct snd_enc_flac32 {
-	u32 num;
-	u32 gain;
-};
-
-struct snd_enc_generic32 {
-	u32 bw;	/* encoder bandwidth */
-	s32 reserved[15];
-};
-struct snd_dec_ddp32 {
-	u32 params_length;
-	u32 params_id[18];
-	u32 params_value[18];
-};
-
-union snd_codec_options32 {
-	struct snd_enc_wma32 wma;
-	struct snd_enc_vorbis32 vorbis;
-	struct snd_enc_real32 real;
-	struct snd_enc_flac32 flac;
-	struct snd_enc_generic32 generic;
-	struct snd_dec_ddp32 ddp;
-};
-
-struct snd_codec32 {
-	u32 id;
-	u32 ch_in;
-	u32 ch_out;
-	u32 sample_rate;
-	u32 bit_rate;
-	u32 rate_control;
-	u32 profile;
-	u32 level;
-	u32 ch_mode;
-	u32 format;
-	u32 align;
-	union snd_codec_options32 options;
-	u32 reserved[3];
-};
-
-struct snd_compressed_buffer32 {
-	u32 fragment_size;
-	u32 fragments;
-};
-
-struct snd_compr_params32 {
-	struct snd_compressed_buffer32 buffer;
-	struct snd_codec32 codec;
-	u8 no_wake_mode;
-};
-
-struct snd_compr_caps32 {
-	u32 num_codecs;
-	u32 direction;
-	u32 min_fragment_size;
-	u32 max_fragment_size;
-	u32 min_fragments;
-	u32 max_fragments;
-	u32 codecs[MAX_NUM_CODECS];
-	u32 reserved[11];
-};
-struct snd_compr_tstamp32 {
-	u32 byte_offset;
-	u32 copied_total;
-	compat_ulong_t pcm_frames;
-	compat_ulong_t pcm_io_frames;
-	u32 sampling_rate;
-	compat_u64 timestamp;
-};
-enum {
-	SNDRV_COMPRESS_TSTAMP32 = _IOR('C', 0x20, struct snd_compr_tstamp32),
-	SNDRV_COMPRESS_GET_CAPS32 = _IOWR('C', 0x10, struct snd_compr_caps32),
-	SNDRV_COMPRESS_SET_PARAMS32 =
-	_IOW('C', 0x12, struct snd_compr_params32),
-};
-static int msm_compr_compat_ioctl(struct snd_pcm_substream *substream,
-		unsigned int cmd, void *arg)
-{
-	int err = 0;
-
-	switch (cmd) {
-	case SNDRV_COMPRESS_TSTAMP32: {
-		struct snd_compr_tstamp tstamp;
-		struct snd_compr_tstamp32 tstamp32;
-
-		memset(&tstamp, 0, sizeof(tstamp));
-		memset(&tstamp32, 0, sizeof(tstamp32));
-		cmd = SNDRV_COMPRESS_TSTAMP;
-		err = msm_compr_ioctl_shared(substream, cmd, &tstamp);
-		if (err) {
-			pr_err("%s: COMPRESS_TSTAMP failed rc %d\n",
-			__func__, err);
-			goto bail_out;
-		}
-		tstamp32.byte_offset = tstamp.byte_offset;
-		tstamp32.copied_total = tstamp.copied_total;
-		tstamp32.pcm_frames = tstamp.pcm_frames;
-		tstamp32.pcm_io_frames = tstamp.pcm_io_frames;
-		tstamp32.sampling_rate = tstamp.sampling_rate;
-		tstamp32.timestamp = tstamp.timestamp;
-		if (copy_to_user(arg, &tstamp32, sizeof(tstamp32))) {
-			pr_err("%s: copytouser failed COMPRESS_TSTAMP32\n",
-			__func__);
-			err = -EFAULT;
-		}
-		break;
-	}
-	case SNDRV_COMPRESS_GET_CAPS32: {
-		struct snd_compr_caps caps;
-		struct snd_compr_caps32 caps32;
-		u32 i;
-
-		memset(&caps, 0, sizeof(caps));
-		memset(&caps32, 0, sizeof(caps32));
-		cmd = SNDRV_COMPRESS_GET_CAPS;
-		err = msm_compr_ioctl_shared(substream, cmd, &caps);
-		if (err) {
-			pr_err("%s: GET_CAPS failed rc %d\n",
-			__func__, err);
-			goto bail_out;
-		}
-		pr_debug("SNDRV_COMPRESS_GET_CAPS_32\n");
-		if (!err && caps.num_codecs >= MAX_NUM_CODECS) {
-			pr_err("%s: Invalid number of codecs\n", __func__);
-			err = -EINVAL;
-			goto bail_out;
-		}
-		caps32.direction = caps.direction;
-		caps32.max_fragment_size = caps.max_fragment_size;
-		caps32.max_fragments = caps.max_fragments;
-		caps32.min_fragment_size = caps.min_fragment_size;
-		caps32.num_codecs = caps.num_codecs;
-		for (i = 0; i < caps.num_codecs; i++)
-			caps32.codecs[i] = caps.codecs[i];
-		if (copy_to_user(arg, &caps32, sizeof(caps32))) {
-			pr_err("%s: copytouser failed COMPRESS_GETCAPS32\n",
-			__func__);
-			err = -EFAULT;
-		}
-		break;
-	}
-	case SNDRV_COMPRESS_SET_PARAMS32: {
-		struct snd_compr_params32 params32;
-		struct snd_compr_params params;
-
-		memset(&params32, 0, sizeof(params32));
-		memset(&params, 0, sizeof(params));
-		cmd = SNDRV_COMPRESS_SET_PARAMS;
-		if (copy_from_user(&params32, arg, sizeof(params32))) {
-			pr_err("%s: copyfromuser failed SET_PARAMS32\n",
-			__func__);
-			err = -EFAULT;
-			goto bail_out;
-		}
-		params.no_wake_mode = params32.no_wake_mode;
-		params.codec.id = params32.codec.id;
-		params.codec.ch_in = params32.codec.ch_in;
-		params.codec.ch_out = params32.codec.ch_out;
-		params.codec.sample_rate = params32.codec.sample_rate;
-		params.codec.bit_rate = params32.codec.bit_rate;
-		params.codec.rate_control = params32.codec.rate_control;
-		params.codec.profile = params32.codec.profile;
-		params.codec.level = params32.codec.level;
-		params.codec.ch_mode = params32.codec.ch_mode;
-		params.codec.format = params32.codec.format;
-		params.codec.align = params32.codec.align;
-
-		switch (params.codec.id) {
-		case SND_AUDIOCODEC_WMA:
-		case SND_AUDIOCODEC_WMA_PRO:
-			params.codec.options.wma.encodeopt1 =
-			params32.codec.options.wma.encodeopt1;
-			params.codec.options.wma.encodeopt2 =
-			params32.codec.options.wma.encodeopt2;
-			params.codec.options.wma.super_block_align =
-			params32.codec.options.wma.super_block_align;
-		break;
-		case SND_AUDIOCODEC_VORBIS:
-			params.codec.options.vorbis.downmix =
-			params32.codec.options.vorbis.downmix;
-			params.codec.options.vorbis.managed =
-			params32.codec.options.vorbis.managed;
-			params.codec.options.vorbis.max_bit_rate =
-			params32.codec.options.vorbis.max_bit_rate;
-			params.codec.options.vorbis.min_bit_rate =
-			params32.codec.options.vorbis.min_bit_rate;
-			params.codec.options.vorbis.quality =
-			params32.codec.options.vorbis.quality;
-		break;
-		case SND_AUDIOCODEC_REAL:
-			params.codec.options.real.num_regions =
-			params32.codec.options.real.num_regions;
-			params.codec.options.real.quant_bits =
-			params32.codec.options.real.quant_bits;
-			params.codec.options.real.start_region =
-			params32.codec.options.real.start_region;
-		break;
-		case SND_AUDIOCODEC_FLAC:
-			params.codec.options.flac.gain =
-			params32.codec.options.flac.gain;
-			params.codec.options.flac.num =
-			params32.codec.options.flac.num;
-		break;
-		case SND_AUDIOCODEC_DTS:
-		case SND_AUDIOCODEC_DTS_PASS_THROUGH:
-		case SND_AUDIOCODEC_DTS_LBR:
-		case SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH:
-		case SND_AUDIOCODEC_DTS_TRANSCODE_LOOPBACK:
-		break;
-		case SND_AUDIOCODEC_AC3:
-		case SND_AUDIOCODEC_EAC3:
-			params.codec.options.ddp.params_length =
-			params32.codec.options.ddp.params_length;
-			memcpy(params.codec.options.ddp.params_value,
-			params32.codec.options.ddp.params_value,
-			sizeof(params32.codec.options.ddp.params_value));
-			memcpy(params.codec.options.ddp.params_id,
-			params32.codec.options.ddp.params_id,
-			sizeof(params32.codec.options.ddp.params_id));
-		break;
-		default:
-			params.codec.options.generic.bw =
-			params32.codec.options.generic.bw;
-		break;
-		}
-		if (!err)
-			err = msm_compr_ioctl_shared(substream, cmd, &params);
-		break;
-	}
-	default:
-		err = msm_compr_ioctl_shared(substream, cmd, arg);
-	}
-bail_out:
-	return err;
-
-}
-#endif
-static int msm_compr_ioctl(struct snd_pcm_substream *substream,
-		unsigned int cmd, void *arg)
-{
-	int err = 0;
-
-	if (!substream) {
-		pr_err("%s: Invalid params\n", __func__);
-		return -EINVAL;
-	}
-	pr_debug("%s called with cmd = %d\n", __func__, cmd);
-	switch (cmd) {
-	case SNDRV_COMPRESS_TSTAMP: {
-		struct snd_compr_tstamp tstamp;
-
-		if (!arg) {
-			pr_err("%s: Invalid params Tstamp\n", __func__);
-			return -EINVAL;
-		}
-		err = msm_compr_ioctl_shared(substream, cmd, &tstamp);
-		if (err)
-			pr_err("%s: COMPRESS_TSTAMP failed rc %d\n",
-			__func__, err);
-		if (!err && copy_to_user(arg, &tstamp, sizeof(tstamp))) {
-			pr_err("%s: copytouser failed COMPRESS_TSTAMP\n",
-			__func__);
-			err = -EFAULT;
-		}
-		break;
-	}
-	case SNDRV_COMPRESS_GET_CAPS: {
-		struct snd_compr_caps cap;
-
-		if (!arg) {
-			pr_err("%s: Invalid params getcaps\n", __func__);
-			return -EINVAL;
-		}
-		pr_debug("SNDRV_COMPRESS_GET_CAPS\n");
-		err = msm_compr_ioctl_shared(substream, cmd, &cap);
-		if (err)
-			pr_err("%s: GET_CAPS failed rc %d\n",
-			__func__, err);
-		if (!err && copy_to_user(arg, &cap, sizeof(cap))) {
-			pr_err("%s: copytouser failed GET_CAPS\n",
-			__func__);
-			err = -EFAULT;
-		}
-		break;
-	}
-	case SNDRV_COMPRESS_SET_PARAMS: {
-		struct snd_compr_params params;
-
-		if (!arg) {
-			pr_err("%s: Invalid params setparam\n", __func__);
-			return -EINVAL;
-		}
-		if (copy_from_user(&params, arg,
-			sizeof(struct snd_compr_params))) {
-			pr_err("%s: SET_PARAMS\n", __func__);
-			return -EFAULT;
-		}
-		err = msm_compr_ioctl_shared(substream, cmd, &params);
-		if (err)
-			pr_err("%s: SET_PARAMS failed rc %d\n",
-			__func__, err);
-		break;
-	}
-	default:
-		err = msm_compr_ioctl_shared(substream, cmd, arg);
-	}
-	return err;
-}
-
-static int msm_compr_restart(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct compr_audio *compr = runtime->private_data;
-	struct msm_audio *prtd = &compr->prtd;
-	struct audio_aio_write_param param;
-	struct audio_buffer *buf = NULL;
-	struct output_meta_data_st output_meta_data;
-	int time_stamp_flag = 0;
-	int buffer_length = 0;
-
-	pr_debug("%s, trigger restart\n", __func__);
-
-	if (runtime->render_flag & SNDRV_RENDER_STOPPED) {
-		buf = prtd->audio_client->port[IN].buf;
-		pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n",
-				__func__, prtd->pcm_count, prtd->out_head);
-		pr_debug("%s:writing buffer[%d] from 0x%08x\n",
-				__func__, prtd->out_head,
-				((unsigned int)buf[0].phys
-				+ (prtd->out_head * prtd->pcm_count)));
-
-		if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
-			time_stamp_flag = SET_TIMESTAMP;
-		else
-			time_stamp_flag = NO_TIMESTAMP;
-		memcpy(&output_meta_data, (char *)(buf->data +
-			prtd->out_head * prtd->pcm_count),
-			COMPRE_OUTPUT_METADATA_SIZE);
-
-		buffer_length = output_meta_data.frame_size;
-		pr_debug("meta_data_length: %d, frame_length: %d\n",
-			 output_meta_data.meta_data_length,
-			 output_meta_data.frame_size);
-		pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n",
-			 output_meta_data.timestamp_msw,
-			 output_meta_data.timestamp_lsw);
-
-		param.paddr = (unsigned long)buf[0].phys
-				+ (prtd->out_head * prtd->pcm_count)
-				+ output_meta_data.meta_data_length;
-		param.len = buffer_length;
-		param.msw_ts = output_meta_data.timestamp_msw;
-		param.lsw_ts = output_meta_data.timestamp_lsw;
-		param.flags = time_stamp_flag;
-		param.uid = prtd->session_id;
-		if (q6asm_async_write(prtd->audio_client,
-					&param) < 0)
-			pr_err("%s:q6asm_async_write failed\n",
-				__func__);
-		else
-			prtd->out_head =
-				(prtd->out_head + 1) & (runtime->periods - 1);
-
-		runtime->render_flag &= ~SNDRV_RENDER_STOPPED;
-		return 0;
-	}
-	return 0;
-}
-
-static int msm_compr_volume_ctl_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	int rc = 0;
-	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
-	struct snd_pcm_substream *substream =
-			 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-	struct msm_audio *prtd;
-	int volume = ucontrol->value.integer.value[0];
-
-	pr_debug("%s: volume : %x\n", __func__, volume);
-	if (!substream)
-		return -ENODEV;
-	if (!substream->runtime)
-		return 0;
-	prtd = substream->runtime->private_data;
-	if (prtd)
-		rc = compressed_set_volume(prtd, volume);
-
-	return rc;
-}
-
-static int msm_compr_volume_ctl_get(struct snd_kcontrol *kcontrol,
-				  struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
-	struct snd_pcm_substream *substream =
-			 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
-	struct msm_audio *prtd;
-
-	pr_debug("%s\n", __func__);
-	if (!substream)
-		return -ENODEV;
-	if (!substream->runtime)
-		return 0;
-	prtd = substream->runtime->private_data;
-	if (prtd)
-		ucontrol->value.integer.value[0] = prtd->volume;
-	return 0;
-}
-
-static int msm_compr_add_controls(struct snd_soc_pcm_runtime *rtd)
-{
-	int ret = 0;
-	struct snd_pcm *pcm = rtd->pcm;
-	struct snd_pcm_volume *volume_info;
-	struct snd_kcontrol *kctl;
-
-	dev_dbg(rtd->dev, "%s, Volume cntrl add\n", __func__);
-	ret = snd_pcm_add_volume_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-				      NULL, 1, rtd->dai_link->id,
-				      &volume_info);
-	if (ret < 0)
-		return ret;
-	kctl = volume_info->kctl;
-	kctl->put = msm_compr_volume_ctl_put;
-	kctl->get = msm_compr_volume_ctl_get;
-	kctl->tlv.p = compr_rx_vol_gain;
-	return 0;
-}
-
-static const struct snd_pcm_ops msm_compr_ops = {
-	.open	   = msm_compr_open,
-	.hw_params	= msm_compr_hw_params,
-	.close	  = msm_compr_close,
-	.ioctl	  = msm_compr_ioctl,
-	.prepare	= msm_compr_prepare,
-	.trigger	= msm_compr_trigger,
-	.pointer	= msm_compr_pointer,
-	.mmap		= msm_compr_mmap,
-	.restart	= msm_compr_restart,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl   = msm_compr_compat_ioctl,
-#endif
-};
-
-static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
-	struct snd_card *card = rtd->card->snd_card;
-	int ret = 0;
-
-	if (!card->dev->coherent_dma_mask)
-		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
-
-	ret = msm_compr_add_controls(rtd);
-	if (ret)
-		pr_err("%s, kctl add failed\n", __func__);
-	return ret;
-}
-
-static struct snd_soc_platform_driver msm_soc_platform = {
-	.ops		= &msm_compr_ops,
-	.pcm_new	= msm_asoc_pcm_new,
-};
-
-static int msm_compr_probe(struct platform_device *pdev)
-{
-
-	dev_info(&pdev->dev, "%s: dev name %s\n",
-			 __func__, dev_name(&pdev->dev));
-
-	return snd_soc_register_platform(&pdev->dev,
-				   &msm_soc_platform);
-}
-
-static int msm_compr_remove(struct platform_device *pdev)
-{
-	snd_soc_unregister_platform(&pdev->dev);
-	return 0;
-}
-
-static const struct of_device_id msm_compr_dt_match[] = {
-	{.compatible = "qcom,msm-compr-dsp"},
-	{}
-};
-MODULE_DEVICE_TABLE(of, msm_compr_dt_match);
-
-static struct platform_driver msm_compr_driver = {
-	.driver = {
-		.name = "msm-compr-dsp",
-		.owner = THIS_MODULE,
-		.of_match_table = msm_compr_dt_match,
-	},
-	.probe = msm_compr_probe,
-	.remove = msm_compr_remove,
-};
-
-static int __init msm_soc_platform_init(void)
-{
-	init_waitqueue_head(&the_locks.enable_wait);
-	init_waitqueue_head(&the_locks.eos_wait);
-	init_waitqueue_head(&the_locks.write_wait);
-	init_waitqueue_head(&the_locks.read_wait);
-	init_waitqueue_head(&the_locks.flush_wait);
-
-	return platform_driver_register(&msm_compr_driver);
-}
-module_init(msm_soc_platform_init);
-
-static void __exit msm_soc_platform_exit(void)
-{
-	platform_driver_unregister(&msm_compr_driver);
-}
-module_exit(msm_soc_platform_exit);
-
-MODULE_DESCRIPTION("PCM module platform driver");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h
deleted file mode 100644
index d6e3ec6..0000000
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
- *
- * This 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 _MSM_COMPR_H
-#define _MSM_COMPR_H
-#include <sound/apr_audio-v2.h>
-#include <sound/q6asm-v2.h>
-#include <sound/compress_params.h>
-#include <sound/compress_offload.h>
-#include <sound/compress_driver.h>
-
-#include "msm-pcm-q6-v2.h"
-
-struct compr_info {
-	struct snd_compr_caps compr_cap;
-	struct snd_compr_codec_caps codec_caps;
-	struct snd_compr_params codec_param;
-};
-
-struct compr_audio {
-	struct msm_audio prtd;
-	struct compr_info info;
-	uint32_t codec;
-};
-
-#endif /*_MSM_COMPR_H*/
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index 37dd31f..421769e 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -1165,28 +1165,27 @@
 		break;
 
 	case SNDRV_LSM_SET_FWK_MODE_CONFIG: {
-		u32 *mode = NULL;
+		u32 mode;
 
-		if (!arg) {
-			dev_err(rtd->dev,
-				"%s: Invalid param arg for ioctl %s session %d\n",
-				__func__, "SNDRV_LSM_SET_FWK_MODE_CONFIG",
-				prtd->lsm_client->session);
-			rc = -EINVAL;
-			break;
+		if (copy_from_user(&mode, arg, sizeof(mode))) {
+			dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n",
+				__func__, "LSM_SET_FWK_MODE_CONFIG");
+			return -EFAULT;
 		}
-		mode = (u32 *)arg;
-		if (prtd->lsm_client->event_mode == *mode) {
+
+		dev_dbg(rtd->dev, "%s: ioctl %s, enable = %d\n",
+			__func__, "SNDRV_LSM_SET_FWK_MODE_CONFIG", mode);
+		if (prtd->lsm_client->event_mode == mode) {
 			dev_dbg(rtd->dev,
 				"%s: mode for %d already set to %d\n",
-				__func__, prtd->lsm_client->session, *mode);
+				__func__, prtd->lsm_client->session, mode);
 			rc = 0;
 		} else {
 			dev_dbg(rtd->dev, "%s: Event mode = %d\n",
-				 __func__, *mode);
-			rc = q6lsm_set_fwk_mode_cfg(prtd->lsm_client, *mode);
+				 __func__, mode);
+			rc = q6lsm_set_fwk_mode_cfg(prtd->lsm_client, mode);
 			if (!rc)
-				prtd->lsm_client->event_mode = *mode;
+				prtd->lsm_client->event_mode = mode;
 			else
 				dev_err(rtd->dev,
 					"%s: set event mode failed %d\n",
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c5a6e0b1..78bd632 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -1826,7 +1826,7 @@
 		filt->addr = start;
 		if (filt->range && !filt->size && !filt->sym_to) {
 			filt->size = size;
-			no_size = !!size;
+			no_size = !size;
 		}
 	}
 
@@ -1840,7 +1840,7 @@
 		if (err)
 			return err;
 		filt->size = start + size - filt->addr;
-		no_size = !!size;
+		no_size = !size;
 	}
 
 	/* The very last symbol in kallsyms does not imply a particular size */
diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c
index 4af4707..e717fed 100644
--- a/tools/testing/selftests/x86/ldt_gdt.c
+++ b/tools/testing/selftests/x86/ldt_gdt.c
@@ -403,6 +403,51 @@
 	}
 }
 
+#ifdef __i386__
+
+#ifndef SA_RESTORE
+#define SA_RESTORER 0x04000000
+#endif
+
+/*
+ * The UAPI header calls this 'struct sigaction', which conflicts with
+ * glibc.  Sigh.
+ */
+struct fake_ksigaction {
+	void *handler;  /* the real type is nasty */
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+	unsigned char sigset[8];
+};
+
+static void fix_sa_restorer(int sig)
+{
+	struct fake_ksigaction ksa;
+
+	if (syscall(SYS_rt_sigaction, sig, NULL, &ksa, 8) == 0) {
+		/*
+		 * glibc has a nasty bug: it sometimes writes garbage to
+		 * sa_restorer.  This interacts quite badly with anything
+		 * that fiddles with SS because it can trigger legacy
+		 * stack switching.  Patch it up.  See:
+		 *
+		 * https://sourceware.org/bugzilla/show_bug.cgi?id=21269
+		 */
+		if (!(ksa.sa_flags & SA_RESTORER) && ksa.sa_restorer) {
+			ksa.sa_restorer = NULL;
+			if (syscall(SYS_rt_sigaction, sig, &ksa, NULL,
+				    sizeof(ksa.sigset)) != 0)
+				err(1, "rt_sigaction");
+		}
+	}
+}
+#else
+static void fix_sa_restorer(int sig)
+{
+	/* 64-bit glibc works fine. */
+}
+#endif
+
 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
 		       int flags)
 {
@@ -414,6 +459,7 @@
 	if (sigaction(sig, &sa, 0))
 		err(1, "sigaction");
 
+	fix_sa_restorer(sig);
 }
 
 static jmp_buf jmpbuf;