Merge "msm: kgsl: Fix leak when preemption init fails"
diff --git a/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt b/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt
index ce2d8bd..1114308 100644
--- a/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt
+++ b/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt
@@ -2,12 +2,15 @@
 
 Required properties:
 -compatible : Should be one of
-	To communicate with modem
+	To communicate with adsp
 		qcom,smp2pgpio_client_rdbg_2_in (inbound)
 		qcom,smp2pgpio_client_rdbg_2_out (outbound)
 	To communicate with modem
 		qcom,smp2pgpio_client_rdbg_1_in (inbound)
 		qcom,smp2pgpio_client_rdbg_1_out (outbound)
+	To communicate with cdsp
+		qcom,smp2pgpio_client_rdbg_5_in (inbound)
+		qcom,smp2pgpio_client_rdbg_5_out (outbound)
 -gpios : the relevant gpio pins of the entry.
 
 Example:
diff --git a/Documentation/devicetree/bindings/cnss/icnss.txt b/Documentation/devicetree/bindings/cnss/icnss.txt
index c801e848..700a8f7 100644
--- a/Documentation/devicetree/bindings/cnss/icnss.txt
+++ b/Documentation/devicetree/bindings/cnss/icnss.txt
@@ -28,6 +28,7 @@
   - qcom,icnss-vadc: VADC handle for vph_pwr read APIs.
   - qcom,icnss-adc_tm: VADC handle for vph_pwr notification APIs.
   - qcom,smmu-s1-bypass: Boolean context flag to set SMMU to S1 bypass
+  - qcom,wlan-msa-fixed-region: phandle, specifier pairs to children of /reserved-memory
 
 Example:
 
@@ -54,6 +55,7 @@
 		   <0 140 0 /* CE10 */ >,
 		   <0 141 0 /* CE11 */ >;
         qcom,wlan-msa-memory = <0x200000>;
+	qcom,wlan-msa-fixed-region = <&wlan_msa_mem>;
 	qcom,smmu-s1-bypass;
 	vdd-0.8-cx-mx-supply = <&pm8998_l5>;
 	qcom,vdd-0.8-cx-mx-config = <800000 800000 2400 1000>;
diff --git a/Documentation/devicetree/bindings/display/msm/sde.txt b/Documentation/devicetree/bindings/display/msm/sde.txt
index d3222fb..dd668cb 100644
--- a/Documentation/devicetree/bindings/display/msm/sde.txt
+++ b/Documentation/devicetree/bindings/display/msm/sde.txt
@@ -52,6 +52,9 @@
 				The number of offsets defined should reflect the
 				amount of mixers that can drive data to a panel
 				interface.
+- qcom,sde-dspp-top-off:		Offset address for the dspp top block.
+				The offset is calculated from register "mdp_phys"
+				defined in reg property.
 - qcom,sde-dspp-off: 		Array of offset addresses for the available dspp
 				blocks. These offsets are calculated from
 				register "mdp_phys" defined in reg property.
@@ -207,6 +210,7 @@
 				e.g. qcom,sde-dspp-blocks
 				-- qcom,sde-dspp-pcc: offset and version of PCC hardware
 				-- qcom,sde-dspp-gc: offset and version of GC hardware
+				-- qcom,sde-dspp-igc: offset and version of IGC hardware
 				-- qcom,sde-dspp-hsic: offset and version of global PA adjustment
 				-- qcom,sde-dspp-memcolor: offset and version of PA memcolor hardware
 				-- qcom,sde-dspp-sixzone: offset and version of PA sixzone hardware
@@ -424,6 +428,7 @@
 		     0x00002600 0x00002800>;
     qcom,sde-mixer-off = <0x00045000 0x00046000
 			0x00047000 0x0004a000>;
+    qcom,sde-dspp-top-off = <0x1300>;
     qcom,sde-dspp-off = <0x00055000 0x00057000>;
     qcom,sde-dspp-ad-off = <0x24000 0x22800>;
     qcom,sde-dspp-ad-version = <0x00030000>;
@@ -481,6 +486,7 @@
     qcom,sde-sspp-src-size = <0x100>;
     qcom,sde-mixer-size = <0x100>;
     qcom,sde-ctl-size = <0x100>;
+    qcom,sde-dspp-top-size = <0xc>;
     qcom,sde-dspp-size = <0x100>;
     qcom,sde-intf-size = <0x100>;
     qcom,sde-dsc-size = <0x100>;
@@ -599,6 +605,7 @@
     };
 
     qcom,sde-dspp-blocks {
+        qcom,sde-dspp-igc = <0x0 0x00010000>;
         qcom,sde-dspp-pcc = <0x1700 0x00010000>;
         qcom,sde-dspp-gc = <0x17c0 0x00010000>;
         qcom,sde-dspp-hsic = <0x0 0x00010000>;
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
index 8598d0c..26cd70e 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
@@ -28,6 +28,9 @@
 	Value type: <string>
 	Definition: Should contain "qcom,pdc-<target>"
 
+	* "qcom,pdc-sdm845": For sdm845 pin data
+	* "qcom,pdc-sdm670": For sdm670 pin data
+
 - reg:
 	Usage: required
 	Value type: <prop-encoded-array>
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index 375eaf2..196f6f7 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -91,6 +91,11 @@
 		  a four level page table configuration. Set to use a three
 		  level page table instead.
 
+- qcom,no-asid-retention:
+		  Some hardware may lose internal state for asid after
+		  retention. No cache invalidation operations involving asid
+		  may be used.
+
 - clocks        : List of clocks to be used during SMMU register access. See
                   Documentation/devicetree/bindings/clock/clock-bindings.txt
                   for information about the format. For each clock specified
diff --git a/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt b/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt
index 937ccb9..58bac0b 100644
--- a/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt
@@ -120,6 +120,8 @@
 				minimum allowable length configuration value.
 - qcom,sde-ubwc-swizzle:	A u32 property to specify the default UBWC
 				swizzle configuration value.
+- qcom,rot-reg-bus:		Property to provide Bus scaling for register
+				access for rotator blocks.
 
 Subnode properties:
 - compatible:		Compatible name used in smmu v2.
@@ -189,6 +191,16 @@
 		cache-slice-names = "rotator";
 		cache-slices = <&llcc 4>;
 
+		rot_reg: qcom,rot-reg-bus {
+			qcom,msm-bus,name = "mdss_rot_reg";
+			qcom,msm-bus,num-cases = <2>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,active-only;
+			qcom,msm-bus,vectors-KBps =
+				<1 590 0 0>,
+				<1 590 0 76800>;
+		};
+
 		smmu_rot_unsec: qcom,smmu_rot_unsec_cb {
 			compatible = "qcom,smmu_sde_rot_unsec";
 			iommus = <&mdp_smmu 0xe00>;
diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt
index a9480be..6109fad 100644
--- a/Documentation/devicetree/bindings/usb/msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/msm-phy.txt
@@ -152,6 +152,7 @@
    and reset lines used by this controller.
  - reset-names: reset signal name strings sorted in the same order as the resets
    property.
+ - qcom,qusb-phy-reg-offset: Provides important phy register offsets in an order defined in phy driver.
 
 Optional properties:
  - reg-names: Additional registers corresponding with the following:
@@ -174,7 +175,6 @@
  - qcom,hold-reset: Indicates that hold QUSB PHY into reset state.
  - qcom,phy-clk-scheme: Should be one of "cml" or "cmos" if ref_clk_addr is provided.
  - qcom,major-rev: provide major revision number to differentiate power up sequence. default is 2.0
- - qcom,phy-auto-resume-offset: Provides phy auto-resume register offset.
 
 Example:
 	qusb_phy: qusb@f9b39000 {
@@ -185,6 +185,13 @@
 		vdda18-supply = <&pm8994_l6>;
 		vdda33-supply = <&pm8994_l24>;
 		qcom,vdd-voltage-level = <1 5 7>;
+		qcom,qusb-phy-reg-offset =
+			<0x240 /* QUSB2PHY_PORT_TUNE1 */
+			 0x1a0 /* QUSB2PHY_PLL_COMMON_STATUS_ONE */
+			 0x210 /* QUSB2PHY_PWR_CTRL1 */
+			 0x230 /* QUSB2PHY_INTR_CTRL */
+			 0x0a8 /* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE */
+			 0x254>; /* QUSB2PHY_TEST1 */
 		qcom,efuse-bit-pos = <21>;
 		qcom,efuse-num-bits = <3>;
 
diff --git a/Documentation/misc-devices/qcom_invoke_driver.txt b/Documentation/misc-devices/qcom_invoke_driver.txt
new file mode 100644
index 0000000..38c976a
--- /dev/null
+++ b/Documentation/misc-devices/qcom_invoke_driver.txt
@@ -0,0 +1,54 @@
+Introduction:
+=============
+Invoke driver is a misc driver which helps communication between non secure
+and secure world. Invoke driver communicates with secure side using SCM
+driver. To use invoke driver, open must be called on invoke device i.e.
+/dev/invoke. Invoke driver exposes only one IOCTL invoke which passes
+userspace request to TZ.
+
+SW Architecture
+===============
+Following is SW stack for Invoke driver.
+
++++++++++++++++++++++++++++++++++++++++++
++           Applications                +
++++++++++++++++++++++++++++++++++++++++++
++          System Layer                 +
++++++++++++++++++++++++++++++++++++++++++
++             Kernel                    +
++       +++++++++++++++++++             +
++       +  Invoke driver  +             +
++       +++++++++++++++++++             +
++       +   SCM Driver    +             +
++++++++++++++++++++++++++++++++++++++++++
+               ||
+               ||
+               \/
++++++++++++++++++++++++++++++++++++++++++
++           Trust Zone                  +
++    +++++++++++    +++++++++++         +
++    + TZ App1 +    + TZ App2 +         +
++++++++++++++++++++++++++++++++++++++++++
+
+
+Interfaces
+==========
+Invoke driver exposes INVOKE_IOCTL_INVOKE_REQ IOCTL for userspace to
+communicate with driver. More details of IOCTL are avilable in
+corresponding header file.
+
+
+Driver Parameters
+=================
+This driver is built and statically linked into the kernel; therefore,
+there are no module parameters supported by this driver.
+
+There are no kernel command line parameters supported by this driver.
+
+Power Management
+================
+TBD
+
+Dependencies
+============
+Invoke driver depends on SCM driver to communicate with TZ.
diff --git a/Makefile b/Makefile
index 88cab97..9839cf4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 9
-SUBLEVEL = 36
+SUBLEVEL = 37
 EXTRAVERSION =
 NAME = Roaring Lionus
 
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d04e168..21c66eb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -117,7 +117,7 @@
 config ARM_DMA_IOMMU_ALIGNMENT
 	int "Maximum PAGE_SIZE order of alignment for DMA IOMMU buffers"
 	range 4 9
-	default 8
+	default 9
 	help
 	  DMA mapping framework by default aligns all buffers to the smallest
 	  PAGE_SIZE order which is greater than or equal to the requested buffer
@@ -230,6 +230,9 @@
 config ARCH_MTD_XIP
 	bool
 
+config ARCH_WANT_KMAP_ATOMIC_FLUSH
+	bool
+
 config VECTORS_BASE
 	hex
 	default 0xffff0000 if MMU || CPU_HIGH_VECTOR
@@ -567,6 +570,7 @@
        select SPARSE_IRQ
        select USE_OF
        select PINCTRL
+       select ARCH_WANT_KMAP_ATOMIC_FLUSH
        help
          Support for Qualcomm MSM/QSD based systems.  This runs on the
          apps processor of the MSM/QSD and depends on a shared memory
@@ -1760,6 +1764,29 @@
 
 source "mm/Kconfig"
 
+choice
+	prompt "Virtual Memory Reclaim"
+	default NO_VM_RECLAIM
+	help
+	  Select the method of reclaiming virtual memory
+
+config ENABLE_VMALLOC_SAVING
+	bool "Reclaim memory for each subsystem"
+	help
+	  Enable this config to reclaim the virtual space belonging
+	  to any subsystem which is expected to have a lifetime of
+	  the entire system. This feature allows lowmem to be non-
+	  contiguous.
+
+config NO_VM_RECLAIM
+	bool "Do not reclaim memory"
+	help
+	  Do not reclaim any memory. This might result in less lowmem
+	  and wasting virtual memory space which could otherwise be
+	  reclaimed by using any of the other two config options.
+
+endchoice
+
 config FORCE_MAX_ZONEORDER
 	int "Maximum zone order"
 	default "12" if SOC_AM33XX
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index d02f818..5d73327 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/highmem.h>
 #include <linux/interrupt.h>
@@ -147,3 +148,58 @@
 
 	return (void *)vaddr;
 }
+
+#ifdef CONFIG_ARCH_WANT_KMAP_ATOMIC_FLUSH
+static void kmap_remove_unused_cpu(int cpu)
+{
+	int start_idx, idx, type;
+
+	pagefault_disable();
+	type = kmap_atomic_idx();
+	start_idx = type + 1 + KM_TYPE_NR * cpu;
+
+	for (idx = start_idx; idx < KM_TYPE_NR + KM_TYPE_NR * cpu; idx++) {
+		unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+		pte_t ptep;
+
+		ptep = get_top_pte(vaddr);
+		if (ptep)
+			set_top_pte(vaddr, __pte(0));
+	}
+	pagefault_enable();
+}
+
+static void kmap_remove_unused(void *unused)
+{
+	kmap_remove_unused_cpu(smp_processor_id());
+}
+
+void kmap_atomic_flush_unused(void)
+{
+	on_each_cpu(kmap_remove_unused, NULL, 1);
+}
+
+static int hotplug_kmap_atomic_callback(struct notifier_block *nfb,
+					unsigned long action, void *hcpu)
+{
+	switch (action & (~CPU_TASKS_FROZEN)) {
+	case CPU_DYING:
+		kmap_remove_unused_cpu((int)hcpu);
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block hotplug_kmap_atomic_notifier = {
+	.notifier_call = hotplug_kmap_atomic_callback,
+};
+
+static int __init init_kmap_atomic(void)
+{
+	return register_hotcpu_notifier(&hotplug_kmap_atomic_notifier);
+}
+early_initcall(init_kmap_atomic);
+#endif
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 370581a..483d126 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -469,6 +469,54 @@
 #endif
 }
 
+#define MLK(b, t) (b), (t), (((t) - (b)) >> 10)
+#define MLM(b, t) (b), (t), (((t) - (b)) >> 20)
+#define MLK_ROUNDUP(b, t) (b), (t), (DIV_ROUND_UP(((t) - (b)), SZ_1K))
+
+#ifdef CONFIG_ENABLE_VMALLOC_SAVING
+static void print_vmalloc_lowmem_info(void)
+{
+	struct memblock_region *reg, *prev_reg = NULL;
+
+	pr_notice(
+		"	   vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n",
+		MLM((unsigned long)high_memory, VMALLOC_END));
+
+	for_each_memblock_rev(memory, reg) {
+		phys_addr_t start_phys = reg->base;
+		phys_addr_t end_phys = reg->base + reg->size;
+
+		if (start_phys > arm_lowmem_limit)
+			continue;
+
+		if (end_phys > arm_lowmem_limit)
+			end_phys = arm_lowmem_limit;
+
+		if (prev_reg == NULL) {
+			prev_reg = reg;
+
+			pr_notice(
+			"	   lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n",
+			MLM((unsigned long)__va(start_phys),
+			(unsigned long)__va(end_phys)));
+
+			continue;
+		}
+
+		pr_notice(
+		"	   vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n",
+		MLM((unsigned long)__va(end_phys),
+		(unsigned long)__va(prev_reg->base)));
+
+
+		pr_notice(
+		"	   lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n",
+		MLM((unsigned long)__va(start_phys),
+		(unsigned long)__va(end_phys)));
+	}
+}
+#endif
+
 /*
  * mem_init() marks the free areas in the mem_map and tells us how much
  * memory is free.  This is done after various parts of the system have
@@ -497,9 +545,6 @@
 
 	mem_init_print_info(NULL);
 
-#define MLK(b, t) b, t, ((t) - (b)) >> 10
-#define MLM(b, t) b, t, ((t) - (b)) >> 20
-#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
 
 	pr_notice("Virtual kernel memory layout:\n"
 			"    vector  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
@@ -507,29 +552,34 @@
 			"    DTCM    : 0x%08lx - 0x%08lx   (%4ld kB)\n"
 			"    ITCM    : 0x%08lx - 0x%08lx   (%4ld kB)\n"
 #endif
-			"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
-			"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
-			"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
-#ifdef CONFIG_HIGHMEM
-			"    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)\n"
-#endif
-#ifdef CONFIG_MODULES
-			"    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
-#endif
-			"      .text : 0x%p" " - 0x%p" "   (%4td kB)\n"
-			"      .init : 0x%p" " - 0x%p" "   (%4td kB)\n"
-			"      .data : 0x%p" " - 0x%p" "   (%4td kB)\n"
-			"       .bss : 0x%p" " - 0x%p" "   (%4td kB)\n",
-
+			"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n",
 			MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) +
 				(PAGE_SIZE)),
 #ifdef CONFIG_HAVE_TCM
 			MLK(DTCM_OFFSET, (unsigned long) dtcm_end),
 			MLK(ITCM_OFFSET, (unsigned long) itcm_end),
 #endif
-			MLK(FIXADDR_START, FIXADDR_END),
+			MLK(FIXADDR_START, FIXADDR_END));
+#ifdef CONFIG_ENABLE_VMALLOC_SAVING
+	print_vmalloc_lowmem_info();
+#else
+	printk(KERN_NOTICE
+		   "    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		   "    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n",
 			MLM(VMALLOC_START, VMALLOC_END),
-			MLM(PAGE_OFFSET, (unsigned long)high_memory),
+			MLM(PAGE_OFFSET, (unsigned long)high_memory));
+#endif
+	printk(KERN_NOTICE
+#ifdef CONFIG_HIGHMEM
+		   "    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+#endif
+#ifdef CONFIG_MODULES
+		   "    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+#endif
+		   "      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
+		   "      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
+		   "      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"
+		   "       .bss : 0x%p" " - 0x%p" "   (%4d kB)\n",
 #ifdef CONFIG_HIGHMEM
 			MLM(PKMAP_BASE, (PKMAP_BASE) + (LAST_PKMAP) *
 				(PAGE_SIZE)),
@@ -543,10 +593,6 @@
 			MLK_ROUNDUP(_sdata, _edata),
 			MLK_ROUNDUP(__bss_start, __bss_stop));
 
-#undef MLK
-#undef MLM
-#undef MLK_ROUNDUP
-
 	/*
 	 * Check boundaries twice: Some fundamental inconsistencies can
 	 * be detected at build time already.
@@ -573,6 +619,11 @@
 }
 
 #ifdef CONFIG_DEBUG_RODATA
+#undef MLK
+#undef MLM
+#undef MLK_ROUNDUP
+
+#ifdef CONFIG_ARM_KERNMEM_PERMS
 struct section_perm {
 	const char *name;
 	unsigned long start;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index f7c7413..81bfc38 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1168,6 +1168,19 @@
 	 */
 	vmalloc_limit = (u64)(uintptr_t)vmalloc_min - PAGE_OFFSET + PHYS_OFFSET;
 
+#ifdef CONFIG_ENABLE_VMALLOC_SAVING
+	struct memblock_region *prev_reg = NULL;
+
+	for_each_memblock(memory, reg) {
+		if (prev_reg == NULL) {
+			prev_reg = reg;
+			continue;
+		}
+		vmalloc_limit += reg->base - (prev_reg->base + prev_reg->size);
+		prev_reg = reg;
+	}
+#endif
+
 	for_each_memblock(memory, reg) {
 		phys_addr_t block_start = reg->base;
 		phys_addr_t block_end = reg->base + reg->size;
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 84867ba..842c38a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -108,6 +108,7 @@
 	select POWER_SUPPLY
 	select SPARSE_IRQ
 	select SYSCTL_EXCEPTION_TRACE
+	select THREAD_INFO_IN_TASK
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 3c8eaf8..20288fe 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -2,6 +2,28 @@
 dtb-$(CONFIG_ARCH_QCOM)	+= msm8996-mtp.dtb
 dtb-$(CONFIG_ARCH_QCOM)	+= apq8096-db820c.dtb
 
+ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
+	dtbo-$(CONFIG_ARCH_SDM845) += \
+		sdm845-cdp-overlay.dtbo \
+		sdm845-mtp-overlay.dtbo \
+		sdm845-qrd-overlay.dtbo \
+		sdm845-v2-cdp-overlay.dtbo \
+		sdm845-v2-mtp-overlay.dtbo \
+		sdm845-v2-qrd-overlay.dtbo \
+		sdm845-4k-panel-mtp-overlay.dtbo \
+		sdm845-4k-panel-cdp-overlay.dtbo \
+		sdm845-4k-panel-qrd-overlay.dtbo
+
+sdm845-cdp-overlay.dtbo-base := sdm845.dtb
+sdm845-mtp-overlay.dtbo-base := sdm845.dtb
+sdm845-qrd-overlay.dtbo-base := sdm845.dtb
+sdm845-v2-cdp-overlay.dtbo-base := sdm845-v2.dtb
+sdm845-v2-mtp-overlay.dtbo-base := sdm845-v2.dtb
+sdm845-v2-qrd-overlay.dtbo-base := sdm845-v2.dtb
+sdm845-4k-panel-mtp-overlay.dtbo-base := sdm845.dtb
+sdm845-4k-panel-cdp-overlay.dtbo-base := sdm845.dtb
+sdm845-4k-panel-qrd-overlay.dtbo-base := sdm845.dtb
+else
 dtb-$(CONFIG_ARCH_SDM845) += sdm845-sim.dtb \
 	sdm845-rumi.dtb \
 	sdm845-mtp.dtb \
@@ -14,16 +36,6 @@
 	sdm845-4k-panel-mtp.dtb \
 	sdm845-4k-panel-cdp.dtb \
 	sdm845-4k-panel-qrd.dtb
-
-ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
-	dtbo-$(CONFIG_ARCH_SDM845) += \
-		sdm845-cdp-overlay.dtbo \
-		sdm845-mtp-overlay.dtbo \
-		sdm845-qrd-overlay.dtbo
-
-sdm845-cdp-overlay.dtbo-base := sdm845.dtb
-sdm845-mtp-overlay.dtbo-base := sdm845.dtb
-sdm845-qrd-overlay.dtbo-base := sdm845.dtb
 endif
 
 dtb-$(CONFIG_ARCH_SDM670) += sdm670-rumi.dtb \
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
index 1a2ca5b..02fedbe 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
@@ -65,6 +65,7 @@
 		#iommu-cells = <2>;
 		qcom,skip-init;
 		qcom,use-3-lvl-tables;
+		qcom,no-asid-retention;
 		#global-interrupts = <1>;
 		#size-cells = <1>;
 		#address-cells = <1>;
@@ -339,10 +340,10 @@
 	apps_iommu_coherent_test_device {
 		compatible = "iommu-debug-test";
 		/*
-		 * This SID belongs to QUP1-DMA. We can't use a fake SID for
+		 * This SID belongs to TSIF. We can't use a fake SID for
 		 * the apps_smmu device.
 		 */
-		iommus = <&apps_smmu 0x3 0>;
+		iommus = <&apps_smmu 0x20 0>;
 		dma-coherent;
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
index 2194a42..da3cf00 100644
--- a/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
@@ -199,25 +199,11 @@
 		status = "disabled";
 	};
 
-	gpu_gx_domain_addr: syscon@0x5091508 {
-		compatible = "syscon";
-		reg = <0x5091508 0x4>;
-	};
-
-	gpu_gx_sw_reset: syscon@0x5091008 {
-		compatible = "syscon";
-		reg = <0x5091008 0x4>;
-	};
-
 	gpu_gx_gdsc: qcom,gdsc@0x509100c {
 		compatible = "qcom,gdsc";
 		regulator-name = "gpu_gx_gdsc";
 		reg = <0x509100c 0x4>;
-		domain-addr = <&gpu_gx_domain_addr>;
-		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/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
index 71eee1f..c8dc1f4 100644
--- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
@@ -436,7 +436,6 @@
 				qcom,max-current = <12>;
 				qcom,default-state = "off";
 				linux,name = "red";
-				linux,default-trigger = "battery-charging";
 			};
 
 			green_led: qcom,rgb_1 {
@@ -448,7 +447,6 @@
 				qcom,max-current = <12>;
 				qcom,default-state = "off";
 				linux,name = "green";
-				linux,default-trigger = "battery-full";
 			};
 
 			blue_led: qcom,rgb_2 {
@@ -460,7 +458,6 @@
 				qcom,max-current = <12>;
 				qcom,default-state = "off";
 				linux,name = "blue";
-				linux,default-trigger = "boot-indication";
 			};
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index 86e2948..cce0860 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -19,6 +19,7 @@
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
+		interrupt-parent = <&pdc>;
 
 		/* QUPv3 South SE mappings */
 		/* SE 0 pin mappings */
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi
index 8501d80..f03d9c2 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi
@@ -195,4 +195,12 @@
 		reg = <0xc300000 0x1000>, <0xc3f0004 0x4>;
 		reg-names = "phys_addr_base", "offset_addr";
 	};
+
+	pdc: interrupt-controller@b220000{
+		compatible = "qcom,pdc-sdm670";
+		reg = <0xb220000 0x400>;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&intc>;
+		interrupt-controller;
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sdm670-qupv3.dtsi
index 0fb455f..1fa6e26 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qupv3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-qupv3.dtsi
@@ -42,7 +42,7 @@
 		pinctrl-names = "default", "sleep";
 		pinctrl-0 = <&qupv3_se6_4uart_active>;
 		pinctrl-1 = <&qupv3_se6_4uart_sleep>;
-		interrupts-extended = <&intc GIC_SPI 607 0>,
+		interrupts-extended = <&pdc GIC_SPI 607 0>,
 				<&tlmm 48 0>;
 		status = "disabled";
 		qcom,wakeup-byte = <0xFD>;
@@ -60,7 +60,7 @@
 		pinctrl-names = "default", "sleep";
 		pinctrl-0 = <&qupv3_se7_4uart_active>;
 		pinctrl-1 = <&qupv3_se7_4uart_sleep>;
-		interrupts-extended = <&intc GIC_SPI 608 0>,
+		interrupts-extended = <&pdc GIC_SPI 608 0>,
 				<&tlmm 96 0>;
 		status = "disabled";
 		qcom,wakeup-byte = <0xFD>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 45d1fa4..3eae5f3 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -26,7 +26,7 @@
 	model = "Qualcomm Technologies, Inc. SDM670";
 	compatible = "qcom,sdm670";
 	qcom,msm-id = <336 0x0>;
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&pdc>;
 
 	aliases {
 		ufshc1 = &ufshc_mem; /* Embedded UFS slot */
@@ -416,6 +416,7 @@
 		reg = <0x17a00000 0x10000>,     /* GICD */
 		      <0x17a60000 0x100000>;    /* GICR * 8 */
 		interrupts = <1 9 4>;
+		interrupt-parent = <&intc>;
 	};
 
 	timer {
@@ -621,6 +622,38 @@
 		};
 	};
 
+	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";
+	};
+
 	cpuss_dump {
 		compatible = "qcom,cpuss-dump";
 		qcom,l1_i_cache0 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp-overlay.dts
new file mode 100644
index 0000000..0006937
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp-overlay.dts
@@ -0,0 +1,66 @@
+/* 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.
+ */
+
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-cdp.dtsi"
+#include "sdm845-cdp-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. sdm845 4K Display Panel CDP";
+	compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
+	qcom,msm-id = <321 0x0>;
+	qcom,board-id = <1 1>;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+	connectors = <&sde_rscc &sde_wb>;
+};
+
+&dsi_sharp_4k_dsc_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 52 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+	qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 52 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+	qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+	qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts
index 94d74e2..faf09c4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "sdm845.dtsi"
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-cdp.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp-overlay.dts
new file mode 100644
index 0000000..2675b96
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp-overlay.dts
@@ -0,0 +1,66 @@
+/* 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.
+ */
+
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-mtp.dtsi"
+#include "sdm845-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. sdm845 4K Display Panel MTP";
+	compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
+	qcom,msm-id = <321 0x0>;
+	qcom,board-id = <8 1>;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+	connectors = <&sde_rscc &sde_wb &sde_dp>;
+};
+
+&dsi_sharp_4k_dsc_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 52 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+	qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 52 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+	qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+	qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts
index fca87e1..2ae9345 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "sdm845.dtsi"
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-mtp.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts
new file mode 100644
index 0000000..39c9d37
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd-overlay.dts
@@ -0,0 +1,32 @@
+/* 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.
+ */
+
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-qrd.dtsi"
+#include "sdm845-qrd-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. sdm845 4K Display Panel QRD";
+	compatible = "qcom,sdm845-qrd", "qcom,sdm845", "qcom,qrd";
+	qcom,msm-id = <321 0x0>;
+	qcom,board-id = <11 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd.dts
index 6171c7b..5951f6d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-qrd.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "sdm845.dtsi"
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-qrd.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi b/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
index 3ce5611..5fbb1db 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
@@ -572,6 +572,18 @@
 			qcom,prio = <2>;
 		};
 
+		mas_xm_pcie_0: mas-xm-pcie-0 {
+			cell-id = <MSM_BUS_MASTER_PCIE>;
+			label = "mas-xm-pcie-0";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,qport = <5>;
+			qcom,connections = <&slv_qns_pcie_a1noc_snoc>;
+			qcom,bus-dev = <&fab_aggre1_noc>;
+			qcom,ap-owned;
+			qcom,prio = <2>;
+		};
+
 		mas_qhm_a2noc_cfg: mas-qhm-a2noc-cfg {
 			cell-id = <MSM_BUS_MASTER_A2NOC_CFG>;
 			label = "mas-qhm-a2noc-cfg";
@@ -648,18 +660,6 @@
 			qcom,prio = <2>;
 		};
 
-		mas_xm_pcie_0: mas-xm-pcie-0 {
-			cell-id = <MSM_BUS_MASTER_PCIE>;
-			label = "mas-xm-pcie-0";
-			qcom,buswidth = <8>;
-			qcom,agg-ports = <1>;
-			qcom,qport = <5>;
-			qcom,connections = <&slv_qns_pcie_snoc>;
-			qcom,bus-dev = <&fab_aggre1_noc>;
-			qcom,ap-owned;
-			qcom,prio = <2>;
-		};
-
 		mas_xm_qdss_etr: mas-xm-qdss-etr {
 			cell-id = <MSM_BUS_MASTER_QDSS_ETR>;
 			label = "mas-xm-qdss-etr";
@@ -715,6 +715,7 @@
 			qcom,agg-ports = <1>;
 			qcom,connections = <&slv_qns_camnoc_uncomp>;
 			qcom,bus-dev = <&fab_camnoc_virt>;
+			qcom,bcms = <&bcm_mm1>;
 		};
 
 		mas_qxm_camnoc_hf1_uncomp: mas-qxm-camnoc-hf1-uncomp {
@@ -724,6 +725,7 @@
 			qcom,agg-ports = <1>;
 			qcom,connections = <&slv_qns_camnoc_uncomp>;
 			qcom,bus-dev = <&fab_camnoc_virt>;
+			qcom,bcms = <&bcm_mm1>;
 		};
 
 		mas_qxm_camnoc_sf_uncomp: mas-qxm-camnoc-sf-uncomp {
@@ -733,6 +735,7 @@
 			qcom,agg-ports = <1>;
 			qcom,connections = <&slv_qns_camnoc_uncomp>;
 			qcom,bus-dev = <&fab_camnoc_virt>;
+			qcom,bcms = <&bcm_mm1>;
 		};
 
 		mas_qhm_spdm: mas-qhm-spdm {
@@ -1222,6 +1225,19 @@
 			qcom,prio = <2>;
 		};
 
+		mas_xm_gic: mas-xm-gic {
+			cell-id = <MSM_BUS_MASTER_GIC>;
+			label = "mas-xm-gic";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,qport = <0>;
+			qcom,connections = <&slv_qxs_imem &slv_qns_memnoc_gc>;
+			qcom,bus-dev = <&fab_system_noc>;
+			qcom,bcms = <&bcm_sn12>;
+			qcom,ap-owned;
+			qcom,prio = <1>;
+		};
+
 		mas_alc: mas-alc {
 			cell-id = <MSM_BUS_MASTER_ALC>;
 			label = "mas-alc";
@@ -1315,6 +1331,15 @@
 			qcom,bcms = <&bcm_sn9>;
 		};
 
+		slv_qns_pcie_a1noc_snoc:slv-qns-pcie-a1noc-snoc {
+			cell-id = <MSM_BUS_SLAVE_ANOC_PCIE_A1NOC_SNOC>;
+			label = "slv-qns-pcie-a1noc-snoc";
+			qcom,buswidth = <16>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_aggre1_noc>;
+			qcom,connections = <&mas_qnm_pcie_anoc>;
+		};
+
 		slv_qns_a2noc_snoc:slv-qns-a2noc-snoc {
 			cell-id = <MSM_BUS_A2NOC_SNOC_SLV>;
 			label = "slv-qns-a2noc-snoc";
@@ -1348,7 +1373,6 @@
 			qcom,buswidth = <32>;
 			qcom,agg-ports = <1>;
 			qcom,bus-dev = <&fab_camnoc_virt>;
-			qcom,bcms = <&bcm_mm1>;
 		};
 
 		slv_qhs_a1_noc_cfg:slv-qhs-a1-noc-cfg {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
index 5db4c35..9d799cb 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
@@ -153,6 +153,7 @@
 		status = "ok";
 		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
 		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
 		clock-rates = <24000000>;
 	};
 
@@ -192,6 +193,7 @@
 		status = "ok";
 		clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
 		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
 		clock-rates = <24000000>;
 	};
 
@@ -234,6 +236,7 @@
 		status = "ok";
 		clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
 		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
 		clock-rates = <24000000>;
 	};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
index 5db4c35..ab6ba18 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
@@ -153,6 +153,7 @@
 		status = "ok";
 		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
 		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
 		clock-rates = <24000000>;
 	};
 
@@ -192,6 +193,7 @@
 		status = "ok";
 		clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
 		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
 		clock-rates = <24000000>;
 	};
 
@@ -234,6 +236,7 @@
 		status = "ok";
 		clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
 		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
 		clock-rates = <24000000>;
 	};
 
@@ -333,7 +336,7 @@
 		compatible = "qcom,cam-sensor";
 		reg = <0x02>;
 		csiphy-sd-index = <2>;
-		sensor-position-roll = <90>;
+		sensor-position-roll = <270>;
 		sensor-position-pitch = <0>;
 		sensor-position-yaw = <0>;
 		eeprom-src = <&eeprom_front>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts
index 4747c99..efc78e0 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts
@@ -15,9 +15,11 @@
 
 #include <dt-bindings/clock/qcom,gcc-sdm845.h>
 #include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
 #include <dt-bindings/clock/qcom,rpmh.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-cdp.dtsi"
 #include "sdm845-cdp-audio-overlay.dtsi"
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dts b/arch/arm64/boot/dts/qcom/sdm845-cdp.dts
index 22e3aea..0a6aa5e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dts
@@ -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
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "sdm845.dtsi"
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-cdp.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index dee2ec2..c4ec012 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -13,7 +13,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include "sdm845-camera-sensor-cdp.dtsi"
 
-/ {
+&vendor {
 	bluetooth: bt_wcn3990 {
 		compatible = "qca,wcn3990";
 		qca,bt-vdd-io-supply = <&pm8998_s3>;
@@ -188,7 +188,7 @@
 	qcom,batteryless-platform;
 };
 
-/ {
+&vendor {
 	extcon_usb1: extcon_usb1 {
 		compatible = "linux,extcon-usb-gpio";
 		id-gpio = <&pmi8998_gpios 9 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
index 1ce68e1..fc80330 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
@@ -195,10 +195,10 @@
 
 			qcom,gpu-pwrlevel@3 {
 				reg = <3>;
-				qcom,gpu-freq = <280000000>;
-				qcom,bus-freq = <4>;
-				qcom,bus-min = <3>;
-				qcom,bus-max = <5>;
+				qcom,gpu-freq = <0>;
+				qcom,bus-freq = <0>;
+				qcom,bus-min = <0>;
+				qcom,bus-max = <0>;
 			};
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts
index 52c0f05..45941a1 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts
@@ -15,9 +15,11 @@
 
 #include <dt-bindings/clock/qcom,gcc-sdm845.h>
 #include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
 #include <dt-bindings/clock/qcom,rpmh.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-mtp.dtsi"
 #include "sdm845-audio-overlay.dtsi"
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
index f7af60c..e74b342 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
@@ -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
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "sdm845.dtsi"
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-mtp.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index fb31b05..1453975 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -14,7 +14,7 @@
 #include "sdm845-camera-sensor-mtp.dtsi"
 #include "smb1355.dtsi"
 
-/ {
+&vendor {
 	bluetooth: bt_wcn3990 {
 		compatible = "qca,wcn3990";
 		qca,bt-vdd-io-supply = <&pm8998_s3>;
@@ -260,7 +260,7 @@
 	pinctrl-1 = <&flash_led3_front_dis>;
 };
 
-/{
+&vendor {
 	mtp_batterydata: qcom,battery-data {
 		qcom,batt-id-range-pct = <15>;
 		#include "fg-gen3-batterydata-itech-3000mah.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-qrd-overlay.dts
index 5729d76..6cead9d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd-overlay.dts
@@ -15,9 +15,11 @@
 
 #include <dt-bindings/clock/qcom,gcc-sdm845.h>
 #include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
 #include <dt-bindings/clock/qcom,rpmh.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-qrd.dtsi"
 #include "sdm845-qrd-audio-overlay.dtsi"
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dts b/arch/arm64/boot/dts/qcom/sdm845-qrd.dts
index 228b924..6cb7815 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "sdm845.dtsi"
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-qrd.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
index 7982625..9cf18b7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
@@ -13,7 +13,7 @@
 #include "smb1355.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 
-/{
+&vendor {
 	bluetooth: bt_wcn3990 {
 		compatible = "qca,wcn3990";
 		qca,bt-vdd-io-supply = <&pm8998_s3>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
index bde64b9..6fb4f37 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
@@ -496,7 +496,7 @@
 	qcom,display-topology = <1 1 1>,
 				<2 2 1>, /* dsc merge */
 				<2 1 1>; /* 3d mux */
-	qcom,default-topology-index = <0>;
+	qcom,default-topology-index = <1>;
 };
 
 &dsi_nt35597_truly_dsc_video {
@@ -506,7 +506,7 @@
 	qcom,display-topology = <1 1 1>,
 				<2 2 1>, /* dsc merge */
 				<2 1 1>; /* 3d mux */
-	qcom,default-topology-index = <0>;
+	qcom,default-topology-index = <1>;
 };
 
 &dsi_sharp_4k_dsc_video {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index 3153e66..e313e58 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -57,6 +57,9 @@
 				      0x48000 0x49000 0x4a000>;
 		qcom,sde-mixer-size = <0x320>;
 
+		qcom,sde-dspp-top-off = <0x1300>;
+		qcom,sde-dspp-top-size = <0xc>;
+
 		qcom,sde-dspp-off = <0x55000 0x57000 0x59000 0x5b000>;
 		qcom,sde-dspp-size = <0x17e0>;
 
@@ -188,8 +191,10 @@
 		};
 
 		qcom,sde-dspp-blocks {
+			qcom,sde-dspp-igc = <0x0 0x00030001>;
 			qcom,sde-dspp-vlut = <0xa00 0x00010008>;
 			qcom,sde-dspp-gamut = <0x1000 0x00040000>;
+			qcom,sde-dspp-pcc = <0x1700 0x00040000>;
 			qcom,sde-dspp-gc = <0x17c0 0x00010008>;
 		};
 
@@ -369,6 +374,17 @@
 		cache-slice-names = "rotator";
 		cache-slices = <&llcc 4>;
 
+		/* reg bus scale settings */
+		rot_reg: qcom,rot-reg-bus {
+			qcom,msm-bus,name = "mdss_rot_reg";
+			qcom,msm-bus,num-cases = <2>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,active-only;
+			qcom,msm-bus,vectors-KBps =
+				<1 590 0 0>,
+				<1 590 0 76800>;
+		};
+
 		smmu_rot_unsec: qcom,smmu_rot_unsec_cb {
 			compatible = "qcom,smmu_sde_rot_unsec";
 			iommus = <&apps_smmu 0x1090 0x0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
index 53cb27e..ac16d03 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
@@ -113,13 +113,24 @@
 	/* Primary USB port related QUSB2 PHY */
 	qusb_phy0: qusb@88e2000 {
 		compatible = "qcom,qusb2phy-v2";
-		reg = <0x088e2000 0x400>;
-		reg-names = "qusb_phy_base";
+		reg = <0x088e2000 0x400>,
+			<0x007801e8 0x4>;
+		reg-names = "qusb_phy_base", "efuse_addr";
 
+		qcom,efuse-bit-pos = <25>;
+		qcom,efuse-num-bits = <3>;
 		vdd-supply = <&pm8998_l1>;
 		vdda18-supply = <&pm8998_l12>;
 		vdda33-supply = <&pm8998_l24>;
 		qcom,vdd-voltage-level = <0 880000 880000>;
+		qcom,qusb-phy-reg-offset =
+			<0x240 /* QUSB2PHY_PORT_TUNE1 */
+			 0x1a0 /* QUSB2PHY_PLL_COMMON_STATUS_ONE */
+			 0x210 /* QUSB2PHY_PWR_CTRL1 */
+			 0x230 /* QUSB2PHY_INTR_CTRL */
+			 0x0a8 /* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE */
+			 0x254>; /* QUSB2PHY_TEST1 */
+
 		qcom,qusb-phy-init-seq =
 			/* <value reg_offset> */
 			   <0x23 0x210 /* PWR_CTRL1 */
@@ -133,7 +144,7 @@
 			    0x21 0x214 /* PWR_CTRL2 */
 			    0x00 0x220 /* IMP_CTRL1 */
 			    0x58 0x224 /* IMP_CTRL2 */
-			    0x32 0x240 /* TUNE1 */
+			    0x30 0x240 /* TUNE1 */
 			    0x29 0x244 /* TUNE2 */
 			    0xca 0x248 /* TUNE3 */
 			    0x04 0x24c /* TUNE4 */
@@ -141,8 +152,6 @@
 			    0x00 0x23c /* CHG_CTRL2 */
 			    0x22 0x210>; /* PWR_CTRL1 */
 
-		qcom,phy-auto-resume-offset = <0x254>;
-
 		phy_type= "utmi";
 		clocks = <&clock_rpmh RPMH_CXO_CLK>,
 			 <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
@@ -385,6 +394,14 @@
 		vdda18-supply = <&pm8998_l12>;
 		vdda33-supply = <&pm8998_l24>;
 		qcom,vdd-voltage-level = <0 880000 880000>;
+		qcom,qusb-phy-reg-offset =
+			<0x240 /* QUSB2PHY_PORT_TUNE1 */
+			 0x1a0 /* QUSB2PHY_PLL_COMMON_STATUS_ONE */
+			 0x210 /* QUSB2PHY_PWR_CTRL1 */
+			 0x230 /* QUSB2PHY_INTR_CTRL */
+			 0x0a8 /* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE */
+			 0x254>; /* QUSB2PHY_TEST1 */
+
 		qcom,qusb-phy-init-seq =
 			/* <value reg_offset> */
 			   <0x23 0x210 /* PWR_CTRL1 */
@@ -398,7 +415,7 @@
 			   0x21 0x214 /* PWR_CTRL2 */
 			   0x00 0x220 /* IMP_CTRL1 */
 			   0x58 0x224 /* IMP_CTRL2 */
-			   0x32 0x240 /* TUNE1 */
+			   0x20 0x240 /* TUNE1 */
 			   0x29 0x244 /* TUNE2 */
 			   0xca 0x248 /* TUNE3 */
 			   0x04 0x24c /* TUNE4 */
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-v2-cdp-overlay.dts
new file mode 100644
index 0000000..3cd7678
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-cdp-overlay.dts
@@ -0,0 +1,31 @@
+/* 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-cdp.dtsi"
+#include "sdm845-cdp-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 v2 CDP";
+	compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
+	qcom,msm-id = <321 0x20000>;
+	qcom,board-id = <1 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-cdp.dts b/arch/arm64/boot/dts/qcom/sdm845-v2-cdp.dts
index 8ab0593..66ee4c7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-cdp.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "sdm845-v2.dtsi"
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-cdp.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-v2-mtp-overlay.dts
new file mode 100644
index 0000000..e049357
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-mtp-overlay.dts
@@ -0,0 +1,31 @@
+/* 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-mtp.dtsi"
+#include "sdm845-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 v2 MTP";
+	compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
+	qcom,msm-id = <321 0x20000>;
+	qcom,board-id = <8 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-v2-mtp.dts
index 57c3e71..cea38e6 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-mtp.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "sdm845-v2.dtsi"
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-mtp.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-v2-qrd-overlay.dts
new file mode 100644
index 0000000..a5a32ab
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-qrd-overlay.dts
@@ -0,0 +1,31 @@
+/* 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-qrd.dtsi"
+#include "sdm845-qrd-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 v2 QRD";
+	compatible = "qcom,sdm845-qrd", "qcom,sdm845", "qcom,qrd";
+	qcom,msm-id = <321 0x20000>;
+	qcom,board-id = <11 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-qrd.dts b/arch/arm64/boot/dts/qcom/sdm845-v2-qrd.dts
index 8a9a544..9a87617 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-qrd.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "sdm845-v2.dtsi"
+#include "sdm845-sde-display.dtsi"
 #include "sdm845-qrd.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.dts b/arch/arm64/boot/dts/qcom/sdm845-v2.dts
new file mode 100644
index 0000000..d36d0fd
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.dts
@@ -0,0 +1,21 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+#include "sdm845-v2.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 v2 SoC";
+	compatible = "qcom,sdm845";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index fbbc382..1944014 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -476,6 +476,10 @@
 		method = "smc";
 	};
 
+	chosen {
+		bootargs = "rcupdate.rcu_expedited=1";
+	};
+
 	soc: soc { };
 
 	vendor: vendor {
@@ -641,7 +645,6 @@
 #include "sdm845-sde-pll.dtsi"
 #include "msm-rdbg.dtsi"
 #include "sdm845-sde.dtsi"
-#include "sdm845-sde-display.dtsi"
 #include "sdm845-qupv3.dtsi"
 
 &soc {
@@ -969,13 +972,13 @@
 		qcom,target-dev = <&l3_cpu0>;
 		qcom,cachemiss-ev = <0x17>;
 		qcom,core-dev-table =
-			<  300000  300000 >,
-			<  748800  576000 >,
-			<  979200  652800 >,
-			< 1209600  806400 >,
-			< 1516800  883200 >,
-			< 1593600  960000 >,
-			< 1708800 1094400 >;
+			<  300000  300000000 >,
+			<  748800  576000000 >,
+			<  979200  652800000 >,
+			< 1209600  806400000 >,
+			< 1516800  883200000 >,
+			< 1593600  960000000 >,
+			< 1708800 1094400000 >;
 	};
 
 	devfreq_l3lat_4: qcom,cpu4-l3lat-mon {
@@ -984,12 +987,12 @@
 		qcom,target-dev = <&l3_cpu4>;
 		qcom,cachemiss-ev = <0x17>;
 		qcom,core-dev-table =
-			<  300000  300000 >,
-			< 1036800  576000 >,
-			< 1190400  806400 >,
-			< 1574400  883200 >,
-			< 1804800  960000 >,
-			< 2092800 1094400 >;
+			<  300000  300000000 >,
+			< 1036800  576000000 >,
+			< 1190400  806400000 >,
+			< 1574400  883200000 >,
+			< 1804800  960000000 >,
+			< 2092800 1094400000 >;
 	};
 
 	cpu_pmu: cpu-pmu {
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 14243fb..b8f115b 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -86,7 +86,6 @@
 CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
 CONFIG_CPU_BOOST=y
 CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
-CONFIG_CPU_FREQ_MSM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 9f98841..992a30b 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -264,9 +264,15 @@
 CONFIG_PPP=y
 CONFIG_PPP_BSDCOMP=y
 CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
 CONFIG_PPPOLAC=y
 CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
 CONFIG_USB_USBNET=y
 CONFIG_WIL6210=m
 # CONFIG_WIL6210_TRACING is not set
@@ -514,6 +520,7 @@
 CONFIG_MSM_PERFORMANCE=y
 CONFIG_MSM_CDSP_LOADER=y
 CONFIG_MSM_AVTIMER=y
+CONFIG_QCOM_SMCINVOKE=y
 CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_PM=y
 CONFIG_MSM_QBT1000=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index cd4cbb1..d7f2629 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -271,9 +271,15 @@
 CONFIG_PPP=y
 CONFIG_PPP_BSDCOMP=y
 CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
 CONFIG_PPPOLAC=y
 CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
 CONFIG_USB_USBNET=y
 CONFIG_WIL6210=m
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
@@ -532,6 +538,7 @@
 CONFIG_MSM_PERFORMANCE=y
 CONFIG_MSM_CDSP_LOADER=y
 CONFIG_MSM_AVTIMER=y
+CONFIG_QCOM_SMCINVOKE=y
 CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_PM=y
 CONFIG_MSM_QBT1000=y
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 44e1d7f..28196b1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -1,7 +1,6 @@
 generic-y += bugs.h
 generic-y += clkdev.h
 generic-y += cputime.h
-generic-y += current.h
 generic-y += delay.h
 generic-y += div64.h
 generic-y += dma.h
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index a4ae545..ef5970e 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -241,14 +241,25 @@
 	.endm
 
 	/*
+	 * @dst: Result of per_cpu(sym, smp_processor_id())
 	 * @sym: The name of the per-cpu variable
-	 * @reg: Result of per_cpu(sym, smp_processor_id())
 	 * @tmp: scratch register
 	 */
-	.macro this_cpu_ptr, sym, reg, tmp
-	adr_l	\reg, \sym
+	.macro adr_this_cpu, dst, sym, tmp
+	adr_l	\dst, \sym
 	mrs	\tmp, tpidr_el1
-	add	\reg, \reg, \tmp
+	add	\dst, \dst, \tmp
+	.endm
+
+	/*
+	 * @dst: Result of READ_ONCE(per_cpu(sym, smp_processor_id()))
+	 * @sym: The name of the per-cpu variable
+	 * @tmp: scratch register
+	 */
+	.macro ldr_this_cpu dst, sym, tmp
+	adr_l	\dst, \sym
+	mrs	\tmp, tpidr_el1
+	ldr	\dst, [\dst, \tmp]
 	.endm
 
 /*
diff --git a/arch/arm64/include/asm/current.h b/arch/arm64/include/asm/current.h
new file mode 100644
index 0000000..86c4041
--- /dev/null
+++ b/arch/arm64/include/asm/current.h
@@ -0,0 +1,30 @@
+#ifndef __ASM_CURRENT_H
+#define __ASM_CURRENT_H
+
+#include <linux/compiler.h>
+
+#include <asm/sysreg.h>
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+/*
+ * We don't use read_sysreg() as we want the compiler to cache the value where
+ * possible.
+ */
+static __always_inline struct task_struct *get_current(void)
+{
+	unsigned long sp_el0;
+
+	asm ("mrs %0, sp_el0" : "=r" (sp_el0));
+
+	return (struct task_struct *)sp_el0;
+}
+
+#define current get_current()
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_CURRENT_H */
+
diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h
index 5394c84..d7a3c62 100644
--- a/arch/arm64/include/asm/percpu.h
+++ b/arch/arm64/include/asm/percpu.h
@@ -16,6 +16,8 @@
 #ifndef __ASM_PERCPU_H
 #define __ASM_PERCPU_H
 
+#include <asm/stack_pointer.h>
+
 static inline void set_my_cpu_offset(unsigned long off)
 {
 	asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory");
diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h
index 38b6a2b..8d5cbec 100644
--- a/arch/arm64/include/asm/perf_event.h
+++ b/arch/arm64/include/asm/perf_event.h
@@ -17,6 +17,8 @@
 #ifndef __ASM_PERF_EVENT_H
 #define __ASM_PERF_EVENT_H
 
+#include <asm/stack_pointer.h>
+
 #define	ARMV8_PMU_MAX_COUNTERS	32
 #define	ARMV8_PMU_COUNTER_MASK	(ARMV8_PMU_MAX_COUNTERS - 1)
 
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 0226447..d050d72 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -29,11 +29,22 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/percpu.h>
+
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/thread_info.h>
 
-#define raw_smp_processor_id() (current_thread_info()->cpu)
+DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
+
+/*
+ * We don't use this_cpu_read(cpu_number) as that has implicit writes to
+ * preempt_count, and associated (compiler) barriers, that we'd like to avoid
+ * the expense of. If we're preemptible, the value can be stale at use anyway.
+ * And we can't use this_cpu_ptr() either, as that winds up recursing back
+ * here under CONFIG_DEBUG_PREEMPT=y.
+ */
+#define raw_smp_processor_id() (*raw_cpu_ptr(&cpu_number))
 
 struct seq_file;
 
@@ -73,6 +84,7 @@
  */
 struct secondary_data {
 	void *stack;
+	struct task_struct *task;
 	long status;
 };
 
diff --git a/arch/arm64/include/asm/stack_pointer.h b/arch/arm64/include/asm/stack_pointer.h
new file mode 100644
index 0000000..ffcdf74
--- /dev/null
+++ b/arch/arm64/include/asm/stack_pointer.h
@@ -0,0 +1,9 @@
+#ifndef __ASM_STACK_POINTER_H
+#define __ASM_STACK_POINTER_H
+
+/*
+ * how to get the current stack pointer from C
+ */
+register unsigned long current_stack_pointer asm ("sp");
+
+#endif /* __ASM_STACK_POINTER_H */
diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/suspend.h
index b8a313f..de5600f 100644
--- a/arch/arm64/include/asm/suspend.h
+++ b/arch/arm64/include/asm/suspend.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_SUSPEND_H
 #define __ASM_SUSPEND_H
 
-#define NR_CTX_REGS 10
+#define NR_CTX_REGS 12
 #define NR_CALLEE_SAVED_REGS 12
 
 /*
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 4ad25a5..ebd18b7 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -36,61 +36,31 @@
 
 struct task_struct;
 
+#include <asm/stack_pointer.h>
 #include <asm/types.h>
 
 typedef unsigned long mm_segment_t;
 
 /*
  * low level task data that entry.S needs immediate access to.
- * __switch_to() assumes cpu_context follows immediately after cpu_domain.
  */
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	mm_segment_t		addr_limit;	/* address limit */
-	struct task_struct	*task;		/* main task structure */
 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
 	u64			ttbr0;		/* saved TTBR0_EL1 */
 #endif
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
-	int			cpu;		/* cpu */
 };
 
 #define INIT_THREAD_INFO(tsk)						\
 {									\
-	.task		= &tsk,						\
-	.flags		= 0,						\
 	.preempt_count	= INIT_PREEMPT_COUNT,				\
 	.addr_limit	= KERNEL_DS,					\
 }
 
-#define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
-/*
- * how to get the current stack pointer from C
- */
-register unsigned long current_stack_pointer asm ("sp");
-
-/*
- * how to get the thread information struct from C
- */
-static inline struct thread_info *current_thread_info(void) __attribute_const__;
-
-/*
- * struct thread_info can be accessed directly via sp_el0.
- *
- * We don't use read_sysreg() as we want the compiler to cache the value where
- * possible.
- */
-static inline struct thread_info *current_thread_info(void)
-{
-	unsigned long sp_el0;
-
-	asm ("mrs %0, sp_el0" : "=r" (sp_el0));
-
-	return (struct thread_info *)sp_el0;
-}
-
 #define thread_saved_pc(tsk)	\
 	((unsigned long)(tsk->thread.cpu_context.pc))
 #define thread_saved_sp(tsk)	\
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 5cdbc55..b3bb7ef 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -36,17 +36,13 @@
 {
   DEFINE(TSK_ACTIVE_MM,		offsetof(struct task_struct, active_mm));
   BLANK();
-  DEFINE(TI_FLAGS,		offsetof(struct thread_info, flags));
-  DEFINE(TI_PREEMPT,		offsetof(struct thread_info, preempt_count));
-  DEFINE(TI_ADDR_LIMIT,		offsetof(struct thread_info, addr_limit));
+  DEFINE(TSK_TI_FLAGS,		offsetof(struct task_struct, thread_info.flags));
+  DEFINE(TSK_TI_PREEMPT,	offsetof(struct task_struct, thread_info.preempt_count));
+  DEFINE(TSK_TI_ADDR_LIMIT,	offsetof(struct task_struct, thread_info.addr_limit));
 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
-  DEFINE(TI_TTBR0,		offsetof(struct thread_info, ttbr0));
+  DEFINE(TSK_TI_TTBR0,		offsetof(struct task_struct, thread_info.ttbr0));
 #endif
-  DEFINE(TI_TASK,		offsetof(struct thread_info, task));
-  DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
-#ifdef CONFIG_ARM64_SW_TTBR0_PAN
-  DEFINE(TSK_TI_TTBR0,		offsetof(struct thread_info, ttbr0));
-#endif
+  DEFINE(TSK_STACK,		offsetof(struct task_struct, stack));
   BLANK();
   DEFINE(THREAD_CPU_CONTEXT,	offsetof(struct task_struct, thread.cpu_context));
   BLANK();
@@ -129,6 +125,7 @@
   DEFINE(TZ_DSTTIME,		offsetof(struct timezone, tz_dsttime));
   BLANK();
   DEFINE(CPU_BOOT_STACK,	offsetof(struct secondary_data, stack));
+  DEFINE(CPU_BOOT_TASK,		offsetof(struct secondary_data, task));
   BLANK();
 #ifdef CONFIG_KVM_ARM_HOST
   DEFINE(VCPU_CONTEXT,		offsetof(struct kvm_vcpu, arch.ctxt));
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index c44a933..718c4c8 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -93,9 +93,8 @@
 
 	.if	\el == 0
 	mrs	x21, sp_el0
-	mov	tsk, sp
-	and	tsk, tsk, #~(THREAD_SIZE - 1)	// Ensure MDSCR_EL1.SS is clear,
-	ldr	x19, [tsk, #TI_FLAGS]		// since we can unmask debug
+	ldr_this_cpu	tsk, __entry_task, x20	// Ensure MDSCR_EL1.SS is clear,
+	ldr	x19, [tsk, #TSK_TI_FLAGS]	// since we can unmask debug
 	disable_step_tsk x19, x20		// exceptions when scheduling.
 
 	mov	x29, xzr			// fp pointed to user-space
@@ -103,10 +102,10 @@
 	add	x21, sp, #S_FRAME_SIZE
 	get_thread_info tsk
 	/* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
-	ldr	x20, [tsk, #TI_ADDR_LIMIT]
+	ldr	x20, [tsk, #TSK_TI_ADDR_LIMIT]
 	str	x20, [sp, #S_ORIG_ADDR_LIMIT]
 	mov	x20, #TASK_SIZE_64
-	str	x20, [tsk, #TI_ADDR_LIMIT]
+	str	x20, [tsk, #TSK_TI_ADDR_LIMIT]
 	/* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */
 	.endif /* \el == 0 */
 	mrs	x22, elr_el1
@@ -168,7 +167,7 @@
 	.if	\el != 0
 	/* Restore the task's original addr_limit. */
 	ldr	x20, [sp, #S_ORIG_ADDR_LIMIT]
-	str	x20, [tsk, #TI_ADDR_LIMIT]
+	str	x20, [tsk, #TSK_TI_ADDR_LIMIT]
 
 	/* No need to restore UAO, it will be restored from SPSR_EL1 */
 	.endif
@@ -252,15 +251,16 @@
 	mov	x19, sp			// preserve the original sp
 
 	/*
-	 * Compare sp with the current thread_info, if the top
-	 * ~(THREAD_SIZE - 1) bits match, we are on a task stack, and
-	 * should switch to the irq stack.
+	 * Compare sp with the base of the task stack.
+	 * If the top ~(THREAD_SIZE - 1) bits match, we are on a task stack,
+	 * and should switch to the irq stack.
 	 */
-	and	x25, x19, #~(THREAD_SIZE - 1)
-	cmp	x25, tsk
-	b.ne	9998f
+	ldr	x25, [tsk, TSK_STACK]
+	eor	x25, x25, x19
+	and	x25, x25, #~(THREAD_SIZE - 1)
+	cbnz	x25, 9998f
 
-	this_cpu_ptr irq_stack, x25, x26
+	adr_this_cpu x25, irq_stack, x26
 	mov	x26, #IRQ_STACK_START_SP
 	add	x26, x25, x26
 
@@ -488,9 +488,9 @@
 	irq_handler
 
 #ifdef CONFIG_PREEMPT
-	ldr	w24, [tsk, #TI_PREEMPT]		// get preempt count
+	ldr	w24, [tsk, #TSK_TI_PREEMPT]	// get preempt count
 	cbnz	w24, 1f				// preempt count != 0
-	ldr	x0, [tsk, #TI_FLAGS]		// get flags
+	ldr	x0, [tsk, #TSK_TI_FLAGS]	// get flags
 	tbz	x0, #TIF_NEED_RESCHED, 1f	// needs rescheduling?
 	bl	el1_preempt
 1:
@@ -505,7 +505,7 @@
 el1_preempt:
 	mov	x24, lr
 1:	bl	preempt_schedule_irq		// irq en/disable is done inside
-	ldr	x0, [tsk, #TI_FLAGS]		// get new tasks TI_FLAGS
+	ldr	x0, [tsk, #TSK_TI_FLAGS]	// get new tasks TI_FLAGS
 	tbnz	x0, #TIF_NEED_RESCHED, 1b	// needs rescheduling?
 	ret	x24
 #endif
@@ -735,8 +735,7 @@
 	ldp	x29, x9, [x8], #16
 	ldr	lr, [x8]
 	mov	sp, x9
-	and	x9, x9, #~(THREAD_SIZE - 1)
-	msr	sp_el0, x9
+	msr	sp_el0, x1
 	ret
 ENDPROC(cpu_switch_to)
 
@@ -747,7 +746,7 @@
 ret_fast_syscall:
 	disable_irq				// disable interrupts
 	str	x0, [sp, #S_X0]			// returned x0
-	ldr	x1, [tsk, #TI_FLAGS]		// re-check for syscall tracing
+	ldr	x1, [tsk, #TSK_TI_FLAGS]	// re-check for syscall tracing
 	and	x2, x1, #_TIF_SYSCALL_WORK
 	cbnz	x2, ret_fast_syscall_trace
 	and	x2, x1, #_TIF_WORK_MASK
@@ -767,14 +766,14 @@
 #ifdef CONFIG_TRACE_IRQFLAGS
 	bl	trace_hardirqs_on		// enabled while in userspace
 #endif
-	ldr	x1, [tsk, #TI_FLAGS]		// re-check for single-step
+	ldr	x1, [tsk, #TSK_TI_FLAGS]	// re-check for single-step
 	b	finish_ret_to_user
 /*
  * "slow" syscall return path.
  */
 ret_to_user:
 	disable_irq				// disable interrupts
-	ldr	x1, [tsk, #TI_FLAGS]
+	ldr	x1, [tsk, #TSK_TI_FLAGS]
 	and	x2, x1, #_TIF_WORK_MASK
 	cbnz	x2, work_pending
 finish_ret_to_user:
@@ -807,7 +806,7 @@
 	enable_dbg_and_irq
 	ct_user_exit 1
 
-	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall hooks
+	ldr	x16, [tsk, #TSK_TI_FLAGS]	// check for syscall hooks
 	tst	x16, #_TIF_SYSCALL_WORK
 	b.ne	__sys_trace
 	cmp     scno, sc_nr                     // check upper syscall limit
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index c7d26bb..7ee6d74 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -428,7 +428,8 @@
 __primary_switched:
 	adrp	x4, init_thread_union
 	add	sp, x4, #THREAD_SIZE
-	msr	sp_el0, x4			// Save thread_info
+	adr_l	x5, init_task
+	msr	sp_el0, x5			// Save thread_info
 
 	adr_l	x8, vectors			// load VBAR_EL1 with virtual
 	msr	vbar_el1, x8			// vector table address
@@ -699,10 +700,10 @@
 	isb
 
 	adr_l	x0, secondary_data
-	ldr	x0, [x0, #CPU_BOOT_STACK]	// get secondary_data.stack
-	mov	sp, x0
-	and	x0, x0, #~(THREAD_SIZE - 1)
-	msr	sp_el0, x0			// save thread_info
+	ldr	x1, [x0, #CPU_BOOT_STACK]	// get secondary_data.stack
+	mov	sp, x1
+	ldr	x2, [x0, #CPU_BOOT_TASK]
+	msr	sp_el0, x2
 	mov	x29, #0
 	b	secondary_start_kernel
 ENDPROC(__secondary_switched)
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index bb24b4e..b325f74 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -1189,20 +1189,24 @@
 {
 	int ret, cpu;
 
-	for_each_possible_cpu(cpu)
-		per_cpu(is_hotplugging, cpu) = false;
+	/* set to true so armv8pmu_idle_update doesn't try to load
+	 * hw_events before arm_pmu_device_probe has initialized it.
+	 */
+	for_each_possible_cpu(cpu) {
+		per_cpu(is_hotplugging, cpu) = true;
+	}
 
-	ret = perf_event_cpu_hp_init();
+	ret = arm_pmu_device_probe(pdev, armv8_pmu_of_device_ids,
+		(acpi_disabled ?  NULL : armv8_pmu_probe_table));
 
-	if (ret)
-		return ret;
+	if (!ret) {
+		for_each_possible_cpu(cpu)
+			per_cpu(is_hotplugging, cpu) = false;
 
-	if (acpi_disabled)
-		return arm_pmu_device_probe(pdev, armv8_pmu_of_device_ids,
-					    NULL);
+		ret = perf_event_cpu_hp_init();
+	}
 
-	return arm_pmu_device_probe(pdev, armv8_pmu_of_device_ids,
-				    armv8_pmu_probe_table);
+	return ret;
 }
 
 static struct platform_driver armv8_pmu_driver = {
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index fc1a286..5fe594e 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -45,6 +45,7 @@
 #include <linux/personality.h>
 #include <linux/notifier.h>
 #include <trace/events/power.h>
+#include <linux/percpu.h>
 
 #include <asm/alternative.h>
 #include <asm/compat.h>
@@ -390,6 +391,20 @@
 }
 
 /*
+ * We store our current task in sp_el0, which is clobbered by userspace. Keep a
+ * shadow copy so that we can restore this upon entry from userspace.
+ *
+ * This is *only* for exception entry from EL0, and is not valid until we
+ * __switch_to() a user task.
+ */
+DEFINE_PER_CPU(struct task_struct *, __entry_task);
+
+static void entry_task_switch(struct task_struct *next)
+{
+	__this_cpu_write(__entry_task, next);
+}
+
+/*
  * Thread switching.
  */
 struct task_struct *__switch_to(struct task_struct *prev,
@@ -401,6 +416,7 @@
 	tls_thread_switch(next);
 	hw_breakpoint_thread_switch(next);
 	contextidr_thread_switch(next);
+	entry_task_switch(next);
 	uao_thread_switch(next);
 
 	/*
@@ -418,27 +434,35 @@
 unsigned long get_wchan(struct task_struct *p)
 {
 	struct stackframe frame;
-	unsigned long stack_page;
+	unsigned long stack_page, ret = 0;
 	int count = 0;
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
 
+	stack_page = (unsigned long)try_get_task_stack(p);
+	if (!stack_page)
+		return 0;
+
 	frame.fp = thread_saved_fp(p);
 	frame.sp = thread_saved_sp(p);
 	frame.pc = thread_saved_pc(p);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	frame.graph = p->curr_ret_stack;
 #endif
-	stack_page = (unsigned long)task_stack_page(p);
 	do {
 		if (frame.sp < stack_page ||
 		    frame.sp >= stack_page + THREAD_SIZE ||
 		    unwind_frame(p, &frame))
-			return 0;
-		if (!in_sched_functions(frame.pc))
-			return frame.pc;
+			goto out;
+		if (!in_sched_functions(frame.pc)) {
+			ret = frame.pc;
+			goto out;
+		}
 	} while (count ++ < 16);
-	return 0;
+
+out:
+	put_task_stack(p);
+	return ret;
 }
 
 unsigned long arch_align_stack(unsigned long sp)
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
index 1718706..12a87f2 100644
--- a/arch/arm64/kernel/return_address.c
+++ b/arch/arm64/kernel/return_address.c
@@ -12,6 +12,7 @@
 #include <linux/export.h>
 #include <linux/ftrace.h>
 
+#include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
 struct return_address_data {
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 49f3ae0..ae02756 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -312,7 +312,7 @@
 	 * faults in case uaccess_enable() is inadvertently called by the init
 	 * thread.
 	 */
-	init_thread_info.ttbr0 = virt_to_phys(empty_zero_page);
+	init_task.thread_info.ttbr0 = virt_to_phys(empty_zero_page);
 #endif
 
 #ifdef CONFIG_VT
diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index 1bec41b..df67652 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -125,9 +125,6 @@
 	/* load sp from context */
 	ldr	x2, [x0, #CPU_CTX_SP]
 	mov	sp, x2
-	/* save thread_info */
-	and	x2, x2, #~(THREAD_SIZE - 1)
-	msr	sp_el0, x2
 	/*
 	 * cpu_do_resume expects x0 to contain context address pointer
 	 */
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index df95830..2437f15 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -58,6 +58,9 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/ipi.h>
 
+DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number);
+EXPORT_PER_CPU_SYMBOL(cpu_number);
+
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
  * so we need some other way of telling a new secondary core
@@ -147,6 +150,7 @@
 	 * We need to tell the secondary core where to find its stack and the
 	 * page tables.
 	 */
+	secondary_data.task = idle;
 	secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
 	update_cpu_boot_status(CPU_MMU_OFF);
 	__flush_dcache_area(&secondary_data, sizeof(secondary_data));
@@ -171,6 +175,7 @@
 		pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
 	}
 
+	secondary_data.task = NULL;
 	secondary_data.stack = NULL;
 	status = READ_ONCE(secondary_data.status);
 	if (ret && status) {
@@ -209,7 +214,10 @@
 asmlinkage void secondary_start_kernel(void)
 {
 	struct mm_struct *mm = &init_mm;
-	unsigned int cpu = smp_processor_id();
+	unsigned int cpu;
+
+	cpu = task_cpu(current);
+	set_my_cpu_offset(per_cpu_offset(cpu));
 
 	/*
 	 * All kernel threads share the same mm context; grab a
@@ -218,8 +226,6 @@
 	atomic_inc(&mm->mm_count);
 	current->active_mm = mm;
 
-	set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
-
 	pr_debug("CPU%u: Booted secondary processor\n", cpu);
 
 	/*
@@ -733,6 +739,8 @@
 	 */
 	for_each_possible_cpu(cpu) {
 
+		per_cpu(cpu_number, cpu) = cpu;
+
 		if (cpu == smp_processor_id())
 			continue;
 
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index bedf97d..900c1ec 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -22,6 +22,7 @@
 #include <linux/stacktrace.h>
 
 #include <asm/irq.h>
+#include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
 /*
@@ -128,7 +129,6 @@
 			break;
 	}
 }
-EXPORT_SYMBOL(walk_stackframe);
 
 #ifdef CONFIG_STACKTRACE
 struct stack_trace_data {
@@ -181,6 +181,9 @@
 	struct stack_trace_data data;
 	struct stackframe frame;
 
+	if (!try_get_task_stack(tsk))
+		return;
+
 	data.trace = trace;
 	data.skip = trace->skip;
 
@@ -202,6 +205,8 @@
 	walk_stackframe(tsk, &frame, save_trace, &data);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
+
+	put_task_stack(tsk);
 }
 EXPORT_SYMBOL(save_stack_trace_tsk);
 
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index bb0cd78..1e3be90 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -47,12 +47,6 @@
 	cpu_uninstall_idmap();
 
 	/*
-	 * Restore per-cpu offset before any kernel
-	 * subsystem relying on it has a chance to run.
-	 */
-	set_my_cpu_offset(per_cpu_offset(cpu));
-
-	/*
 	 * PSTATE was not saved over suspend/resume, re-enable any detected
 	 * features that might not have been set correctly.
 	 */
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index d8253fb..e576c1d 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -38,6 +38,7 @@
 #include <asm/esr.h>
 #include <asm/insn.h>
 #include <asm/traps.h>
+#include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 #include <asm/exception.h>
 #include <asm/system_misc.h>
@@ -147,6 +148,9 @@
 	if (!tsk)
 		tsk = current;
 
+	if (!try_get_task_stack(tsk))
+		return;
+
 	/*
 	 * Switching between stacks is valid when tracing current and in
 	 * non-preemptible context.
@@ -212,6 +216,8 @@
 				 stack + sizeof(struct pt_regs));
 		}
 	}
+
+	put_task_stack(tsk);
 }
 
 void show_stack(struct task_struct *tsk, unsigned long *sp)
@@ -227,10 +233,9 @@
 #endif
 #define S_SMP " SMP"
 
-static int __die(const char *str, int err, struct thread_info *thread,
-		 struct pt_regs *regs)
+static int __die(const char *str, int err, struct pt_regs *regs)
 {
-	struct task_struct *tsk = thread->task;
+	struct task_struct *tsk = current;
 	static int die_counter;
 	int ret;
 
@@ -245,7 +250,8 @@
 	print_modules();
 	__show_regs(regs);
 	pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n",
-		 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
+		 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk),
+		 end_of_stack(tsk));
 
 	if (!user_mode(regs)) {
 		dump_backtrace(regs, tsk);
@@ -310,7 +316,6 @@
  */
 void die(const char *str, struct pt_regs *regs, int err)
 {
-	struct thread_info *thread = current_thread_info();
 	enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE;
 	unsigned long flags = oops_begin();
 	int ret;
@@ -320,7 +325,7 @@
 	if (bug_type != BUG_TRAP_TYPE_NONE && !strlen(str))
 		str = "Oops - BUG";
 
-	ret = __die(str, err, thread, regs);
+	ret = __die(str, err, regs);
 
 	oops_end(flags, regs, ret);
 }
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 0a34644..d0ffade 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -40,7 +40,6 @@
 #include <asm/system_misc.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
-#include <asm/kryo3xx-arm64-edac.h>
 #include <soc/qcom/scm.h>
 
 struct fault_info {
@@ -521,7 +520,6 @@
  */
 static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 {
-	kryo3xx_poll_cache_errors(NULL);
 	return 1;
 }
 
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 61330c9..8d21250 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -116,11 +116,14 @@
 	mrs	x8, mdscr_el1
 	mrs	x9, oslsr_el1
 	mrs	x10, sctlr_el1
+	mrs	x11, tpidr_el1
+	mrs	x12, sp_el0
 	stp	x2, x3, [x0]
 	stp	x4, xzr, [x0, #16]
 	stp	x5, x6, [x0, #32]
 	stp	x7, x8, [x0, #48]
 	stp	x9, x10, [x0, #64]
+	stp	x11, x12, [x0, #80]
 	ret
 ENDPROC(cpu_do_suspend)
 
@@ -136,6 +139,7 @@
 	ldp	x6, x8, [x0, #32]
 	ldp	x9, x10, [x0, #48]
 	ldp	x11, x12, [x0, #64]
+	ldp	x13, x14, [x0, #80]
 	msr	tpidr_el0, x2
 	msr	tpidrro_el0, x3
 	msr	contextidr_el1, x4
@@ -158,6 +162,8 @@
 	msr	mdscr_el1, x10
 
 	msr	sctlr_el1, x12
+	msr	tpidr_el1, x13
+	msr	sp_el0, x14
 	/*
 	 * Restore oslsr_el1 by writing oslar_el1
 	 */
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index d376e4b..04c067b 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -84,7 +84,7 @@
 	movl %edx,%ecx
 	andl $63,%edx
 	shrl $6,%ecx
-	jz 17f
+	jz .L_copy_short_string
 1:	movq (%rsi),%r8
 2:	movq 1*8(%rsi),%r9
 3:	movq 2*8(%rsi),%r10
@@ -105,7 +105,8 @@
 	leaq 64(%rdi),%rdi
 	decl %ecx
 	jnz 1b
-17:	movl %edx,%ecx
+.L_copy_short_string:
+	movl %edx,%ecx
 	andl $7,%edx
 	shrl $3,%ecx
 	jz 20f
@@ -221,6 +222,8 @@
  */
 ENTRY(copy_user_enhanced_fast_string)
 	ASM_STAC
+	cmpl $64,%edx
+	jb .L_copy_short_string	/* less then 64 bytes, avoid the costly 'rep' */
 	movl %edx,%ecx
 1:	rep
 	movsb
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 0c2fae8..73eb7fd 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -992,11 +992,12 @@
 		die("Segment relocations found but --realmode not specified\n");
 
 	/* Order the relocations for more efficient processing */
-	sort_relocs(&relocs16);
 	sort_relocs(&relocs32);
 #if ELF_BITS == 64
 	sort_relocs(&relocs32neg);
 	sort_relocs(&relocs64);
+#else
+	sort_relocs(&relocs16);
 #endif
 
 	/* Print the relocations */
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 123d211..8cac3d3 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1691,6 +1691,7 @@
 		return PTR_ERR(sk_tfm);
 	}
 	drbg->ctr_handle = sk_tfm;
+	init_completion(&drbg->ctr_completion);
 
 	req = skcipher_request_alloc(sk_tfm, GFP_KERNEL);
 	if (!req) {
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index c4af003..5eba478 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -856,7 +856,7 @@
 				     const char *buf, size_t count)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	char *driver_override, *old = pdev->driver_override, *cp;
+	char *driver_override, *old, *cp;
 
 	if (count > PATH_MAX)
 		return -EINVAL;
@@ -869,12 +869,15 @@
 	if (cp)
 		*cp = '\0';
 
+	device_lock(dev);
+	old = pdev->driver_override;
 	if (strlen(driver_override)) {
 		pdev->driver_override = driver_override;
 	} else {
 		kfree(driver_override);
 		pdev->driver_override = NULL;
 	}
+	device_unlock(dev);
 
 	kfree(old);
 
@@ -885,8 +888,12 @@
 				    struct device_attribute *attr, char *buf)
 {
 	struct platform_device *pdev = to_platform_device(dev);
+	ssize_t len;
 
-	return sprintf(buf, "%s\n", pdev->driver_override);
+	device_lock(dev);
+	len = sprintf(buf, "%s\n", pdev->driver_override);
+	device_unlock(dev);
+	return len;
 }
 static DEVICE_ATTR_RW(driver_override);
 
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index ce86c27..13fac71 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -572,6 +572,13 @@
 		goto bail;
 	if (sess->smmu.enabled) {
 		attrs = DMA_ATTR_EXEC_MAPPING;
+
+		if (map->attr & FASTRPC_ATTR_NON_COHERENT ||
+			(sess->smmu.coherent && map->uncached))
+			attrs |= DMA_ATTR_FORCE_NON_COHERENT;
+		else if (map->attr & FASTRPC_ATTR_COHERENT)
+			attrs |= DMA_ATTR_FORCE_COHERENT;
+
 		VERIFY(err, map->table->nents ==
 			msm_dma_map_sg_attrs(sess->dev,
 				map->table->sgl, map->table->nents,
@@ -1121,7 +1128,7 @@
 	for (i = 0; i < M_FDLIST; i++)
 		fdlist[i] = 0;
 	crclist = (uint32_t *)&fdlist[M_FDLIST];
-	memset(crclist, 0, sizeof(uint32_t)*M_FDLIST);
+	memset(crclist, 0, sizeof(uint32_t)*M_CRCLIST);
 
 	/* copy non ion buffers */
 	PERF(ctx->fl->profile, ctx->fl->perf.copy,
@@ -1169,10 +1176,14 @@
 		int i = ctx->overps[oix]->raix;
 		struct fastrpc_mmap *map = ctx->maps[i];
 
-		if (ctx->fl->sctx->smmu.coherent)
-			continue;
 		if (map && map->uncached)
 			continue;
+		if (ctx->fl->sctx->smmu.coherent &&
+			!(map && (map->attr & FASTRPC_ATTR_NON_COHERENT)))
+			continue;
+		if (map && (map->attr & FASTRPC_ATTR_COHERENT))
+			continue;
+
 		if (rpra[i].buf.len && ctx->overps[oix]->mstart)
 			dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
 			uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len));
@@ -1261,6 +1272,12 @@
 			continue;
 		if (!rpra[i].buf.len)
 			continue;
+		if (ctx->fl->sctx->smmu.coherent &&
+			!(map && (map->attr & FASTRPC_ATTR_NON_COHERENT)))
+			continue;
+		if (map && (map->attr & FASTRPC_ATTR_COHERENT))
+			continue;
+
 		if (buf_page_start(ptr_to_uint64((void *)rpra)) ==
 				buf_page_start(rpra[i].buf.pv))
 			continue;
@@ -1291,6 +1308,12 @@
 			continue;
 		if (!rpra[i].buf.len)
 			continue;
+		if (ctx->fl->sctx->smmu.coherent &&
+			!(map && (map->attr & FASTRPC_ATTR_NON_COHERENT)))
+			continue;
+		if (map && (map->attr & FASTRPC_ATTR_COHERENT))
+			continue;
+
 		if (buf_page_start(ptr_to_uint64((void *)rpra)) ==
 				buf_page_start(rpra[i].buf.pv)) {
 			continue;
@@ -1726,6 +1749,8 @@
 	cid = ctx - &gcinfo[0];
 	fastrpc_glink_close(ctx->chan, cid);
 	ctx->chan = 0;
+	glink_unregister_link_state_cb(ctx->link.link_notify_handle);
+	ctx->link.link_notify_handle = NULL;
 	mutex_unlock(&me->smd_mutex);
 	pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name,
 						MAJOR(me->dev_no), cid);
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index fb7afa3..e3fe064 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -36,6 +36,12 @@
 /* Set for buffers that have no virtual mapping in userspace */
 #define FASTRPC_ATTR_NOVA 0x1
 
+/* Set for buffers that are NOT dma coherent */
+#define FASTRPC_ATTR_NON_COHERENT 0x2
+
+/* Set for buffers that are dma coherent */
+#define FASTRPC_ATTR_COHERENT 0x4
+
 /* Driver should operate in parallel with the co-processor */
 #define FASTRPC_MODE_PARALLEL    0
 
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 89fba64..a0a9ab6 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -264,8 +264,10 @@
 	struct list_head *temp;
 	struct diag_cmd_reg_t *item = NULL;
 
+	mutex_lock(&driver->cmd_reg_mutex);
 	if (diag_dbgfs_table_index == driver->cmd_reg_count) {
 		diag_dbgfs_table_index = 0;
+		mutex_unlock(&driver->cmd_reg_mutex);
 		return 0;
 	}
 
@@ -274,6 +276,7 @@
 	buf = kcalloc(buf_size, sizeof(char), GFP_KERNEL);
 	if (ZERO_OR_NULL_PTR(buf)) {
 		pr_err("diag: %s, Error allocating memory\n", __func__);
+		mutex_unlock(&driver->cmd_reg_mutex);
 		return -ENOMEM;
 	}
 	buf_size = ksize(buf);
@@ -318,6 +321,7 @@
 			break;
 	}
 	diag_dbgfs_table_index = i;
+	mutex_unlock(&driver->cmd_reg_mutex);
 
 	*ppos = 0;
 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index a7511a1..8069b36 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -59,7 +59,7 @@
 /*
  * Assigned numbers, used for dynamic minors
  */
-#define DYNAMIC_MINORS 75 /* like dynamic majors */
+#define DYNAMIC_MINORS 64 /* like dynamic majors */
 static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS);
 
 #ifdef CONFIG_PROC_FS
diff --git a/drivers/char/rdbg.c b/drivers/char/rdbg.c
index 92d9399..8612112 100644
--- a/drivers/char/rdbg.c
+++ b/drivers/char/rdbg.c
@@ -22,7 +22,7 @@
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
 
-#define SMP2P_NUM_PROCS				8
+#define SMP2P_NUM_PROCS				16
 #define MAX_RETRIES				20
 
 #define SM_VERSION				1
@@ -146,9 +146,17 @@
 		{"rdbg_adsp", SMEM_LC_DEBUGGER, 16*1024},	/*ADSP*/
 		{0},	/*SMP2P_RESERVED_PROC_1*/
 		{"rdbg_wcnss", 0, 0},		/*WCNSS*/
-		{0},	/*SMP2P_RESERVED_PROC_2*/
-		{0},	/*SMP2P_POWER_PROC*/
-		{0}		/*SMP2P_REMOTE_MOCK_PROC*/
+		{"rdbg_cdsp", SMEM_LC_DEBUGGER, 16*1024},		/*CDSP*/
+		{NULL},	/*SMP2P_POWER_PROC*/
+		{NULL},	/*SMP2P_TZ_PROC*/
+		{NULL},	/*EMPTY*/
+		{NULL},	/*EMPTY*/
+		{NULL},	/*EMPTY*/
+		{NULL},	/*EMPTY*/
+		{NULL},	/*EMPTY*/
+		{NULL},	/*EMPTY*/
+		{NULL},	/*EMPTY*/
+		{NULL}		/*SMP2P_REMOTE_MOCK_PROC*/
 };
 
 static int smq_blockmap_get(struct smq_block_map *block_map,
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index a76ab4a..4700584 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -35,9 +35,10 @@
 	ssize_t err;
 	int i, rc;
 	char *str = buf;
-
 	struct tpm_chip *chip = to_tpm_chip(dev);
 
+	memset(&tpm_cmd, 0, sizeof(tpm_cmd));
+
 	tpm_cmd.header.in = tpm_readpubek_header;
 	err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, 0,
 			       "attempting to read the PUBEK");
diff --git a/drivers/clk/qcom/clk-regmap-divider.c b/drivers/clk/qcom/clk-regmap-divider.c
index 5348491..c314d2c 100644
--- a/drivers/clk/qcom/clk-regmap-divider.c
+++ b/drivers/clk/qcom/clk-regmap-divider.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 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
@@ -28,8 +28,10 @@
 {
 	struct clk_regmap_div *divider = to_clk_regmap_div(hw);
 
-	return divider_round_rate(hw, rate, prate, NULL, divider->width,
-				  CLK_DIVIDER_ROUND_CLOSEST);
+	return divider_round_rate(hw, rate, prate, divider->table,
+				  divider->width,
+				  CLK_DIVIDER_ROUND_CLOSEST |
+				  divider->flags);
 }
 
 static int div_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -39,8 +41,9 @@
 	struct clk_regmap *clkr = &divider->clkr;
 	u32 div;
 
-	div = divider_get_val(rate, parent_rate, NULL, divider->width,
-			      CLK_DIVIDER_ROUND_CLOSEST);
+	div = divider_get_val(rate, parent_rate, divider->table,
+			      divider->width, CLK_DIVIDER_ROUND_CLOSEST |
+			      divider->flags);
 
 	return regmap_update_bits(clkr->regmap, divider->reg,
 				  (BIT(divider->width) - 1) << divider->shift,
@@ -58,8 +61,8 @@
 	div >>= divider->shift;
 	div &= BIT(divider->width) - 1;
 
-	return divider_recalc_rate(hw, parent_rate, div, NULL,
-				   CLK_DIVIDER_ROUND_CLOSEST);
+	return divider_recalc_rate(hw, parent_rate, div, divider->table,
+				   CLK_DIVIDER_ROUND_CLOSEST | divider->flags);
 }
 
 const struct clk_ops clk_regmap_div_ops = {
diff --git a/drivers/clk/qcom/clk-regmap-divider.h b/drivers/clk/qcom/clk-regmap-divider.h
index fc4492e..1c5e087 100644
--- a/drivers/clk/qcom/clk-regmap-divider.h
+++ b/drivers/clk/qcom/clk-regmap-divider.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 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
@@ -18,10 +18,12 @@
 #include "clk-regmap.h"
 
 struct clk_regmap_div {
-	u32			reg;
-	u32			shift;
-	u32			width;
-	struct clk_regmap	clkr;
+	u32				reg;
+	u32				shift;
+	u32				width;
+	u32				flags;
+	const struct clk_div_table	*table;
+	struct clk_regmap		clkr;
 };
 
 extern const struct clk_ops clk_regmap_div_ops;
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 7536aa9b..827ee8f 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -571,22 +571,21 @@
 	int best_level = -1;
 	uint32_t latency_us = pm_qos_request_for_cpu(PM_QOS_CPU_DMA_LATENCY,
 							dev->cpu);
-	uint32_t sleep_us =
-		(uint32_t)(ktime_to_us(tick_nohz_get_sleep_length()));
+	s64 sleep_us = ktime_to_us(tick_nohz_get_sleep_length());
 	uint32_t modified_time_us = 0;
 	uint32_t next_event_us = 0;
 	int i, idx_restrict;
 	uint32_t lvl_latency_us = 0;
 	uint64_t predicted = 0;
 	uint32_t htime = 0, idx_restrict_time = 0;
-	uint32_t next_wakeup_us = sleep_us;
+	uint32_t next_wakeup_us = (uint32_t)sleep_us;
 	uint32_t *min_residency = get_per_cpu_min_residency(dev->cpu);
 	uint32_t *max_residency = get_per_cpu_max_residency(dev->cpu);
 
 	if (!cpu)
 		return -EINVAL;
 
-	if (sleep_disabled)
+	if (sleep_disabled || sleep_us < 0)
 		return 0;
 
 	idx_restrict = cpu->nlevels + 1;
diff --git a/drivers/firmware/qcom/tz_log.c b/drivers/firmware/qcom/tz_log.c
index 471476c..9c1c81b 100644
--- a/drivers/firmware/qcom/tz_log.c
+++ b/drivers/firmware/qcom/tz_log.c
@@ -960,7 +960,7 @@
 
 	for (i = 0; i < TZDBG_STATS_MAX; i++) {
 		tzdbg.debug_tz[i] = i;
-		dent = debugfs_create_file(tzdbg.stat[i].name,
+		dent = debugfs_create_file_unsafe(tzdbg.stat[i].name,
 				0444, dent_dir,
 				&tzdbg.debug_tz[i], &tzdbg_fops);
 		if (dent == NULL) {
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 70581e2..67c6b2d 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -131,13 +131,14 @@
 		return -ETIMEDOUT;
 	}
 
-	pr_debug("aux status %s\n",
-		dp_aux_get_error(aux->aux_error_num));
-
-	if (aux->aux_error_num == DP_AUX_ERR_NONE)
+	if (aux->aux_error_num == DP_AUX_ERR_NONE) {
 		ret = len;
-	else
+	} else {
+		pr_err_ratelimited("aux err: %s\n",
+			dp_aux_get_error(aux->aux_error_num));
+
 		ret = -EINVAL;
+	}
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 9361b52..5825ba8 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -471,6 +471,8 @@
 	dp_catalog_get_priv(ctrl);
 	base = catalog->io->ctrl_io.base;
 
+	pr_debug("DP_CONFIGURATION_CTRL=0x%x\n", cfg);
+
 	dp_write(base + DP_CONFIGURATION_CTRL, cfg);
 	dp_write(base + DP_MAINLINK_LEVELS, 0xa08);
 	dp_write(base + MMSS_DP_ASYNC_FIFO_CONFIG, 0x1);
@@ -507,10 +509,7 @@
 	dp_catalog_get_priv(ctrl);
 	base = catalog->io->ctrl_io.base;
 
-	mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL);
-
 	if (enable) {
-		mainlink_ctrl |= BIT(0);
 		dp_write(base + DP_MAINLINK_CTRL, 0x02000000);
 		wmb(); /* make sure mainlink is turned off before reset */
 		dp_write(base + DP_MAINLINK_CTRL, 0x02000002);
@@ -520,8 +519,9 @@
 		dp_write(base + DP_MAINLINK_CTRL, 0x02000001);
 		wmb(); /* make sure mainlink turned on */
 	} else {
+		mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL);
 		mainlink_ctrl &= ~BIT(0);
-		dp_write(base + DP_MAINLINK_CTRL, 0x0);
+		dp_write(base + DP_MAINLINK_CTRL, mainlink_ctrl);
 	}
 }
 
@@ -543,14 +543,16 @@
 	misc_val |= (tb << 5);
 	misc_val |= BIT(0); /* Configure clock to synchronous mode */
 
-	pr_debug("isc settings = 0x%x\n", misc_val);
+	pr_debug("misc settings = 0x%x\n", misc_val);
 	dp_write(base + DP_MISC1_MISC0, misc_val);
 }
 
-static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl)
+static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl,
+					u32 rate)
 {
 	u32 pixel_m, pixel_n;
 	u32 mvid, nvid;
+	u32 const link_rate = 540000;
 	struct dp_catalog_private *catalog;
 	void __iomem *base_cc, *base_ctrl;
 
@@ -570,6 +572,11 @@
 	mvid = (pixel_m & 0xFFFF) * 5;
 	nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
 
+	pr_debug("rate = %d\n", rate);
+
+	if (link_rate == rate)
+		nvid *= 2;
+
 	pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
 	dp_write(base_ctrl + DP_SOFTWARE_MVID, mvid);
 	dp_write(base_ctrl + DP_SOFTWARE_NVID, nvid);
@@ -593,7 +600,7 @@
 
 	bit = 1;
 	bit <<= (pattern - 1);
-	pr_debug("bit=%d train=%d\n", bit, pattern);
+	pr_debug("hw: bit=%d train=%d\n", bit, pattern);
 	dp_write(base + DP_STATE_CTRL, bit);
 
 	bit = 8;
@@ -792,7 +799,7 @@
 	base0 = catalog->io->ln_tx0_io.base;
 	base1 = catalog->io->ln_tx1_io.base;
 
-	pr_debug("v=%d p=%d\n", v_level, p_level);
+	pr_debug("hw: v=%d p=%d\n", v_level, p_level);
 
 	value0 = vm_voltage_swing[v_level][p_level];
 	value1 = vm_pre_emphasis[v_level][p_level];
@@ -814,8 +821,11 @@
 		dp_write(base0 + TXn_TX_EMP_POST1_LVL, value1);
 		dp_write(base1 + TXn_TX_EMP_POST1_LVL, value1);
 
-		pr_debug("host PHY settings: value0=0x%x value1=0x%x",
-						value0, value1);
+		pr_debug("hw: vx_value=0x%x px_value=0x%x\n",
+			value0, value1);
+	} else {
+		pr_err("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n",
+			v_level, value0, p_level, value1);
 	}
 }
 
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index ce88569..c9916c72 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -58,7 +58,7 @@
 	void (*lane_mapping)(struct dp_catalog_ctrl *ctrl);
 	void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl, bool enable);
 	void (*config_misc)(struct dp_catalog_ctrl *ctrl, u32 cc, u32 tb);
-	void (*config_msa)(struct dp_catalog_ctrl *ctrl);
+	void (*config_msa)(struct dp_catalog_ctrl *ctrl, u32 rate);
 	void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern);
 	void (*reset)(struct dp_catalog_ctrl *ctrl);
 	bool (*mainlink_ready)(struct dp_catalog_ctrl *ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 706398db2..b78f0df 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -67,6 +67,7 @@
 
 	bool psm_enabled;
 	bool orientation;
+	atomic_t aborted;
 
 	u32 pixel_rate;
 	u32 vic;
@@ -92,6 +93,20 @@
 	complete(&ctrl->video_comp);
 }
 
+static void dp_ctrl_abort(struct dp_ctrl *dp_ctrl)
+{
+	struct dp_ctrl_private *ctrl;
+
+	if (!dp_ctrl) {
+		pr_err("Invalid input data\n");
+		return;
+	}
+
+	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+
+	atomic_set(&ctrl->aborted, 1);
+}
+
 static void dp_ctrl_state_ctrl(struct dp_ctrl_private *ctrl, u32 state)
 {
 	ctrl->catalog->state_ctrl(ctrl->catalog, state);
@@ -109,8 +124,6 @@
 
 	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
 
-	drm_dp_link_power_down(ctrl->aux->drm_aux, &ctrl->panel->dp_link);
-
 	reinit_completion(&ctrl->idle_comp);
 	dp_ctrl_state_ctrl(ctrl, ST_PUSH_IDLE);
 
@@ -135,6 +148,10 @@
 
 	tbd = ctrl->link->get_test_bits_depth(ctrl->link,
 			ctrl->panel->pinfo.bpp);
+
+	if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN)
+		tbd = DP_TEST_BIT_DEPTH_8;
+
 	config |= tbd << 8;
 
 	/* Num of Lanes */
@@ -170,9 +187,6 @@
 		ctrl->panel->pinfo.bpp);
 	cc = ctrl->link->get_colorimetry_config(ctrl->link);
 	ctrl->catalog->config_misc(ctrl->catalog, cc, tb);
-
-	ctrl->catalog->config_msa(ctrl->catalog);
-
 	ctrl->panel->timing_cfg(ctrl->panel);
 }
 
@@ -226,7 +240,7 @@
 {
 	u32 const multiplier = 1000000;
 	u64 pclk, lclk;
-	u8 bpp, ln_cnt, link_rate;
+	u8 bpp, ln_cnt;
 	int run_idx = 0;
 	u32 lwidth, h_blank;
 	u32 fifo_empty = 0;
@@ -289,7 +303,6 @@
 	u64 brute_force_threshold = 10;
 	u64 diff_abs;
 
-	link_rate = ctrl->link->link_rate;
 	ln_cnt =  ctrl->link->lane_count;
 
 	bpp = pinfo->bpp;
@@ -309,7 +322,7 @@
 	even_distribution = 0;
 	min_hblank = 0;
 
-	lclk = drm_dp_bw_code_to_link_rate(link_rate) * DP_KHZ_TO_HZ;
+	lclk = drm_dp_bw_code_to_link_rate(ctrl->link->bw_code) * DP_KHZ_TO_HZ;
 
 	pr_debug("pclk=%lld, active_width=%d, h_blank=%d\n",
 						pclk, lwidth, h_blank);
@@ -734,14 +747,12 @@
 		max_level_reached  |= BIT(5);
 	}
 
-	pr_debug("max_level_reached = 0x%x\n", max_level_reached);
-
 	pre_emphasis_level <<= 3;
 
 	for (i = 0; i < 4; i++)
 		buf[i] = voltage_level | pre_emphasis_level | max_level_reached;
 
-	pr_debug("p|v=0x%x\n", voltage_level | pre_emphasis_level);
+	pr_debug("sink: p|v=0x%x\n", voltage_level | pre_emphasis_level);
 	return drm_dp_dpcd_write(ctrl->aux->drm_aux, 0x103, buf, 4);
 }
 
@@ -749,8 +760,6 @@
 {
 	struct dp_link *link = ctrl->link;
 
-	pr_debug("v=%d p=%d\n", link->v_level, link->p_level);
-
 	ctrl->catalog->update_vx_px(ctrl->catalog,
 			link->v_level, link->p_level);
 
@@ -762,15 +771,38 @@
 {
 	u8 buf[4];
 
-	pr_debug("pattern=%x\n", pattern);
+	pr_debug("sink: pattern=%x\n", pattern);
 
 	buf[0] = pattern;
 	drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_TRAINING_PATTERN_SET, buf, 1);
 }
 
+static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl,
+					u8 *link_status)
+{
+	int ret = 0, len;
+	u32 const offset = DP_LANE_ALIGN_STATUS_UPDATED - DP_LANE0_1_STATUS;
+	u32 link_status_read_max_retries = 100;
+
+	while (--link_status_read_max_retries) {
+		len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux,
+			link_status);
+		if (len != DP_LINK_STATUS_SIZE) {
+			pr_err("DP link status read failed, err: %d\n", len);
+			ret = len;
+			break;
+		}
+
+		if (!(link_status[offset] & DP_LINK_STATUS_UPDATED))
+			break;
+	}
+
+	return ret;
+}
+
 static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl)
 {
-	int tries, old_v_level, ret = 0, len = 0;
+	int tries, old_v_level, ret = 0;
 	u8 link_status[DP_LINK_STATUS_SIZE];
 	int const maximum_retries = 5;
 
@@ -780,7 +812,7 @@
 
 	ctrl->catalog->set_pattern(ctrl->catalog, 0x01);
 	dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |
-		DP_RECOVERED_CLOCK_OUT_EN); /* train_1 */
+		DP_LINK_SCRAMBLING_DISABLE); /* train_1 */
 	dp_ctrl_update_vx_px(ctrl);
 
 	tries = 0;
@@ -788,36 +820,35 @@
 	while (1) {
 		drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd);
 
-		len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux,
-			link_status);
-		if (len < DP_LINK_STATUS_SIZE) {
-			pr_err("[%s]: DP link status read failed\n", __func__);
-			ret = -1;
+		ret = dp_ctrl_read_link_status(ctrl, link_status);
+		if (ret)
 			break;
-		}
 
 		if (drm_dp_clock_recovery_ok(link_status,
 			ctrl->link->lane_count)) {
-			ret = 0;
 			break;
 		}
 
 		if (ctrl->link->v_level == DP_LINK_VOLTAGE_MAX) {
-			ret = -1;
-			break;	/* quit */
+			pr_err_ratelimited("max v_level reached\n");
+			ret = -EAGAIN;
+			break;
 		}
 
 		if (old_v_level == ctrl->link->v_level) {
 			tries++;
 			if (tries >= maximum_retries) {
-				ret = -1;
-				break;	/* quit */
+				pr_err("max tries reached\n");
+				ret = -EAGAIN;
+				break;
 			}
 		} else {
 			tries = 0;
 			old_v_level = ctrl->link->v_level;
 		}
 
+		pr_debug("clock recovery not done, adjusting vx px\n");
+
 		ctrl->link->adjust_levels(ctrl->link, link_status);
 		dp_ctrl_update_vx_px(ctrl);
 	}
@@ -828,27 +859,41 @@
 static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl)
 {
 	int ret = 0;
+	u32 min_req_link_rate_khz;
+	u32 new_proposed_link_bw_code;
+	u32 new_proposed_link_rate_khz;
 
 	if (!ctrl)
 		return -EINVAL;
 
-	switch (ctrl->link->link_rate) {
+	min_req_link_rate_khz = ctrl->panel->get_min_req_link_rate(ctrl->panel);
+
+	switch (ctrl->link->bw_code) {
 	case DP_LINK_RATE_810:
-		ctrl->link->link_rate = DP_LINK_BW_5_4;
+		new_proposed_link_bw_code = DP_LINK_BW_5_4;
 		break;
 	case DP_LINK_BW_5_4:
-		ctrl->link->link_rate = DP_LINK_BW_2_7;
+		new_proposed_link_bw_code = DP_LINK_BW_2_7;
 		break;
 	case DP_LINK_BW_2_7:
-		ctrl->link->link_rate = DP_LINK_BW_1_62;
-		break;
 	case DP_LINK_BW_1_62:
 	default:
-		ret = -EINVAL;
+		new_proposed_link_bw_code = DP_LINK_BW_1_62;
 		break;
 	};
 
-	pr_debug("new rate=%d\n", ctrl->link->link_rate);
+	new_proposed_link_rate_khz = drm_dp_bw_code_to_link_rate(
+						new_proposed_link_bw_code);
+
+	pr_debug("new proposed link rate=%d khz\n", new_proposed_link_rate_khz);
+	pr_debug("min required link rate=%d khz\n", min_req_link_rate_khz);
+
+	if (new_proposed_link_rate_khz >= min_req_link_rate_khz)
+		ctrl->link->bw_code = new_proposed_link_bw_code;
+	else
+		pr_debug("can't go below min required link rate\n");
+
+	pr_debug("new bw code=0x%x\n", ctrl->link->bw_code);
 
 	return ret;
 }
@@ -861,11 +906,15 @@
 
 static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl)
 {
-	int tries = 0, ret = 0, len = 0;
+	int tries = 0, ret = 0;
 	char pattern;
 	int const maximum_retries = 5;
 	u8 link_status[DP_LINK_STATUS_SIZE];
 
+	dp_ctrl_state_ctrl(ctrl, 0);
+	/* Make sure to clear the current pattern before starting a new one */
+	wmb();
+
 	if (drm_dp_tps3_supported(ctrl->panel->dpcd))
 		pattern = DP_TRAINING_PATTERN_3;
 	else
@@ -878,21 +927,15 @@
 	do  {
 		drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd);
 
-		len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux,
-			link_status);
-		if (len < DP_LINK_STATUS_SIZE) {
-			pr_err("[%s]: DP link status read failed\n", __func__);
-			ret = -1;
+		ret = dp_ctrl_read_link_status(ctrl, link_status);
+		if (ret)
 			break;
-		}
 
-		if (drm_dp_channel_eq_ok(link_status, ctrl->link->lane_count)) {
-			ret = 0;
+		if (drm_dp_channel_eq_ok(link_status, ctrl->link->lane_count))
 			break;
-		}
 
 		if (tries > maximum_retries) {
-			ret = -1;
+			ret = -EAGAIN;
 			break;
 		}
 		tries++;
@@ -907,61 +950,45 @@
 static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl)
 {
 	int ret = 0;
-	struct drm_dp_link dp_link;
+	u8 encoding = 0x1;
+	struct drm_dp_link link_info = {0};
 
 	ctrl->link->p_level = 0;
 	ctrl->link->v_level = 0;
 
 	dp_ctrl_config_ctrl(ctrl);
-	dp_ctrl_state_ctrl(ctrl, 0);
 
-	dp_link.num_lanes = ctrl->link->lane_count;
-	dp_link.rate = ctrl->link->link_rate;
-	dp_link.capabilities = ctrl->panel->dp_link.capabilities;
-	drm_dp_link_configure(ctrl->aux->drm_aux, &dp_link);
+	link_info.num_lanes = ctrl->link->lane_count;
+	link_info.rate = drm_dp_bw_code_to_link_rate(ctrl->link->bw_code);
+	link_info.capabilities = ctrl->panel->link_info.capabilities;
+
+	drm_dp_link_configure(ctrl->aux->drm_aux, &link_info);
+	drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
+				&encoding, 1);
 
 	ret = dp_ctrl_link_train_1(ctrl);
-	if (ret < 0) {
-		if (!dp_ctrl_link_rate_down_shift(ctrl)) {
-			pr_debug("retry with lower rate\n");
-
-			dp_ctrl_clear_training_pattern(ctrl);
-			return -EAGAIN;
-		}
-
-		pr_err("Training 1 failed\n");
-		ret = -EINVAL;
-		goto clear;
+	if (ret) {
+		pr_err("link training #1 failed\n");
+		goto end;
 	}
 
-	pr_debug("Training 1 completed successfully\n");
-
-	dp_ctrl_state_ctrl(ctrl, 0);
-
-	/* Make sure to clear the current pattern before starting a new one */
-	wmb();
+	/* print success info as this is a result of user initiated action */
+	pr_info("link training #1 successful\n");
 
 	ret = dp_ctrl_link_training_2(ctrl);
-	if (ret < 0) {
-		if (!dp_ctrl_link_rate_down_shift(ctrl)) {
-			pr_debug("retry with lower rate\n");
-
-			dp_ctrl_clear_training_pattern(ctrl);
-			return -EAGAIN;
-		}
-
-		pr_err("Training 2 failed\n");
-		ret = -EINVAL;
-		goto clear;
+	if (ret) {
+		pr_err("link training #2 failed\n");
+		goto end;
 	}
 
-	pr_debug("Training 2 completed successfully\n");
+	/* print success info as this is a result of user initiated action */
+	pr_debug("link training #2 successful\n");
 
+end:
 	dp_ctrl_state_ctrl(ctrl, 0);
 	/* Make sure to clear the current pattern before starting a new one */
 	wmb();
 
-clear:
 	dp_ctrl_clear_training_pattern(ctrl);
 	return ret;
 }
@@ -973,7 +1000,7 @@
 
 	ctrl->catalog->mainlink_ctrl(ctrl->catalog, true);
 
-	drm_dp_link_power_up(ctrl->aux->drm_aux, &ctrl->panel->dp_link);
+	drm_dp_link_power_up(ctrl->aux->drm_aux, &ctrl->panel->link_info);
 
 	if (ctrl->link->phy_pattern_requested(ctrl->link))
 		goto end;
@@ -1018,6 +1045,8 @@
 		cfg++;
 	}
 
+	pr_debug("setting rate=%d on clk=%s\n", rate, name);
+
 	if (num)
 		cfg->rate = rate;
 	else
@@ -1031,7 +1060,7 @@
 	ctrl->power->set_pixel_clk_parent(ctrl->power);
 
 	dp_ctrl_set_clock_rate(ctrl, "ctrl_link_clk",
-		drm_dp_bw_code_to_link_rate(ctrl->link->link_rate));
+		drm_dp_bw_code_to_link_rate(ctrl->link->bw_code));
 
 	dp_ctrl_set_clock_rate(ctrl, "ctrl_pixel_clk", ctrl->pixel_rate);
 
@@ -1128,6 +1157,9 @@
 
 		dp_ctrl_configure_source_params(ctrl);
 
+		ctrl->catalog->config_msa(ctrl->catalog,
+			drm_dp_bw_code_to_link_rate(ctrl->link->bw_code));
+
 		reinit_completion(&ctrl->idle_comp);
 
 		if (ctrl->psm_enabled) {
@@ -1148,16 +1180,20 @@
 static int dp_ctrl_on_hpd(struct dp_ctrl_private *ctrl)
 {
 	int ret = 0;
+	u32 rate = ctrl->panel->link_info.rate;
+	u32 link_train_max_retries = 100;
+
+	atomic_set(&ctrl->aborted, 0);
 
 	ctrl->power->clk_enable(ctrl->power, DP_CORE_PM, true);
 	ctrl->catalog->hpd_config(ctrl->catalog, true);
 
-	ctrl->link->link_rate  = ctrl->panel->get_link_rate(ctrl->panel);
-	ctrl->link->lane_count = ctrl->panel->dp_link.num_lanes;
+	ctrl->link->bw_code  = drm_dp_link_rate_to_bw_code(rate);
+	ctrl->link->lane_count = ctrl->panel->link_info.num_lanes;
 	ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz;
 
-	pr_debug("link_rate=%d, lane_count=%d, pixel_rate=%d\n",
-		ctrl->link->link_rate, ctrl->link->lane_count,
+	pr_debug("bw_code=%d, lane_count=%d, pixel_rate=%d\n",
+		ctrl->link->bw_code, ctrl->link->lane_count,
 		ctrl->pixel_rate);
 
 	ctrl->catalog->phy_lane_cfg(ctrl->catalog,
@@ -1174,8 +1210,25 @@
 	if (ctrl->psm_enabled)
 		ret = ctrl->link->send_psm_request(ctrl->link, false);
 
-	while (-EAGAIN == dp_ctrl_setup_main_link(ctrl, true))
-		pr_debug("MAIN LINK TRAINING RETRY\n");
+	while (--link_train_max_retries && !atomic_read(&ctrl->aborted)) {
+		ctrl->catalog->config_msa(ctrl->catalog,
+			drm_dp_bw_code_to_link_rate(ctrl->link->bw_code));
+
+		ret = dp_ctrl_setup_main_link(ctrl, true);
+		if (!ret)
+			break;
+
+		/* try with lower link rate */
+		dp_ctrl_link_rate_down_shift(ctrl);
+
+		ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);
+
+		dp_ctrl_disable_mainlink_clocks(ctrl);
+		/* hw recommended delay before re-enabling clocks */
+		msleep(20);
+
+		dp_ctrl_enable_mainlink_clocks(ctrl);
+	}
 
 	pr_debug("End-\n");
 
@@ -1292,6 +1345,7 @@
 	dp_ctrl->on        = dp_ctrl_on;
 	dp_ctrl->off       = dp_ctrl_off;
 	dp_ctrl->push_idle = dp_ctrl_push_idle;
+	dp_ctrl->abort     = dp_ctrl_abort;
 	dp_ctrl->isr       = dp_ctrl_isr;
 
 	return dp_ctrl;
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index 474e0ad..2ecfa0d 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -28,6 +28,7 @@
 	int (*on)(struct dp_ctrl *dp_ctrl, bool hpd_irq);
 	void (*off)(struct dp_ctrl *dp_ctrl, bool hpd_irq);
 	void (*push_idle)(struct dp_ctrl *dp_ctrl);
+	void (*abort)(struct dp_ctrl *dp_ctrl);
 	void (*isr)(struct dp_ctrl *dp_ctrl);
 };
 
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 5a33fdb..b45cf4d 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -12,7 +12,7 @@
  *
  */
 
-#define pr_fmt(fmt)	"[drm-dp]: %s: " fmt, __func__
+#define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__
 
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -45,7 +45,7 @@
 
 	struct platform_device *pdev;
 	struct dentry *root;
-	struct mutex lock;
+	struct completion notification_comp;
 
 	struct dp_usbpd   *usbpd;
 	struct dp_parser  *parser;
@@ -171,7 +171,7 @@
 		pr_err("invalid param(s), dev %pK, pdev %pK, master %pK\n",
 				dev, pdev, master);
 		rc = -EINVAL;
-		goto error;
+		goto end;
 	}
 
 	drm = dev_get_drvdata(master);
@@ -180,14 +180,12 @@
 		pr_err("invalid param(s), drm %pK, dp %pK\n",
 				drm, dp);
 		rc = -EINVAL;
-		goto error;
+		goto end;
 	}
 
 	dp->dp_display.drm_dev = drm;
 	priv = drm->dev_private;
 
-	mutex_lock(&dp->lock);
-
 	rc = dp_display_debugfs_init(dp);
 	if (rc) {
 		pr_err("[%s]Debugfs init failed, rc=%d\n", dp->name, rc);
@@ -218,8 +216,6 @@
 		goto end;
 	}
 end:
-	mutex_unlock(&dp->lock);
-error:
 	return rc;
 }
 
@@ -240,17 +236,10 @@
 		return;
 	}
 
-	mutex_lock(&dp->lock);
-
 	(void)dp->power->power_client_deinit(dp->power);
-
-	(void) dp->panel->sde_edid_deregister(dp->panel);
-
-	(void) dp->aux->drm_aux_deregister(dp->aux);
-
+	(void)dp->panel->sde_edid_deregister(dp->panel);
+	(void)dp->aux->drm_aux_deregister(dp->aux);
 	(void)dp_display_debugfs_deinit(dp);
-
-	mutex_unlock(&dp->lock);
 }
 
 static const struct component_ops dp_display_comp_ops = {
@@ -276,8 +265,13 @@
 		dp->parser->max_pclk_khz);
 
 	dp->dp_display.is_connected = true;
+
 	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
 
+	reinit_completion(&dp->notification_comp);
+	if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
+		pr_warn("timeout\n");
+
 	return rc;
 }
 
@@ -316,8 +310,15 @@
 
 static void dp_display_process_hpd_low(struct dp_display_private *dp)
 {
+	/* cancel any pending request */
+	dp->ctrl->abort(dp->ctrl);
+
 	dp->dp_display.is_connected = false;
 	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
+
+	reinit_completion(&dp->notification_comp);
+	if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
+		pr_warn("timeout\n");
 }
 
 static int dp_display_usbpd_configure_cb(struct device *dev)
@@ -338,11 +339,10 @@
 		goto end;
 	}
 
-	mutex_lock(&dp->lock);
 	dp_display_host_init(dp);
+
 	if (dp->usbpd->hpd_high)
 		dp_display_process_hpd_high(dp);
-	mutex_unlock(&dp->lock);
 end:
 	return rc;
 }
@@ -365,11 +365,16 @@
 		goto end;
 	}
 
-	mutex_lock(&dp->lock);
+	/* cancel any pending request */
+	dp->ctrl->abort(dp->ctrl);
 
 	dp->dp_display.is_connected = false;
 	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
 
+	reinit_completion(&dp->notification_comp);
+	if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
+		pr_warn("timeout\n");
+
 	/*
 	 * If a cable/dongle is connected to the TX device but
 	 * no sink device is connected, we call host
@@ -381,8 +386,6 @@
 	 */
 	if (!dp->power_on && dp->core_initialized)
 		dp_display_host_deinit(dp);
-
-	mutex_unlock(&dp->lock);
 end:
 	return rc;
 }
@@ -403,8 +406,6 @@
 		return -ENODEV;
 	}
 
-	mutex_lock(&dp->lock);
-
 	if (dp->usbpd->hpd_irq) {
 		dp->hpd_irq_on = true;
 		rc = dp->link->process_request(dp->link);
@@ -423,7 +424,6 @@
 		dp_display_process_hpd_high(dp);
 	}
 end:
-	mutex_unlock(&dp->lock);
 	return rc;
 }
 
@@ -543,18 +543,29 @@
 
 	dp = container_of(dp_display, struct dp_display_private, dp_display);
 
-	mutex_lock(&dp->lock);
 	rc = dp->ctrl->on(dp->ctrl, dp->hpd_irq_on);
 	if (!rc)
 		dp->power_on = true;
-	mutex_unlock(&dp->lock);
 error:
 	return rc;
 }
 
-static int dp_display_post_enable(struct dp_display *dp)
+static int dp_display_post_enable(struct dp_display *dp_display)
 {
-	return 0;
+	int rc = 0;
+	struct dp_display_private *dp;
+
+	if (!dp_display) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	dp = container_of(dp_display, struct dp_display_private, dp_display);
+
+	complete_all(&dp->notification_comp);
+end:
+	return rc;
 }
 
 static int dp_display_pre_disable(struct dp_display *dp_display)
@@ -570,9 +581,7 @@
 
 	dp = container_of(dp_display, struct dp_display_private, dp_display);
 
-	mutex_lock(&dp->lock);
 	dp->ctrl->push_idle(dp->ctrl);
-	mutex_unlock(&dp->lock);
 error:
 	return rc;
 }
@@ -590,11 +599,12 @@
 
 	dp = container_of(dp_display, struct dp_display_private, dp_display);
 
-	mutex_lock(&dp->lock);
 	dp->ctrl->off(dp->ctrl, dp->hpd_irq_on);
 	dp_display_host_deinit(dp);
+
 	dp->power_on = false;
-	mutex_unlock(&dp->lock);
+
+	complete_all(&dp->notification_comp);
 error:
 	return rc;
 }
@@ -668,7 +678,8 @@
 	if (!dp)
 		return -ENOMEM;
 
-	mutex_init(&dp->lock);
+	init_completion(&dp->notification_comp);
+
 	dp->pdev = pdev;
 	dp->name = "drm_dp";
 
diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c
index 741acfca..7e3d81f 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.c
+++ b/drivers/gpu/drm/msm/dp/dp_link.c
@@ -47,13 +47,6 @@
 	DP_TEST_VIDEO_PATTERN_COLOR_SQUARE = 0x03,
 };
 
-enum test_bit_depth {
-	DP_TEST_BIT_DEPTH_6 = 0x00,
-	DP_TEST_BIT_DEPTH_8 = 0x01,
-	DP_TEST_BIT_DEPTH_10 = 0x02,
-	DP_TEST_BIT_DEPTH_UNKNOWN = 0xFFFFFFFF,
-};
-
 enum dp_link_response {
 	TEST_ACK			= 0x1,
 	TEST_NACK			= 0x2,
@@ -218,7 +211,7 @@
 static int dp_link_get_period(struct dp_link_private *link, int const addr)
 {
 	int ret = 0;
-	u8 *bp;
+	u8 bp;
 	u8 data;
 	u32 const param_len = 0x1;
 	u32 const max_audio_period = 0xA;
@@ -231,7 +224,7 @@
 		goto exit;
 	}
 
-	data = *bp;
+	data = bp;
 
 	/* Period - Bits 3:0 */
 	data = data & 0xF;
@@ -329,7 +322,7 @@
 static int dp_link_parse_audio_pattern_type(struct dp_link_private *link)
 {
 	int ret = 0;
-	u8 *bp;
+	u8 bp;
 	u8 data;
 	int rlen;
 	int const param_len = 0x1;
@@ -344,7 +337,7 @@
 		ret = -EINVAL;
 		goto exit;
 	}
-	data = *bp;
+	data = bp;
 
 	/* Audio Pattern Type - Bits 7:0 */
 	if ((int)data > max_audio_pattern_type) {
@@ -363,7 +356,7 @@
 static int dp_link_parse_audio_mode(struct dp_link_private *link)
 {
 	int ret = 0;
-	u8 *bp;
+	u8 bp;
 	u8 data;
 	int rlen;
 	int const param_len = 0x1;
@@ -381,7 +374,7 @@
 		ret = -EINVAL;
 		goto exit;
 	}
-	data = *bp;
+	data = bp;
 
 	/* Sampling Rate - Bits 3:0 */
 	sampling_rate = data & 0xF;
@@ -535,14 +528,14 @@
 static int dp_link_parse_timing_params1(struct dp_link_private *link,
 	int const addr, int const len, u32 *val)
 {
-	u8 *bp;
+	u8 bp[2];
 	int rlen;
 
 	if (len < 2)
 		return -EINVAL;
 
 	/* Read the requested video link pattern (Byte 0x221). */
-	rlen = drm_dp_dpcd_read(link->aux->drm_aux, addr, &bp, len);
+	rlen = drm_dp_dpcd_read(link->aux->drm_aux, addr, bp, len);
 	if (rlen < len) {
 		pr_err("failed to read 0x%x\n", addr);
 		return -EINVAL;
@@ -556,14 +549,14 @@
 static int dp_link_parse_timing_params2(struct dp_link_private *link,
 	int const addr, int const len, u32 *val1, u32 *val2)
 {
-	u8 *bp;
+	u8 bp[2];
 	int rlen;
 
 	if (len < 2)
 		return -EINVAL;
 
 	/* Read the requested video link pattern (Byte 0x221). */
-	rlen = drm_dp_dpcd_read(link->aux->drm_aux, addr, &bp, len);
+	rlen = drm_dp_dpcd_read(link->aux->drm_aux, addr, bp, len);
 	if (rlen < len) {
 		pr_err("failed to read 0x%x\n", addr);
 		return -EINVAL;
@@ -578,7 +571,7 @@
 static int dp_link_parse_timing_params3(struct dp_link_private *link,
 	int const addr, u32 *val)
 {
-	u8 *bp;
+	u8 bp;
 	u32 len = 1;
 	int rlen;
 
@@ -588,7 +581,7 @@
 		pr_err("failed to read 0x%x\n", addr);
 		return -EINVAL;
 	}
-	*val = bp[0];
+	*val = bp;
 
 	return 0;
 }
@@ -604,7 +597,7 @@
 {
 	int ret = 0;
 	int rlen;
-	u8 *bp;
+	u8 bp;
 	u8 data;
 	u32 dyn_range;
 	int const param_len = 0x1;
@@ -619,7 +612,7 @@
 		ret = -EINVAL;
 		goto exit;
 	}
-	data = *bp;
+	data = bp;
 
 	if (!dp_link_is_video_pattern_valid(data)) {
 		pr_err("invalid link video pattern = 0x%x\n", data);
@@ -641,7 +634,7 @@
 		ret = -EINVAL;
 		goto exit;
 	}
-	data = *bp;
+	data = bp;
 
 	/* Dynamic Range */
 	dyn_range = (data & BIT(3)) >> 3;
@@ -765,12 +758,12 @@
  *
  * Returns true if the requested link rate is supported.
  */
-static bool dp_link_is_link_rate_valid(u32 link_rate)
+static bool dp_link_is_link_rate_valid(u32 bw_code)
 {
-	return ((link_rate == DP_LINK_BW_1_62) ||
-		(link_rate == DP_LINK_BW_2_7) ||
-		(link_rate == DP_LINK_BW_5_4) ||
-		(link_rate == DP_LINK_RATE_810));
+	return ((bw_code == DP_LINK_BW_1_62) ||
+		(bw_code == DP_LINK_BW_2_7) ||
+		(bw_code == DP_LINK_BW_5_4) ||
+		(bw_code == DP_LINK_RATE_810));
 }
 
 /**
@@ -796,7 +789,7 @@
  */
 static int dp_link_parse_link_training_params(struct dp_link_private *link)
 {
-	u8 *bp;
+	u8 bp;
 	u8 data;
 	int ret = 0;
 	int rlen;
@@ -810,7 +803,7 @@
 		ret = -EINVAL;
 		goto exit;
 	}
-	data = *bp;
+	data = bp;
 
 	if (!dp_link_is_link_rate_valid(data)) {
 		pr_err("invalid link rate = 0x%x\n", data);
@@ -829,7 +822,7 @@
 		ret = -EINVAL;
 		goto exit;
 	}
-	data = *bp;
+	data = bp;
 	data &= 0x1F;
 
 	if (!dp_link_is_lane_count_valid(data)) {
@@ -868,7 +861,7 @@
  */
 static int dp_link_parse_phy_test_params(struct dp_link_private *link)
 {
-	u8 *bp;
+	u8 bp;
 	u8 data;
 	int rlen;
 	int const param_len = 0x1;
@@ -883,7 +876,7 @@
 		goto end;
 	}
 
-	data = *bp;
+	data = bp;
 
 	link->request.phy_test_pattern_sel = data;
 
@@ -946,7 +939,7 @@
 static int dp_link_parse_request(struct dp_link_private *link)
 {
 	int ret = 0;
-	u8 *bp;
+	u8 bp;
 	u8 data;
 	int rlen;
 	u32 const param_len = 0x1;
@@ -964,12 +957,12 @@
 		goto end;
 	}
 
-	data = *bp;
+	data = bp;
 
 	pr_debug("device service irq vector = 0x%x\n", data);
 
 	if (!(data & BIT(1))) {
-		pr_debug("no link requested\n");
+		pr_debug("no test requested\n");
 		goto end;
 	}
 
@@ -985,7 +978,7 @@
 		goto end;
 	}
 
-	data = *bp;
+	data = bp;
 
 	if (!dp_link_is_test_supported(data)) {
 		pr_debug("link 0x%x not supported\n", data);
@@ -1039,7 +1032,7 @@
  */
 static void dp_link_parse_sink_count(struct dp_link_private *link)
 {
-	u8 *bp;
+	u8 bp;
 	u8 data;
 	int rlen;
 	int const param_len = 0x1;
@@ -1051,7 +1044,7 @@
 		return;
 	}
 
-	data = *bp;
+	data = bp;
 
 	/* BIT 7, BIT 5:0 */
 	link->sink_count.count = (data & BIT(7)) << 6 | (data & 0x63);
@@ -1101,7 +1094,7 @@
 			link->request.test_lane_count);
 
 	link->dp_link.lane_count = link->request.test_lane_count;
-	link->dp_link.link_rate = link->request.test_link_rate;
+	link->dp_link.bw_code = link->request.test_link_rate;
 
 	return 0;
 }
@@ -1116,7 +1109,7 @@
 
 static int dp_link_parse_vx_px(struct dp_link_private *link)
 {
-	u8 *bp;
+	u8 bp;
 	u8 data;
 	int const param_len = 0x1;
 	int const addr1 = 0x206;
@@ -1134,7 +1127,7 @@
 		goto end;
 	}
 
-	data = *bp;
+	data = bp;
 
 	pr_debug("lanes 0/1 (Byte 0x206): 0x%x\n", data);
 
@@ -1155,7 +1148,7 @@
 		goto end;
 	}
 
-	data = *bp;
+	data = bp;
 
 	pr_debug("lanes 2/3 (Byte 0x207): 0x%x\n", data);
 
@@ -1216,7 +1209,7 @@
 	pr_debug("start\n");
 
 	link->dp_link.lane_count = link->request.test_lane_count;
-	link->dp_link.link_rate = link->request.test_link_rate;
+	link->dp_link.bw_code = link->request.test_link_rate;
 
 	dp_link_parse_vx_px(link);
 
@@ -1517,7 +1510,7 @@
 		dp_link->p_level = DP_LINK_PRE_EMPHASIS_LEVEL_1;
 	}
 
-	pr_debug("v_level=%d, p_level=%d\n",
+	pr_debug("adjusted: v_level=%d, p_level=%d\n",
 		dp_link->v_level, dp_link->p_level);
 
 	return 0;
diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h
index 26249d6..8ea43da 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.h
+++ b/drivers/gpu/drm/msm/dp/dp_link.h
@@ -46,11 +46,18 @@
 	DS_PORT_STATUS_CHANGED = 0x200,
 };
 
+enum test_bit_depth {
+	DP_TEST_BIT_DEPTH_6 = 0x00,
+	DP_TEST_BIT_DEPTH_8 = 0x01,
+	DP_TEST_BIT_DEPTH_10 = 0x02,
+	DP_TEST_BIT_DEPTH_UNKNOWN = 0xFFFFFFFF,
+};
+
 struct dp_link {
 	u32 test_requested;
 
 	u32 lane_count;
-	u32 link_rate;
+	u32 bw_code;
 	u32 v_level;
 	u32 p_level;
 
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 4496e9a..5f25b2d 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -16,6 +16,8 @@
 
 #include "dp_panel.h"
 
+#define DP_PANEL_DEFAULT_BPP 24
+
 enum {
 	DP_LINK_RATE_MULTIPLIER = 27000000,
 };
@@ -25,14 +27,16 @@
 	struct dp_panel dp_panel;
 	struct dp_aux *aux;
 	struct dp_catalog_panel *catalog;
+	bool lane_switch_supported;
 };
 
 static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
 {
 	int rlen, rc = 0;
 	struct dp_panel_private *panel;
-	struct drm_dp_link *dp_link;
+	struct drm_dp_link *link_info;
 	u8 major = 0, minor = 0;
+	unsigned long caps = DP_LINK_CAP_ENHANCED_FRAMING;
 
 	if (!dp_panel) {
 		pr_err("invalid input\n");
@@ -41,7 +45,7 @@
 	}
 
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-	dp_link = &dp_panel->dp_link;
+	link_info = &dp_panel->link_info;
 
 	rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_DPCD_REV,
 		dp_panel->dpcd, (DP_RECEIVER_CAP_SIZE + 1));
@@ -51,22 +55,26 @@
 		goto end;
 	}
 
-	dp_link->revision = dp_panel->dpcd[DP_DPCD_REV];
+	link_info->revision = dp_panel->dpcd[DP_DPCD_REV];
 
-	major = (dp_link->revision >> 4) & 0x0f;
-	minor = dp_link->revision & 0x0f;
+	major = (link_info->revision >> 4) & 0x0f;
+	minor = link_info->revision & 0x0f;
 	pr_debug("version: %d.%d\n", major, minor);
 
-	dp_link->rate =
+	link_info->rate =
 		drm_dp_bw_code_to_link_rate(dp_panel->dpcd[DP_MAX_LINK_RATE]);
-	pr_debug("link_rate=%d\n", dp_link->rate);
+	pr_debug("link_rate=%d\n", link_info->rate);
 
-	dp_link->num_lanes = dp_panel->dpcd[DP_MAX_LANE_COUNT] &
+	if (panel->lane_switch_supported)
+		link_info->num_lanes = dp_panel->dpcd[DP_MAX_LANE_COUNT] &
 			DP_MAX_LANE_COUNT_MASK;
-	pr_debug("lane_count=%d\n", dp_link->num_lanes);
+	else
+		link_info->num_lanes = 2;
+
+	pr_debug("lane_count=%d\n", link_info->num_lanes);
 
 	if (dp_panel->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)
-		dp_link->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING;
+		link_info->capabilities |= caps;
 
 end:
 	return rc;
@@ -74,26 +82,26 @@
 
 static u32 dp_panel_get_max_pclk(struct dp_panel *dp_panel)
 {
-	struct dp_panel_private *panel;
-	struct drm_dp_link *dp_link;
-	u32 bpc, bpp, max_data_rate_khz, max_pclk_rate_khz;
+	struct drm_dp_link *link_info;
 	const u8 num_components = 3;
+	u32 bpc, bpp, max_data_rate_khz, max_pclk_rate_khz;
 
 	if (!dp_panel) {
 		pr_err("invalid input\n");
 		return 0;
 	}
 
-	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-	dp_link = &dp_panel->dp_link;
+	link_info = &dp_panel->link_info;
 
 	bpc = sde_get_sink_bpc(dp_panel->edid_ctrl);
 	bpp = bpc * num_components;
+	if (!bpp)
+		bpp = DP_PANEL_DEFAULT_BPP;
 
-	max_data_rate_khz = (dp_link->num_lanes * dp_link->rate * 8);
+	max_data_rate_khz = (link_info->num_lanes * link_info->rate * 8);
 	max_pclk_rate_khz = max_data_rate_khz / bpp;
 
-	pr_debug("bpp=%d, max_lane_cnt=%d\n", bpp, dp_link->num_lanes);
+	pr_debug("bpp=%d, max_lane_cnt=%d\n", bpp, link_info->num_lanes);
 	pr_debug("max_data_rate=%dKHz, max_pclk_rate=%dKHz\n",
 		max_data_rate_khz, max_pclk_rate_khz);
 
@@ -196,7 +204,7 @@
 static int dp_panel_init_panel_info(struct dp_panel *dp_panel)
 {
 	int rc = 0;
-	struct dp_panel_private *panel;
+	struct dp_panel_info *pinfo;
 
 	if (!dp_panel) {
 		pr_err("invalid input\n");
@@ -204,18 +212,38 @@
 		goto end;
 	}
 
-	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+	pinfo = &dp_panel->pinfo;
+
+	/*
+	 * print resolution info as this is a result
+	 * of user initiated action of cable connection
+	 */
+	pr_info("SET NEW RESOLUTION:\n");
+	pr_info("%dx%d@%dfps\n", pinfo->h_active,
+		pinfo->v_active, pinfo->refresh_rate);
+	pr_info("h_porches(back|front|width) = (%d|%d|%d)\n",
+			pinfo->h_back_porch,
+			pinfo->h_front_porch,
+			pinfo->h_sync_width);
+	pr_info("v_porches(back|front|width) = (%d|%d|%d)\n",
+			pinfo->v_back_porch,
+			pinfo->v_front_porch,
+			pinfo->v_sync_width);
+	pr_info("pixel clock (KHz)=(%d)\n", pinfo->pixel_clk_khz);
+	pr_info("bpp = %d\n", pinfo->bpp);
+	pr_info("active low (h|v)=(%d|%d)\n", pinfo->h_active_low,
+		pinfo->v_active_low);
+
+	pinfo->bpp = max_t(u32, 18, min_t(u32, pinfo->bpp, 30));
+	pr_info("updated bpp = %d\n", pinfo->bpp);
 end:
 	return rc;
 }
 
-static u32 dp_panel_get_link_rate(struct dp_panel *dp_panel)
+static u32 dp_panel_get_min_req_link_rate(struct dp_panel *dp_panel)
 {
 	const u32 encoding_factx10 = 8;
-	const u32 ln_to_link_ratio = 10;
-	u32 min_link_rate, reminder = 0;
-	u32 calc_link_rate = 0, lane_cnt, max_rate = 0;
-	struct dp_panel_private *panel;
+	u32 min_link_rate_khz = 0, lane_cnt;
 	struct dp_panel_info *pinfo;
 
 	if (!dp_panel) {
@@ -223,54 +251,19 @@
 		goto end;
 	}
 
-	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-
-	lane_cnt = dp_panel->dp_link.num_lanes;
-	max_rate = drm_dp_link_rate_to_bw_code(dp_panel->dp_link.rate);
+	lane_cnt = dp_panel->link_info.num_lanes;
 	pinfo = &dp_panel->pinfo;
 
-	/*
-	 * The max pixel clock supported is 675Mhz. The
-	 * current calculations below will make sure
-	 * the min_link_rate is within 32 bit limits.
-	 * Any changes in the section of code should
-	 * consider this limitation.
-	 */
-	min_link_rate = (u32)div_u64(pinfo->pixel_clk_khz * 1000,
-				(lane_cnt * encoding_factx10));
-	min_link_rate /= ln_to_link_ratio;
-	min_link_rate = (min_link_rate * pinfo->bpp);
-	min_link_rate = (u32)div_u64_rem(min_link_rate * 10,
-				DP_LINK_RATE_MULTIPLIER, &reminder);
+	/* num_lanes * lane_count * 8 >= pclk * bpp * 10 */
+	min_link_rate_khz = pinfo->pixel_clk_khz /
+				(lane_cnt * encoding_factx10);
+	min_link_rate_khz *= pinfo->bpp;
 
-	/*
-	 * To avoid any fractional values,
-	 * increment the min_link_rate
-	 */
-	if (reminder)
-		min_link_rate += 1;
-	pr_debug("min_link_rate = %d\n", min_link_rate);
-
-	if (min_link_rate <= DP_LINK_BW_1_62)
-		calc_link_rate = DP_LINK_BW_1_62;
-	else if (min_link_rate <= DP_LINK_BW_2_7)
-		calc_link_rate = DP_LINK_BW_2_7;
-	else if (min_link_rate <= DP_LINK_BW_5_4)
-		calc_link_rate = DP_LINK_BW_5_4;
-	else if (min_link_rate <= DP_LINK_RATE_810)
-		calc_link_rate = DP_LINK_RATE_810;
-	else {
-		/* Cap the link rate to the max supported rate */
-		pr_debug("link_rate = %d is unsupported\n", min_link_rate);
-		calc_link_rate = DP_LINK_RATE_810;
-	}
-
-	if (calc_link_rate > max_rate)
-		calc_link_rate = max_rate;
-
-	pr_debug("calc_link_rate = 0x%x\n", calc_link_rate);
+	pr_debug("min lclk req=%d khz for pclk=%d khz, lanes=%d, bpp=%d\n",
+		min_link_rate_khz, pinfo->pixel_clk_khz, lane_cnt,
+		pinfo->bpp);
 end:
-	return calc_link_rate;
+	return min_link_rate_khz;
 }
 
 struct dp_panel *dp_panel_get(struct device *dev, struct dp_aux *aux,
@@ -303,7 +296,7 @@
 	dp_panel->init_info = dp_panel_init_panel_info;
 	dp_panel->timing_cfg = dp_panel_timing_cfg;
 	dp_panel->read_dpcd = dp_panel_read_dpcd;
-	dp_panel->get_link_rate = dp_panel_get_link_rate;
+	dp_panel->get_min_req_link_rate = dp_panel_get_min_req_link_rate;
 	dp_panel->get_max_pclk = dp_panel_get_max_pclk;
 
 	return dp_panel;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index b63c51f..6cca0f1 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -40,7 +40,7 @@
 struct dp_panel {
 	/* dpcd raw data */
 	u8 dpcd[DP_RECEIVER_CAP_SIZE];
-	struct drm_dp_link dp_link;
+	struct drm_dp_link link_info;
 
 	struct sde_edid_ctrl *edid_ctrl;
 	struct dp_panel_info pinfo;
@@ -53,7 +53,7 @@
 	int (*init_info)(struct dp_panel *dp_panel);
 	int (*timing_cfg)(struct dp_panel *dp_panel);
 	int (*read_dpcd)(struct dp_panel *dp_panel);
-	u32 (*get_link_rate)(struct dp_panel *dp_panel);
+	u32 (*get_min_req_link_rate)(struct dp_panel *dp_panel);
 	u32 (*get_max_pclk)(struct dp_panel *dp_panel);
 };
 
diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.c b/drivers/gpu/drm/msm/dp/dp_usbpd.c
index 6ef8266..7bc1433 100644
--- a/drivers/gpu/drm/msm/dp/dp_usbpd.c
+++ b/drivers/gpu/drm/msm/dp/dp_usbpd.c
@@ -345,12 +345,11 @@
 		pd->vdo = *vdos;
 		dp_usbpd_get_status(pd);
 
-		if (pd->dp_cb && pd->dp_cb->attention) {
+		if (pd->dp_cb && pd->dp_cb->attention)
 			pd->dp_cb->attention(pd->dev);
 
-			if (!pd->dp_usbpd.alt_mode_cfg_done)
-				dp_usbpd_send_event(pd, DP_USBPD_EVT_CONFIGURE);
-		}
+		if (!pd->dp_usbpd.alt_mode_cfg_done)
+			dp_usbpd_send_event(pd, DP_USBPD_EVT_CONFIGURE);
 		break;
 	case DP_USBPD_VDM_STATUS:
 		pd->vdo = *vdos;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 810d0d6..0be17b9 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -58,13 +58,14 @@
 #define MSM_VERSION_PATCHLEVEL	0
 
 #define TEARDOWN_DEADLOCK_RETRY_MAX 5
+#define HPD_STRING_SIZE 30
 
 static void msm_drm_helper_hotplug_event(struct drm_device *dev)
 {
 	struct drm_connector *connector;
-	char *event_string;
+	char name[HPD_STRING_SIZE], status[HPD_STRING_SIZE];
 	char const *connector_name;
-	char *envp[2];
+	char *envp[3];
 
 	if (!dev) {
 		DRM_ERROR("hotplug_event failed, invalid input\n");
@@ -74,12 +75,6 @@
 	if (!dev->mode_config.poll_enabled)
 		return;
 
-	event_string = kzalloc(SZ_4K, GFP_KERNEL);
-	if (!event_string) {
-		DRM_ERROR("failed to allocate event string\n");
-		return;
-	}
-
 	mutex_lock(&dev->mode_config.mutex);
 	drm_for_each_connector(connector, dev) {
 		/* Only handle HPD capable connectors. */
@@ -93,17 +88,20 @@
 		else
 			connector_name = "unknown";
 
-		snprintf(event_string, SZ_4K, "name=%s status=%s\n",
-			connector_name,
+		snprintf(name, HPD_STRING_SIZE, "name=%s", connector_name);
+
+		snprintf(status, HPD_STRING_SIZE, "status=%s",
 			drm_get_connector_status_name(connector->status));
-		DRM_DEBUG("generating hotplug event [%s]\n", event_string);
-		envp[0] = event_string;
-		envp[1] = NULL;
+
+		DRM_DEBUG("generating hotplug event [%s]: [%s]\n",
+			name, status);
+		envp[0] = name;
+		envp[1] = status;
+		envp[2] = NULL;
 		kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE,
 				envp);
 	}
 	mutex_unlock(&dev->mode_config.mutex);
-	kfree(event_string);
 }
 
 static void msm_fb_output_poll_changed(struct drm_device *dev)
@@ -126,21 +124,10 @@
 int msm_atomic_check(struct drm_device *dev,
 			    struct drm_atomic_state *state)
 {
-	struct msm_drm_private *priv;
-
-	if (!dev)
-		return -EINVAL;
-
 	if (msm_is_suspend_blocked(dev)) {
 		DRM_DEBUG("rejecting commit during suspend\n");
 		return -EBUSY;
 	}
-
-	priv = dev->dev_private;
-	if (priv && priv->kms && priv->kms->funcs &&
-			priv->kms->funcs->atomic_check)
-		return priv->kms->funcs->atomic_check(priv->kms, state);
-
 	return drm_atomic_helper_check(dev, state);
 }
 
@@ -534,6 +521,7 @@
 	struct msm_kms *kms;
 	struct sde_dbg_power_ctrl dbg_power_ctrl = { 0 };
 	int ret, i;
+	struct sched_param param;
 
 	ddev = drm_dev_alloc(drv, dev);
 	if (!ddev) {
@@ -637,6 +625,12 @@
 	}
 	ddev->mode_config.funcs = &mode_config_funcs;
 
+	/**
+	 * this priority was found during empiric testing to have appropriate
+	 * realtime scheduling to process display updates and interact with
+	 * other real time and normal priority task
+	 */
+	param.sched_priority = 16;
 	for (i = 0; i < priv->num_crtcs; i++) {
 
 		/* initialize display thread */
@@ -647,6 +641,11 @@
 			kthread_run(kthread_worker_fn,
 				&priv->disp_thread[i].worker,
 				"crtc_commit:%d", priv->disp_thread[i].crtc_id);
+		ret = sched_setscheduler(priv->disp_thread[i].thread,
+							SCHED_FIFO, &param);
+		if (ret)
+			pr_warn("display thread priority update failed: %d\n",
+									ret);
 
 		if (IS_ERR(priv->disp_thread[i].thread)) {
 			dev_err(dev, "failed to create crtc_commit kthread\n");
@@ -661,6 +660,18 @@
 			kthread_run(kthread_worker_fn,
 				&priv->event_thread[i].worker,
 				"crtc_event:%d", priv->event_thread[i].crtc_id);
+		/**
+		 * event thread should also run at same priority as disp_thread
+		 * because it is handling frame_done events. A lower priority
+		 * event thread and higher priority disp_thread can causes
+		 * frame_pending counters beyond 2. This can lead to commit
+		 * failure at crtc commit level.
+		 */
+		ret = sched_setscheduler(priv->event_thread[i].thread,
+							SCHED_FIFO, &param);
+		if (ret)
+			pr_warn("display event thread priority update failed: %d\n",
+									ret);
 
 		if (IS_ERR(priv->event_thread[i].thread)) {
 			dev_err(dev, "failed to create crtc_event kthread\n");
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index eb10d6b..35e6b71 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -75,9 +75,6 @@
 			const struct msm_format *msm_fmt,
 			const struct drm_mode_fb_cmd2 *cmd,
 			struct drm_gem_object **bos);
-	/* perform complete atomic check of given atomic state */
-	int (*atomic_check)(struct msm_kms *kms,
-				    struct drm_atomic_state *state);
 	/* misc: */
 	long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
 			struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index e999a6a..0fc982e 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -60,6 +60,8 @@
 
 static void dspp_gc_install_property(struct drm_crtc *crtc);
 
+static void dspp_igc_install_property(struct drm_crtc *crtc);
+
 typedef void (*dspp_prop_install_func_t)(struct drm_crtc *crtc);
 
 static dspp_prop_install_func_t dspp_prop_install_func[SDE_DSPP_MAX];
@@ -80,6 +82,7 @@
 	func[SDE_DSPP_VLUT] = dspp_vlut_install_property; \
 	func[SDE_DSPP_GAMUT] = dspp_gamut_install_property; \
 	func[SDE_DSPP_GC] = dspp_gc_install_property; \
+	func[SDE_DSPP_IGC] = dspp_igc_install_property; \
 } while (0)
 
 typedef void (*lm_prop_install_func_t)(struct drm_crtc *crtc);
@@ -1061,6 +1064,7 @@
 		"SDE_DSPP_PCC_V", version);
 	switch (version) {
 	case 1:
+	case 4:
 		sde_cp_crtc_install_blob_property(crtc, feature_name,
 			SDE_CP_CRTC_DSPP_PCC, sizeof(struct drm_msm_pcc));
 		break;
@@ -1241,6 +1245,30 @@
 	}
 }
 
+static void dspp_igc_install_property(struct drm_crtc *crtc)
+{
+	char feature_name[256];
+	struct sde_kms *kms = NULL;
+	struct sde_mdss_cfg *catalog = NULL;
+	u32 version;
+
+	kms = get_kms(crtc);
+	catalog = kms->catalog;
+
+	version = catalog->dspp[0].sblk->igc.version >> 16;
+	snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d",
+		"SDE_DSPP_IGC_V", version);
+	switch (version) {
+	case 3:
+		sde_cp_crtc_install_blob_property(crtc, feature_name,
+			SDE_CP_CRTC_DSPP_IGC, sizeof(struct drm_msm_igc_lut));
+		break;
+	default:
+		DRM_ERROR("version %d not supported\n", version);
+		break;
+	}
+}
+
 static void sde_cp_update_list(struct sde_cp_node *prop_node,
 		struct sde_crtc *crtc, bool dirty_list)
 {
diff --git a/drivers/gpu/drm/msm/sde/sde_core_perf.c b/drivers/gpu/drm/msm/sde/sde_core_perf.c
index 71dfc12..7243fe2 100644
--- a/drivers/gpu/drm/msm/sde/sde_core_perf.c
+++ b/drivers/gpu/drm/msm/sde/sde_core_perf.c
@@ -225,8 +225,17 @@
 				struct sde_crtc_state *tmp_cstate =
 					to_sde_crtc_state(tmp_crtc->state);
 
-				bw_sum_of_intfs +=
-					tmp_cstate->new_perf.bw_ctl[i];
+				SDE_DEBUG("crtc:%d bw:%llu ctrl:%d\n",
+					tmp_crtc->base.id,
+					tmp_cstate->new_perf.bw_ctl[i],
+					tmp_cstate->bw_control);
+				/*
+				 * For bw check only use the bw if the
+				 * atomic property has been already set
+				 */
+				if (tmp_cstate->bw_control)
+					bw_sum_of_intfs +=
+						tmp_cstate->new_perf.bw_ctl[i];
 			}
 		}
 
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 7417514..6bc1309 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -55,9 +55,13 @@
 static int sde_crtc_power_interrupt_handler(struct drm_crtc *crtc_drm,
 	bool en, struct sde_irq_callback *ad_irq);
 
+static int sde_crtc_pm_event_handler(struct drm_crtc *crtc_drm,
+	bool en, struct sde_irq_callback *noirq);
+
 static struct sde_crtc_custom_events custom_events[] = {
 	{DRM_EVENT_AD_BACKLIGHT, sde_cp_ad_interrupt},
-	{DRM_EVENT_CRTC_POWER, sde_crtc_power_interrupt_handler}
+	{DRM_EVENT_CRTC_POWER, sde_crtc_power_interrupt_handler},
+	{DRM_EVENT_SDE_POWER, sde_crtc_pm_event_handler},
 };
 
 /* default input fence timeout, in ms */
@@ -979,7 +983,7 @@
 	 * 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)
+	if (sde_crtc->num_mixers < 2)
 		return 0;
 
 	roi[0] = &crtc_state->lm_roi[0];
@@ -2021,6 +2025,16 @@
 	if (unlikely(!sde_crtc->num_mixers))
 		return;
 
+	/*
+	 * For planes without commit update, drm framework will not add
+	 * those planes to current state since hardware update is not
+	 * required. However, if those planes were power collapsed since
+	 * last commit cycle, driver has to restore the hardware state
+	 * of those planes explicitly here prior to plane flush.
+	 */
+	drm_atomic_crtc_for_each_plane(plane, crtc)
+		sde_plane_restore(plane);
+
 	/* wait for acquire fences before anything else is done */
 	_sde_crtc_wait_for_fences(crtc);
 
@@ -2339,8 +2353,6 @@
 
 	_sde_crtc_rp_duplicate(&old_cstate->rp, &cstate->rp);
 
-	cstate->idle_pc = sde_crtc->idle_pc;
-
 	return &cstate->base;
 }
 
@@ -2421,6 +2433,8 @@
 	struct drm_crtc *crtc = arg;
 	struct sde_crtc *sde_crtc;
 	struct drm_encoder *encoder;
+	struct drm_event event;
+	u32 power_on = 0;
 
 	if (!crtc) {
 		SDE_ERROR("invalid crtc\n");
@@ -2441,24 +2455,11 @@
 			sde_encoder_virt_restore(encoder);
 		}
 
-	} else if (event_type == SDE_POWER_EVENT_PRE_DISABLE) {
-		/*
-		 * Serialize h/w idle state update with crtc atomic check.
-		 * Grab the modeset lock to ensure that there is no on-going
-		 * atomic check, then increment the idle_pc counter. The next
-		 * atomic check will detect a new idle_pc since the counter
-		 * has advanced between the old_state and new_state, and
-		 * therefore properly reprogram all relevant drm objects'
-		 * hardware.
-		 */
-		drm_modeset_lock_crtc(crtc, NULL);
-
-		sde_crtc->idle_pc++;
-
-		SDE_DEBUG("crtc%d idle_pc:%d\n", crtc->base.id,
-				sde_crtc->idle_pc);
-		SDE_EVT32(DRMID(crtc), sde_crtc->idle_pc);
-
+		event.type = DRM_EVENT_SDE_POWER;
+		event.length = sizeof(power_on);
+		power_on = 1;
+		msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
+				(u8 *)&power_on);
 	} else if (event_type == SDE_POWER_EVENT_POST_DISABLE) {
 		struct drm_plane *plane;
 
@@ -2469,8 +2470,13 @@
 		drm_atomic_crtc_for_each_plane(plane, crtc)
 			sde_plane_set_revalidate(plane, true);
 
-		drm_modeset_unlock_crtc(crtc);
 		sde_cp_crtc_suspend(crtc);
+
+		event.type = DRM_EVENT_SDE_POWER;
+		event.length = sizeof(power_on);
+		power_on = 0;
+		msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
+				(u8 *)&power_on);
 	}
 
 	mutex_unlock(&sde_crtc->crtc_lock);
@@ -2599,8 +2605,7 @@
 
 	sde_crtc->power_event = sde_power_handle_register_event(
 		&priv->phandle,
-		SDE_POWER_EVENT_POST_ENABLE | SDE_POWER_EVENT_POST_DISABLE |
-		SDE_POWER_EVENT_PRE_DISABLE,
+		SDE_POWER_EVENT_POST_ENABLE | SDE_POWER_EVENT_POST_DISABLE,
 		sde_crtc_handle_power_event, crtc, sde_crtc->name);
 }
 
@@ -2770,7 +2775,8 @@
 
 		/* 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) {
+			if (cstate->dim_layer[i].stage
+					== (pstates[cnt].stage + SDE_STAGE_0)) {
 				SDE_ERROR(
 					"plane:%d/dim_layer:%i-same stage:%d\n",
 					plane->base.id, i,
@@ -3987,3 +3993,13 @@
 {
 	return 0;
 }
+
+static int sde_crtc_pm_event_handler(struct drm_crtc *crtc, bool en,
+		struct sde_irq_callback *noirq)
+{
+	/*
+	 * IRQ object noirq is not being used here since there is
+	 * no crtc irq from pm event.
+	 */
+	return 0;
+}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index f021477..0d72ff1 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -125,7 +125,6 @@
  * @vblank_cb_time  : ktime at vblank count reset
  * @vblank_refcount : reference count for vblank enable request
  * @suspend         : whether or not a suspend operation is in progress
- * @idle_pc       : count of current idle power collapse request
  * @feature_list  : list of color processing features supported on a crtc
  * @active_list   : list of color processing features are active
  * @dirty_list    : list of color processing features are dirty
@@ -174,7 +173,6 @@
 	ktime_t vblank_cb_time;
 	atomic_t vblank_refcount;
 	bool suspend;
-	u32 idle_pc;
 
 	struct list_head feature_list;
 	struct list_head active_list;
@@ -280,7 +278,6 @@
  * @sbuf_cfg: stream buffer configuration
  * @sbuf_prefill_line: number of line for inline rotator prefetch
  * @sbuf_flush_mask: flush mask for inline rotator
- * @idle_pc: count of idle power collapse request when state is duplicated
  */
 struct sde_crtc_state {
 	struct drm_crtc_state base;
@@ -310,8 +307,6 @@
 	u32 sbuf_prefill_line;
 	u32 sbuf_flush_mask;
 
-	u32 idle_pc;
-
 	struct sde_crtc_respool rp;
 };
 
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 56e1151..3aafb6e 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -1709,15 +1709,15 @@
 		}
 	}
 
+	if (sde_enc->cur_master && sde_enc->cur_master->ops.disable)
+		sde_enc->cur_master->ops.disable(sde_enc->cur_master);
+
 	/* after phys waits for frame-done, should be no more frames pending */
 	if (atomic_xchg(&sde_enc->frame_done_timeout, 0)) {
 		SDE_ERROR("enc%d timeout pending\n", drm_enc->base.id);
 		del_timer_sync(&sde_enc->frame_done_timer);
 	}
 
-	if (sde_enc->cur_master && sde_enc->cur_master->ops.disable)
-		sde_enc->cur_master->ops.disable(sde_enc->cur_master);
-
 	sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_STOP);
 
 	if (sde_enc->cur_master) {
@@ -2017,7 +2017,8 @@
 			if (rc) {
 				SDE_ERROR_ENC(sde_enc,
 						"connector soft reset failure\n");
-				SDE_DBG_DUMP("panic");
+				SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus",
+								"panic");
 			}
 		}
 	}
@@ -2025,7 +2026,7 @@
 	rc = ctl->ops.reset(ctl);
 	if (rc) {
 		SDE_ERROR_ENC(sde_enc, "ctl %d reset failure\n",  ctl->idx);
-		SDE_DBG_DUMP("panic");
+		SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus", "panic");
 	}
 
 	phys_enc->enable_state = SDE_ENC_ENABLED;
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 6ee1aae..da85257 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -161,7 +161,7 @@
 	unsigned long lock_flags;
 	int new_cnt;
 
-	if (!phys_enc)
+	if (!phys_enc || !phys_enc->hw_pp)
 		return;
 
 	/* notify all synchronous clients first, then asynchronous clients */
@@ -207,7 +207,7 @@
 {
 	struct sde_encoder_phys *phys_enc = arg;
 
-	if (!phys_enc)
+	if (!phys_enc || !phys_enc->hw_pp)
 		return;
 
 	SDE_EVT32_IRQ(DRMID(phys_enc->parent),
@@ -359,9 +359,7 @@
 		SDE_EVT32(DRMID(phys_enc->parent), SDE_EVTLOG_FATAL);
 
 		sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_RDPTR);
-		SDE_DBG_DUMP("sde", "dsi0_ctrl", "dsi0_phy", "dsi1_ctrl",
-				"dsi1_phy", "vbif", "dbg_bus",
-				"vbif_dbg_bus", "panic");
+		SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus", "panic");
 	}
 
 	atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);
@@ -418,9 +416,7 @@
 				phys_enc->hw_pp->idx - PINGPONG_0,
 				timeout_us,
 				ret);
-		SDE_DBG_DUMP("sde", "dsi0_ctrl", "dsi0_phy", "dsi1_ctrl",
-				"dsi1_phy", "vbif_rt", "dbg_bus",
-				"vbif_dbg_bus", "panic");
+		SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus", "panic");
 	}
 
 	return ret;
@@ -607,7 +603,7 @@
 	struct sde_encoder_phys_cmd *cmd_enc =
 		to_sde_encoder_phys_cmd(phys_enc);
 	struct sde_hw_tear_check tc_cfg = { 0 };
-	struct drm_display_mode *mode = &phys_enc->cached_mode;
+	struct drm_display_mode *mode;
 	bool tc_enable = true;
 	u32 vsync_hz;
 	struct msm_drm_private *priv;
@@ -617,6 +613,7 @@
 		SDE_ERROR("invalid encoder\n");
 		return;
 	}
+	mode = &phys_enc->cached_mode;
 
 	SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
 
@@ -627,7 +624,12 @@
 	}
 
 	sde_kms = phys_enc->sde_kms;
+	if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev_private) {
+		SDE_ERROR("invalid device\n");
+		return;
+	}
 	priv = sde_kms->dev->dev_private;
+
 	/*
 	 * TE default: dsi byte clock calculated base on 70 fps;
 	 * around 14 ms to complete a kickoff cycle if te disabled;
@@ -638,8 +640,10 @@
 	 * frequency divided by the no. of rows (lines) in the LCDpanel.
 	 */
 	vsync_hz = sde_power_clk_get_rate(&priv->phandle, "vsync_clk");
-	if (!vsync_hz) {
-		SDE_DEBUG_CMDENC(cmd_enc, "invalid vsync clock rate\n");
+	if (!vsync_hz || !mode->vtotal || !mode->vrefresh) {
+		SDE_DEBUG_CMDENC(cmd_enc,
+			"invalid params - vsync_hz %u vtot %u vrefresh %u\n",
+			vsync_hz, mode->vtotal, mode->vrefresh);
 		return;
 	}
 
@@ -687,8 +691,8 @@
 	struct sde_encoder_phys_cmd *cmd_enc =
 		to_sde_encoder_phys_cmd(phys_enc);
 
-	if (!phys_enc || !phys_enc->hw_ctl ||
-			!phys_enc->hw_ctl->ops.setup_intf_cfg) {
+	if (!phys_enc || !phys_enc->hw_ctl || !phys_enc->hw_pp
+			|| !phys_enc->hw_ctl->ops.setup_intf_cfg) {
 		SDE_ERROR("invalid arg(s), enc %d\n", phys_enc != 0);
 		return;
 	}
@@ -717,7 +721,7 @@
 	struct sde_hw_ctl *ctl;
 	u32 flush_mask = 0;
 
-	if (!phys_enc || !phys_enc->hw_ctl) {
+	if (!phys_enc || !phys_enc->hw_ctl || !phys_enc->hw_pp) {
 		SDE_ERROR("invalid arg(s), encoder %d\n", phys_enc != 0);
 		return;
 	}
@@ -747,10 +751,11 @@
 	struct sde_encoder_phys_cmd *cmd_enc =
 		to_sde_encoder_phys_cmd(phys_enc);
 
-	if (!phys_enc) {
+	if (!phys_enc || !phys_enc->hw_pp) {
 		SDE_ERROR("invalid phys encoder\n");
 		return;
 	}
+
 	SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
 
 	if (phys_enc->enable_state == SDE_ENC_ENABLED) {
@@ -803,7 +808,7 @@
 		to_sde_encoder_phys_cmd(phys_enc);
 	int ret;
 
-	if (!phys_enc) {
+	if (!phys_enc || !phys_enc->hw_pp) {
 		SDE_ERROR("invalid encoder\n");
 		return;
 	}
@@ -857,6 +862,12 @@
 		SDE_ERROR("invalid encoder\n");
 		return;
 	}
+
+	if ((phys_enc->intf_idx - INTF_0) >= INTF_MAX) {
+		SDE_ERROR("invalid intf idx:%d\n", phys_enc->intf_idx);
+		return;
+	}
+
 	SDE_DEBUG_CMDENC(cmd_enc, "\n");
 	hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_CMD;
 }
@@ -869,7 +880,7 @@
 			to_sde_encoder_phys_cmd(phys_enc);
 	int ret;
 
-	if (!phys_enc) {
+	if (!phys_enc || !phys_enc->hw_pp) {
 		SDE_ERROR("invalid encoder\n");
 		return;
 	}
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index afd61ae..e34f46e 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -49,6 +49,23 @@
 		struct intf_timing_params *timing)
 {
 	memset(timing, 0, sizeof(*timing));
+
+	if ((mode->htotal < mode->hsync_end)
+			|| (mode->hsync_start < mode->hdisplay)
+			|| (mode->vtotal < mode->vsync_end)
+			|| (mode->vsync_start < mode->vdisplay)
+			|| (mode->hsync_end < mode->hsync_start)
+			|| (mode->vsync_end < mode->vsync_start)) {
+		SDE_ERROR(
+		    "invalid params - hstart:%d,hend:%d,htot:%d,hdisplay:%d\n",
+				mode->hsync_start, mode->hsync_end,
+				mode->htotal, mode->hdisplay);
+		SDE_ERROR("vstart:%d,vend:%d,vtot:%d,vdisplay:%d\n",
+				mode->vsync_start, mode->vsync_end,
+				mode->vtotal, mode->vdisplay);
+		return;
+	}
+
 	/*
 	 * https://www.kernel.org/doc/htmldocs/drm/ch02s05.html
 	 *  Active Region      Front Porch   Sync   Back Porch
@@ -139,6 +156,15 @@
 	u32 needed_vfp_lines = worst_case_needed_lines - start_of_frame_lines;
 	u32 actual_vfp_lines = 0;
 
+	if (worst_case_needed_lines < start_of_frame_lines) {
+		needed_vfp_lines = 0;
+		SDE_ERROR("invalid params - needed_lines:%d, frame_lines:%d\n",
+				worst_case_needed_lines, start_of_frame_lines);
+	} else {
+		needed_vfp_lines = worst_case_needed_lines
+					- start_of_frame_lines;
+	}
+
 	/* Fetch must be outside active lines, otherwise undefined. */
 	if (start_of_frame_lines >= worst_case_needed_lines) {
 		SDE_DEBUG_VIDENC(vid_enc,
@@ -442,15 +468,18 @@
 	struct sde_encoder_phys_vid *vid_enc;
 
 	if (!phys_enc || !phys_enc->sde_kms) {
-		SDE_ERROR("invalid encoder\n");
+		SDE_ERROR("invalid encoder/kms\n");
 		return;
 	}
 
 	rm = &phys_enc->sde_kms->rm;
 	vid_enc = to_sde_encoder_phys_vid(phys_enc);
-	phys_enc->cached_mode = *adj_mode;
-	SDE_DEBUG_VIDENC(vid_enc, "caching mode:\n");
-	drm_mode_debug_printmodeline(adj_mode);
+
+	if (adj_mode) {
+		phys_enc->cached_mode = *adj_mode;
+		drm_mode_debug_printmodeline(adj_mode);
+		SDE_DEBUG_VIDENC(vid_enc, "caching mode:\n");
+	}
 
 	instance = phys_enc->split_role == ENC_ROLE_SLAVE ? 1 : 0;
 
@@ -620,13 +649,18 @@
 static int sde_encoder_phys_vid_wait_for_vblank(
 		struct sde_encoder_phys *phys_enc, bool notify)
 {
-	struct sde_encoder_wait_info wait_info = {
-		.wq = &phys_enc->pending_kickoff_wq,
-		.atomic_cnt = &phys_enc->pending_kickoff_cnt,
-		.timeout_ms = KICKOFF_TIMEOUT_MS,
-	};
+	struct sde_encoder_wait_info wait_info;
 	int ret;
 
+	if (!phys_enc) {
+		pr_err("invalid encoder\n");
+		return -EINVAL;
+	}
+
+	wait_info.wq = &phys_enc->pending_kickoff_wq;
+	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
+	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
+
 	if (!sde_encoder_phys_vid_is_master(phys_enc)) {
 		/* signal done for slave video encoder, unless it is pp-split */
 		if (!_sde_encoder_phys_is_ppsplit(phys_enc) &&
@@ -654,11 +688,7 @@
 static int sde_encoder_phys_vid_wait_for_commit_done(
 		struct sde_encoder_phys *phys_enc)
 {
-	int ret;
-
-	ret = sde_encoder_phys_vid_wait_for_vblank(phys_enc, true);
-
-	return ret;
+	return sde_encoder_phys_vid_wait_for_vblank(phys_enc, true);
 }
 
 static void sde_encoder_phys_vid_prepare_for_kickoff(
@@ -688,7 +718,7 @@
 		SDE_ERROR_VIDENC(vid_enc, "ctl %d reset failure: %d\n",
 				ctl->idx, rc);
 		sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_VSYNC);
-		SDE_DBG_DUMP("panic");
+		SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus", "panic");
 	}
 
 	programmable_rot_fetch_config(phys_enc, params->inline_rotate_prefill);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index 305d45e..b1772ed 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -230,6 +230,12 @@
 };
 
 enum {
+	DSPP_TOP_OFF,
+	DSPP_TOP_SIZE,
+	DSPP_TOP_PROP_MAX,
+};
+
+enum {
 	DSPP_OFF,
 	DSPP_SIZE,
 	DSPP_BLOCKS,
@@ -463,6 +469,11 @@
 	{MIXER_GC_PROP, "qcom,sde-mixer-gc", false, PROP_TYPE_U32_ARRAY},
 };
 
+static struct sde_prop_type dspp_top_prop[] = {
+	{DSPP_TOP_OFF, "qcom,sde-dspp-top-off", true, PROP_TYPE_U32},
+	{DSPP_TOP_SIZE, "qcom,sde-dspp-top-size", false, PROP_TYPE_U32},
+};
+
 static struct sde_prop_type dspp_prop[] = {
 	{DSPP_OFF, "qcom,sde-dspp-off", true, PROP_TYPE_U32_ARRAY},
 	{DSPP_SIZE, "qcom,sde-dspp-size", false, PROP_TYPE_U32},
@@ -1859,6 +1870,54 @@
 	return rc;
 }
 
+static int sde_dspp_top_parse_dt(struct device_node *np,
+		struct sde_mdss_cfg *sde_cfg)
+{
+	int rc, prop_count[DSPP_TOP_PROP_MAX];
+	bool prop_exists[DSPP_TOP_PROP_MAX];
+	struct sde_prop_value *prop_value = NULL;
+	u32 off_count;
+
+	if (!sde_cfg) {
+		SDE_ERROR("invalid argument\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	prop_value = kzalloc(DSPP_TOP_PROP_MAX *
+			sizeof(struct sde_prop_value), GFP_KERNEL);
+	if (!prop_value) {
+		rc = -ENOMEM;
+		goto end;
+	}
+
+	rc = _validate_dt_entry(np, dspp_top_prop, ARRAY_SIZE(dspp_top_prop),
+		prop_count, &off_count);
+	if (rc)
+		goto end;
+
+	rc = _read_dt_entry(np, dspp_top_prop, ARRAY_SIZE(dspp_top_prop),
+		prop_count, prop_exists, prop_value);
+	if (rc)
+		goto end;
+
+	if (off_count != 1) {
+		SDE_ERROR("invalid dspp_top off_count:%d\n", off_count);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	sde_cfg->dspp_top.base =
+		PROP_VALUE_ACCESS(prop_value, DSPP_TOP_OFF, 0);
+	sde_cfg->dspp_top.len =
+		PROP_VALUE_ACCESS(prop_value, DSPP_TOP_SIZE, 0);
+	snprintf(sde_cfg->dspp_top.name, SDE_HW_BLK_NAME_LEN, "dspp_top");
+
+end:
+	kfree(prop_value);
+	return rc;
+}
+
 static int sde_dspp_parse_dt(struct device_node *np,
 						struct sde_mdss_cfg *sde_cfg)
 {
@@ -2992,6 +3051,10 @@
 	if (rc)
 		goto end;
 
+	rc = sde_dspp_top_parse_dt(np, sde_cfg);
+	if (rc)
+		goto end;
+
 	rc = sde_dspp_parse_dt(np, sde_cfg);
 	if (rc)
 		goto end;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 29698bc..db5a6b4 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -568,6 +568,17 @@
 };
 
 /**
+ * struct sde_dspp_cfg - information of DSPP top block
+ * @id                 enum identifying this block
+ * @base               register offset of this block
+ * @features           bit mask identifying sub-blocks/features
+ *                     supported by this block
+ */
+struct sde_dspp_top_cfg  {
+	SDE_HW_BLK_INFO;
+};
+
+/**
  * struct sde_dspp_cfg - information of DSPP blocks
  * @id                 enum identifying this block
  * @base               register offset of this block
@@ -891,6 +902,8 @@
 	u32 mixer_count;
 	struct sde_lm_cfg mixer[MAX_BLOCKS];
 
+	struct sde_dspp_top_cfg dspp_top;
+
 	u32 dspp_count;
 	struct sde_dspp_cfg dspp[MAX_BLOCKS];
 
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 8f7764d..5cbfe8e 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
@@ -37,4 +37,33 @@
 #define GC_TBL_NUM 3
 #define GC_LUT_SWAP_OFF 0x1c
 
+#define IGC_TBL_NUM 3
+#define IGC_DITHER_OFF 0x7e0
+#define IGC_OPMODE_OFF 0x0
+#define IGC_C0_OFF 0x0
+#define IGC_DATA_MASK (BIT(12) - 1)
+#define IGC_DSPP_SEL_MASK_MAX (BIT(4) - 1)
+#define IGC_DSPP_SEL_MASK(n) \
+	((IGC_DSPP_SEL_MASK_MAX & ~(1 << (n))) << 28)
+#define IGC_INDEX_UPDATE BIT(25)
+#define IGC_EN BIT(0)
+#define IGC_DIS 0
+#define IGC_DITHER_DATA_MASK (BIT(4) - 1)
+
+#define PCC_NUM_PLANES 3
+#define PCC_NUM_COEFF 11
+#define PCC_EN BIT(0)
+#define PCC_DIS 0
+#define PCC_C_OFF 0x4
+#define PCC_R_OFF 0x10
+#define PCC_G_OFF 0x1c
+#define PCC_B_OFF 0x28
+#define PCC_RG_OFF 0x34
+#define PCC_RB_OFF 0x40
+#define PCC_GB_OFF 0x4c
+#define PCC_RGB_OFF 0x58
+#define PCC_RR_OFF 0x64
+#define PCC_GG_OFF 0x70
+#define PCC_BB_OFF 0x7c
+
 #endif /* _SDE_HW_COLOR_PROC_COMMON_V4_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_color_proc_v4.c b/drivers/gpu/drm/msm/sde/sde_hw_color_proc_v4.c
index 42d1480..4da0456 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_color_proc_v4.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_color_proc_v4.c
@@ -109,3 +109,127 @@
 		&op_mode);
 
 }
+
+void sde_setup_dspp_igcv3(struct sde_hw_dspp *ctx, void *cfg)
+{
+	struct drm_msm_igc_lut *lut_cfg;
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	int i = 0, j = 0;
+	u32 *addr = NULL;
+	u32 offset = 0;
+
+	if (!ctx || !cfg) {
+		DRM_ERROR("invalid param ctx %pK cfg %pK\n", ctx, cfg);
+		return;
+	}
+
+	if (!hw_cfg->payload) {
+		DRM_DEBUG_DRIVER("disable igc feature\n");
+		SDE_REG_WRITE(&ctx->hw, IGC_OPMODE_OFF, 0);
+		return;
+	}
+
+	if (hw_cfg->len != sizeof(struct drm_msm_igc_lut)) {
+		DRM_ERROR("invalid size of payload len %d exp %zd\n",
+				hw_cfg->len, sizeof(struct drm_msm_igc_lut));
+		return;
+	}
+
+	lut_cfg = hw_cfg->payload;
+
+	for (i = 0; i < IGC_TBL_NUM; i++) {
+		addr = lut_cfg->c0 + (i * ARRAY_SIZE(lut_cfg->c0));
+		offset = IGC_C0_OFF + (i * sizeof(u32));
+
+		for (j = 0; j < IGC_TBL_LEN; j++) {
+			addr[j] &= IGC_DATA_MASK;
+			addr[j] |= IGC_DSPP_SEL_MASK(ctx->idx - 1);
+			if (j == 0)
+				addr[j] |= IGC_INDEX_UPDATE;
+			/* IGC lut registers are part of DSPP Top HW block */
+			SDE_REG_WRITE(&ctx->hw_top, offset, addr[j]);
+		}
+	}
+
+	if (lut_cfg->flags & IGC_DITHER_ENABLE) {
+		SDE_REG_WRITE(&ctx->hw, IGC_DITHER_OFF,
+			lut_cfg->strength & IGC_DITHER_DATA_MASK);
+	}
+
+	SDE_REG_WRITE(&ctx->hw, IGC_OPMODE_OFF, IGC_EN);
+}
+
+void sde_setup_dspp_pccv4(struct sde_hw_dspp *ctx, void *cfg)
+{
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	struct drm_msm_pcc *pcc_cfg;
+	struct drm_msm_pcc_coeff *coeffs = NULL;
+	int i = 0;
+	u32 base = 0;
+
+	if (!ctx || !cfg) {
+		DRM_ERROR("invalid param ctx %pK cfg %pK\n", ctx, cfg);
+		return;
+	}
+
+	if (!hw_cfg->payload) {
+		DRM_DEBUG_DRIVER("disable pcc feature\n");
+		SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->pcc.base, 0);
+		return;
+	}
+
+	if (hw_cfg->len != sizeof(struct drm_msm_pcc)) {
+		DRM_ERROR("invalid size of payload len %d exp %zd\n",
+				hw_cfg->len, sizeof(struct drm_msm_pcc));
+		return;
+	}
+
+	pcc_cfg = hw_cfg->payload;
+
+	for (i = 0; i < PCC_NUM_PLANES; i++) {
+		base = ctx->cap->sblk->pcc.base + (i * sizeof(u32));
+		switch (i) {
+		case 0:
+			coeffs = &pcc_cfg->r;
+			SDE_REG_WRITE(&ctx->hw,
+				base + PCC_RR_OFF, pcc_cfg->r_rr);
+			SDE_REG_WRITE(&ctx->hw,
+				base + PCC_GG_OFF, pcc_cfg->r_gg);
+			SDE_REG_WRITE(&ctx->hw,
+				base + PCC_BB_OFF, pcc_cfg->r_bb);
+			break;
+		case 1:
+			coeffs = &pcc_cfg->g;
+			SDE_REG_WRITE(&ctx->hw,
+				base + PCC_RR_OFF, pcc_cfg->g_rr);
+			SDE_REG_WRITE(&ctx->hw,
+				base + PCC_GG_OFF, pcc_cfg->g_gg);
+			SDE_REG_WRITE(&ctx->hw,
+				base + PCC_BB_OFF, pcc_cfg->g_bb);
+			break;
+		case 2:
+			coeffs = &pcc_cfg->b;
+			SDE_REG_WRITE(&ctx->hw,
+				base + PCC_RR_OFF, pcc_cfg->b_rr);
+			SDE_REG_WRITE(&ctx->hw,
+				base + PCC_GG_OFF, pcc_cfg->b_gg);
+			SDE_REG_WRITE(&ctx->hw,
+				base + PCC_BB_OFF, pcc_cfg->b_bb);
+			break;
+		default:
+			DRM_ERROR("invalid pcc plane: %d\n", i);
+			return;
+		}
+
+		SDE_REG_WRITE(&ctx->hw, base + PCC_C_OFF, coeffs->c);
+		SDE_REG_WRITE(&ctx->hw, base + PCC_R_OFF, coeffs->r);
+		SDE_REG_WRITE(&ctx->hw, base + PCC_G_OFF, coeffs->g);
+		SDE_REG_WRITE(&ctx->hw, base + PCC_B_OFF, coeffs->b);
+		SDE_REG_WRITE(&ctx->hw, base + PCC_RG_OFF, coeffs->rg);
+		SDE_REG_WRITE(&ctx->hw, base + PCC_RB_OFF, coeffs->rb);
+		SDE_REG_WRITE(&ctx->hw, base + PCC_GB_OFF, coeffs->gb);
+		SDE_REG_WRITE(&ctx->hw, base + PCC_RGB_OFF, coeffs->rgb);
+	}
+
+	SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->pcc.base, PCC_EN);
+}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_color_proc_v4.h b/drivers/gpu/drm/msm/sde/sde_hw_color_proc_v4.h
index 250830e..ad4f556 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_color_proc_v4.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_color_proc_v4.h
@@ -22,5 +22,19 @@
  * @cfg: pointer to sde_hw_cp_cfg
  */
 void sde_setup_dspp_3d_gamutv4(struct sde_hw_dspp *ctx, void *cfg);
+/**
+ * sde_setup_dspp_igcv3 - Function for igc v3 version feature
+ *                             programming.
+ * @ctx: dspp ctx pointer
+ * @cfg: pointer to sde_hw_cp_cfg
+ */
+void sde_setup_dspp_igcv3(struct sde_hw_dspp *ctx, void *cfg);
+/**
+ * sde_setup_dspp_pccv4 - Function for pcc v4 version feature
+ *                             programming.
+ * @ctx: dspp ctx pointer
+ * @cfg: pointer to sde_hw_cp_cfg
+ */
+void sde_setup_dspp_pccv4(struct sde_hw_dspp *ctx, void *cfg);
 
 #endif /* _SDE_HW_COLOR_PROC_V4_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
index e766cdb..5b3f51e 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
@@ -58,6 +58,16 @@
 			if (c->cap->sblk->pcc.version ==
 				(SDE_COLOR_PROCESS_VER(0x1, 0x7)))
 				c->ops.setup_pcc = sde_setup_dspp_pcc_v1_7;
+			else if (c->cap->sblk->pcc.version ==
+					(SDE_COLOR_PROCESS_VER(0x4, 0x0))) {
+				ret = reg_dmav1_init_dspp_op_v4(i, c->idx);
+				if (!ret)
+					c->ops.setup_pcc =
+						reg_dmav1_setup_dspp_pccv4;
+				else
+					c->ops.setup_pcc =
+						sde_setup_dspp_pccv4;
+			}
 			break;
 		case SDE_DSPP_HSIC:
 			if (c->cap->sblk->hsic.version ==
@@ -104,6 +114,18 @@
 						sde_setup_dspp_gc_v1_7;
 			}
 			break;
+		case SDE_DSPP_IGC:
+			if (c->cap->sblk->igc.version ==
+					SDE_COLOR_PROCESS_VER(0x3, 0x1)) {
+				ret = reg_dmav1_init_dspp_op_v4(i, c->idx);
+				if (!ret)
+					c->ops.setup_igc =
+						reg_dmav1_setup_dspp_igcv31;
+				else
+					c->ops.setup_igc =
+						sde_setup_dspp_igcv3;
+			}
+			break;
 		case SDE_DSPP_AD:
 			if (c->cap->sblk->ad.version ==
 			    SDE_COLOR_PROCESS_VER(4, 0)) {
@@ -145,6 +167,13 @@
 		return ERR_PTR(-EINVAL);
 	}
 
+	/* Populate DSPP Top HW block */
+	c->hw_top.base_off = addr;
+	c->hw_top.blk_off = m->dspp_top.base;
+	c->hw_top.length = m->dspp_top.len;
+	c->hw_top.hwversion = m->hwversion;
+	c->hw_top.log_mask = SDE_DBG_MASK_DSPP;
+
 	/* Assign ops */
 	c->idx = idx;
 	c->cap = cfg;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dspp.h b/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
index 0baa970..44b3831 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
@@ -170,13 +170,17 @@
  * struct sde_hw_dspp - dspp description
  * @base: Hardware block base structure
  * @hw: Block hardware details
+ * @hw_top: Block hardware top details
  * @idx: DSPP index
  * @cap: Pointer to layer_cfg
  * @ops: Pointer to operations possible for this DSPP
  */
 struct sde_hw_dspp {
 	struct sde_hw_blk base;
-	 struct sde_hw_blk_reg_map hw;
+	struct sde_hw_blk_reg_map hw;
+
+	/* dspp top */
+	struct sde_hw_blk_reg_map hw_top;
 
 	/* dspp */
 	enum sde_dspp idx;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
index 4140a12..9a5035a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
@@ -90,6 +90,8 @@
 	[GAMUT] = GRP_VIG_HW_BLK_SELECT | GRP_DSPP_HW_BLK_SELECT,
 	[VLUT] = GRP_DSPP_HW_BLK_SELECT,
 	[GC] = GRP_DSPP_HW_BLK_SELECT,
+	[IGC] = DSPP_IGC | GRP_DSPP_HW_BLK_SELECT,
+	[PCC] = GRP_DSPP_HW_BLK_SELECT,
 };
 
 static int validate_dma_cfg(struct sde_reg_dma_setup_ops_cfg *cfg);
@@ -182,7 +184,7 @@
 	loc =  (u8 *)cfg->dma_buf->vaddr + cfg->dma_buf->index;
 	memcpy(loc, cfg->data, cfg->data_size);
 	cfg->dma_buf->index += cfg->data_size;
-	cfg->dma_buf->next_op_allowed = REG_WRITE_OP;
+	cfg->dma_buf->next_op_allowed = REG_WRITE_OP | DECODE_SEL_OP;
 	cfg->dma_buf->ops_completed |= REG_WRITE_OP;
 
 	return 0;
@@ -244,7 +246,7 @@
 	loc[1] = *cfg->data;
 	cfg->dma_buf->index += ops_mem_size[cfg->ops];
 	cfg->dma_buf->ops_completed |= REG_WRITE_OP;
-	cfg->dma_buf->next_op_allowed = REG_WRITE_OP;
+	cfg->dma_buf->next_op_allowed = REG_WRITE_OP | DECODE_SEL_OP;
 
 	return 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 285ef11..70427ab 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
@@ -30,6 +30,14 @@
 #define GC_LUT_MEM_SIZE ((sizeof(struct drm_msm_pgc_lut)) + \
 		REG_DMA_HEADERS_BUFFER_SZ)
 
+#define IGC_LUT_MEM_SIZE ((sizeof(struct drm_msm_igc_lut)) + \
+		REG_DMA_HEADERS_BUFFER_SZ)
+
+#define PCC_LUT_ENTRIES (PCC_NUM_PLANES * PCC_NUM_COEFF)
+#define PCC_LEN (PCC_LUT_ENTRIES * sizeof(u32))
+#define PCC_MEM_SIZE (PCC_LEN + \
+		REG_DMA_HEADERS_BUFFER_SZ)
+
 #define REG_MASK(n) ((BIT(n)) - 1)
 
 static struct sde_reg_dma_buffer *dspp_buf[REG_DMA_FEATURES_MAX][DSPP_MAX];
@@ -37,8 +45,8 @@
 static u32 feature_map[SDE_DSPP_MAX] = {
 	[SDE_DSPP_VLUT] = VLUT,
 	[SDE_DSPP_GAMUT] = GAMUT,
-	[SDE_DSPP_IGC] = REG_DMA_FEATURES_MAX,
-	[SDE_DSPP_PCC] = REG_DMA_FEATURES_MAX,
+	[SDE_DSPP_IGC] = IGC,
+	[SDE_DSPP_PCC] = PCC,
 	[SDE_DSPP_GC] = GC,
 	[SDE_DSPP_HSIC] = REG_DMA_FEATURES_MAX,
 	[SDE_DSPP_MEMCOLOR] = REG_DMA_FEATURES_MAX,
@@ -52,6 +60,8 @@
 	[SDE_DSPP_VLUT] = VLUT_MEM_SIZE,
 	[SDE_DSPP_GAMUT] = GAMUT_LUT_MEM_SIZE,
 	[SDE_DSPP_GC] = GC_LUT_MEM_SIZE,
+	[SDE_DSPP_IGC] = IGC_LUT_MEM_SIZE,
+	[SDE_DSPP_PCC] = PCC_MEM_SIZE,
 };
 
 static u32 dspp_mapping[DSPP_MAX] = {
@@ -233,6 +243,7 @@
 	int rc = -ENOTSUPP;
 	struct sde_hw_reg_dma_ops *dma_ops;
 	bool is_supported = false;
+	u32 blk;
 
 	if (feature >= SDE_DSPP_MAX || idx >= DSPP_MAX) {
 		DRM_ERROR("invalid feature %x max %x dspp idx %x max %xd\n",
@@ -250,8 +261,8 @@
 	if (IS_ERR_OR_NULL(dma_ops))
 		return -ENOTSUPP;
 
-	rc = dma_ops->check_support(feature_map[feature], dspp_mapping[idx],
-			&is_supported);
+	blk = (feature_map[feature] == IGC) ? DSPP_IGC : dspp_mapping[idx];
+	rc = dma_ops->check_support(feature_map[feature], blk, &is_supported);
 	if (!rc)
 		rc = (is_supported) ? 0 : -ENOTSUPP;
 
@@ -379,7 +390,7 @@
 {
 	struct sde_reg_dma_kickoff_cfg kick_off;
 	struct sde_hw_cp_cfg *hw_cfg = cfg;
-	u32 op_mode;
+	u32 op_mode = 0;
 	struct sde_hw_reg_dma_ops *dma_ops;
 	struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
 	int rc;
@@ -519,7 +530,7 @@
 	int rc, i = 0;
 	u32 reg;
 
-	rc = reg_dma_dspp_check(ctx, cfg, GAMUT);
+	rc = reg_dma_dspp_check(ctx, cfg, GC);
 	if (rc)
 		return;
 
@@ -603,6 +614,298 @@
 	}
 }
 
+static void _dspp_igcv31_off(struct sde_hw_dspp *ctx, void *cfg)
+{
+	struct sde_reg_dma_kickoff_cfg kick_off;
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	struct sde_hw_reg_dma_ops *dma_ops;
+	struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
+	int rc;
+	u32 reg;
+
+	dma_ops = sde_reg_dma_get_ops();
+	dma_ops->reset_reg_dma_buf(dspp_buf[IGC][ctx->idx]);
+
+	REG_DMA_INIT_OPS(dma_write_cfg, dspp_mapping[ctx->idx], IGC,
+		dspp_buf[IGC][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 = IGC_DIS;
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->igc.base + IGC_OPMODE_OFF,
+		&reg, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("setting opcode failed ret %d\n", rc);
+		return;
+	}
+
+	REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[IGC][ctx->idx],
+			REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE);
+	rc = dma_ops->kick_off(&kick_off);
+	if (rc)
+		DRM_ERROR("failed to kick off ret %d\n", rc);
+}
+
+void reg_dmav1_setup_dspp_igcv31(struct sde_hw_dspp *ctx, void *cfg)
+{
+	struct drm_msm_igc_lut *lut_cfg;
+	struct sde_hw_reg_dma_ops *dma_ops;
+	struct sde_reg_dma_kickoff_cfg kick_off;
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
+	int rc, i = 0, j = 0;
+	u32 *addr = NULL;
+	u32 offset = 0;
+	u32 reg;
+
+	rc = reg_dma_dspp_check(ctx, cfg, IGC);
+	if (rc)
+		return;
+
+	if (!hw_cfg->payload) {
+		DRM_DEBUG_DRIVER("disable igc feature\n");
+		_dspp_igcv31_off(ctx, cfg);
+		return;
+	}
+
+	if (hw_cfg->len != sizeof(struct drm_msm_igc_lut)) {
+		DRM_ERROR("invalid size of payload len %d exp %zd\n",
+				hw_cfg->len, sizeof(struct drm_msm_igc_lut));
+		return;
+	}
+
+	lut_cfg = hw_cfg->payload;
+
+	dma_ops = sde_reg_dma_get_ops();
+	dma_ops->reset_reg_dma_buf(dspp_buf[IGC][ctx->idx]);
+
+	REG_DMA_INIT_OPS(dma_write_cfg, DSPP_IGC, IGC, dspp_buf[IGC][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;
+	}
+
+	for (i = 0; i < IGC_TBL_NUM; i++) {
+		addr = lut_cfg->c0 + (i * ARRAY_SIZE(lut_cfg->c0));
+		offset = IGC_C0_OFF + (i * sizeof(u32));
+
+		for (j = 0; j < IGC_TBL_LEN; j++) {
+			addr[j] &= IGC_DATA_MASK;
+			addr[j] |= IGC_DSPP_SEL_MASK(ctx->idx - 1);
+			if (j == 0)
+				addr[j] |= IGC_INDEX_UPDATE;
+		}
+
+		REG_DMA_SETUP_OPS(dma_write_cfg, offset, addr,
+			IGC_TBL_LEN * sizeof(u32),
+			REG_BLK_WRITE_INC, 0, 0);
+		rc = dma_ops->setup_payload(&dma_write_cfg);
+		if (rc) {
+			DRM_ERROR("lut write failed ret %d\n", rc);
+			return;
+		}
+	}
+
+	REG_DMA_INIT_OPS(dma_write_cfg, dspp_mapping[ctx->idx], IGC,
+		dspp_buf[IGC][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;
+	}
+
+	if (lut_cfg->flags & IGC_DITHER_ENABLE) {
+		reg = lut_cfg->strength & IGC_DITHER_DATA_MASK;
+		REG_DMA_SETUP_OPS(dma_write_cfg,
+			ctx->cap->sblk->igc.base + IGC_DITHER_OFF,
+			&reg, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+		rc = dma_ops->setup_payload(&dma_write_cfg);
+		if (rc) {
+			DRM_ERROR("dither strength failed ret %d\n", rc);
+			return;
+		}
+	}
+
+	reg = IGC_EN;
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->igc.base + IGC_OPMODE_OFF,
+		&reg, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("setting opcode failed ret %d\n", rc);
+		return;
+	}
+
+	REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[IGC][ctx->idx],
+			REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE);
+	rc = dma_ops->kick_off(&kick_off);
+	if (rc)
+		DRM_ERROR("failed to kick off ret %d\n", rc);
+}
+
+static void _dspp_pccv4_off(struct sde_hw_dspp *ctx, void *cfg)
+{
+	struct sde_reg_dma_kickoff_cfg kick_off;
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	struct sde_hw_reg_dma_ops *dma_ops;
+	struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
+	int rc;
+	u32 reg;
+
+	dma_ops = sde_reg_dma_get_ops();
+	dma_ops->reset_reg_dma_buf(dspp_buf[PCC][ctx->idx]);
+
+	REG_DMA_INIT_OPS(dma_write_cfg, dspp_mapping[ctx->idx], PCC,
+		dspp_buf[PCC][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 = PCC_DIS;
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->pcc.base,
+		&reg, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("setting opcode failed ret %d\n", rc);
+		return;
+	}
+
+	REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[PCC][ctx->idx],
+			REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE);
+	rc = dma_ops->kick_off(&kick_off);
+	if (rc)
+		DRM_ERROR("failed to kick off ret %d\n", rc);
+}
+
+void reg_dmav1_setup_dspp_pccv4(struct sde_hw_dspp *ctx, void *cfg)
+{
+	struct sde_hw_reg_dma_ops *dma_ops;
+	struct sde_reg_dma_kickoff_cfg kick_off;
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
+	struct drm_msm_pcc *pcc_cfg;
+	struct drm_msm_pcc_coeff *coeffs = NULL;
+	u32 *data = NULL;
+	int rc, i = 0;
+	u32 reg = 0;
+
+	rc = reg_dma_dspp_check(ctx, cfg, PCC);
+	if (rc)
+		return;
+
+	if (!hw_cfg->payload) {
+		DRM_DEBUG_DRIVER("disable pcc feature\n");
+		_dspp_pccv4_off(ctx, cfg);
+		return;
+	}
+
+	if (hw_cfg->len != sizeof(struct drm_msm_pcc)) {
+		DRM_ERROR("invalid size of payload len %d exp %zd\n",
+				hw_cfg->len, sizeof(struct drm_msm_pcc));
+		return;
+	}
+
+	pcc_cfg = hw_cfg->payload;
+
+	dma_ops = sde_reg_dma_get_ops();
+	dma_ops->reset_reg_dma_buf(dspp_buf[PCC][ctx->idx]);
+
+	REG_DMA_INIT_OPS(dma_write_cfg, dspp_mapping[ctx->idx],
+		PCC, dspp_buf[PCC][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;
+	}
+
+	data = kzalloc(PCC_LEN, GFP_KERNEL);
+	if (!data)
+		return;
+
+	for (i = 0; i < PCC_NUM_PLANES; i++) {
+		switch (i) {
+		case 0:
+			coeffs = &pcc_cfg->r;
+			data[i + 24] = pcc_cfg->r_rr;
+			data[i + 27] = pcc_cfg->r_gg;
+			data[i + 30] = pcc_cfg->r_bb;
+			break;
+		case 1:
+			coeffs = &pcc_cfg->g;
+			data[i + 24] = pcc_cfg->g_rr;
+			data[i + 27] = pcc_cfg->g_gg;
+			data[i + 30] = pcc_cfg->g_bb;
+			break;
+		case 2:
+			coeffs = &pcc_cfg->b;
+			data[i + 24] = pcc_cfg->b_rr;
+			data[i + 27] = pcc_cfg->b_gg;
+			data[i + 30] = pcc_cfg->b_bb;
+			break;
+		default:
+			DRM_ERROR("invalid pcc plane: %d\n", i);
+			goto exit;
+		}
+
+		data[i] = coeffs->c;
+		data[i + 3] = coeffs->r;
+		data[i + 6] = coeffs->g;
+		data[i + 9] = coeffs->b;
+		data[i + 12] = coeffs->rg;
+		data[i + 15] = coeffs->rb;
+		data[i + 18] = coeffs->gb;
+		data[i + 21] = coeffs->rgb;
+	}
+
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->pcc.base + PCC_C_OFF,
+		data, PCC_LEN,
+		REG_BLK_WRITE_SINGLE, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("write pcc lut failed ret %d\n", rc);
+		goto exit;
+	}
+
+	reg = PCC_EN;
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->pcc.base,
+		&reg, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("setting opcode failed ret %d\n", rc);
+		goto exit;
+	}
+
+	REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[PCC][ctx->idx],
+			REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE);
+	rc = dma_ops->kick_off(&kick_off);
+	if (rc)
+		DRM_ERROR("failed to kick off ret %d\n", rc);
+
+exit:
+	kfree(data);
+}
+
 int reg_dmav1_deinit_dspp_ops(enum sde_dspp idx)
 {
 	int i;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h
index 94e1a5c..bb72c8f 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h
@@ -46,13 +46,27 @@
 void reg_dmav1_setup_dspp_3d_gamutv4(struct sde_hw_dspp *ctx, void *cfg);
 
 /**
- * reg_dmav1_setup_dspp_gc_v18() - gc v18 implementation using reg dma v1.
+ * reg_dmav1_setup_dspp_gcv18() - gc v18 implementation using reg dma v1.
  * @ctx: dspp ctx info
  * @cfg: pointer to struct sde_hw_cp_cfg
  */
 void reg_dmav1_setup_dspp_gcv18(struct sde_hw_dspp *ctx, void *cfg);
 
 /**
+ * reg_dmav1_setup_dspp_igcv31() - igc v31 implementation using reg dma v1.
+ * @ctx: dspp ctx info
+ * @cfg: pointer to struct sde_hw_cp_cfg
+ */
+void reg_dmav1_setup_dspp_igcv31(struct sde_hw_dspp *ctx, void *cfg);
+
+/**
+ * reg_dmav1_setup_dspp_pccv4() - pcc v4 implementation using reg dma v1.
+ * @ctx: dspp ctx info
+ * @cfg: pointer to struct sde_hw_cp_cfg
+ */
+void reg_dmav1_setup_dspp_pccv4(struct sde_hw_dspp *ctx, void *cfg);
+
+/**
  * reg_dmav1_deinit_dspp_ops() - deinitialize the dspp feature op for sde v4
  *                               which were initialized.
  * @idx: dspp idx
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 7b620bf..b9fbd62 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -1376,48 +1376,6 @@
 		sde_crtc_cancel_pending_flip(priv->crtcs[i], file);
 }
 
-static int sde_kms_atomic_check(struct msm_kms *kms,
-		struct drm_atomic_state *state)
-{
-	struct sde_kms *sde_kms = to_sde_kms(kms);
-	struct drm_device *dev = sde_kms->dev;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	int rc, i;
-
-	if (!kms || !state)
-		return -EINVAL;
-
-	/*
-	 * Add planes (and other affected DRM objects, if any) to new state
-	 * if idle power collapse occurred since previous commit.
-	 * Since atomic state is a delta from the last, if the user-space
-	 * did not request any changes on a plane/connector, that object
-	 * will not be included in the new atomic state. Idle power collapse
-	 * is driver-autonomous, so the driver needs to ensure that all
-	 * hardware is reprogrammed as the power comes back on by forcing
-	 * the drm objects attached to the CRTC into the new atomic state.
-	 */
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
-		struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state);
-		struct sde_crtc_state *old_cstate =
-				to_sde_crtc_state(crtc->state);
-
-		if (cstate->idle_pc != old_cstate->idle_pc) {
-			SDE_DEBUG("crtc%d idle_pc:%d/%d\n",
-					crtc->base.id, cstate->idle_pc,
-					old_cstate->idle_pc);
-			SDE_EVT32(DRMID(crtc), cstate->idle_pc,
-					old_cstate->idle_pc);
-			rc = drm_atomic_add_affected_planes(state, crtc);
-			if (rc)
-				return rc;
-		}
-	}
-
-	return drm_atomic_helper_check(dev, state);
-}
-
 static struct msm_gem_address_space*
 _sde_kms_get_address_space(struct msm_kms *kms,
 		unsigned int domain)
@@ -1458,7 +1416,6 @@
 	.enable_vblank   = sde_kms_enable_vblank,
 	.disable_vblank  = sde_kms_disable_vblank,
 	.check_modified_format = sde_format_check_modified_format,
-	.atomic_check    = sde_kms_atomic_check,
 	.get_format      = sde_get_msm_format,
 	.round_pixclk    = sde_kms_round_pixclk,
 	.destroy         = sde_kms_destroy,
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 6d5c09d..20fca52 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -94,25 +94,6 @@
 	SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
 };
 
-/**
- * enum sde_plane_sclcheck_state - User scaler data status
- *
- * @SDE_PLANE_SCLCHECK_NONE: No user data provided
- * @SDE_PLANE_SCLCHECK_INVALID: Invalid user data provided
- * @SDE_PLANE_SCLCHECK_SCALER_V1: Valid scaler v1 data
- * @SDE_PLANE_SCLCHECK_SCALER_V1_CHECK: Unchecked scaler v1 data
- * @SDE_PLANE_SCLCHECK_SCALER_V2: Valid scaler v2 data
- * @SDE_PLANE_SCLCHECK_SCALER_V2_CHECK: Unchecked scaler v2 data
- */
-enum sde_plane_sclcheck_state {
-	SDE_PLANE_SCLCHECK_NONE,
-	SDE_PLANE_SCLCHECK_INVALID,
-	SDE_PLANE_SCLCHECK_SCALER_V1,
-	SDE_PLANE_SCLCHECK_SCALER_V1_CHECK,
-	SDE_PLANE_SCLCHECK_SCALER_V2,
-	SDE_PLANE_SCLCHECK_SCALER_V2_CHECK,
-};
-
 /*
  * struct sde_plane - local sde plane structure
  * @aspace: address space pointer
@@ -124,7 +105,6 @@
  * @sbuf_mode: force stream buffer mode if set
  * @sbuf_writeback: force stream buffer writeback if set
  * @revalidate: force revalidation of all the plane properties
- * @scaler_check_state: Indicates status of user provided pixle extension data
  * @blob_rot_caps: Pointer to rotator capability blob
  */
 struct sde_plane {
@@ -140,7 +120,6 @@
 	struct sde_hw_pipe *pipe_hw;
 	struct sde_hw_pipe_cfg pipe_cfg;
 	struct sde_hw_sharp_cfg sharp_cfg;
-	struct sde_hw_scaler3_cfg *scaler3_cfg;
 	struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
 	uint32_t color_fill;
 	bool is_error;
@@ -152,9 +131,6 @@
 	u32 sbuf_writeback;
 	bool revalidate;
 
-	struct sde_hw_pixel_ext pixel_ext;
-	enum sde_plane_sclcheck_state scaler_check_state;
-
 	struct sde_csc_cfg csc_cfg;
 	struct sde_csc_cfg *csc_usr_ptr;
 	struct sde_csc_cfg *csc_ptr;
@@ -972,16 +948,12 @@
 	struct sde_hw_scaler3_cfg *cfg;
 	int ret = 0;
 
-	if (!psde || !psde->scaler3_cfg) {
+	if (!psde || !pstate) {
 		SDE_ERROR("invalid args\n");
 		return -EINVAL;
-	} else if (!pstate) {
-		/* pstate is expected to be null on forced color fill */
-		SDE_DEBUG("null pstate\n");
-		return -EINVAL;
 	}
 
-	cfg = psde->scaler3_cfg;
+	cfg = &pstate->scaler3_cfg;
 
 	cfg->dir_lut = msm_property_get_blob(
 			&psde->property_info,
@@ -1001,6 +973,7 @@
 }
 
 static void _sde_plane_setup_scaler3(struct sde_plane *psde,
+		struct sde_plane_state *pstate,
 		uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
 		struct sde_hw_scaler3_cfg *scale_cfg,
 		const struct sde_format *fmt,
@@ -1008,16 +981,17 @@
 {
 	uint32_t decimated, i;
 
-	if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
+	if (!psde || !pstate || !scale_cfg || !fmt || !chroma_subsmpl_h ||
 			!chroma_subsmpl_v) {
-		SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
-			, psde, scale_cfg, fmt, chroma_subsmpl_h,
+		SDE_ERROR(
+			"psde %d pstate %d scale_cfg %d fmt %d smp_h %d smp_v %d\n",
+			!!psde, !!pstate, !!scale_cfg, !!fmt, chroma_subsmpl_h,
 			chroma_subsmpl_v);
 		return;
 	}
 
 	memset(scale_cfg, 0, sizeof(*scale_cfg));
-	memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
+	memset(&pstate->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
 
 	decimated = DECIMATED_DIMENSION(src_w,
 			psde->pipe_cfg.horz_decimation);
@@ -1055,9 +1029,9 @@
 		}
 		scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
 		scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
-		psde->pixel_ext.num_ext_pxls_top[i] =
+		pstate->pixel_ext.num_ext_pxls_top[i] =
 			scale_cfg->src_height[i];
-		psde->pixel_ext.num_ext_pxls_left[i] =
+		pstate->pixel_ext.num_ext_pxls_left[i] =
 			scale_cfg->src_width[i];
 	}
 	if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
@@ -1327,19 +1301,19 @@
 }
 
 static void _sde_plane_setup_scaler(struct sde_plane *psde,
-		const struct sde_format *fmt,
-		struct sde_plane_state *pstate)
+		struct sde_plane_state *pstate,
+		const struct sde_format *fmt, bool color_fill)
 {
 	struct sde_hw_pixel_ext *pe;
 	uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
 
-	if (!psde || !fmt) {
+	if (!psde || !fmt || !pstate) {
 		SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
 				psde != 0, fmt != 0, pstate != 0);
 		return;
 	}
 
-	pe = &(psde->pixel_ext);
+	pe = &pstate->pixel_ext;
 
 	psde->pipe_cfg.horz_decimation =
 		sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
@@ -1354,23 +1328,25 @@
 
 	/* update scaler */
 	if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
-		int error;
+		int rc;
 
-		error = _sde_plane_setup_scaler3_lut(psde, pstate);
-		if (error || psde->debugfs_default_scale ||
-			psde->scaler_check_state !=
-				SDE_PLANE_SCLCHECK_SCALER_V2) {
+		if (!color_fill && !psde->debugfs_default_scale)
+			rc = _sde_plane_setup_scaler3_lut(psde, pstate);
+		else
+			rc = -EINVAL;
+		if (rc || pstate->scaler_check_state !=
+			SDE_PLANE_SCLCHECK_SCALER_V2) {
 			/* calculate default config for QSEED3 */
-			_sde_plane_setup_scaler3(psde,
+			_sde_plane_setup_scaler3(psde, pstate,
 					psde->pipe_cfg.src_rect.w,
 					psde->pipe_cfg.src_rect.h,
 					psde->pipe_cfg.dst_rect.w,
 					psde->pipe_cfg.dst_rect.h,
-					psde->scaler3_cfg, fmt,
+					&pstate->scaler3_cfg, fmt,
 					chroma_subsmpl_h, chroma_subsmpl_v);
 		}
-	} else if (psde->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V1 ||
-			!pstate || psde->debugfs_default_scale) {
+	} else if (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V1 ||
+			color_fill || psde->debugfs_default_scale) {
 		uint32_t deci_dim, i;
 
 		/* calculate default configuration for QSEED2 */
@@ -1446,9 +1422,9 @@
 {
 	const struct sde_format *fmt;
 	const struct drm_plane *plane;
-	const struct sde_plane_state *pstate;
+	struct sde_plane_state *pstate;
 
-	if (!psde) {
+	if (!psde || !psde->base.state) {
 		SDE_ERROR("invalid plane\n");
 		return -EINVAL;
 	}
@@ -1480,7 +1456,7 @@
 		psde->pipe_cfg.src_rect.y = 0;
 		psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
 		psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
-		_sde_plane_setup_scaler(psde, fmt, 0);
+		_sde_plane_setup_scaler(psde, pstate, fmt, true);
 
 		if (psde->pipe_hw->ops.setup_format)
 			psde->pipe_hw->ops.setup_format(psde->pipe_hw,
@@ -1494,7 +1470,7 @@
 
 		if (psde->pipe_hw->ops.setup_pe)
 			psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
-					&psde->pixel_ext);
+					&pstate->pixel_ext);
 	}
 
 	return 0;
@@ -1864,7 +1840,7 @@
 		struct sde_hw_fmt_layout layout;
 
 		memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
-		sde_format_populate_layout(rstate->aspace, state->fb,
+		sde_format_populate_layout(pstate->aspace, state->fb,
 				&layout);
 		for (i = 0; i < ARRAY_SIZE(rot_cmd->src_iova); i++) {
 			rot_cmd->src_iova[i] = layout.plane_addr[i];
@@ -1873,7 +1849,7 @@
 		rot_cmd->src_planes = layout.num_planes;
 
 		memset(&layout, 0, sizeof(struct sde_hw_fmt_layout));
-		sde_format_populate_layout(rstate->aspace, rstate->out_fb,
+		sde_format_populate_layout(pstate->aspace, rstate->out_fb,
 				&layout);
 		for (i = 0; i < ARRAY_SIZE(rot_cmd->dst_iova); i++) {
 			rot_cmd->dst_iova[i] = layout.plane_addr[i];
@@ -2066,7 +2042,6 @@
 
 		SDE_DEBUG("plane%d.%d allocate fb/fbo\n", plane->base.id,
 				new_rstate->sequence_id);
-		new_rstate->aspace = new_pstate->aspace;
 
 		/* check if out_fb is already attached to rotator */
 		new_rstate->out_fbo = sde_kms_fbo_alloc(plane->dev, fb_w, fb_h,
@@ -2105,9 +2080,9 @@
 	}
 
 	/* prepare rotator input buffer */
-	ret = msm_framebuffer_prepare(new_state->fb, new_rstate->aspace);
+	ret = msm_framebuffer_prepare(new_state->fb, new_pstate->aspace);
 	if (ret) {
-		SDE_ERROR("failed to prepare input framebuffer\n");
+		SDE_ERROR("failed to prepare input framebuffer, %d\n", ret);
 		goto error_prepare_input_buffer;
 	}
 
@@ -2117,9 +2092,10 @@
 				new_rstate->sequence_id);
 
 		ret = msm_framebuffer_prepare(new_rstate->out_fb,
-				new_rstate->aspace);
+				new_pstate->aspace);
 		if (ret) {
-			SDE_ERROR("failed to prepare inline framebuffer\n");
+			SDE_ERROR("failed to prepare inline framebuffer, %d\n",
+					ret);
 			goto error_prepare_output_buffer;
 		}
 	}
@@ -2127,7 +2103,7 @@
 	return 0;
 
 error_prepare_output_buffer:
-	msm_framebuffer_cleanup(new_state->fb, new_rstate->aspace);
+	msm_framebuffer_cleanup(new_state->fb, new_pstate->aspace);
 error_prepare_input_buffer:
 	sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
 			(u64) &new_rstate->rot_hw->base);
@@ -2183,7 +2159,7 @@
 	if (sde_plane_enabled(old_state)) {
 		if (old_rstate->out_fb) {
 			msm_framebuffer_cleanup(old_rstate->out_fb,
-					old_rstate->aspace);
+					old_pstate->aspace);
 			sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
 					(u64) &old_rstate->rot_hw->base);
 			old_rstate->out_fb = NULL;
@@ -2192,7 +2168,7 @@
 			old_rstate->out_fbo = NULL;
 		}
 
-		msm_framebuffer_cleanup(old_state->fb, old_rstate->aspace);
+		msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace);
 	}
 }
 
@@ -2747,16 +2723,19 @@
 		struct drm_plane_state *old_state)
 {
 	struct sde_plane *psde = to_sde_plane(plane);
+	struct sde_plane_state *old_pstate;
 	struct sde_plane_rot_state *old_rstate;
 
-	if (!old_state->fb)
+	if (!old_state || !old_state->fb)
 		return;
 
+	old_pstate = to_sde_plane_state(old_state);
+
 	SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);
 
-	old_rstate = &to_sde_plane_state(old_state)->rot;
+	old_rstate = &old_pstate->rot;
 
-	msm_framebuffer_cleanup(old_rstate->out_fb, old_rstate->aspace);
+	msm_framebuffer_cleanup(old_rstate->out_fb, old_pstate->aspace);
 
 	sde_plane_rot_cleanup_fb(plane, old_state);
 }
@@ -2860,6 +2839,7 @@
 }
 
 static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
+		struct sde_plane_state *pstate,
 		const struct sde_format *fmt,
 		uint32_t img_w, uint32_t img_h,
 		uint32_t src_w, uint32_t src_h,
@@ -2867,17 +2847,16 @@
 {
 	int i;
 
-	if (!psde || !fmt) {
+	if (!psde || !pstate || !fmt) {
 		SDE_ERROR_PLANE(psde, "invalid arguments\n");
 		return -EINVAL;
 	}
 
 	/* don't run checks unless scaler data was changed */
-	if (psde->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK ||
-			!psde->scaler3_cfg)
+	if (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK)
 		return 0;
 
-	psde->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
+	pstate->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
 
 	for (i = 0; i < SDE_MAX_PLANES; i++) {
 		uint32_t hor_req_pixels, hor_fetch_pixels;
@@ -2907,17 +2886,17 @@
 				src_h_tmp >>= 1;
 		}
 
-		hor_req_pixels = psde->pixel_ext.roi_w[i];
-		vert_req_pixels = psde->pixel_ext.roi_h[i];
+		hor_req_pixels = pstate->pixel_ext.roi_w[i];
+		vert_req_pixels = pstate->pixel_ext.roi_h[i];
 
 		hor_fetch_pixels = DECIMATED_DIMENSION(src_w_tmp +
-				(int8_t)(psde->pixel_ext.left_ftch[i] & 0xFF) +
-				(int8_t)(psde->pixel_ext.right_ftch[i] & 0xFF),
-				deci_w);
+			(int8_t)(pstate->pixel_ext.left_ftch[i] & 0xFF) +
+			(int8_t)(pstate->pixel_ext.right_ftch[i] & 0xFF),
+			deci_w);
 		vert_fetch_pixels = DECIMATED_DIMENSION(src_h_tmp +
-				(int8_t)(psde->pixel_ext.top_ftch[i] & 0xFF) +
-				(int8_t)(psde->pixel_ext.btm_ftch[i] & 0xFF),
-				deci_h);
+			(int8_t)(pstate->pixel_ext.top_ftch[i] & 0xFF) +
+			(int8_t)(pstate->pixel_ext.btm_ftch[i] & 0xFF),
+			deci_h);
 
 		if ((hor_req_pixels != hor_fetch_pixels) ||
 			(hor_fetch_pixels > img_w) ||
@@ -2937,20 +2916,20 @@
 		 * for Y and UV plane
 		 */
 		if (i != 3 &&
-			(hor_req_pixels != psde->scaler3_cfg->src_width[i] ||
-			vert_req_pixels != psde->scaler3_cfg->src_height[i])) {
+			(hor_req_pixels != pstate->scaler3_cfg.src_width[i] ||
+			vert_req_pixels != pstate->scaler3_cfg.src_height[i])) {
 			SDE_ERROR_PLANE(psde,
 				"roi[%d] %d/%d, scaler src %dx%d, src %dx%d\n",
-				i, psde->pixel_ext.roi_w[i],
-				psde->pixel_ext.roi_h[i],
-				psde->scaler3_cfg->src_width[i],
-				psde->scaler3_cfg->src_height[i],
+				i, pstate->pixel_ext.roi_w[i],
+				pstate->pixel_ext.roi_h[i],
+				pstate->scaler3_cfg.src_width[i],
+				pstate->scaler3_cfg.src_height[i],
 				src_w, src_h);
 			return -EINVAL;
 		}
 	}
 
-	psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
+	pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
 	return 0;
 }
 
@@ -3089,7 +3068,7 @@
 			"too much scaling requested %ux%u->%ux%u\n",
 			src_deci_w, src_deci_h, dst.w, dst.h);
 		ret = -E2BIG;
-	} else if (_sde_plane_validate_scaler_v2(psde, fmt,
+	} else if (_sde_plane_validate_scaler_v2(psde, pstate, fmt,
 				rstate->out_fb_width,
 				rstate->out_fb_height,
 				src.w, src.h, deci_w, deci_h)) {
@@ -3388,7 +3367,7 @@
 		psde->pipe_cfg.src_rect = src;
 		psde->pipe_cfg.dst_rect = dst;
 
-		_sde_plane_setup_scaler(psde, fmt, pstate);
+		_sde_plane_setup_scaler(psde, pstate, fmt, false);
 
 		/* check for color fill */
 		psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
@@ -3405,7 +3384,7 @@
 		if (psde->pipe_hw->ops.setup_pe &&
 				(pstate->multirect_index != SDE_SSPP_RECT_1))
 			psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
-					&psde->pixel_ext);
+					&pstate->pixel_ext);
 
 		/**
 		 * when programmed in multirect mode, scalar block will be
@@ -3415,8 +3394,8 @@
 		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);
+					&psde->pipe_cfg, &pstate->pixel_ext,
+					&pstate->scaler3_cfg);
 
 		/* update excl rect */
 		if (psde->pipe_hw->ops.setup_excl_rect)
@@ -3598,6 +3577,29 @@
 	}
 }
 
+void sde_plane_restore(struct drm_plane *plane)
+{
+	struct sde_plane *psde;
+
+	if (!plane || !plane->state) {
+		SDE_ERROR("invalid plane\n");
+		return;
+	}
+
+	psde = to_sde_plane(plane);
+
+	/*
+	 * Revalidate is only true here if idle PC occurred and
+	 * there is no plane state update in current commit cycle.
+	 */
+	if (!psde->revalidate)
+		return;
+
+	SDE_DEBUG_PLANE(psde, "\n");
+
+	/* last plane state is same as current state */
+	sde_plane_atomic_update(plane, plane->state);
+}
 
 /* helper to install properties which are common to planes and crtcs */
 static void _sde_plane_install_properties(struct drm_plane *plane,
@@ -3879,18 +3881,19 @@
 	psde->csc_usr_ptr = &psde->csc_cfg;
 }
 
-static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
+static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde,
+		struct sde_plane_state *pstate, void *usr)
 {
 	struct sde_drm_scaler_v1 scale_v1;
 	struct sde_hw_pixel_ext *pe;
 	int i;
 
-	if (!psde) {
-		SDE_ERROR("invalid plane\n");
+	if (!psde || !pstate) {
+		SDE_ERROR("invalid argument(s)\n");
 		return;
 	}
 
-	psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
+	pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
 	if (!usr) {
 		SDE_DEBUG_PLANE(psde, "scale data removed\n");
 		return;
@@ -3905,7 +3908,7 @@
 	msm_property_set_dirty(&psde->property_info, PLANE_PROP_SCALER_V1);
 
 	/* populate from user space */
-	pe = &(psde->pixel_ext);
+	pe = &pstate->pixel_ext;
 	memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
 	for (i = 0; i < SDE_MAX_PLANES; i++) {
 		pe->init_phase_x[i] = scale_v1.init_phase_x[i];
@@ -3930,7 +3933,7 @@
 		pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
 	}
 
-	psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V1;
+	pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V1;
 
 	SDE_EVT32_VERBOSE(DRMID(&psde->base));
 	SDE_DEBUG_PLANE(psde, "user property data copied\n");
@@ -3944,13 +3947,13 @@
 	int i;
 	struct sde_hw_scaler3_cfg *cfg;
 
-	if (!psde || !psde->scaler3_cfg) {
-		SDE_ERROR("invalid plane\n");
+	if (!psde || !pstate) {
+		SDE_ERROR("invalid argument(s)\n");
 		return;
 	}
 
-	cfg = psde->scaler3_cfg;
-	psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
+	cfg = &pstate->scaler3_cfg;
+	pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
 	if (!usr) {
 		SDE_DEBUG_PLANE(psde, "scale data removed\n");
 		return;
@@ -3971,7 +3974,7 @@
 	msm_property_set_dirty(&psde->property_info, PLANE_PROP_SCALER_V2);
 
 	/* populate from user space */
-	pe = &(psde->pixel_ext);
+	pe = &pstate->pixel_ext;
 	memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
 	cfg->enable = scale_v2.enable;
 	cfg->dir_en = scale_v2.dir_en;
@@ -4029,7 +4032,7 @@
 		pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
 		pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
 	}
-	psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2_CHECK;
+	pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2_CHECK;
 
 	SDE_EVT32_VERBOSE(DRMID(&psde->base), cfg->enable, cfg->de.enable,
 			cfg->src_width[0], cfg->src_height[0],
@@ -4098,7 +4101,8 @@
 				_sde_plane_set_csc_v1(psde, (void *)val);
 				break;
 			case PLANE_PROP_SCALER_V1:
-				_sde_plane_set_scaler_v1(psde, (void *)val);
+				_sde_plane_set_scaler_v1(psde, pstate,
+						(void *)val);
 				break;
 			case PLANE_PROP_SCALER_V2:
 				_sde_plane_set_scaler_v2(psde, pstate,
@@ -4602,7 +4606,6 @@
 	plane = &psde->base;
 	psde->pipe = pipe;
 	psde->is_virtual = (master_plane_id != 0);
-	psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
 	INIT_LIST_HEAD(&psde->mplane_list);
 	master_plane = drm_plane_find(dev, master_plane_id);
 	if (master_plane) {
@@ -4631,17 +4634,6 @@
 		goto clean_sspp;
 	}
 
-	if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
-		psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
-			GFP_KERNEL);
-		if (!psde->scaler3_cfg) {
-			SDE_ERROR("[%u]failed to allocate scale struct\n",
-				pipe);
-			ret = -ENOMEM;
-			goto clean_sspp;
-		}
-	}
-
 	format_list = psde->pipe_sblk->format_list;
 
 	if (master_plane_id) {
@@ -4711,9 +4703,6 @@
 clean_sspp:
 	if (psde && psde->pipe_hw)
 		sde_hw_sspp_destroy(psde->pipe_hw);
-
-	if (psde && psde->scaler3_cfg)
-		kfree(psde->scaler3_cfg);
 clean_plane:
 	kfree(psde);
 exit:
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index ccbf005..2f0068a 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -34,7 +34,6 @@
  * @rot90: true if rotation of 90 degree is required
  * @hflip: true if horizontal flip is required
  * @vflip: true if vertical flip is required
- * @aspace:  pointer address space for input/output buffers
  * @rot_cmd: rotator configuration command
  * @nplane: total number of drm plane attached to rotator
  * @in_fb: input fb attached to rotator
@@ -64,7 +63,6 @@
 	bool rot90;
 	bool hflip;
 	bool vflip;
-	struct msm_gem_address_space *aspace;
 	struct sde_hw_rot_cmd rot_cmd;
 	int nplane;
 	/* input */
@@ -100,6 +98,25 @@
 #define SDE_PLANE_DIRTY_ALL	0xFFFFFFFF
 
 /**
+ * enum sde_plane_sclcheck_state - User scaler data status
+ *
+ * @SDE_PLANE_SCLCHECK_NONE: No user data provided
+ * @SDE_PLANE_SCLCHECK_INVALID: Invalid user data provided
+ * @SDE_PLANE_SCLCHECK_SCALER_V1: Valid scaler v1 data
+ * @SDE_PLANE_SCLCHECK_SCALER_V1_CHECK: Unchecked scaler v1 data
+ * @SDE_PLANE_SCLCHECK_SCALER_V2: Valid scaler v2 data
+ * @SDE_PLANE_SCLCHECK_SCALER_V2_CHECK: Unchecked scaler v2 data
+ */
+enum sde_plane_sclcheck_state {
+	SDE_PLANE_SCLCHECK_NONE,
+	SDE_PLANE_SCLCHECK_INVALID,
+	SDE_PLANE_SCLCHECK_SCALER_V1,
+	SDE_PLANE_SCLCHECK_SCALER_V1_CHECK,
+	SDE_PLANE_SCLCHECK_SCALER_V2,
+	SDE_PLANE_SCLCHECK_SCALER_V2_CHECK,
+};
+
+/**
  * struct sde_plane_state: Define sde extension of drm plane state object
  * @base:	base drm plane state object
  * @property_values:	cached plane property values
@@ -112,6 +129,9 @@
  * @multirect_index: index of the rectangle of SSPP
  * @multirect_mode: parallel or time multiplex multirect mode
  * @pending:	whether the current update is still pending
+ * @scaler3_cfg: configuration data for scaler3
+ * @pixel_ext: configuration data for pixel extensions
+ * @scaler_check_state: indicates status of user provided pixel extension data
  * @cdp_cfg:	CDP configuration
  */
 struct sde_plane_state {
@@ -127,6 +147,11 @@
 	uint32_t multirect_mode;
 	bool pending;
 
+	/* scaler configuration */
+	struct sde_hw_scaler3_cfg scaler3_cfg;
+	struct sde_hw_pixel_ext pixel_ext;
+	enum sde_plane_sclcheck_state scaler_check_state;
+
 	/* @sc_cfg: system_cache configuration */
 	struct sde_hw_pipe_sc_cfg sc_cfg;
 	struct sde_plane_rot_state rot;
@@ -190,6 +215,12 @@
 bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill);
 
 /**
+ * sde_plane_restore - restore hw state if previously power collapsed
+ * @plane: Pointer to drm plane structure
+ */
+void sde_plane_restore(struct drm_plane *plane);
+
+/**
  * sde_plane_flush - final plane operations before commit flush
  * @plane: Pointer to drm plane structure
  */
diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
index 1483dae..6f66b73 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -81,8 +81,10 @@
 		return -ENOMEM;
 	size = roundup(size, PAGE_SIZE);
 	ret = drm_gem_object_init(vgdev->ddev, &bo->gem_base, size);
-	if (ret != 0)
+	if (ret != 0) {
+		kfree(bo);
 		return ret;
+	}
 	bo->dumb = false;
 	virtio_gpu_init_ttm_placement(bo, pinned);
 
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index 13c36e6..742da91 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -55,7 +55,7 @@
 	{ adreno_is_a530, a530_vbif },
 	{ adreno_is_a512, a540_vbif },
 	{ adreno_is_a510, a530_vbif },
-	{ adreno_is_a508, a540_vbif },
+	{ adreno_is_a508, a530_vbif },
 	{ adreno_is_a505, a530_vbif },
 	{ adreno_is_a506, a530_vbif },
 };
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index ed0129f..1f97888 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -205,13 +205,16 @@
 	0x3410, 0x3410, 0x3800, 0x3801,
 };
 
-static const unsigned int a6xx_gmu_registers[] = {
+static const unsigned int a6xx_gmu_gx_registers[] = {
 	/* GMU GX */
 	0x1A800, 0x1A800, 0x1A810, 0x1A813, 0x1A816, 0x1A816, 0x1A818, 0x1A81B,
 	0x1A81E, 0x1A81E, 0x1A820, 0x1A823, 0x1A826, 0x1A826, 0x1A828, 0x1A82B,
 	0x1A82E, 0x1A82E, 0x1A830, 0x1A833, 0x1A836, 0x1A836, 0x1A838, 0x1A83B,
 	0x1A83E, 0x1A83E, 0x1A840, 0x1A843, 0x1A846, 0x1A846, 0x1A880, 0x1A884,
 	0x1A900, 0x1A92B, 0x1A940, 0x1A940,
+};
+
+static const unsigned int a6xx_gmu_registers[] = {
 	/* GMU TCM */
 	0x1B400, 0x1C3FF, 0x1C400, 0x1D3FF,
 	/* GMU CX */
@@ -1321,11 +1324,19 @@
 static void a6xx_snapshot_gmu(struct kgsl_device *device,
 		struct kgsl_snapshot *snapshot)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
+
 	if (!kgsl_gmu_isenabled(device))
 		return;
 
 	adreno_snapshot_registers(device, snapshot, a6xx_gmu_registers,
 					ARRAY_SIZE(a6xx_gmu_registers) / 2);
+
+	if (gpudev->gx_is_on(adreno_dev))
+		adreno_snapshot_registers(device, snapshot,
+				a6xx_gmu_gx_registers,
+				ARRAY_SIZE(a6xx_gmu_gx_registers) / 2);
 }
 
 /* a6xx_snapshot_sqe() - Dump SQE data in snapshot */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 4e67efb..129e99c 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2225,21 +2225,23 @@
 		if (fd != 0)
 			dmabuf = dma_buf_get(fd - 1);
 	}
-	up_read(&current->mm->mmap_sem);
 
-	if (IS_ERR_OR_NULL(dmabuf))
+	if (IS_ERR_OR_NULL(dmabuf)) {
+		up_read(&current->mm->mmap_sem);
 		return dmabuf ? PTR_ERR(dmabuf) : -ENODEV;
+	}
 
 	ret = kgsl_setup_dma_buf(device, pagetable, entry, dmabuf);
 	if (ret) {
 		dma_buf_put(dmabuf);
+		up_read(&current->mm->mmap_sem);
 		return ret;
 	}
 
 	/* Setup the user addr/cache mode for cache operations */
 	entry->memdesc.useraddr = hostptr;
 	_setup_cache_mode(entry, vma);
-
+	up_read(&current->mm->mmap_sem);
 	return 0;
 }
 #else
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index c9f1483..dff46d2 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -436,6 +436,7 @@
 	struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	int perf_idx = INVALID_DCVS_IDX, bw_idx = INVALID_DCVS_IDX;
 
 	if (gpu_pwrlevel < gmu->num_gpupwrlevels)
@@ -448,6 +449,10 @@
 		(bw_idx == INVALID_DCVS_IDX))
 		return -EINVAL;
 
+	if (bw_idx == INVALID_DCVS_IDX)
+		/* Use default BW, algorithm changes on V2 */
+		bw_idx = pwr->pwrlevels[gpu_pwrlevel].bus_freq;
+
 	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
 		return gpudev->rpmh_gpu_pwrctrl(adreno_dev,
 			GMU_DCVS_NOHFI, perf_idx, bw_idx);
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 051ab8e..6aa2e36 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -123,32 +123,40 @@
 
 static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err)
 {
-	u32 m_stat = readl_relaxed(gi2c->base + SE_GENI_M_IRQ_STATUS);
-	u32 rx_st = readl_relaxed(gi2c->base + SE_GENI_RX_FIFO_STATUS);
-	u32 tx_st = readl_relaxed(gi2c->base + SE_GENI_TX_FIFO_STATUS);
 	u32 m_cmd = readl_relaxed(gi2c->base + SE_GENI_M_CMD0);
+	u32 m_stat = readl_relaxed(gi2c->base + SE_GENI_M_IRQ_STATUS);
 	u32 geni_s = readl_relaxed(gi2c->base + SE_GENI_STATUS);
 	u32 geni_ios = readl_relaxed(gi2c->base + SE_GENI_IOS);
+	u32 dma = readl_relaxed(gi2c->base + SE_GENI_DMA_MODE_EN);
+	u32 rx_st, tx_st;
+
+	if (gi2c->cur)
+		GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
+			    "len:%d, slv-addr:0x%x, RD/WR:%d\n", gi2c->cur->len,
+			    gi2c->cur->addr, gi2c->cur->flags);
 
 	if (err == I2C_NACK || err == GENI_ABORT_DONE) {
 		GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "%s\n",
-			    gi2c_log[err].msg);
-		GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
-			     "m_stat:0x%x, tx_stat:0x%x, rx_stat:0x%x, ",
-			     m_stat, tx_st, rx_st);
-		GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
-			     "m_cmd:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
-			     m_cmd, geni_s, geni_ios);
+			     gi2c_log[err].msg);
+		goto err_ret;
 	} else {
 		GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s\n",
 			     gi2c_log[err].msg);
-		GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
-			     "m_stat:0x%x, tx_stat:0x%x, rx_stat:0x%x, ",
-			     m_stat, tx_st, rx_st);
-		GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+	}
+	if (dma) {
+		rx_st = readl_relaxed(gi2c->base + SE_DMA_RX_IRQ_STAT);
+		tx_st = readl_relaxed(gi2c->base + SE_DMA_TX_IRQ_STAT);
+	} else {
+		rx_st = readl_relaxed(gi2c->base + SE_GENI_RX_FIFO_STATUS);
+		tx_st = readl_relaxed(gi2c->base + SE_GENI_TX_FIFO_STATUS);
+	}
+	GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
+		     "DMA:%d tx_stat:0x%x, rx_stat:0x%x, irq-stat:0x%x\n",
+		     dma, tx_st, rx_st, m_stat);
+	GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
 			     "m_cmd:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
 			     m_cmd, geni_s, geni_ios);
-	}
+err_ret:
 	gi2c->err = gi2c_log[err].err;
 }
 
@@ -185,7 +193,6 @@
 		if (!dma)
 			writel_relaxed(0, (gi2c->base +
 					   SE_GENI_TX_WATERMARK_REG));
-		gi2c->err = -EIO;
 		goto irqret;
 	}
 
@@ -310,11 +317,12 @@
 				ret = geni_se_rx_dma_prep(gi2c->wrapper_dev,
 							gi2c->base, msgs[i].buf,
 							msgs[i].len, &rx_dma);
-				if (ret)
+				if (ret) {
 					mode = FIFO_MODE;
+					ret = geni_se_select_mode(gi2c->base,
+								  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, m_param:0x%x\n",
@@ -327,15 +335,15 @@
 				ret = geni_se_tx_dma_prep(gi2c->wrapper_dev,
 							gi2c->base, msgs[i].buf,
 							msgs[i].len, &tx_dma);
-				if (ret)
+				if (ret) {
 					mode = FIFO_MODE;
+					ret = geni_se_select_mode(gi2c->base,
+								  mode);
+				}
 			}
-			if (mode == FIFO_MODE) {
-				geni_se_select_mode(gi2c->base, mode);
-				/* Get FIFO IRQ */
+			if (mode == FIFO_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();
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index cb3f515a..01e3a37 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -2342,6 +2342,10 @@
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
+	if (cmd.port_num < rdma_start_port(ib_dev) ||
+	    cmd.port_num > rdma_end_port(ib_dev))
+		return -EINVAL;
+
 	INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
 		   out_len);
 
@@ -2882,6 +2886,10 @@
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
+	if (cmd.attr.port_num < rdma_start_port(ib_dev) ||
+	    cmd.attr.port_num > rdma_end_port(ib_dev))
+		return -EINVAL;
+
 	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
 	if (!uobj)
 		return -ENOMEM;
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 1d5c514..9a4d11f 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -238,6 +238,7 @@
 #define ARM_SMMU_CB_FSYNR0		0x68
 #define ARM_SMMU_CB_S1_TLBIVA		0x600
 #define ARM_SMMU_CB_S1_TLBIASID		0x610
+#define ARM_SMMU_CB_S1_TLBIALL		0x618
 #define ARM_SMMU_CB_S1_TLBIVAL		0x620
 #define ARM_SMMU_CB_S2_TLBIIPAS2	0x630
 #define ARM_SMMU_CB_S2_TLBIIPAS2L	0x638
@@ -415,6 +416,7 @@
 #define ARM_SMMU_OPT_SKIP_INIT		(1 << 2)
 #define ARM_SMMU_OPT_DYNAMIC		(1 << 3)
 #define ARM_SMMU_OPT_3LVL_TABLES	(1 << 4)
+#define ARM_SMMU_OPT_NO_ASID_RETENTION	(1 << 5)
 	u32				options;
 	enum arm_smmu_arch_version	version;
 	enum arm_smmu_implementation	model;
@@ -534,6 +536,7 @@
 	{ ARM_SMMU_OPT_SKIP_INIT, "qcom,skip-init" },
 	{ ARM_SMMU_OPT_DYNAMIC, "qcom,dynamic" },
 	{ ARM_SMMU_OPT_3LVL_TABLES, "qcom,use-3-lvl-tables" },
+	{ ARM_SMMU_OPT_NO_ASID_RETENTION, "qcom,no-asid-retention" },
 	{ 0, NULL},
 };
 
@@ -991,12 +994,17 @@
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
 	void __iomem *base;
+	bool use_tlbiall = smmu->options & ARM_SMMU_OPT_NO_ASID_RETENTION;
 
-	if (stage1) {
+	if (stage1 && !use_tlbiall) {
 		base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
 		writel_relaxed(ARM_SMMU_CB_ASID(smmu, cfg),
 			       base + ARM_SMMU_CB_S1_TLBIASID);
 		arm_smmu_tlb_sync_cb(smmu, cfg->cbndx);
+	} else if (stage1 && use_tlbiall) {
+		base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
+		writel_relaxed(0, base + ARM_SMMU_CB_S1_TLBIALL);
+		arm_smmu_tlb_sync_cb(smmu, cfg->cbndx);
 	} else {
 		base = ARM_SMMU_GR0(smmu);
 		writel_relaxed(ARM_SMMU_CB_VMID(smmu, cfg),
@@ -1013,8 +1021,9 @@
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
 	void __iomem *reg;
+	bool use_tlbiall = smmu->options & ARM_SMMU_OPT_NO_ASID_RETENTION;
 
-	if (stage1) {
+	if (stage1 && !use_tlbiall) {
 		reg = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
 		reg += leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA;
 
@@ -1033,6 +1042,10 @@
 				iova += granule >> 12;
 			} while (size -= granule);
 		}
+	} else if (stage1 && use_tlbiall) {
+		reg = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
+		reg += ARM_SMMU_CB_S1_TLBIALL;
+		writel_relaxed(0, reg);
 	} else if (smmu->version == ARM_SMMU_V2) {
 		reg = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
 		reg += leaf ? ARM_SMMU_CB_S2_TLBIIPAS2L :
diff --git a/drivers/irqchip/qcom/Kconfig b/drivers/irqchip/qcom/Kconfig
index e4a7a88..b892109 100644
--- a/drivers/irqchip/qcom/Kconfig
+++ b/drivers/irqchip/qcom/Kconfig
@@ -13,3 +13,10 @@
         default y if ARCH_SDM845
         help
           QTI Power Domain Controller for SDM845
+
+config QTI_PDC_SDM670
+        bool "QTI PDC SDM670"
+        select QTI_PDC
+        default y if ARCH_SDM670
+        help
+          QTI Power Domain Controller for SDM670
diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile
index 1b7856d..5e99040 100644
--- a/drivers/irqchip/qcom/Makefile
+++ b/drivers/irqchip/qcom/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_QTI_PDC)			+= pdc.o
 obj-$(CONFIG_QTI_PDC_SDM845)		+= pdc-sdm845.o
+obj-$(CONFIG_QTI_PDC_SDM670)		+= pdc-sdm670.o
diff --git a/drivers/irqchip/qcom/pdc-sdm670.c b/drivers/irqchip/qcom/pdc-sdm670.c
new file mode 100644
index 0000000..7bd6333
--- /dev/null
+++ b/drivers/irqchip/qcom/pdc-sdm670.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 sdm670_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}, /* not-connected */
+	{8, 520}, /* eud_p0_dmse_int_mx */
+	{9, 521}, /* eud_p0_dpse_int_mx */
+	{10, 522}, /* not-connected */
+	{11, 523}, /* not-connected */
+	{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}, /* bi_px_ssc_23 */
+	{60, 572}, /* bi_px_ssc_24 */
+	{61, 573}, /* bi_px_ssc_25 */
+	{62, 574}, /* bi_px_ssc_26 */
+	{63, 575}, /* bi_px_ssc_27 */
+	{64, 576}, /* bi_px_ssc_28 */
+	{65, 577}, /* bi_px_ssc_29 */
+	{66, 578}, /* core_bi_px_gpio_66 */
+	{67, 579}, /* core_bi_px_gpio_68 */
+	{68, 580}, /* bi_px_ssc_20 */
+	{69, 581}, /* bi_px_ssc_30 */
+	{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}, /* bi_px_ssc_22 */
+	{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, 95}, /* 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, sdm670_data);
+}
+
+IRQCHIP_DECLARE(pdc_sdm670, "qcom,pdc-sdm670", qcom_pdc_gic_init);
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index d2cb1e8..3989bc6 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -330,6 +330,16 @@
 }
 EXPORT_SYMBOL(mbox_controller_is_idle);
 
+
+void mbox_chan_debug(struct mbox_chan *chan)
+{
+	if (!chan || !chan->cl || !chan->mbox->debug)
+		return;
+
+	return chan->mbox->debug(chan);
+}
+EXPORT_SYMBOL(mbox_chan_debug);
+
 /**
  * mbox_request_channel - Request a mailbox channel.
  * @cl: Identity of the client requesting the channel.
diff --git a/drivers/mailbox/qti-tcs.c b/drivers/mailbox/qti-tcs.c
index be91a65..15d0805 100644
--- a/drivers/mailbox/qti-tcs.c
+++ b/drivers/mailbox/qti-tcs.c
@@ -241,11 +241,11 @@
 		return;
 
 	msg = resp->msg;
-	pr_debug("Response object idx=%d:\n\tfor-tcs=%d\tin-use=%d\n",
+	pr_warn("Response object idx=%d:\n\tfor-tcs=%d\tin-use=%d\n",
 			resp->idx, resp->m, resp->in_use);
-	pr_debug("Msg: state=%d\n", msg->state);
+	pr_warn("Msg: state=%d\n", msg->state);
 	for (i = 0; i < msg->num_payload; i++)
-		pr_debug("addr=0x%x data=0x%x complete=0x%x\n",
+		pr_warn("addr=0x%x data=0x%x complete=0x%x\n",
 				msg->payload[i].addr,
 				msg->payload[i].data,
 				msg->payload[i].complete);
@@ -804,14 +804,14 @@
 	if (!enable)
 		return;
 
-	pr_debug("TCS-%d contents:\n", m);
+	pr_warn("TCS-%d contents:\n", m);
 	for (n = 0; n < tcs->ncpt; n++) {
 		if (!(enable & BIT(n)))
 			continue;
 		addr = read_tcs_reg(base, TCS_DRV_CMD_ADDR, m, n);
 		data = read_tcs_reg(base, TCS_DRV_CMD_DATA, m, n);
 		msgid = read_tcs_reg(base, TCS_DRV_CMD_MSGID, m, n);
-		pr_debug("\tn=%d addr=0x%x data=0x%x hdr=0x%x\n",
+		pr_warn("\tn=%d addr=0x%x data=0x%x hdr=0x%x\n",
 						n, addr, data, msgid);
 	}
 }
@@ -824,7 +824,7 @@
 	for (i = 0; i < drv->num_tcs; i++) {
 		if (!atomic_read(&drv->tcs_in_use[i]))
 			continue;
-		pr_debug("Time: %llu: TCS-%d:\n\tReq Sent:%d Last Sent:%llu\n\tResp Recv:%d Last Recvd:%llu\n",
+		pr_warn("Time: %llu: TCS-%d:\n\tReq Sent:%d Last Sent:%llu\n\tResp Recv:%d Last Recvd:%llu\n",
 				curr, i,
 				atomic_read(&drv->tcs_send_count[i]),
 				drv->tcs_last_sent_ts[i],
@@ -835,6 +835,13 @@
 	}
 }
 
+static void chan_debug(struct mbox_chan *chan)
+{
+	struct tcs_drv *drv = container_of(chan->mbox, struct tcs_drv, mbox);
+
+	dump_tcs_stats(drv);
+}
+
 /**
  * chan_tcs_write: Validate the incoming message and write to the
  * appropriate TCS block.
@@ -910,7 +917,6 @@
 	/* If we were just busy waiting for TCS, dump the state and return */
 	if (ret == -EBUSY) {
 		pr_info_ratelimited("TCS Busy, retrying RPMH message send\n");
-		dump_tcs_stats(drv);
 		ret = -EAGAIN;
 	}
 
@@ -1162,6 +1168,7 @@
 	drv->mbox.txdone_irq = true;
 	drv->mbox.of_xlate = of_tcs_mbox_xlate;
 	drv->mbox.is_idle = tcs_drv_is_idle;
+	drv->mbox.debug = chan_debug;
 	drv->num_tcs = st;
 	drv->pdev = pdev;
 	INIT_LIST_HEAD(&drv->response_pending);
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index c68239e..98b067b 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -468,7 +468,7 @@
 
 	while ((entity_err = media_entity_graph_walk_next(graph))) {
 		/* don't let the stream_count go negative */
-		if (entity->stream_count > 0) {
+		if (entity_err->stream_count > 0) {
 			entity_err->stream_count--;
 			if (entity_err->stream_count == 0)
 				entity_err->pipe = NULL;
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
index fc7a493..38f13c4 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm.h
@@ -233,6 +233,7 @@
 	struct cam_cdm_client *clients[CAM_PER_CDM_MAX_REGISTERED_CLIENTS];
 	uint8_t bl_tag;
 	atomic_t error;
+	atomic_t bl_done;
 	struct cam_cdm_hw_mem gen_irq;
 	uint32_t cpas_handle;
 };
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.c
index 341406a..3604357 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_core_common.c
@@ -107,7 +107,7 @@
 		if (node->bl_tag == tag)
 			return node;
 	}
-	pr_err("Could not find the bl request for tag=%d\n", tag);
+	pr_err("Could not find the bl request for tag=%x\n", tag);
 
 	return NULL;
 }
@@ -216,7 +216,7 @@
 {
 	struct cam_hw_info *cdm_hw = hw_priv;
 	struct cam_cdm *core = NULL;
-	int rc = -1;
+	int rc = -EPERM;
 	int client_idx;
 	struct cam_cdm_client *client;
 	uint32_t *handle = start_args;
@@ -476,7 +476,8 @@
 				core->clients[idx] = NULL;
 				mutex_unlock(
 					&cdm_hw->hw_mutex);
-				rc = -1;
+				rc = -EPERM;
+				pr_err("Invalid ops for virtual cdm\n");
 				break;
 			}
 		} else {
@@ -521,7 +522,7 @@
 		if (client->refcount != 0) {
 			pr_err("CDM Client refcount not zero %d",
 				client->refcount);
-			rc = -1;
+			rc = -EPERM;
 			mutex_unlock(&client->lock);
 			mutex_unlock(&cdm_hw->hw_mutex);
 			break;
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
index 6009c25..5fac7d8 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
@@ -66,19 +66,74 @@
 	if (cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_PENDING_REQ_RB,
 		pending_bl)) {
 		pr_err("Failed to read CDM pending BL's\n");
-		rc = -1;
+		rc = -EIO;
 	}
 
 	return rc;
 }
 
+static int cam_hw_cdm_enable_bl_done_irq(struct cam_hw_info *cdm_hw,
+	bool enable)
+{
+	int rc = -EIO;
+	uint32_t irq_mask = 0;
+	struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
+
+	if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_MASK,
+		&irq_mask)) {
+		pr_err("Failed to read CDM IRQ mask\n");
+		return rc;
+	}
+
+	if (enable == true) {
+		if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK,
+			(irq_mask | 0x4))) {
+			pr_err("Write failed to enable BL done irq\n");
+		} else {
+			atomic_inc(&core->bl_done);
+			rc = 0;
+			CDM_CDBG("BL done irq enabled =%d\n",
+				atomic_read(&core->bl_done));
+		}
+	} else {
+		if (cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK,
+			(irq_mask & 0x70003))) {
+			pr_err("Write failed to disable BL done irq\n");
+		} else {
+			atomic_dec(&core->bl_done);
+			rc = 0;
+			CDM_CDBG("BL done irq disable =%d\n",
+				atomic_read(&core->bl_done));
+		}
+	}
+	return rc;
+}
+
+static int cam_hw_cdm_enable_core(struct cam_hw_info *cdm_hw, bool enable)
+{
+	int rc = 0;
+
+	if (enable == true) {
+		if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CORE_EN, 0x01)) {
+			pr_err("Failed to Write CDM HW core enable\n");
+			rc = -EIO;
+		}
+	} else {
+		if (cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CORE_EN, 0x02)) {
+			pr_err("Failed to Write CDM HW core disable\n");
+			rc = -EIO;
+		}
+	}
+	return rc;
+}
+
 int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw)
 {
 	int rc = 0;
 
 	if (cam_cdm_write_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, 0x10100)) {
 		pr_err("Failed to Write CDM HW core debug\n");
-		rc = -1;
+		rc = -EIO;
 	}
 
 	return rc;
@@ -90,7 +145,7 @@
 
 	if (cam_cdm_write_hw_reg(cdm_hw, CDM_DBG_CORE_DBUG, 0)) {
 		pr_err("Failed to Write CDM HW core debug\n");
-		rc = -1;
+		rc = -EIO;
 	}
 
 	return rc;
@@ -137,8 +192,8 @@
 	mutex_lock(&cdm_hw->hw_mutex);
 	cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_CORE_EN, &dump_reg);
 	pr_err("CDM HW core status=%x\n", dump_reg);
-	/* First pause CDM */
-	cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CORE_EN, 0x03);
+	/* First pause CDM, If it fails still proceed to dump debug info */
+	cam_hw_cdm_enable_core(cdm_hw, false);
 	cam_hw_cdm_bl_fifo_pending_bl_rb(cdm_hw, &dump_reg);
 	pr_err("CDM HW current pending BL=%x\n", dump_reg);
 	loop_cnt = dump_reg;
@@ -196,7 +251,7 @@
 	pr_err("CDM HW current pending BL=%x\n", dump_reg);
 
 	/* Enable CDM back */
-	cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CORE_EN, 1);
+	cam_hw_cdm_enable_core(cdm_hw, true);
 	mutex_unlock(&cdm_hw->hw_mutex);
 
 }
@@ -206,7 +261,7 @@
 {
 	uint32_t pending_bl = 0;
 	int32_t available_bl_slots = 0;
-	int rc = -1;
+	int rc = -EIO;
 	long time_left;
 	struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
 
@@ -214,7 +269,7 @@
 		if (cam_cdm_read_hw_reg(cdm_hw, CDM_BL_FIFO_PENDING_REQ_RB,
 			&pending_bl)) {
 			pr_err("Failed to read CDM pending BL's\n");
-			rc = -1;
+			rc = -EIO;
 			break;
 		}
 		available_bl_slots = CAM_CDM_HWFIFO_SIZE - pending_bl;
@@ -230,14 +285,24 @@
 				rc = bl_count;
 				break;
 		} else if (0 == (available_bl_slots - 1)) {
+			rc = cam_hw_cdm_enable_bl_done_irq(cdm_hw, true);
+			if (rc) {
+				pr_err("Enable BL done irq failed\n");
+				break;
+			}
 			time_left = wait_for_completion_timeout(
 				&core->bl_complete, msecs_to_jiffies(
 				CAM_CDM_BL_FIFO_WAIT_TIMEOUT));
 			if (time_left <= 0) {
 				pr_err("CDM HW BL Wait timed out failed\n");
-				rc = -1;
+				if (cam_hw_cdm_enable_bl_done_irq(cdm_hw,
+					false))
+					pr_err("Disable BL done irq failed\n");
+				rc = -EIO;
 				break;
 			}
+			if (cam_hw_cdm_enable_bl_done_irq(cdm_hw, false))
+				pr_err("Disable BL done irq failed\n");
 			rc = 0;
 			CDM_CDBG("CDM HW is ready for data\n");
 		} else {
@@ -286,8 +351,8 @@
 		rc = -EINVAL;
 		goto end;
 	}
-	CDM_CDBG("CDM write BL last cmd tag=%d total=%d\n",
-		core->bl_tag, req->data->cmd_arrary_count);
+	CDM_CDBG("CDM write BL last cmd tag=%x total=%d cookie=%d\n",
+		core->bl_tag, req->data->cmd_arrary_count, req->data->cookie);
 	node = kzalloc(sizeof(struct cam_cdm_bl_cb_request_entry),
 			GFP_KERNEL);
 	if (!node) {
@@ -311,7 +376,7 @@
 			core->bl_tag);
 		list_del_init(&node->entry);
 		kfree(node);
-		rc = -1;
+		rc = -EIO;
 		goto end;
 	}
 
@@ -320,7 +385,7 @@
 			core->bl_tag);
 		list_del_init(&node->entry);
 		kfree(node);
-		rc = -1;
+		rc = -EIO;
 	}
 
 end:
@@ -331,7 +396,7 @@
 	struct cam_cdm_hw_intf_cmd_submit_bl *req,
 	struct cam_cdm_client *client)
 {
-	int i, rc = -1;
+	int i, rc;
 	struct cam_cdm_bl_request *cdm_cmd = req->data;
 	struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
 	uint32_t pending_bl = 0;
@@ -342,10 +407,8 @@
 			req->data->cmd_arrary_count, CAM_CDM_HWFIFO_SIZE);
 	}
 
-	if (atomic_read(&core->error) != 0) {
-		pr_err("HW in error state, cannot trigger transactions now\n");
-		return rc;
-	}
+	if (atomic_read(&core->error))
+		return -EIO;
 
 	mutex_lock(&cdm_hw->hw_mutex);
 	mutex_lock(&client->lock);
@@ -366,13 +429,13 @@
 			pr_err("cmd len(%d) is invalid cnt=%d total cnt=%d\n",
 				cdm_cmd->cmd[i].len, i,
 				req->data->cmd_arrary_count);
-			rc = -1;
+			rc = -EINVAL;
 			break;
 		}
-		if (atomic_read(&core->error) != 0) {
-			pr_err("HW in error state cmd_count=%d total cnt=%d\n",
+		if (atomic_read(&core->error)) {
+			pr_err_ratelimited("In error state cnt=%d total cnt=%d\n",
 				i, req->data->cmd_arrary_count);
-			rc = -1;
+			rc = -EIO;
 			break;
 		}
 		if (write_count == 0) {
@@ -381,7 +444,7 @@
 			if (write_count < 0) {
 				pr_err("wait for bl fifo failed %d:%d\n",
 					i, req->data->cmd_arrary_count);
-				rc = -1;
+				rc = -EIO;
 				break;
 			}
 		} else {
@@ -397,7 +460,7 @@
 			if (!cdm_cmd->cmd[i].bl_addr.hw_iova) {
 				pr_err("Hw bl hw_iova is invalid %d:%d\n",
 					i, req->data->cmd_arrary_count);
-				rc = -1;
+				rc = -EINVAL;
 				break;
 			}
 			rc = 0;
@@ -407,13 +470,16 @@
 		} else {
 			pr_err("Only mem hdl/hw va type is supported %d\n",
 				req->data->type);
-			rc = -1;
+			rc = -EINVAL;
 			break;
 		}
 
 		if ((!rc) && (hw_vaddr_ptr) && (len) &&
 			(len >= cdm_cmd->cmd[i].offset)) {
 			CDM_CDBG("Got the HW VA\n");
+			if (core->bl_tag >=
+				(CAM_CDM_HWFIFO_SIZE - 1))
+				core->bl_tag = 0;
 			rc = cam_hw_cdm_bl_write(cdm_hw,
 				((uint32_t)hw_vaddr_ptr +
 					cdm_cmd->cmd[i].offset),
@@ -421,7 +487,7 @@
 			if (rc) {
 				pr_err("Hw bl write failed %d:%d\n",
 					i, req->data->cmd_arrary_count);
-				rc = -1;
+				rc = -EIO;
 				break;
 			}
 		} else {
@@ -430,23 +496,24 @@
 				cdm_cmd->cmd[i].offset);
 			pr_err("Sanity check failed for %d:%d\n",
 				i, req->data->cmd_arrary_count);
-			rc = -1;
+			rc = -EINVAL;
 			break;
 		}
 
 		if (!rc) {
 			CDM_CDBG("write BL success for cnt=%d with tag=%d\n",
 				i, core->bl_tag);
-			core->bl_tag++;
+
 			CDM_CDBG("Now commit the BL\n");
 			if (cam_hw_cdm_commit_bl_write(cdm_hw)) {
 				pr_err("Cannot commit the BL %d tag=%d\n",
-					i, (core->bl_tag - 1));
-				rc = -1;
+					i, core->bl_tag);
+				rc = -EIO;
 				break;
 			}
 			CDM_CDBG("BL commit success BL %d tag=%d\n", i,
-				(core->bl_tag - 1));
+				core->bl_tag);
+			core->bl_tag++;
 			if ((req->data->flag == true) &&
 				(i == (req->data->cmd_arrary_count -
 				1))) {
@@ -455,9 +522,6 @@
 				if (rc == 0)
 					core->bl_tag++;
 			}
-			if (!rc && ((CAM_CDM_HWFIFO_SIZE - 1) ==
-				core->bl_tag))
-				core->bl_tag = 0;
 		}
 	}
 	mutex_unlock(&client->lock);
@@ -502,7 +566,8 @@
 				list_del_init(&node->entry);
 				kfree(node);
 			} else {
-				pr_err("Invalid node for inline irq\n");
+				pr_err("Invalid node for inline irq status=%x data=%x\n",
+					payload->irq_status, payload->irq_data);
 			}
 			mutex_unlock(&cdm_hw->hw_mutex);
 		}
@@ -514,25 +579,30 @@
 		}
 		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_INFO_BL_DONE_MASK) {
-			pr_err("CDM HW BL done IRQ\n");
-			complete(&core->bl_complete);
+			if (atomic_read(&core->bl_done)) {
+				CDM_CDBG("CDM HW BL done IRQ\n");
+				complete(&core->bl_complete);
+			}
 		}
 		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) {
-			pr_err("Invalid command IRQ, Need HW reset\n");
+			pr_err_ratelimited("Invalid command IRQ, Need HW reset\n");
+			atomic_inc(&core->error);
+			cam_hw_cdm_dump_core_debug_registers(cdm_hw);
+		}
+		if (payload->irq_status &
+			CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK) {
+			pr_err_ratelimited("AHB Error IRQ\n");
 			atomic_inc(&core->error);
 			cam_hw_cdm_dump_core_debug_registers(cdm_hw);
 			atomic_dec(&core->error);
 		}
 		if (payload->irq_status &
-			CAM_CDM_IRQ_STATUS_ERROR_AHB_BUS_MASK) {
-			pr_err("AHB IRQ\n");
-			cam_hw_cdm_dump_core_debug_registers(cdm_hw);
-		}
-		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_ERROR_OVER_FLOW_MASK) {
-			pr_err("Overflow IRQ\n");
+			pr_err_ratelimited("Overflow Error IRQ\n");
+			atomic_inc(&core->error);
 			cam_hw_cdm_dump_core_debug_registers(cdm_hw);
+			atomic_dec(&core->error);
 		}
 		kfree(payload);
 	} else {
@@ -552,7 +622,7 @@
 		core = (struct cam_cdm *)cdm_hw->core_info;
 		atomic_inc(&core->error);
 		cam_hw_cdm_dump_core_debug_registers(cdm_hw);
-		pr_err("Page fault iova addr %pK\n", (void *)iova);
+		pr_err_ratelimited("Page fault iova addr %pK\n", (void *)iova);
 		cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_PAGEFAULT,
 			(void *)iova);
 		atomic_dec(&core->error);
@@ -576,6 +646,11 @@
 				&payload->irq_status)) {
 			pr_err("Failed to read CDM HW IRQ status\n");
 		}
+		if (!payload->irq_status) {
+			pr_err_ratelimited("Invalid irq received\n");
+			kfree(payload);
+			return IRQ_HANDLED;
+		}
 		if (payload->irq_status &
 			CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK) {
 			if (cam_cdm_read_hw_reg(cdm_hw, CDM_IRQ_USR_DATA,
@@ -618,8 +693,7 @@
 	genirq_alloc_cmd.align = 0;
 	genirq_alloc_cmd.size = (8 * CAM_CDM_HWFIFO_SIZE);
 	genirq_alloc_cmd.smmu_hdl = cdm_core->iommu_hdl.non_secure;
-	genirq_alloc_cmd.flags = 0;
-	genirq_alloc_cmd.region = CAM_MEM_MGR_REGION_NON_SECURE_IO;
+	genirq_alloc_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE;
 	rc = cam_mem_mgr_request_mem(&genirq_alloc_cmd,
 		&genirq_alloc_out);
 	if (rc) {
@@ -679,6 +753,8 @@
 	CDM_CDBG("Enable soc done\n");
 
 /* Before triggering the reset to HW, clear the reset complete */
+	atomic_set(&cdm_core->error, 0);
+	atomic_set(&cdm_core->bl_done, 0);
 	reinit_completion(&cdm_core->reset_complete);
 	reinit_completion(&cdm_core->bl_complete);
 
@@ -713,13 +789,12 @@
 		CDM_CDBG("CDM Init success\n");
 		cdm_hw->hw_state = CAM_HW_STATE_POWER_UP;
 		cam_cdm_write_hw_reg(cdm_hw, CDM_IRQ_MASK, 0x70003);
-		cam_cdm_write_hw_reg(cdm_hw, CDM_CFG_CGC_CFG, 0x7);
 		rc = 0;
 		goto end;
 	}
 
 disable_return:
-	rc = -1;
+	rc = -EIO;
 	cam_soc_util_disable_platform_resource(soc_info, true, true);
 end:
 	return rc;
@@ -757,6 +832,8 @@
 	struct cam_cdm *cdm_core = NULL;
 	struct cam_cdm_private_dt_data *soc_private = NULL;
 	struct cam_cpas_register_params cpas_parms;
+	struct cam_ahb_vote ahb_vote;
+	struct cam_axi_vote axi_vote;
 
 	cdm_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
 	if (!cdm_hw_intf)
@@ -788,7 +865,7 @@
 		pr_err("Failed to get dt properties\n");
 		goto release_mem;
 	}
-	cdm_hw_intf->hw_idx = cdm_hw->soc_info.pdev->id;
+	cdm_hw_intf->hw_idx = cdm_hw->soc_info.index;
 	cdm_core = (struct cam_cdm *)cdm_hw->core_info;
 	soc_private = (struct cam_cdm_private_dt_data *)
 		cdm_hw->soc_info.soc_private;
@@ -798,7 +875,6 @@
 		cdm_core->flags = CAM_CDM_FLAG_PRIVATE_CDM;
 
 	cdm_core->bl_tag = 0;
-	atomic_set(&cdm_core->error, 0);
 	cdm_core->id = cam_hw_cdm_get_id_by_name(cdm_core->name);
 	if (cdm_core->id >= CAM_CDM_MAX) {
 		pr_err("Failed to get CDM HW name for %s\n", cdm_core->name);
@@ -863,10 +939,20 @@
 		cpas_parms.client_handle);
 	cdm_core->cpas_handle = cpas_parms.client_handle;
 
+	ahb_vote.type = CAM_VOTE_ABSOLUTE;
+	ahb_vote.vote.level = CAM_SVS_VOTE;
+	axi_vote.compressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
+	axi_vote.uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
+	rc = cam_cpas_start(cdm_core->cpas_handle, &ahb_vote, &axi_vote);
+	if (rc) {
+		pr_err("CPAS start failed\n");
+		goto cpas_unregister;
+	}
+
 	rc = cam_hw_cdm_init(cdm_hw, NULL, 0);
 	if (rc) {
 		pr_err("Failed to Init CDM HW\n");
-		goto init_failed;
+		goto cpas_stop;
 	}
 	cdm_hw->open_count++;
 
@@ -876,7 +962,7 @@
 		goto deinit;
 	}
 
-	if (cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_HW_VERSION,
+	if (cam_cdm_read_hw_reg(cdm_hw, CDM_CFG_TITAN_VERSION,
 		&cdm_core->hw_family_version)) {
 		pr_err("Failed to read CDM family Version\n");
 		goto deinit;
@@ -900,14 +986,23 @@
 	rc = cam_hw_cdm_deinit(cdm_hw, NULL, 0);
 	if (rc) {
 		pr_err("Failed to Deinit CDM HW\n");
-		goto release_platform_resource;
+		cdm_hw->open_count--;
+		goto cpas_stop;
+	}
+
+	rc = cam_cpas_stop(cdm_core->cpas_handle);
+	if (rc) {
+		pr_err("CPAS stop failed\n");
+		cdm_hw->open_count--;
+		goto cpas_unregister;
 	}
 
 	rc = cam_cdm_intf_register_hw_cdm(cdm_hw_intf,
 		soc_private, CAM_HW_CDM, &cdm_core->index);
 	if (rc) {
 		pr_err("HW CDM Interface registration failed\n");
-		goto release_platform_resource;
+		cdm_hw->open_count--;
+		goto cpas_unregister;
 	}
 	cdm_hw->open_count--;
 	mutex_unlock(&cdm_hw->hw_mutex);
@@ -920,7 +1015,10 @@
 	if (cam_hw_cdm_deinit(cdm_hw, NULL, 0))
 		pr_err("Deinit failed for hw\n");
 	cdm_hw->open_count--;
-init_failed:
+cpas_stop:
+	if (cam_cpas_stop(cdm_core->cpas_handle))
+		pr_err("CPAS stop failed\n");
+cpas_unregister:
 	if (cam_cpas_unregister_client(cdm_core->cpas_handle))
 		pr_err("CPAS unregister failed\n");
 release_platform_resource:
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
index b1b2117..59f5b92 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
@@ -42,7 +42,7 @@
 	mutex_lock(&cam_cdm_mgr_lock);
 	if (cdm_mgr.probe_done == false) {
 		pr_err("CDM intf mgr not probed yet\n");
-		rc = -1;
+		rc = -EPERM;
 	} else {
 		CDM_CDBG("CDM intf mgr get refcount=%d\n",
 			cdm_mgr.refcount);
@@ -73,7 +73,7 @@
 static int get_cdm_iommu_handle(struct cam_iommu_handle *cdm_handles,
 	uint32_t hw_idx)
 {
-	int rc = -1;
+	int rc = -EPERM;
 	struct cam_hw_intf *hw = cdm_mgr.nodes[hw_idx].device;
 
 	if (hw->hw_ops.get_hw_caps) {
@@ -87,7 +87,7 @@
 static int get_cdm_index_by_id(char *identifier,
 	uint32_t cell_index, uint32_t *hw_index)
 {
-	int rc = -1, i, j;
+	int rc = -EPERM, i, j;
 	char client_name[128];
 
 	CDM_CDBG("Looking for HW id of =%s and index=%d\n",
@@ -125,7 +125,7 @@
 int cam_cdm_get_iommu_handle(char *identifier,
 	struct cam_iommu_handle *cdm_handles)
 {
-	int i, j, rc = -1;
+	int i, j, rc = -EPERM;
 
 	if ((!identifier) || (!cdm_handles))
 		return -EINVAL;
@@ -164,7 +164,7 @@
 
 int cam_cdm_acquire(struct cam_cdm_acquire_data *data)
 {
-	int rc = -1;
+	int rc = -EPERM;
 	struct cam_hw_intf *hw;
 	uint32_t hw_index = 0;
 
@@ -179,7 +179,7 @@
 
 	if (data->id > CAM_CDM_HW_ANY) {
 		pr_err("only CAM_CDM_VIRTUAL/CAM_CDM_HW_ANY is supported\n");
-		rc = -1;
+		rc = -EPERM;
 		goto end;
 	}
 	rc = get_cdm_index_by_id(data->identifier, data->cell_index,
@@ -200,7 +200,7 @@
 			}
 		} else {
 			pr_err("idx %d doesn't have acquire ops\n", hw_index);
-			rc = -1;
+			rc = -EPERM;
 		}
 	}
 end:
@@ -216,7 +216,7 @@
 int cam_cdm_release(uint32_t handle)
 {
 	uint32_t hw_index;
-	int rc = -1;
+	int rc = -EPERM;
 	struct cam_hw_intf *hw;
 
 	if (get_cdm_mgr_refcount()) {
@@ -250,7 +250,7 @@
 int cam_cdm_submit_bls(uint32_t handle, struct cam_cdm_bl_request *data)
 {
 	uint32_t hw_index;
-	int rc = -1;
+	int rc = -EINVAL;
 	struct cam_hw_intf *hw;
 
 	if (!data)
@@ -258,6 +258,7 @@
 
 	if (get_cdm_mgr_refcount()) {
 		pr_err("CDM intf mgr get refcount failed\n");
+		rc = -EPERM;
 		return rc;
 	}
 
@@ -289,11 +290,12 @@
 int cam_cdm_stream_on(uint32_t handle)
 {
 	uint32_t hw_index;
-	int rc = -1;
+	int rc = -EINVAL;
 	struct cam_hw_intf *hw;
 
 	if (get_cdm_mgr_refcount()) {
 		pr_err("CDM intf mgr get refcount failed\n");
+		rc = -EPERM;
 		return rc;
 	}
 
@@ -320,11 +322,12 @@
 int cam_cdm_stream_off(uint32_t handle)
 {
 	uint32_t hw_index;
-	int rc = -1;
+	int rc = -EINVAL;
 	struct cam_hw_intf *hw;
 
 	if (get_cdm_mgr_refcount()) {
 		pr_err("CDM intf mgr get refcount failed\n");
+		rc = -EPERM;
 		return rc;
 	}
 
@@ -351,11 +354,12 @@
 int cam_cdm_reset_hw(uint32_t handle)
 {
 	uint32_t hw_index;
-	int rc = -1;
+	int rc = -EINVAL;
 	struct cam_hw_intf *hw;
 
 	if (get_cdm_mgr_refcount()) {
 		pr_err("CDM intf mgr get refcount failed\n");
+		rc = -EPERM;
 		return rc;
 	}
 
@@ -426,13 +430,14 @@
 	struct cam_cdm_private_dt_data *data, enum cam_cdm_type type,
 	uint32_t index)
 {
-	int rc = -1;
+	int rc = -EINVAL;
 
 	if ((!hw) || (!data))
-		return -EINVAL;
+		return rc;
 
 	if (get_cdm_mgr_refcount()) {
 		pr_err("CDM intf mgr get refcount failed\n");
+		rc = -EPERM;
 		return rc;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_soc.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_soc.c
index 0f5458c..fbf185c 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_soc.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_soc.c
@@ -48,13 +48,13 @@
 
 	if ((reg > cdm->offset_tbl->offset_max_size) ||
 		(reg > cdm->offset_tbl->last_offset)) {
-		pr_err("CDM accessing invalid reg=%d\n", reg);
+		pr_err_ratelimited("Invalid reg=%d\n", reg);
 		goto permission_error;
 	} else {
 		reg_addr = (base + (CAM_CDM_OFFSET_FROM_REG(
 				cdm->offset_tbl, reg)));
 		if (reg_addr > (base + mem_len)) {
-			pr_err("accessing invalid mapped region %d\n", reg);
+			pr_err_ratelimited("Invalid mapped region %d\n", reg);
 			goto permission_error;
 		}
 		*value = cam_io_r_mb(reg_addr);
@@ -84,13 +84,13 @@
 
 	if ((reg > cdm->offset_tbl->offset_max_size) ||
 		(reg > cdm->offset_tbl->last_offset)) {
-		pr_err("CDM accessing invalid reg=%d\n", reg);
+		pr_err_ratelimited("CDM accessing invalid reg=%d\n", reg);
 		goto permission_error;
 	} else {
 		reg_addr = (base + CAM_CDM_OFFSET_FROM_REG(
 				cdm->offset_tbl, reg));
 		if (reg_addr > (base + mem_len)) {
-			pr_err("Accessing invalid region %d:%d\n",
+			pr_err_ratelimited("Accessing invalid region %d:%d\n",
 				reg, (CAM_CDM_OFFSET_FROM_REG(
 				cdm->offset_tbl, reg)));
 			goto permission_error;
@@ -106,7 +106,7 @@
 int cam_cdm_soc_load_dt_private(struct platform_device *pdev,
 	struct cam_cdm_private_dt_data *ptr)
 {
-	int i, rc = -1;
+	int i, rc = -EINVAL;
 
 	ptr->dt_num_supported_clients = of_property_count_strings(
 						pdev->dev.of_node,
@@ -186,7 +186,7 @@
 	return rc;
 
 error:
-	rc = -1;
+	rc = -EINVAL;
 	kfree(soc_ptr->soc_private);
 	soc_ptr->soc_private = NULL;
 	return rc;
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c
index 3d258b4..a3de3d1 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c
@@ -323,7 +323,7 @@
 	struct cam_soc_reg_map *base_table[CAM_SOC_MAX_BLOCK],
 	void __iomem **device_base)
 {
-	int ret = -1, i;
+	int ret = -EINVAL, i;
 
 	for (i = 0; i < base_array_size; i++) {
 		if (base_table[i])
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
index e34bfc2..bfe14e1 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
@@ -83,7 +83,7 @@
 	struct cam_cdm_hw_intf_cmd_submit_bl *req,
 	struct cam_cdm_client *client)
 {
-	int i, rc = -1;
+	int i, rc = -EINVAL;
 	struct cam_cdm_bl_request *cdm_cmd = req->data;
 	struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
 
@@ -97,7 +97,7 @@
 			pr_err("len(%d) is invalid count=%d total cnt=%d\n",
 				cdm_cmd->cmd[i].len, i,
 				req->data->cmd_arrary_count);
-			rc = -1;
+			rc = -EINVAL;
 			break;
 		}
 		if (req->data->type == CAM_CDM_BL_CMD_TYPE_MEM_HANDLE) {
@@ -113,7 +113,7 @@
 		} else {
 			pr_err("Only mem hdl/Kernel va type is supported %d\n",
 				req->data->type);
-			rc = -1;
+			rc = -EINVAL;
 			break;
 		}
 
@@ -140,7 +140,7 @@
 				cdm_cmd->cmd[i].offset);
 			pr_err("Sanity check failed for cmd_count=%d cnt=%d\n",
 				i, req->data->cmd_arrary_count);
-			rc = -1;
+			rc = -EINVAL;
 			break;
 		}
 		if (!rc) {
@@ -229,9 +229,8 @@
 	}
 
 	rc = cam_cdm_soc_load_dt_private(pdev, cdm_hw->soc_info.soc_private);
-	if (rc != 0) {
+	if (rc) {
 		pr_err("Failed to load CDM dt private data\n");
-		rc = -1;
 		kfree(cdm_hw->soc_info.soc_private);
 		cdm_hw->soc_info.soc_private = NULL;
 		goto soc_load_failed;
diff --git a/drivers/media/platform/msm/camera/cam_core/Makefile b/drivers/media/platform/msm/camera/cam_core/Makefile
index 60f94d1..6fb1200 100644
--- a/drivers/media/platform/msm/camera/cam_core/Makefile
+++ b/drivers/media/platform/msm/camera/cam_core/Makefile
@@ -1,4 +1,6 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
 
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_context.o cam_context_utils.o cam_node.o cam_subdev.o
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.h b/drivers/media/platform/msm/camera/cam_core/cam_context.h
index 7f0fb7f..d87c984 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.h
@@ -13,6 +13,7 @@
 #ifndef _CAM_CONTEXT_H_
 #define _CAM_CONTEXT_H_
 
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include "cam_req_mgr_interface.h"
 #include "cam_hw_mgr_intf.h"
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
index edd2e11..e934dff 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
@@ -19,11 +19,12 @@
 #include <media/cam_sync.h>
 #include <media/cam_defs.h>
 
-#include "cam_sync_api.h"
-#include "cam_req_mgr_util.h"
+#include "cam_context.h"
 #include "cam_mem_mgr.h"
 #include "cam_node.h"
-#include "cam_context.h"
+#include "cam_req_mgr_util.h"
+#include "cam_sync_api.h"
+#include "cam_trace.h"
 
 int cam_context_buf_done_from_hw(struct cam_context *ctx,
 	void *done_event_data, uint32_t bubble_state)
@@ -42,6 +43,8 @@
 	req = list_first_entry(&ctx->active_req_list,
 		struct cam_ctx_request, list);
 
+	trace_cam_buf_done("UTILS", ctx, req);
+
 	if (done->request_id != req->request_id) {
 		pr_err("mismatch: done request [%lld], active request [%lld]\n",
 			done->request_id, req->request_id);
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_node.c b/drivers/media/platform/msm/camera/cam_core/cam_node.c
index ab4c25d..fa26ea0 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c
@@ -15,6 +15,7 @@
 #include <linux/uaccess.h>
 
 #include "cam_node.h"
+#include "cam_trace.h"
 
 static void  __cam_node_handle_shutdown(struct cam_node *node)
 {
@@ -255,6 +256,8 @@
 		return -EINVAL;
 	}
 
+	trace_cam_apply_req("Node", apply);
+
 	return cam_context_handle_crm_apply_req(ctx, apply);
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/Makefile b/drivers/media/platform/msm/camera/cam_icp/Makefile
index b35e4e4..5aba168 100644
--- a/drivers/media/platform/msm/camera/cam_icp/Makefile
+++ b/drivers/media/platform/msm/camera/cam_icp/Makefile
@@ -8,6 +8,7 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_icp/fw_inc
 ccflags-y += -Idrivers/media/platform/msm/camera
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 
 obj-$(CONFIG_SPECTRA_CAMERA) += icp_hw/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_icp_subdev.o cam_icp_context.o hfi.o
diff --git a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
index 2311f66..776847d 100644
--- a/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
+++ b/drivers/media/platform/msm/camera/cam_icp/cam_icp_context.c
@@ -25,6 +25,7 @@
 #include "cam_icp_context.h"
 #include "cam_req_mgr_util.h"
 #include "cam_mem_mgr.h"
+#include "cam_trace.h"
 
 static int __cam_icp_acquire_dev_in_available(struct cam_context *ctx,
 	struct cam_acquire_dev_cmd *cmd)
@@ -32,8 +33,10 @@
 	int rc;
 
 	rc = cam_context_acquire_dev_to_hw(ctx, cmd);
-	if (!rc)
+	if (!rc) {
 		ctx->state = CAM_CTX_ACQUIRED;
+		trace_cam_context_state("ICP", ctx);
+	}
 
 	return rc;
 }
@@ -48,6 +51,7 @@
 		pr_err("Unable to release device\n");
 
 	ctx->state = CAM_CTX_AVAILABLE;
+	trace_cam_context_state("ICP", ctx);
 	return rc;
 }
 
@@ -57,8 +61,10 @@
 	int rc;
 
 	rc = cam_context_start_dev_to_hw(ctx, cmd);
-	if (!rc)
+	if (!rc) {
 		ctx->state = CAM_CTX_READY;
+		trace_cam_context_state("ICP", ctx);
+	}
 
 	return rc;
 }
@@ -85,6 +91,7 @@
 		pr_err("Unable to stop device\n");
 
 	ctx->state = CAM_CTX_ACQUIRED;
+	trace_cam_context_state("ICP", ctx);
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index fe719c7..f273a7b 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -416,7 +416,8 @@
 	memset(&out, 0, sizeof(out));
 	alloc.size = SZ_1M;
 	alloc.align = 0;
-	alloc.region = CAM_MEM_MGR_REGION_SHARED;
+	alloc.flags = CAM_MEM_FLAG_HW_READ_WRITE |
+		CAM_MEM_FLAG_HW_SHARED_ACCESS;
 	alloc.smmu_hdl = icp_hw_mgr.iommu_hdl;
 	rc = cam_mem_mgr_request_mem(&alloc, &out);
 	if (rc)
@@ -462,7 +463,7 @@
 	int rc;
 
 	rc = cam_smmu_get_region_info(icp_hw_mgr.iommu_hdl,
-		CAM_MEM_MGR_REGION_SHARED,
+		CAM_SMMU_REGION_SHARED,
 		&icp_hw_mgr.hfi_mem.shmem);
 	if (rc) {
 		pr_err("Unable to get shared memory info\n");
diff --git a/drivers/media/platform/msm/camera/cam_isp/Makefile b/drivers/media/platform/msm/camera/cam_isp/Makefile
index 77ad6fc..4851535 100644
--- a/drivers/media/platform/msm/camera/cam_isp/Makefile
+++ b/drivers/media/platform/msm/camera/cam_isp/Makefile
@@ -1,8 +1,9 @@
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
-ccflags-y += -Idrivers/media/platform/msm/camera/utils
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
 
 obj-$(CONFIG_SPECTRA_CAMERA) += isp_hw_mgr/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp_dev.o cam_isp_context.o
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 83009d2..766ea89 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
@@ -21,10 +21,48 @@
 #include "cam_mem_mgr.h"
 #include "cam_sync_api.h"
 #include "cam_req_mgr_dev.h"
+#include "cam_trace.h"
 
 #undef CDBG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
 
+static uint64_t __cam_isp_ctx_get_event_ts(uint32_t evt_id, void *evt_data)
+{
+	uint64_t ts = 0;
+
+	if (!evt_data)
+		return 0;
+
+	switch (evt_id) {
+	case CAM_ISP_HW_EVENT_ERROR:
+		ts = ((struct cam_isp_hw_error_event_data *)evt_data)->
+			timestamp;
+		break;
+	case CAM_ISP_HW_EVENT_SOF:
+		ts = ((struct cam_isp_hw_sof_event_data *)evt_data)->
+			timestamp;
+		break;
+	case CAM_ISP_HW_EVENT_REG_UPDATE:
+		ts = ((struct cam_isp_hw_reg_update_event_data *)evt_data)->
+			timestamp;
+		break;
+	case CAM_ISP_HW_EVENT_EPOCH:
+		ts = ((struct cam_isp_hw_epoch_event_data *)evt_data)->
+			timestamp;
+		break;
+	case CAM_ISP_HW_EVENT_EOF:
+		ts = ((struct cam_isp_hw_eof_event_data *)evt_data)->
+			timestamp;
+		break;
+	case CAM_ISP_HW_EVENT_DONE:
+		break;
+	default:
+		CDBG("%s: Invalid Event Type %d\n", __func__, evt_id);
+	}
+
+	return ts;
+}
+
 static int __cam_isp_ctx_handle_buf_done_in_activated_state(
 	struct cam_isp_context *ctx_isp,
 	struct cam_isp_hw_done_event_data *done,
@@ -45,6 +83,9 @@
 
 	req = list_first_entry(&ctx->active_req_list,
 			struct cam_ctx_request, list);
+
+	trace_cam_buf_done("ISP", ctx, req);
+
 	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
 	for (i = 0; i < done->num_handles; i++) {
 		for (j = 0; j < req_isp->num_fence_map_out; j++) {
@@ -99,12 +140,39 @@
 	if (req_isp->num_acked == req_isp->num_fence_map_out) {
 		list_del_init(&req->list);
 		list_add_tail(&req->list, &ctx->free_req_list);
+		ctx_isp->active_req_cnt--;
+		CDBG("%s: Move active request %lld to free list(cnt = %d)\n",
+			__func__, req->request_id, ctx_isp->active_req_cnt);
 	}
 
 end:
 	return rc;
 }
 
+static void __cam_isp_ctx_send_sof_timestamp(
+	struct cam_isp_context *ctx_isp, uint64_t request_id,
+	uint32_t sof_event_status)
+{
+	struct cam_req_mgr_message   req_msg;
+
+	req_msg.session_hdl = ctx_isp->base->session_hdl;
+	req_msg.u.frame_msg.frame_id = ctx_isp->frame_id;
+	req_msg.u.frame_msg.request_id = request_id;
+	req_msg.u.frame_msg.timestamp = ctx_isp->sof_timestamp_val;
+	req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl;
+	req_msg.u.frame_msg.sof_status = sof_event_status;
+
+	CDBG("%s: request id:%lld frame number:%lld SOF time stamp:0x%llx\n",
+		__func__, request_id, ctx_isp->frame_id,
+		ctx_isp->sof_timestamp_val);
+	CDBG("%s sof status:%d\n", __func__, sof_event_status);
+
+	if (cam_req_mgr_notify_frame_message(&req_msg,
+		V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT))
+		pr_err("%s: Error in notifying the sof time for req id:%lld\n",
+				__func__, request_id);
+}
+
 static int __cam_isp_ctx_reg_upd_in_activated_state(
 	struct cam_isp_context *ctx_isp, void *evt_data)
 {
@@ -123,12 +191,15 @@
 
 	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
 	if (req_isp->num_fence_map_out != 0) {
-		CDBG("%s: move request %lld to active list\n", __func__,
-			req->request_id);
 		list_add_tail(&req->list, &ctx->active_req_list);
+		ctx_isp->active_req_cnt++;
+		CDBG("%s: move request %lld to active list(cnt = %d)\n",
+			__func__, req->request_id, ctx_isp->active_req_cnt);
 	} else {
 		/* no io config, so the request is completed. */
 		list_add_tail(&req->list, &ctx->free_req_list);
+		CDBG("%s: move active request %lld to free list(cnt = %d)\n",
+			__func__, req->request_id, ctx_isp->active_req_cnt);
 	}
 
 	/*
@@ -145,12 +216,20 @@
 static int __cam_isp_ctx_notify_sof_in_actived_state(
 	struct cam_isp_context *ctx_isp, void *evt_data)
 {
-	int rc = 0;
 	struct cam_req_mgr_sof_notify  notify;
 	struct cam_context *ctx = ctx_isp->base;
+	struct cam_ctx_request  *req;
+	uint64_t  request_id  = 0;
 
-	/* notify reqmgr with sof  signal */
-	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof) {
+	/*
+	 * notify reqmgr with sof signal. Note, due to scheduling delay
+	 * we can run into situation that two active requests has already
+	 * be in the active queue while we try to do the notification.
+	 * In this case, we need to skip the current notification. This
+	 * helps the state machine to catch up the delay.
+	 */
+	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof &&
+		ctx_isp->active_req_cnt <= 2) {
 		notify.link_hdl = ctx->link_hdl;
 		notify.dev_hdl = ctx->dev_hdl;
 		notify.frame_id = ctx_isp->frame_id;
@@ -158,21 +237,40 @@
 		ctx->ctx_crm_intf->notify_sof(&notify);
 		CDBG("%s: Notify CRM  SOF frame %lld\n", __func__,
 			ctx_isp->frame_id);
+
+		list_for_each_entry(req, &ctx->active_req_list, list) {
+			if (req->request_id > ctx_isp->reported_req_id) {
+				request_id = req->request_id;
+				ctx_isp->reported_req_id = request_id;
+				break;
+			}
+		}
+
+		__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+			CAM_REQ_MGR_SOF_EVENT_SUCCESS);
 	} else {
 		pr_err("%s: Can not notify SOF to CRM\n", __func__);
 	}
 
-	return rc;
+	return 0;
 }
 
 
-static int __cam_isp_ctx_sof_in_sof(struct cam_isp_context *ctx_isp,
-	void *evt_data)
+static int __cam_isp_ctx_sof_in_activated_state(
+	struct cam_isp_context *ctx_isp, void *evt_data)
 {
 	int rc = 0;
+	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
 
-	CDBG("%s: Enter\n", __func__);
+	if (!evt_data) {
+		pr_err("%s: in valid sof event data\n", __func__);
+		return -EINVAL;
+	}
+
 	ctx_isp->frame_id++;
+	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	CDBG("%s: frame id: %lld time stamp:0x%llx\n", __func__,
+		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
 
 	return rc;
 }
@@ -199,11 +297,15 @@
 			struct cam_ctx_request, list);
 		list_del_init(&req->list);
 		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
-		if (req_isp->num_fence_map_out == req_isp->num_acked)
+		if (req_isp->num_fence_map_out == req_isp->num_acked) {
 			list_add_tail(&req->list, &ctx->free_req_list);
-		else {
+		} else {
 			/* need to handle the buf done */
 			list_add_tail(&req->list, &ctx->active_req_list);
+			ctx_isp->active_req_cnt++;
+			CDBG("%s: move request %lld to active list(cnt = %d)\n",
+				__func__, req->request_id,
+				ctx_isp->active_req_cnt);
 			ctx_isp->substate_activated =
 				CAM_ISP_CTX_ACTIVATED_EPOCH;
 		}
@@ -215,10 +317,10 @@
 static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
 	void *evt_data)
 {
-	int rc = 0;
 	struct cam_ctx_request    *req;
 	struct cam_isp_ctx_req    *req_isp;
 	struct cam_context        *ctx = ctx_isp->base;
+	uint64_t  request_id = 0;
 
 	if (list_empty(&ctx->pending_req_list)) {
 		/*
@@ -227,6 +329,11 @@
 		 */
 		pr_err("%s: No pending request\n", __func__);
 		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
+
+		/* Send SOF event as empty frame*/
+		__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+			CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+
 		goto end;
 	}
 
@@ -253,14 +360,21 @@
 		 */
 		list_del_init(&req->list);
 		list_add_tail(&req->list, &ctx->active_req_list);
+		ctx_isp->active_req_cnt++;
+		CDBG("%s: move request %lld to active list(cnt = %d)\n",
+			__func__, req->request_id, ctx_isp->active_req_cnt);
 		req_isp->bubble_report = 0;
 	}
 
+	request_id = req->request_id;
+	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+		CAM_REQ_MGR_SOF_EVENT_ERROR);
+
 	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
 	CDBG("%s: next substate %d\n", __func__,
 		ctx_isp->substate_activated);
 end:
-	return rc;
+	return 0;
 }
 
 
@@ -280,14 +394,22 @@
 	void *evt_data)
 {
 	int rc = 0;
-	struct cam_context        *ctx = ctx_isp->base;
+	struct cam_context                    *ctx = ctx_isp->base;
+	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
 
+	if (!evt_data) {
+		pr_err("%s: in valid sof event data\n", __func__);
+		return -EINVAL;
+	}
 
 	ctx_isp->frame_id++;
+	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+
 	if (list_empty(&ctx->active_req_list))
 		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
 	else
 		CDBG("%s: Still need to wait for the buf done\n", __func__);
+
 	CDBG("%s: next substate %d\n", __func__,
 		ctx_isp->substate_activated);
 
@@ -305,14 +427,6 @@
 	return rc;
 }
 
-
-static int __cam_isp_ctx_sof_in_bubble(struct cam_isp_context *ctx_isp,
-	void *evt_data)
-{
-	ctx_isp->frame_id++;
-	return 0;
-}
-
 static int __cam_isp_ctx_buf_done_in_bubble(
 	struct cam_isp_context *ctx_isp, void *evt_data)
 {
@@ -324,20 +438,13 @@
 	return rc;
 }
 
-static int __cam_isp_ctx_sof_in_bubble_applied(
-	struct cam_isp_context *ctx_isp, void *evt_data)
-{
-	ctx_isp->frame_id++;
-	return 0;
-}
-
-
 static int __cam_isp_ctx_epoch_in_bubble_applied(
 	struct cam_isp_context *ctx_isp, void *evt_data)
 {
 	struct cam_ctx_request    *req;
 	struct cam_isp_ctx_req    *req_isp;
 	struct cam_context        *ctx = ctx_isp->base;
+	uint64_t  request_id = 0;
 
 	/*
 	 * This means we missed the reg upd ack. So we need to
@@ -350,6 +457,9 @@
 		 * Just go back to the bubble state.
 		 */
 		pr_err("%s: No pending request.\n", __func__);
+		__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+			CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+
 		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
 		goto end;
 	}
@@ -376,9 +486,16 @@
 		 */
 		list_del_init(&req->list);
 		list_add_tail(&req->list, &ctx->active_req_list);
+		ctx_isp->active_req_cnt++;
+		CDBG("%s: move request %lld to active list(cnt = %d)\n",
+			__func__, req->request_id, ctx_isp->active_req_cnt);
 		req_isp->bubble_report = 0;
 	}
 
+	request_id = req->request_id;
+	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+		CAM_REQ_MGR_SOF_EVENT_ERROR);
+
 	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
 	CDBG("%s: next substate %d\n", __func__, ctx_isp->substate_activated);
 end:
@@ -457,7 +574,7 @@
 	{
 		.irq_ops = {
 			NULL,
-			__cam_isp_ctx_sof_in_sof,
+			__cam_isp_ctx_sof_in_activated_state,
 			__cam_isp_ctx_reg_upd_in_sof,
 			__cam_isp_ctx_notify_sof_in_actived_state,
 			NULL,
@@ -468,7 +585,7 @@
 	{
 		.irq_ops = {
 			__cam_isp_ctx_handle_error,
-			__cam_isp_ctx_sof_in_sof,
+			__cam_isp_ctx_sof_in_activated_state,
 			__cam_isp_ctx_reg_upd_in_activated_state,
 			__cam_isp_ctx_epoch_in_applied,
 			NULL,
@@ -490,7 +607,7 @@
 	{
 		.irq_ops = {
 			NULL,
-			__cam_isp_ctx_sof_in_bubble,
+			__cam_isp_ctx_sof_in_activated_state,
 			NULL,
 			__cam_isp_ctx_notify_sof_in_actived_state,
 			NULL,
@@ -501,7 +618,7 @@
 	{
 		.irq_ops = {
 			NULL,
-			__cam_isp_ctx_sof_in_bubble_applied,
+			__cam_isp_ctx_sof_in_activated_state,
 			__cam_isp_ctx_reg_upd_in_activated_state,
 			__cam_isp_ctx_epoch_in_bubble_applied,
 			NULL,
@@ -518,7 +635,6 @@
 	uint32_t next_state)
 {
 	int rc = 0;
-	int cnt = 0;
 	struct cam_ctx_request          *req;
 	struct cam_isp_ctx_req          *req_isp;
 	struct cam_isp_context          *ctx_isp;
@@ -537,13 +653,12 @@
 	 * The maximum number of request allowed to be outstanding is 2.
 	 *
 	 */
-	list_for_each_entry(req, &ctx->active_req_list, list) {
-		if (++cnt > 2) {
-			pr_err_ratelimited("%s: Apply failed due to congest\n",
-				__func__);
-			rc = -EFAULT;
-			goto end;
-		}
+	ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
+	if (ctx_isp->active_req_cnt >=  2) {
+		CDBG("%s: Reject apply request due to congestion(cnt = %d)\n",
+				__func__, ctx_isp->active_req_cnt);
+		rc = -EFAULT;
+		goto end;
 	}
 
 	req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
@@ -560,7 +675,6 @@
 
 	CDBG("%s: Apply request %lld\n", __func__, req->request_id);
 	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
-	ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
 
 	req_isp->bubble_report = apply->report_if_bubble;
 
@@ -712,6 +826,8 @@
 		ctx->state = CAM_CTX_ACQUIRED;
 	spin_unlock(&ctx->lock);
 
+	trace_cam_context_state("ISP", ctx);
+
 	CDBG("%s: Flush request in ready state. next state %d\n",
 		__func__, ctx->state);
 	return rc;
@@ -786,6 +902,8 @@
 	ctx->link_hdl = 0;
 	ctx->ctx_crm_intf = NULL;
 	ctx_isp->frame_id = 0;
+	ctx_isp->active_req_cnt = 0;
+	ctx_isp->reported_req_id = 0;
 
 	/*
 	 * Ideally, we should never have any active request here.
@@ -803,6 +921,8 @@
 	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, &flush_req);
 
 	ctx->state = CAM_CTX_AVAILABLE;
+
+	trace_cam_context_state("ISP", ctx);
 	CDBG("%s: next state %d\n", __func__, ctx->state);
 	return rc;
 }
@@ -855,7 +975,7 @@
 	CDBG("%s: packet address is 0x%llx\n", __func__, packet_addr);
 	CDBG("%s: packet with length %zu, offset 0x%llx\n", __func__,
 		len, cmd->offset);
-	CDBG("%s: Packet request id 0x%llx\n", __func__,
+	CDBG("%s: Packet request id %lld\n", __func__,
 		packet->header.request_id);
 	CDBG("%s: Packet size 0x%x\n", __func__, packet->header.size);
 	CDBG("%s: packet op %d\n", __func__, packet->header.op_code);
@@ -1011,6 +1131,7 @@
 
 	ctx->state = CAM_CTX_ACQUIRED;
 
+	trace_cam_context_state("ISP", ctx);
 	CDBG("%s:%d: Acquire success.\n", __func__, __LINE__);
 	kfree(isp_res);
 	return rc;
@@ -1032,8 +1153,10 @@
 
 	rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd);
 
-	if (!rc && ctx->link_hdl)
+	if (!rc && ctx->link_hdl) {
 		ctx->state = CAM_CTX_READY;
+		trace_cam_context_state("ISP", ctx);
+	}
 
 	CDBG("%s: next state %d\n", __func__, ctx->state);
 	return rc;
@@ -1050,8 +1173,10 @@
 	ctx->ctx_crm_intf = link->crm_cb;
 
 	/* change state only if we had the init config */
-	if (!list_empty(&ctx->pending_req_list))
+	if (!list_empty(&ctx->pending_req_list)) {
 		ctx->state = CAM_CTX_READY;
+		trace_cam_context_state("ISP", ctx);
+	}
 
 	CDBG("%s: next state %d\n", __func__, ctx->state);
 
@@ -1121,6 +1246,8 @@
 	arg.num_hw_update_entries = req_isp->num_cfg;
 
 	ctx_isp->frame_id = 0;
+	ctx_isp->active_req_cnt = 0;
+	ctx_isp->reported_req_id = 0;
 	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
 
 	/*
@@ -1129,11 +1256,13 @@
 	 * irq handling comes early
 	 */
 	ctx->state = CAM_CTX_ACTIVATED;
+	trace_cam_context_state("ISP", ctx);
 	rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &arg);
 	if (rc) {
 		/* HW failure. user need to clean up the resource */
 		pr_err("Start HW failed\n");
 		ctx->state = CAM_CTX_READY;
+		trace_cam_context_state("ISP", ctx);
 		goto end;
 	}
 	CDBG("%s: start device success\n", __func__);
@@ -1149,6 +1278,7 @@
 	ctx->link_hdl = 0;
 	ctx->ctx_crm_intf = NULL;
 	ctx->state = CAM_CTX_ACQUIRED;
+	trace_cam_context_state("ISP", ctx);
 
 	return rc;
 }
@@ -1209,6 +1339,8 @@
 		list_add_tail(&req->list, &ctx->free_req_list);
 	}
 	ctx_isp->frame_id = 0;
+	ctx_isp->active_req_cnt = 0;
+	ctx_isp->reported_req_id = 0;
 
 	CDBG("%s: next state %d", __func__, ctx->state);
 	return rc;
@@ -1221,6 +1353,7 @@
 
 	__cam_isp_ctx_stop_dev_in_activated_unlock(ctx);
 	ctx->state = CAM_CTX_ACQUIRED;
+	trace_cam_context_state("ISP", ctx);
 	return rc;
 }
 
@@ -1248,6 +1381,7 @@
 	ctx->ctx_crm_intf = NULL;
 
 	ctx->state =  CAM_CTX_AVAILABLE;
+	trace_cam_context_state("ISP", ctx);
 
 	return rc;
 }
@@ -1259,8 +1393,9 @@
 	struct cam_isp_context *ctx_isp =
 		(struct cam_isp_context *) ctx->ctx_priv;
 
-	CDBG("%s: Enter: apply req in Substate %d\n",
-		__func__, ctx_isp->substate_activated);
+	trace_cam_apply_req("ISP", apply);
+	CDBG("%s: Enter: apply req in Substate %d request _id:%lld\n",
+		__func__, ctx_isp->substate_activated, apply->request_id);
 	if (ctx_isp->substate_machine[ctx_isp->substate_activated].
 		crm_ops.apply_req) {
 		rc = ctx_isp->substate_machine[ctx_isp->substate_activated].
@@ -1288,6 +1423,10 @@
 		(struct cam_isp_context *)ctx->ctx_priv;
 
 	spin_lock_bh(&ctx->lock);
+
+	trace_cam_isp_activated_irq(ctx, ctx_isp->substate_activated, evt_id,
+		__cam_isp_ctx_get_event_ts(evt_id, evt_data));
+
 	CDBG("%s: Enter: State %d, Substate %d, evt id %d\n",
 		__func__, ctx->state, ctx_isp->substate_activated, evt_id);
 	if (ctx_isp->substate_machine_irq[ctx_isp->substate_activated].
@@ -1383,6 +1522,8 @@
 
 	ctx->base = ctx_base;
 	ctx->frame_id = 0;
+	ctx->active_req_cnt = 0;
+	ctx->reported_req_id = 0;
 	ctx->hw_ctx = NULL;
 	ctx->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
 	ctx->substate_machine = cam_isp_ctx_activated_state_machine;
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
index dae1dda..b0b883c 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
@@ -106,7 +106,9 @@
  * @req_base:              Common request object storage
  * @req_isp:               ISP private request object storage
  * @hw_ctx:                HW object returned by the acquire device command
- *
+ * @sof_timestamp_val:     Captured time stamp value at sof hw event
+ * @active_req_cnt:        Counter for the active request
+ * @reported_req_id:       Last reported request id
  */
 struct cam_isp_context {
 	struct cam_context              *base;
@@ -120,6 +122,9 @@
 	struct cam_isp_ctx_req           req_isp[CAM_CTX_REQ_MAX];
 
 	void                            *hw_ctx;
+	uint64_t                         sof_timestamp_val;
+	int32_t                          active_req_cnt;
+	int64_t                          reported_req_id;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/Makefile b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/Makefile
index 2c6eaba..7e3c353 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/Makefile
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/Makefile
@@ -7,6 +7,7 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 
 obj-$(CONFIG_SPECTRA_CAMERA) += hw_utils/ isp_hw/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp_hw_mgr.o cam_ife_hw_mgr.o
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 2bc4b00..cb38d8f 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
@@ -489,6 +489,7 @@
 			continue;
 
 		vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops;
+		vfe_acquire.vfe_out.ctx = ife_ctx;
 		vfe_acquire.vfe_out.out_port_info = out_port;
 		vfe_acquire.vfe_out.split_id = CAM_ISP_HW_SPLIT_LEFT;
 		vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index;
@@ -552,6 +553,7 @@
 		vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_OUT;
 		vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
 		vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops;
+		vfe_acquire.vfe_out.ctx = ife_ctx;
 		vfe_acquire.vfe_out.out_port_info =  out_port;
 		vfe_acquire.vfe_out.is_dual       = ife_src_res->is_dual_vfe;
 		vfe_acquire.vfe_out.unique_id     = ife_ctx->ctx_index;
@@ -1334,7 +1336,7 @@
 		return -EPERM;
 	}
 
-	CDBG("%s%d: Enter...ctx id:%d\n", __func__, __LINE__, ctx->ctx_index);
+	CDBG("%s:%d Enter ctx id:%d\n", __func__, __LINE__, ctx->ctx_index);
 
 	if (cfg->num_hw_update_entries > 0) {
 		cdm_cmd = ctx->cdm_cmd;
@@ -1980,6 +1982,57 @@
 	return rc;
 }
 
+static int cam_ife_mgr_cmd_get_sof_timestamp(
+	struct cam_ife_hw_mgr_ctx      *ife_ctx,
+	uint64_t                       *time_stamp)
+{
+	int rc = -EINVAL;
+	uint32_t i;
+	struct cam_ife_hw_mgr_res            *hw_mgr_res;
+	struct cam_hw_intf                   *hw_intf;
+	struct cam_csid_get_time_stamp_args   csid_get_time;
+
+	list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_csid, list) {
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (!hw_mgr_res->hw_res[i] ||
+				(i == CAM_ISP_HW_SPLIT_RIGHT))
+				continue;
+			/*
+			 * Get the SOF time stamp from left resource only.
+			 * Left resource is master for dual vfe case and
+			 * Rdi only context case left resource only hold
+			 * the RDI resource
+			 */
+			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+			if (hw_intf->hw_ops.process_cmd) {
+				csid_get_time.node_res =
+					hw_mgr_res->hw_res[i];
+				rc = hw_intf->hw_ops.process_cmd(
+					hw_intf->hw_priv,
+					CAM_IFE_CSID_CMD_GET_TIME_STAMP,
+					&csid_get_time,
+					sizeof(
+					struct cam_csid_get_time_stamp_args));
+				if (!rc)
+					*time_stamp =
+						csid_get_time.time_stamp_val;
+			/*
+			 * Single VFE case, Get the time stamp from available
+			 * one csid hw in the context
+			 * Dual VFE case, get the time stamp from master(left)
+			 * would be sufficient
+			 */
+				goto end;
+			}
+		}
+	}
+end:
+	if (rc)
+		pr_err("%s:error in getting sof time stamp\n", __func__);
+
+	return rc;
+}
+
 static int cam_ife_mgr_process_recovery_cb(void *priv, void *data)
 {
 	int32_t rc = 0;
@@ -2326,7 +2379,9 @@
 
 	}
 
-	CDBG("%s: Exit (rup_status = %d)!\n", __func__, rup_status);
+	if (!rup_status)
+		CDBG("%s: Exit rup_status = %d\n", __func__, rup_status);
+
 	return 0;
 }
 
@@ -2470,7 +2525,9 @@
 		}
 	}
 
-	CDBG("%s: Exit (epoch_status = %d)!\n", __func__, epoch_status);
+	if (!epoch_status)
+		CDBG("%s: Exit epoch_status = %d\n", __func__, epoch_status);
+
 	return 0;
 }
 
@@ -2566,11 +2623,16 @@
 			if (core_idx == hw_res_l->hw_intf->hw_idx) {
 				sof_status = hw_res_l->bottom_half_handler(
 					hw_res_l, evt_payload);
-				if (!sof_status)
+				if (!sof_status) {
+					cam_ife_mgr_cmd_get_sof_timestamp(
+						ife_hwr_mgr_ctx,
+						&sof_done_event_data.timestamp);
+
 					ife_hwr_irq_sof_cb(
 						ife_hwr_mgr_ctx->common.cb_priv,
 						CAM_ISP_HW_EVENT_SOF,
 						&sof_done_event_data);
+				}
 			}
 
 			break;
@@ -2617,12 +2679,16 @@
 			rc = cam_ife_hw_mgr_check_sof_for_dual_vfe(
 				ife_hwr_mgr_ctx, core_index0, core_index1);
 
-			if (!rc)
+			if (!rc) {
+				cam_ife_mgr_cmd_get_sof_timestamp(
+					ife_hwr_mgr_ctx,
+					&sof_done_event_data.timestamp);
+
 				ife_hwr_irq_sof_cb(
 					ife_hwr_mgr_ctx->common.cb_priv,
 					CAM_ISP_HW_EVENT_SOF,
 					&sof_done_event_data);
-
+			}
 			break;
 
 		default:
@@ -2640,11 +2706,11 @@
 
 {
 	int32_t                              buf_done_status = 0;
-	int32_t                              i = 0;
+	int32_t                              i;
 	int32_t                              rc = 0;
 	cam_hw_event_cb_func                 ife_hwr_irq_wm_done_cb;
 	struct cam_isp_resource_node        *hw_res_l = NULL;
-	struct cam_ife_hw_mgr_ctx           *ife_hwr_mgr_ctx = handler_priv;
+	struct cam_ife_hw_mgr_ctx           *ife_hwr_mgr_ctx = NULL;
 	struct cam_vfe_bus_irq_evt_payload  *evt_payload = payload;
 	struct cam_ife_hw_mgr_res           *isp_ife_out_res = NULL;
 	struct cam_hw_event_recovery_data    recovery_data;
@@ -2655,6 +2721,7 @@
 
 	CDBG("%s:Enter\n", __func__);
 
+	ife_hwr_mgr_ctx = evt_payload->ctx;
 	ife_hwr_irq_wm_done_cb =
 		ife_hwr_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_DONE];
 
@@ -2734,13 +2801,11 @@
 			}
 			break;
 		}
-		CDBG("%s:buf_done status:(%d),isp_ife_out_res->res_id : 0x%x\n",
-			__func__, buf_done_status, isp_ife_out_res->res_id);
+		if (!buf_done_status)
+			CDBG("buf_done status:(%d),out_res->res_id: 0x%x\n",
+			buf_done_status, isp_ife_out_res->res_id);
 	}
 
-
-	CDBG("%s: Exit (buf_done_status (Success) = %d)!\n", __func__,
-			buf_done_status);
 	return rc;
 
 err:
@@ -2775,7 +2840,7 @@
 		return rc;
 
 	evt_payload = evt_payload_priv;
-	ife_hwr_mgr_ctx = (struct cam_ife_hw_mgr_ctx *)handler_priv;
+	ife_hwr_mgr_ctx = (struct cam_ife_hw_mgr_ctx *)evt_payload->ctx;
 
 	CDBG("addr of evt_payload = %llx\n", (uint64_t)evt_payload);
 	CDBG("bus_irq_status_0: = %x\n", evt_payload->irq_reg_val[0]);
@@ -2786,19 +2851,6 @@
 	CDBG("bus_irq_dual_comp_err: = %x\n", evt_payload->irq_reg_val[5]);
 	CDBG("bus_irq_dual_comp_owrt: = %x\n", evt_payload->irq_reg_val[6]);
 
-	/*
-	 * If overflow/overwrite/error/violation are pending
-	 * for this context it needs to be handled remaining
-	 * interrupts are ignored.
-	 */
-	rc = cam_ife_hw_mgr_handle_camif_error(ife_hwr_mgr_ctx,
-		evt_payload_priv);
-	if (rc) {
-		pr_err("%s: Encountered Error (%d), ignoring other irqs\n",
-			__func__, rc);
-		return IRQ_HANDLED;
-	}
-
 	CDBG("%s: Calling Buf_done\n", __func__);
 	/* WM Done */
 	return cam_ife_hw_mgr_handle_buf_done_for_hw_res(ife_hwr_mgr_ctx,
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/Makefile b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/Makefile
index 19da180..b60e7de 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/Makefile
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/Makefile
@@ -6,6 +6,7 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_tasklet_util.o cam_isp_packet_parser.o
 obj-$(CONFIG_SPECTRA_CAMERA) += irq_controller/
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
index bf4d174..9a42b6e 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
@@ -271,14 +271,6 @@
 		return -EINVAL;
 	}
 
-	if (sizeof(evt_bit_mask_arr) !=
-		sizeof(uint32_t) * controller->num_registers) {
-		pr_err("Invalid evt_mask size = %lu expected = %lu\n",
-			sizeof(evt_bit_mask_arr),
-			sizeof(uint32_t) * controller->num_registers);
-		return -EINVAL;
-	}
-
 	evt_handler = kzalloc(sizeof(struct cam_irq_evt_handler), GFP_KERNEL);
 	if (!evt_handler) {
 		CDBG("Error allocating hlist_node\n");
@@ -306,6 +298,8 @@
 	evt_handler->bottom_half              = bottom_half;
 	evt_handler->bottom_half_enqueue_func = bottom_half_enqueue_func;
 	evt_handler->index                    = controller->hdl_idx++;
+
+	/* Avoid rollover to negative values */
 	if (controller->hdl_idx > 0x3FFFFFFF)
 		controller->hdl_idx = 1;
 
@@ -468,7 +462,8 @@
 				(void *)th_payload);
 
 		if (!rc && evt_handler->bottom_half_handler) {
-			CDBG("Enqueuing bottom half\n");
+			CDBG("Enqueuing bottom half for %s\n",
+				controller->name);
 			if (evt_handler->bottom_half_enqueue_func) {
 				evt_handler->bottom_half_enqueue_func(
 					evt_handler->bottom_half,
@@ -492,6 +487,8 @@
 	if (!controller)
 		return IRQ_NONE;
 
+	CDBG("locking controller %pK name %s rw_lock %pK\n",
+		controller, controller->name, &controller->rw_lock);
 	read_lock(&controller->rw_lock);
 	for (i = 0; i < controller->num_registers; i++) {
 		controller->irq_status_arr[i] = cam_io_r_mb(
@@ -500,7 +497,8 @@
 		cam_io_w_mb(controller->irq_status_arr[i],
 			controller->mem_base +
 			controller->irq_register_arr[i].clear_reg_offset);
-		CDBG("Read irq status%d = 0x%x\n", i,
+		CDBG("Read irq status%d (0x%x) = 0x%x\n", i,
+			controller->irq_register_arr[i].status_reg_offset,
 			controller->irq_status_arr[i]);
 		for (j = 0; j < CAM_IRQ_PRIORITY_MAX; j++) {
 			if (controller->irq_register_arr[i].
@@ -512,6 +510,8 @@
 		}
 	}
 	read_unlock(&controller->rw_lock);
+	CDBG("unlocked controller %pK name %s rw_lock %pK\n",
+		controller, controller->name, &controller->rw_lock);
 
 	CDBG("Status Registers read Successful\n");
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
index 9f2204b4..b32bdb2 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
@@ -50,32 +50,32 @@
 /**
  * struct cam_isp_hw_sof_event_data - Event payload for CAM_HW_EVENT_SOF
  *
- * @timestamp:             Timestamp for the buf done event
+ * @timestamp:     Time stamp for the sof event
  *
  */
 struct cam_isp_hw_sof_event_data {
-	struct timeval       timestamp;
+	uint64_t       timestamp;
 };
 
 /**
  * struct cam_isp_hw_reg_update_event_data - Event payload for
  *                         CAM_HW_EVENT_REG_UPDATE
  *
- * @timestamp:             Timestamp for the buf done event
+ * @timestamp:     Time stamp for the reg update event
  *
  */
 struct cam_isp_hw_reg_update_event_data {
-	struct timeval       timestamp;
+	uint64_t       timestamp;
 };
 
 /**
  * struct cam_isp_hw_epoch_event_data - Event payload for CAM_HW_EVENT_EPOCH
  *
- * @timestamp:             Timestamp for the buf done event
+ * @timestamp:     Time stamp for the epoch event
  *
  */
 struct cam_isp_hw_epoch_event_data {
-	struct timeval       timestamp;
+	uint64_t       timestamp;
 };
 
 /**
@@ -90,29 +90,29 @@
 	uint32_t             num_handles;
 	uint32_t             resource_handle[
 				CAM_NUM_OUT_PER_COMP_IRQ_MAX];
-	struct timeval       timestamp;
+	uint64_t       timestamp;
 };
 
 /**
  * struct cam_isp_hw_eof_event_data - Event payload for CAM_HW_EVENT_EOF
  *
- * @timestamp:             Timestamp for the buf done event
+ * @timestamp:             Timestamp for the eof event
  *
  */
 struct cam_isp_hw_eof_event_data {
-	struct timeval       timestamp;
+	uint64_t       timestamp;
 };
 
 /**
  * struct cam_isp_hw_error_event_data - Event payload for CAM_HW_EVENT_ERROR
  *
- * @error_type:            error type for the error event
- * @timestamp:             Timestamp for the buf done event
+ * @error_type:            Error type for the error event
+ * @timestamp:             Timestamp for the error event
  *
  */
 struct cam_isp_hw_error_event_data {
 	uint32_t             error_type;
-	struct timeval       timestamp;
+	uint64_t             timestamp;
 };
 
 /**
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 f09fdc7..e779aef 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
@@ -1033,7 +1033,7 @@
 	val = (csid_hw->csi2_rx_cfg.lane_num - 1)  |
 		(csid_hw->csi2_rx_cfg.lane_cfg << 4) |
 		(csid_hw->csi2_rx_cfg.lane_type << 24);
-	val |= csid_hw->csi2_rx_cfg.phy_sel & 0x3;
+	val |= (csid_hw->csi2_rx_cfg.phy_sel & 0x3) << 20;
 	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
 		csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr);
 
@@ -1150,6 +1150,10 @@
 	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
 		csid_reg->ipp_reg->csid_ipp_cfg0_addr);
 
+	/* select the post irq sub sample strobe for time stamp capture */
+	cam_io_w_mb(CSID_TIMESTAMP_STB_POST_IRQ, soc_info->reg_map[0].mem_base +
+		csid_reg->ipp_reg->csid_ipp_cfg1_addr);
+
 	if (path_data->crop_enable) {
 		val = ((path_data->width +
 			path_data->start_pixel) & 0xFFFF <<
@@ -1435,6 +1439,10 @@
 	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
 			csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);
 
+	/* select the post irq sub sample strobe for time stamp capture */
+	cam_io_w_mb(CSID_TIMESTAMP_STB_POST_IRQ, soc_info->reg_map[0].mem_base +
+			csid_reg->rdi_reg[id]->csid_rdi_cfg1_addr);
+
 	if (path_data->crop_enable) {
 		val = ((path_data->width +
 			path_data->start_pixel) & 0xFFFF <<
@@ -2220,7 +2228,6 @@
 	csid_hw_info = (struct cam_hw_info  *)hw_priv;
 	csid_hw = (struct cam_ife_csid_hw   *)csid_hw_info->core_info;
 
-	mutex_lock(&csid_hw->hw_info->hw_mutex);
 	switch (cmd_type) {
 	case CAM_IFE_CSID_CMD_GET_TIME_STAMP:
 		rc = cam_ife_csid_get_time_stamp(csid_hw, cmd_args);
@@ -2231,7 +2238,6 @@
 		rc = -EINVAL;
 		break;
 	}
-	mutex_unlock(&csid_hw->hw_info->hw_mutex);
 
 	return rc;
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
index d36c576..60e184b 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
@@ -65,6 +65,7 @@
 #define CSID_PATH_ERROR_PIX_COUNT                 BIT(13)
 #define CSID_PATH_ERROR_LINE_COUNT                BIT(14)
 
+/* enum cam_csid_path_halt_mode select the path halt mode control */
 enum cam_csid_path_halt_mode {
 	CSID_HALT_MODE_INTERNAL,
 	CSID_HALT_MODE_GLOBAL,
@@ -72,6 +73,16 @@
 	CSID_HALT_MODE_SLAVE,
 };
 
+/**
+ *enum cam_csid_path_timestamp_stb_sel - select the sof/eof strobes used to
+ *        capture the timestamp
+ */
+enum cam_csid_path_timestamp_stb_sel {
+	CSID_TIMESTAMP_STB_PRE_HALT,
+	CSID_TIMESTAMP_STB_POST_HALT,
+	CSID_TIMESTAMP_STB_POST_IRQ,
+	CSID_TIMESTAMP_STB_MAX,
+};
 
 struct cam_ife_csid_ipp_reg_offset {
 	/*Image pixel path register offsets*/
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
index 15db6a6..418280a 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
@@ -108,6 +108,7 @@
  *                           (Default is Master in case of Single VFE)
  * @dual_slave_core:         If Master and Slave exists, HW Index of Slave
  * @cdm_ops:                 CDM operations
+ * @ctx:                     Context data
  */
 struct cam_vfe_hw_vfe_out_acquire_args {
 	struct cam_isp_resource_node      *rsrc_node;
@@ -118,6 +119,7 @@
 	uint32_t                           is_master;
 	uint32_t                           dual_slave_core;
 	struct cam_cdm_utils_ops          *cdm_ops;
+	void                              *ctx;
 };
 
 /*
@@ -192,22 +194,21 @@
  *
  * @list:                    list_head node for the payload
  * @core_index:              Index of VFE HW that generated this IRQ event
- * @core_info:               Private data of handler in bottom half context
  * @evt_id:                  IRQ event
  * @irq_reg_val:             IRQ and Error register values, read when IRQ was
  *                           handled
  * @error_type:              Identify different errors
  * @ts:                      Timestamp
+ * @ctx:                     Context data received during acquire
  */
 struct cam_vfe_bus_irq_evt_payload {
-	struct list_head             list;
-	uint32_t                     core_index;
-	void                        *core_info;
-	uint32_t                     evt_id;
-	uint32_t                     irq_reg_val[CAM_IFE_BUS_IRQ_REGISTERS_MAX];
-	uint32_t                     error_type;
-	struct cam_vfe_bus_ver2_priv *bus_priv;
-	struct cam_isp_timestamp     ts;
+	struct list_head            list;
+	uint32_t                    core_index;
+	uint32_t                    evt_id;
+	uint32_t                    irq_reg_val[CAM_IFE_BUS_IRQ_REGISTERS_MAX];
+	uint32_t                    error_type;
+	struct cam_isp_timestamp    ts;
+	void                       *ctx;
 };
 
 /*
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index f6aab7f..e25d973 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
@@ -51,11 +51,6 @@
 	0x00000000,
 };
 
-static uint32_t bus_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
-	0x00000200,
-	0x00000000,
-};
-
 static int cam_vfe_get_evt_payload(struct cam_vfe_hw_core_info *core_info,
 	struct cam_vfe_top_irq_evt_payload    **evt_payload)
 {
@@ -188,15 +183,25 @@
 
 	CDBG("Enable soc done\n");
 
+	rc = core_info->vfe_bus->hw_ops.init(core_info->vfe_bus->bus_priv,
+		NULL, 0);
+	if (rc) {
+		pr_err("Bus HW init Failed rc=%d\n", rc);
+		goto disable_soc;
+	}
+
 	/* Do HW Reset */
 	rc = cam_vfe_reset(hw_priv, NULL, 0);
 	if (rc) {
-		pr_err("Reset Failed\n");
-		goto disable_soc;
+		pr_err("Reset Failed rc=%d\n", rc);
+		goto deinit_bus;
 	}
 
 	return 0;
 
+deinit_bus:
+	core_info->vfe_bus->hw_ops.deinit(core_info->vfe_bus->bus_priv,
+		NULL, 0);
 disable_soc:
 	cam_vfe_disable_soc_resources(soc_info);
 decrement_open_cnt:
@@ -382,10 +387,11 @@
 		rc = core_info->vfe_top->hw_ops.reserve(
 			core_info->vfe_top->top_priv,
 			acquire,
-			sizeof(acquire));
+			sizeof(*acquire));
 	else if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_OUT)
-		rc = core_info->vfe_bus->acquire_resource(
-			core_info->vfe_bus->bus_priv, acquire);
+		rc = core_info->vfe_bus->hw_ops.reserve(
+			core_info->vfe_bus->bus_priv, acquire,
+			sizeof(*acquire));
 	else
 		pr_err("Invalid res type:%d\n", acquire->rsrc_type);
 
@@ -415,10 +421,11 @@
 	if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_IN)
 		rc = core_info->vfe_top->hw_ops.release(
 			core_info->vfe_top->top_priv, isp_res,
-			sizeof(struct cam_isp_resource_node));
+			sizeof(*isp_res));
 	else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT)
-		rc = core_info->vfe_bus->release_resource(
-			core_info->vfe_bus->bus_priv, isp_res);
+		rc = core_info->vfe_bus->hw_ops.release(
+			core_info->vfe_bus->bus_priv, isp_res,
+			sizeof(*isp_res));
 	else
 		pr_err("Invalid res type:%d\n", isp_res->res_type);
 
@@ -468,16 +475,7 @@
 		else
 			pr_err("Error! subscribe irq controller failed\n");
 	} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
-		isp_res->irq_handle = cam_irq_controller_subscribe_irq(
-			core_info->vfe_irq_controller, CAM_IRQ_PRIORITY_2,
-			bus_irq_reg_mask, &core_info->irq_payload,
-			core_info->vfe_bus->top_half_handler,
-			cam_ife_mgr_do_tasklet_buf_done,
-			isp_res->tasklet_info, cam_tasklet_enqueue_cmd);
-		if (isp_res->irq_handle > 0)
-			rc = core_info->vfe_bus->start_resource(isp_res);
-		else
-			pr_err("Error! subscribe irq controller failed\n");
+		rc = core_info->vfe_bus->hw_ops.start(isp_res, NULL, 0);
 	} else {
 		pr_err("Invalid res type:%d\n", isp_res->res_type);
 	}
@@ -513,7 +511,7 @@
 	} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
 		cam_irq_controller_unsubscribe_irq(
 			core_info->vfe_irq_controller, isp_res->irq_handle);
-		rc = core_info->vfe_bus->stop_resource(isp_res);
+		rc = core_info->vfe_bus->hw_ops.stop(isp_res, NULL, 0);
 	} else {
 		pr_err("Invalid res type:%d\n", isp_res->res_type);
 	}
@@ -560,7 +558,7 @@
 
 		break;
 	case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
-		rc = core_info->vfe_bus->process_cmd(
+		rc = core_info->vfe_bus->hw_ops.process_cmd(
 			core_info->vfe_bus->bus_priv, cmd_type, cmd_args,
 			arg_size);
 		break;
@@ -611,15 +609,15 @@
 		&core_info->vfe_top);
 	if (rc) {
 		pr_err("Error! cam_vfe_top_init failed\n");
-		return rc;
+		goto deinit_controller;
 	}
 
-	rc = cam_vfe_bus_init(vfe_hw_info->bus_version,
-		soc_info->reg_map[0].mem_base, hw_intf,
-		vfe_hw_info->bus_hw_info, NULL, &core_info->vfe_bus);
+	rc = cam_vfe_bus_init(vfe_hw_info->bus_version, soc_info, hw_intf,
+		vfe_hw_info->bus_hw_info, core_info->vfe_irq_controller,
+		&core_info->vfe_bus);
 	if (rc) {
 		pr_err("Error! cam_vfe_bus_init failed\n");
-		return rc;
+		goto deinit_top;
 	}
 
 	INIT_LIST_HEAD(&core_info->free_payload_list);
@@ -632,4 +630,46 @@
 	spin_lock_init(&core_info->spin_lock);
 
 	return rc;
+
+deinit_top:
+	cam_vfe_top_deinit(vfe_hw_info->top_version,
+		&core_info->vfe_top);
+
+deinit_controller:
+	cam_irq_controller_deinit(&core_info->vfe_irq_controller);
+
+	return rc;
 }
+
+int cam_vfe_core_deinit(struct cam_vfe_hw_core_info  *core_info,
+	struct cam_vfe_hw_info                       *vfe_hw_info)
+{
+	int                rc = -EINVAL;
+	int                i;
+	unsigned long      flags;
+
+	spin_lock_irqsave(&core_info->spin_lock, flags);
+
+	INIT_LIST_HEAD(&core_info->free_payload_list);
+	for (i = 0; i < CAM_VFE_EVT_MAX; i++)
+		INIT_LIST_HEAD(&core_info->evt_payload[i].list);
+
+	rc = cam_vfe_bus_deinit(vfe_hw_info->bus_version,
+		&core_info->vfe_bus);
+	if (rc)
+		pr_err("Error cam_vfe_bus_deinit failed rc=%d\n", rc);
+
+	rc = cam_vfe_top_deinit(vfe_hw_info->top_version,
+		&core_info->vfe_top);
+	if (rc)
+		pr_err("Error cam_vfe_top_deinit failed rc=%d\n", rc);
+
+	rc = cam_irq_controller_deinit(&core_info->vfe_irq_controller);
+	if (rc)
+		pr_err("Error cam_irq_controller_deinit failed rc=%d\n", rc);
+
+	spin_unlock_irqrestore(&core_info->spin_lock, flags);
+
+	return rc;
+}
+
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
index 94b4cf0..ee29e1cf 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
@@ -89,4 +89,7 @@
 	struct cam_hw_intf                 *hw_intf,
 	struct cam_vfe_hw_info             *vfe_hw_info);
 
+int cam_vfe_core_deinit(struct cam_vfe_hw_core_info *core_info,
+	struct cam_vfe_hw_info             *vfe_hw_info);
+
 #endif /* _CAM_VFE_CORE_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c
index 40279ae..cdb8d6f 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c
@@ -88,14 +88,14 @@
 	rc = cam_vfe_init_soc_resources(&vfe_hw->soc_info, cam_vfe_irq,
 		vfe_hw);
 	if (rc < 0) {
-		pr_err("Failed to init soc\n");
+		pr_err("Failed to init soc rc=%d\n", rc);
 		goto free_core_info;
 	}
 
 	rc = cam_vfe_core_init(core_info, &vfe_hw->soc_info,
 		vfe_hw_intf, hw_info);
 	if (rc < 0) {
-		pr_err("Failed to init core\n");
+		pr_err("Failed to init core rc=%d\n", rc);
 		goto deinit_soc;
 	}
 
@@ -115,6 +115,8 @@
 	return rc;
 
 deinit_soc:
+	if (cam_vfe_deinit_soc_resources(&vfe_hw->soc_info))
+		pr_err("Failed to deinit soc\n");
 free_core_info:
 	kfree(vfe_hw->core_info);
 free_vfe_hw:
@@ -125,6 +127,60 @@
 	return rc;
 }
 
+int cam_vfe_remove(struct platform_device *pdev)
+{
+	struct cam_hw_info                *vfe_hw = NULL;
+	struct cam_hw_intf                *vfe_hw_intf = NULL;
+	struct cam_vfe_hw_core_info       *core_info = NULL;
+	int                                rc = 0;
+
+	vfe_hw_intf = platform_get_drvdata(pdev);
+	if (!vfe_hw_intf) {
+		pr_err("Error! No data in pdev\n");
+		return -EINVAL;
+	}
+
+	CDBG("type %d index %d\n", vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx);
+
+	if (vfe_hw_intf->hw_idx < CAM_VFE_HW_NUM_MAX)
+		cam_vfe_hw_list[vfe_hw_intf->hw_idx] = NULL;
+
+	vfe_hw = vfe_hw_intf->hw_priv;
+	if (!vfe_hw) {
+		pr_err("Error! HW data is NULL\n");
+		rc = -ENODEV;
+		goto free_vfe_hw_intf;
+	}
+
+	core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info;
+	if (!core_info) {
+		pr_err("Error! core data NULL");
+		rc = -EINVAL;
+		goto deinit_soc;
+	}
+
+	rc = cam_vfe_core_deinit(core_info, core_info->vfe_hw_info);
+	if (rc < 0)
+		pr_err("Failed to deinit core rc=%d\n", rc);
+
+	kfree(vfe_hw->core_info);
+
+deinit_soc:
+	rc = cam_vfe_deinit_soc_resources(&vfe_hw->soc_info);
+	if (rc < 0)
+		pr_err("Failed to deinit soc rc=%d\n", rc);
+
+	mutex_destroy(&vfe_hw->hw_mutex);
+	kfree(vfe_hw);
+
+	CDBG("VFE%d remove successful\n", vfe_hw_intf->hw_idx);
+
+free_vfe_hw_intf:
+	kfree(vfe_hw_intf);
+
+	return rc;
+}
+
 int cam_vfe_hw_init(struct cam_hw_intf **vfe_hw, uint32_t hw_idx)
 {
 	int rc = 0;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.h
index ca54d81..9e73528 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.h
@@ -27,4 +27,16 @@
  */
 int cam_vfe_probe(struct platform_device *pdev);
 
+/*
+ * cam_vfe_remove()
+ *
+ * @brief:                   Driver remove function
+ *
+ * @pdev:                    Platform Device pointer
+ *
+ * @Return:                  0: Success
+ *                           Non-zero: Failure
+ */
+int cam_vfe_remove(struct platform_device *pdev);
+
 #endif /* _CAM_VFE_DEV_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
index 9f8f8c5..fa9d86b 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
@@ -25,7 +25,7 @@
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc) {
-		pr_err("Error! get DT properties failed\n");
+		pr_err("Error! get DT properties failed rc=%d\n", rc);
 		return rc;
 	}
 
@@ -40,6 +40,19 @@
 
 	rc = cam_soc_util_request_platform_resource(soc_info, vfe_irq_handler,
 		irq_data);
+	if (rc)
+		pr_err("Error! Request platform resource failed rc=%d\n", rc);
+
+	return rc;
+}
+
+static int cam_vfe_release_platform_resource(struct cam_hw_soc_info *soc_info)
+{
+	int rc = 0;
+
+	rc = cam_soc_util_release_platform_resource(soc_info);
+	if (rc)
+		pr_err("Error! Release platform resource failed rc=%d\n", rc);
 
 	return rc;
 }
@@ -61,14 +74,14 @@
 
 	rc = cam_vfe_get_dt_properties(soc_info);
 	if (rc < 0) {
-		pr_err("Error! Get DT properties failed\n");
+		pr_err("Error! Get DT properties failed rc=%d\n", rc);
 		goto free_soc_private;
 	}
 
 	rc = cam_vfe_request_platform_resource(soc_info, vfe_irq_handler,
 		irq_data);
 	if (rc < 0) {
-		pr_err("Error! Request platform resources failed\n");
+		pr_err("Error! Request platform resources failed rc=%d\n", rc);
 		goto free_soc_private;
 	}
 
@@ -79,7 +92,7 @@
 	cpas_register_param.dev = &soc_info->pdev->dev;
 	rc = cam_cpas_register_client(&cpas_register_param);
 	if (rc) {
-		pr_err("CPAS registration failed\n");
+		pr_err("CPAS registration failed rc=%d\n", rc);
 		goto release_soc;
 	} else {
 		soc_private->cpas_handle = cpas_register_param.client_handle;
@@ -95,6 +108,35 @@
 	return rc;
 }
 
+int cam_vfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info)
+{
+	int                               rc = 0;
+	struct cam_vfe_soc_private       *soc_private;
+
+	if (!soc_info) {
+		pr_err("Error! soc_info NULL\n");
+		return -ENODEV;
+	}
+
+	soc_private = soc_info->soc_private;
+	if (!soc_private) {
+		pr_err("Error! soc_private NULL\n");
+		return -ENODEV;
+	}
+
+	rc = cam_cpas_unregister_client(soc_private->cpas_handle);
+	if (rc)
+		pr_err("CPAS unregistration failed rc=%d\n", rc);
+
+	rc = cam_vfe_release_platform_resource(soc_info);
+	if (rc < 0)
+		pr_err("Error! Release platform resources failed rc=%d\n", rc);
+
+	kfree(soc_private);
+
+	return rc;
+}
+
 int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
 {
 	int                               rc = 0;
@@ -117,7 +159,7 @@
 
 	rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
 	if (rc) {
-		pr_err("Error! CPAS start failed.\n");
+		pr_err("Error! CPAS start failed rc=%d\n", rc);
 		rc = -EFAULT;
 		goto end;
 	}
@@ -125,7 +167,7 @@
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
 		CAM_TURBO_VOTE, true);
 	if (rc) {
-		pr_err("Error! enable platform failed\n");
+		pr_err("Error! enable platform failed rc=%d\n", rc);
 		goto stop_cpas;
 	}
 
@@ -152,13 +194,13 @@
 
 	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
 	if (rc) {
-		pr_err("%s: disable platform failed\n", __func__);
+		pr_err("Disable platform failed rc=%d\n", rc);
 		return rc;
 	}
 
 	rc = cam_cpas_stop(soc_private->cpas_handle);
 	if (rc) {
-		pr_err("Error! CPAS stop failed.\n");
+		pr_err("Error! CPAS stop failed rc=%d\n", rc);
 		return rc;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
index 27fb192..094c977 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
@@ -45,6 +45,18 @@
 	irq_handler_t vfe_irq_handler, void *irq_data);
 
 /*
+ * cam_vfe_deinit_soc_resources()
+ *
+ * @Brief:                   Deinitialize SOC resources including private data
+ *
+ * @soc_info:                Device soc information
+ *
+ * @Return:                  0: Success
+ *                           Non-zero: Failure
+ */
+int cam_vfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info);
+
+/*
  * cam_vfe_enable_soc_resources()
  *
  * @brief:                   Enable regulator, irq resources, start CPAS
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
index 2245ab1..0ac5f6d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
@@ -30,6 +30,7 @@
 
 static struct platform_driver cam_vfe170_driver = {
 	.probe = cam_vfe_probe,
+	.remove = cam_vfe_remove,
 	.driver = {
 		.name = "cam_vfe170",
 		.owner = THIS_MODULE,
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
index cea1137..4a328ee 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
@@ -1,7 +1,10 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils/
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_cdm/
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_core/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
index 50952f8..63ca5c2 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
@@ -17,17 +17,17 @@
 #include "cam_vfe_bus_ver2.h"
 
 int cam_vfe_bus_init(uint32_t          bus_version,
-	void __iomem                  *mem_base,
+	struct cam_hw_soc_info        *soc_info,
 	struct cam_hw_intf            *hw_intf,
 	void                          *bus_hw_info,
 	void                          *vfe_irq_controller,
-	struct cam_vfe_bus            **vfe_bus)
+	struct cam_vfe_bus           **vfe_bus)
 {
 	int rc = -ENODEV;
 
 	switch (bus_version) {
 	case CAM_VFE_BUS_VER_2_0:
-		rc = cam_vfe_bus_ver2_init(mem_base, hw_intf, bus_hw_info,
+		rc = cam_vfe_bus_ver2_init(soc_info, hw_intf, bus_hw_info,
 			vfe_irq_controller, vfe_bus);
 		break;
 	default:
@@ -37,3 +37,21 @@
 
 	return rc;
 }
+
+int cam_vfe_bus_deinit(uint32_t        bus_version,
+	struct cam_vfe_bus           **vfe_bus)
+{
+	int rc = -ENODEV;
+
+	switch (bus_version) {
+	case CAM_VFE_BUS_VER_2_0:
+		rc = cam_vfe_bus_ver2_deinit(vfe_bus);
+		break;
+	default:
+		pr_err("Unsupported Bus Version %x\n", bus_version);
+		break;
+	}
+
+	return rc;
+}
+
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index c4fae99..489689c 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -17,8 +17,10 @@
 #include "cam_io_util.h"
 #include "cam_cdm_util.h"
 #include "cam_hw_intf.h"
+#include "cam_ife_hw_mgr.h"
 #include "cam_vfe_hw_intf.h"
 #include "cam_irq_controller.h"
+#include "cam_tasklet_util.h"
 #include "cam_vfe_bus.h"
 #include "cam_vfe_bus_ver2.h"
 #include "cam_vfe_core.h"
@@ -26,28 +28,25 @@
 #undef CDBG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
 
-#define FRAME_BASED_EN 0
+static const char drv_name[] = "vfe_bus";
+
+#define CAM_VFE_BUS_IRQ_REG0                     0
+#define CAM_VFE_BUS_IRQ_REG1                     1
+#define CAM_VFE_BUS_IRQ_REG2                     2
+#define CAM_VFE_BUS_IRQ_MAX                      3
+
+#define CAM_VFE_BUS_VER2_PAYLOAD_MAX             256
 
 #define MAX_BUF_UPDATE_REG_NUM   \
 	(sizeof(struct cam_vfe_bus_ver2_reg_offset_bus_client)/4)
 #define MAX_REG_VAL_PAIR_SIZE    \
-		(MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
+	(MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
 
 #define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val)    \
-		do {                                               \
-			buf_array[index++] = offset;               \
-			buf_array[index++] = val;                  \
-		} while (0)
-
-static uint32_t irq_reg_offset[CAM_IFE_BUS_IRQ_REGISTERS_MAX] = {
-	0x0000205C,
-	0x00002060,
-	0x00002064,
-	0x0000206C,
-	0x00002070,
-	0x00002074,
-	0x00002078,
-};
+	do {                                               \
+		buf_array[index++] = offset;               \
+		buf_array[index++] = val;                  \
+	} while (0)
 
 enum cam_vfe_bus_packer_format {
 	PACKER_FMT_PLAIN_128                   = 0x0,
@@ -70,23 +69,29 @@
 };
 
 struct cam_vfe_bus_ver2_common_data {
+	uint32_t                                    core_index;
 	void __iomem                               *mem_base;
 	struct cam_hw_intf                         *hw_intf;
 	void                                       *bus_irq_controller;
 	void                                       *vfe_irq_controller;
 	struct cam_vfe_bus_ver2_reg_offset_common  *common_reg;
 	uint32_t                                    io_buf_update[
-							MAX_REG_VAL_PAIR_SIZE];
+		MAX_REG_VAL_PAIR_SIZE];
+
+	struct cam_vfe_bus_irq_evt_payload          evt_payload[
+		CAM_VFE_BUS_VER2_PAYLOAD_MAX];
+	struct list_head                            free_payload_list;
 };
 
 struct cam_vfe_bus_ver2_wm_resource_data {
 	uint32_t             index;
 	struct cam_vfe_bus_ver2_common_data            *common_data;
 	struct cam_vfe_bus_ver2_reg_offset_bus_client  *hw_regs;
+	void                                *ctx;
 
 	uint32_t             irq_enabled;
-
 	uint32_t             init_cfg_done;
+
 	uint32_t             offset;
 	uint32_t             width;
 	uint32_t             height;
@@ -127,6 +132,8 @@
 	uint32_t                         dual_slave_core;
 	uint32_t                         intra_client_mask;
 	uint32_t                         composite_mask;
+
+	void                            *ctx;
 };
 
 struct cam_vfe_bus_ver2_vfe_out_data {
@@ -147,7 +154,6 @@
 	struct cam_cdm_utils_ops        *cdm_util_ops;
 };
 
-
 struct cam_vfe_bus_ver2_priv {
 	struct cam_vfe_bus_ver2_common_data common_data;
 
@@ -159,12 +165,59 @@
 	struct list_head                    free_dual_comp_grp;
 	struct list_head                    used_comp_grp;
 
-	struct cam_vfe_bus_irq_evt_payload  evt_payload[128];
-	struct list_head                    free_payload_list;
+	uint32_t                            irq_handle;
 };
 
+static int cam_vfe_bus_get_evt_payload(
+	struct cam_vfe_bus_ver2_common_data  *common_data,
+	struct cam_vfe_bus_irq_evt_payload  **evt_payload)
+{
+	if (list_empty(&common_data->free_payload_list)) {
+		*evt_payload = NULL;
+		pr_err("No free payload\n");
+		return -ENODEV;
+	}
+
+	*evt_payload = list_first_entry(&common_data->free_payload_list,
+		struct cam_vfe_bus_irq_evt_payload, list);
+	list_del_init(&(*evt_payload)->list);
+	return 0;
+}
+
 static int cam_vfe_bus_put_evt_payload(void     *core_info,
-	struct cam_vfe_bus_irq_evt_payload     **evt_payload);
+	struct cam_vfe_bus_irq_evt_payload     **evt_payload)
+{
+	struct cam_vfe_bus_ver2_common_data *common_data = NULL;
+	uint32_t  *ife_irq_regs = NULL;
+	uint32_t   status_reg0, status_reg1, status_reg2;
+
+	if (!core_info) {
+		pr_err("Invalid param core_info NULL");
+		return -EINVAL;
+	}
+	if (*evt_payload == NULL) {
+		pr_err("No payload to put\n");
+		return -EINVAL;
+	}
+
+	ife_irq_regs = (*evt_payload)->irq_reg_val;
+	status_reg0 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
+	status_reg1 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
+	status_reg2 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
+
+	if (status_reg0 || status_reg1 || status_reg2) {
+		CDBG("status0 0x%x status1 0x%x status2 0x%x\n",
+			status_reg0, status_reg1, status_reg2);
+		return 0;
+	}
+
+	common_data = core_info;
+	list_add_tail(&(*evt_payload)->list,
+		&common_data->free_payload_list);
+	*evt_payload = NULL;
+
+	return 0;
+}
 
 static int cam_vfe_bus_ver2_get_intra_client_mask(
 	enum cam_vfe_bus_ver2_vfe_core_id  dual_slave_core,
@@ -371,7 +424,6 @@
 	case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
 		switch (format) {
 		case CAM_FORMAT_PLAIN64:
-		case CAM_FORMAT_PLAIN128:
 			return 1;
 		default:
 			break;
@@ -583,7 +635,26 @@
 	switch (out_fmt) {
 	case CAM_FORMAT_NV21:
 	case CAM_FORMAT_NV12:
-		return PACKER_FMT_PLAIN_8;
+		return PACKER_FMT_PLAIN_8_LSB_MSB_10;
+	case CAM_FORMAT_PLAIN16_16:
+		return PACKER_FMT_PLAIN_16_16BPP;
+	case CAM_FORMAT_PLAIN64:
+		return PACKER_FMT_PLAIN_64;
+	case CAM_FORMAT_MIPI_RAW_6:
+	case CAM_FORMAT_MIPI_RAW_8:
+	case CAM_FORMAT_MIPI_RAW_10:
+	case CAM_FORMAT_MIPI_RAW_12:
+	case CAM_FORMAT_MIPI_RAW_14:
+	case CAM_FORMAT_MIPI_RAW_16:
+	case CAM_FORMAT_MIPI_RAW_20:
+	case CAM_FORMAT_QTI_RAW_8:
+	case CAM_FORMAT_QTI_RAW_10:
+	case CAM_FORMAT_QTI_RAW_12:
+	case CAM_FORMAT_QTI_RAW_14:
+	case CAM_FORMAT_PLAIN128:
+	case CAM_FORMAT_PD8:
+	case CAM_FORMAT_PD10:
+		return PACKER_FMT_PLAIN_128;
 	default:
 		return PACKER_FMT_MAX;
 	}
@@ -592,6 +663,8 @@
 static int cam_vfe_bus_acquire_wm(
 	struct cam_vfe_bus_ver2_priv          *ver2_bus_priv,
 	struct cam_isp_out_port_info          *out_port_info,
+	void                                  *tasklet,
+	void                                  *ctx,
 	enum cam_vfe_bus_ver2_vfe_out_type     vfe_out_res_id,
 	enum cam_vfe_bus_plane_type            plane,
 	enum cam_isp_hw_split_id               split_id,
@@ -615,10 +688,12 @@
 	}
 
 	wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
+	wm_res_local->tasklet_info = tasklet;
 	wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
 
 	rsrc_data = wm_res_local->res_priv;
 	rsrc_data->irq_enabled = subscribe_irq;
+	rsrc_data->ctx = ctx;
 	rsrc_data->format = out_port_info->format;
 	rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
 
@@ -628,7 +703,6 @@
 	if (rsrc_data->index < 3) {
 		rsrc_data->width = rsrc_data->width * 5/4 * rsrc_data->height;
 		rsrc_data->height = 1;
-		rsrc_data->pack_fmt = 0x0;
 		rsrc_data->en_cfg = 0x3;
 	} else if (rsrc_data->index < 5 ||
 		rsrc_data->index == 7 || rsrc_data->index == 8) {
@@ -664,18 +738,15 @@
 			pr_err("Invalid plane type %d\n", plane);
 			return -EINVAL;
 		}
-		rsrc_data->pack_fmt = 0xE;
 		rsrc_data->en_cfg = 0x1;
 	} else if (rsrc_data->index >= 11) {
 		rsrc_data->width = 0;
 		rsrc_data->height = 0;
-		rsrc_data->pack_fmt = 0x0;
 		rsrc_data->stride = 1;
 		rsrc_data->en_cfg = 0x3;
 	} else {
 		rsrc_data->width = rsrc_data->width * 4;
 		rsrc_data->height = rsrc_data->height / 2;
-		rsrc_data->pack_fmt = 0x0;
 		rsrc_data->en_cfg = 0x1;
 	}
 
@@ -718,6 +789,8 @@
 	rsrc_data->ubwc_meta_offset = 0;
 	rsrc_data->init_cfg_done = 0;
 	rsrc_data->en_cfg = 0;
+
+	wm_res->tasklet_info = NULL;
 	wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
 
 	return 0;
@@ -730,6 +803,7 @@
 		wm_res->res_priv;
 	struct cam_vfe_bus_ver2_common_data        *common_data =
 		rsrc_data->common_data;
+	uint32_t                   bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
 
 	cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
 	cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
@@ -753,6 +827,28 @@
 	cam_io_w(0x0,
 		common_data->mem_base + rsrc_data->hw_regs->framedrop_period);
 
+	/* Subscribe IRQ */
+	if (rsrc_data->irq_enabled) {
+		CDBG("Subscribe WM%d IRQ\n", rsrc_data->index);
+		bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] =
+			(1 << rsrc_data->index);
+		wm_res->irq_handle = cam_irq_controller_subscribe_irq(
+			common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
+			bus_irq_reg_mask, wm_res,
+			wm_res->top_half_handler,
+			cam_ife_mgr_do_tasklet_buf_done,
+			wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
+		if (wm_res->irq_handle < 0) {
+			pr_err("Subscribe IRQ failed for WM %d\n",
+				rsrc_data->index);
+			return -EFAULT;
+		}
+	}
+
+	/* Enable WM */
+	cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
+		rsrc_data->hw_regs->cfg);
+
 	CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
 		rsrc_data->width, rsrc_data->height);
 	CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
@@ -781,12 +877,10 @@
 
 	CDBG("irq_enabled %d", rsrc_data->irq_enabled);
 	/* Unsubscribe IRQ */
-	if (rsrc_data->irq_enabled) {
-		/*
-		 * Currently all WM IRQ are unsubscribed in one place. Need to
-		 * make it dynamic.
-		 */
-	}
+	if (rsrc_data->irq_enabled)
+		rc = cam_irq_controller_unsubscribe_irq(
+			common_data->bus_irq_controller,
+			wm_res->irq_handle);
 
 	/* Halt & Reset WM */
 	cam_io_w_mb(BIT(rsrc_data->index),
@@ -800,7 +894,42 @@
 static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
 	struct cam_irq_th_payload *th_payload)
 {
-	return -EPERM;
+	int32_t                                     rc;
+	int                                         i;
+	struct cam_isp_resource_node               *wm_res = NULL;
+	struct cam_vfe_bus_ver2_wm_resource_data   *rsrc_data = NULL;
+	struct cam_vfe_bus_irq_evt_payload         *evt_payload;
+
+	wm_res = th_payload->handler_priv;
+	if (!wm_res) {
+		pr_err_ratelimited("Error! No resource\n");
+		return -ENODEV;
+	}
+
+	rsrc_data = wm_res->res_priv;
+
+	CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
+	CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
+
+	rc  = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
+	if (rc) {
+		pr_err_ratelimited("No tasklet_cmd is free in queue\n");
+		return rc;
+	}
+
+	cam_isp_hw_get_timestamp(&evt_payload->ts);
+
+	evt_payload->ctx = rsrc_data->ctx;
+	evt_payload->core_index = rsrc_data->common_data->core_index;
+	evt_payload->evt_id  = evt_id;
+
+	for (i = 0; i < th_payload->num_registers; i++)
+		evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
+
+	th_payload->evt_payload_priv = evt_payload;
+
+	CDBG("Exit\n");
+	return rc;
 }
 
 static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
@@ -825,9 +954,10 @@
 			~BIT(rsrc_data->index);
 		rc = CAM_VFE_IRQ_STATUS_SUCCESS;
 	}
+	CDBG("status_reg %x rc %d\n", status_reg, rc);
 
 	if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
-		cam_vfe_bus_put_evt_payload(evt_payload->core_info,
+		cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
 			&evt_payload);
 
 	return rc;
@@ -838,15 +968,13 @@
 	struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
 	struct cam_isp_resource_node    *wm_res)
 {
-	int rc = 0;
 	struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
 
 	rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
 		GFP_KERNEL);
 	if (!rsrc_data) {
-		CDBG("Failed to alloc for wm res priv\n");
-		rc = -ENOMEM;
-		return rc;
+		CDBG("Failed to alloc for WM res priv\n");
+		return -ENOMEM;
 	}
 	wm_res->res_priv = rsrc_data;
 
@@ -863,7 +991,32 @@
 	wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
 	wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
 
-	return rc;
+	return 0;
+}
+
+static int cam_vfe_bus_deinit_wm_resource(
+	struct cam_isp_resource_node    *wm_res)
+{
+	struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
+
+	wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+	INIT_LIST_HEAD(&wm_res->list);
+
+	wm_res->start = NULL;
+	wm_res->stop = NULL;
+	wm_res->top_half_handler = NULL;
+	wm_res->bottom_half_handler = NULL;
+	wm_res->hw_intf = NULL;
+
+	rsrc_data = wm_res->res_priv;
+	wm_res->res_priv = NULL;
+	if (!rsrc_data) {
+		pr_err("Error! WM res priv is NULL\n");
+		return -ENOMEM;
+	}
+	kfree(rsrc_data);
+
+	return 0;
 }
 
 static void cam_vfe_bus_add_wm_to_comp_grp(
@@ -901,6 +1054,8 @@
 static int cam_vfe_bus_acquire_comp_grp(
 	struct cam_vfe_bus_ver2_priv        *ver2_bus_priv,
 	struct cam_isp_out_port_info        *out_port_info,
+	void                                *tasklet,
+	void                                *ctx,
 	uint32_t                             unique_id,
 	uint32_t                             is_dual,
 	uint32_t                             is_master,
@@ -942,6 +1097,7 @@
 		}
 
 		list_del(&comp_grp_local->list);
+		comp_grp_local->tasklet_info = tasklet;
 		comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
 
 		rsrc_data->is_master = is_master;
@@ -964,6 +1120,7 @@
 		}
 	}
 
+	rsrc_data->ctx = ctx;
 	*comp_grp = comp_grp_local;
 
 	return rc;
@@ -1017,6 +1174,7 @@
 	in_rsrc_data->composite_mask = 0;
 	in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
 
+	comp_grp->tasklet_info = NULL;
 	comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
 
 	return 0;
@@ -1029,11 +1187,7 @@
 		comp_grp->res_priv;
 	struct cam_vfe_bus_ver2_common_data        *common_data =
 		rsrc_data->common_data;
-
-	/*
-	 * Individual Comp_Grp Subscribe IRQ can be done here once
-	 * dynamic IRQ enable support is added.
-	 */
+	uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
 
 	cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
 		rsrc_data->hw_regs->comp_mask);
@@ -1055,9 +1209,30 @@
 
 		cam_io_w_mb(intra_client_en, common_data->mem_base +
 			common_data->common_reg->dual_master_comp_cfg);
+
+		bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = (1 << dual_comp_grp);
+	} else {
+		/* IRQ bits for COMP GRP start at 5. So add 5 to the shift */
+		bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] =
+			(1 << (rsrc_data->comp_grp_type + 5));
+	}
+
+	/* Subscribe IRQ */
+	CDBG("Subscribe COMP_GRP%d IRQ\n", rsrc_data->comp_grp_type);
+	comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
+		common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
+		bus_irq_reg_mask, comp_grp,
+		comp_grp->top_half_handler,
+		cam_ife_mgr_do_tasklet_buf_done,
+		comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
+	if (comp_grp->irq_handle < 0) {
+		pr_err("Subscribe IRQ failed for comp_grp %d\n",
+			rsrc_data->comp_grp_type);
+		return -EFAULT;
 	}
 
 	comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
+
 	return rc;
 }
 
@@ -1070,6 +1245,9 @@
 		rsrc_data->common_data;
 
 	/* Unsubscribe IRQ */
+	rc = cam_irq_controller_unsubscribe_irq(
+		common_data->bus_irq_controller,
+		comp_grp->irq_handle);
 
 	cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
 		rsrc_data->hw_regs->comp_mask);
@@ -1097,7 +1275,42 @@
 static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
 	struct cam_irq_th_payload *th_payload)
 {
-	return -EPERM;
+	int32_t                                     rc;
+	int                                         i;
+	struct cam_isp_resource_node               *comp_grp = NULL;
+	struct cam_vfe_bus_ver2_comp_grp_data      *rsrc_data = NULL;
+	struct cam_vfe_bus_irq_evt_payload         *evt_payload;
+
+	comp_grp = th_payload->handler_priv;
+	if (!comp_grp) {
+		pr_err_ratelimited("Error! No resource\n");
+		return -ENODEV;
+	}
+
+	rsrc_data = comp_grp->res_priv;
+
+	CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
+	CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
+
+	rc  = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
+	if (rc) {
+		pr_err_ratelimited("No tasklet_cmd is free in queue\n");
+		return rc;
+	}
+
+	cam_isp_hw_get_timestamp(&evt_payload->ts);
+
+	evt_payload->ctx = rsrc_data->ctx;
+	evt_payload->core_index = rsrc_data->common_data->core_index;
+	evt_payload->evt_id  = evt_id;
+
+	for (i = 0; i < th_payload->num_registers; i++)
+		evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
+
+	th_payload->evt_payload_priv = evt_payload;
+
+	CDBG("Exit\n");
+	return rc;
 }
 
 static int cam_vfe_bus_handle_comp_done_bottom_half(
@@ -1113,12 +1326,13 @@
 	uint32_t                               comp_err_reg;
 	uint32_t                               comp_grp_id;
 
+	CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
+
 	if (!evt_payload)
 		return rc;
 
 	cam_ife_irq_regs = evt_payload->irq_reg_val;
 
-	CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
 	switch (rsrc_data->comp_grp_type) {
 	case CAM_VFE_BUS_VER2_COMP_GRP_0:
 	case CAM_VFE_BUS_VER2_COMP_GRP_1:
@@ -1155,8 +1369,8 @@
 			rc = CAM_VFE_IRQ_STATUS_SUCCESS;
 		}
 
-		CDBG("status reg = 0x%x, bit index = %d\n",
-			status_reg, (comp_grp_id + 5));
+		CDBG("status reg = 0x%x, bit index = %d rc %d\n",
+			status_reg, (comp_grp_id + 5), rc);
 		break;
 
 	case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
@@ -1197,11 +1411,13 @@
 		break;
 	default:
 		rc = CAM_VFE_IRQ_STATUS_ERR;
+		pr_err("Error! Invalid comp_grp_type %u\n",
+			rsrc_data->comp_grp_type);
 		break;
 	}
 
 	if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
-		cam_vfe_bus_put_evt_payload(evt_payload->core_info,
+		cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
 			&evt_payload);
 
 	return rc;
@@ -1212,8 +1428,7 @@
 	struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
 	struct cam_isp_resource_node    *comp_grp)
 {
-	struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
-		comp_grp->res_priv;
+	struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
 
 	rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
 		GFP_KERNEL);
@@ -1231,7 +1446,6 @@
 	rsrc_data->hw_regs         = &ver2_hw_info->comp_grp_reg[index];
 	rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
 
-
 	if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
 		rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
 		list_add_tail(&comp_grp->list,
@@ -1250,7 +1464,34 @@
 	return 0;
 }
 
-static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args)
+static int cam_vfe_bus_deinit_comp_grp(
+	struct cam_isp_resource_node    *comp_grp)
+{
+	struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
+		comp_grp->res_priv;
+
+	comp_grp->start = NULL;
+	comp_grp->stop = NULL;
+	comp_grp->top_half_handler = NULL;
+	comp_grp->bottom_half_handler = NULL;
+	comp_grp->hw_intf = NULL;
+
+	list_del_init(&comp_grp->list);
+	comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+
+	comp_grp->res_priv = NULL;
+
+	if (!rsrc_data) {
+		pr_err("Error! comp_grp_priv is NULL\n");
+		return -ENODEV;
+	}
+	kfree(rsrc_data);
+
+	return 0;
+}
+
+static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
+	uint32_t args_size)
 {
 	int                                     rc = -ENODEV;
 	int                                     i;
@@ -1306,30 +1547,43 @@
 		CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
 		rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
 			out_acquire_args->out_port_info,
+			acq_args->tasklet,
+			out_acquire_args->ctx,
 			out_acquire_args->unique_id,
 			out_acquire_args->is_dual,
 			out_acquire_args->is_master,
 			out_acquire_args->dual_slave_core,
 			&rsrc_data->comp_grp);
-		if (rc < 0)
+		if (rc) {
+			pr_err("VFE%d Comp_Grp acquire failed for Out %d rc=%d\n",
+				rsrc_data->common_data->core_index,
+				vfe_out_res_id, rc);
 			return rc;
+		}
 
 		subscribe_irq = 0;
-	} else
+	} else {
 		subscribe_irq = 1;
+	}
 
 	/* Reserve WM */
 	for (i = 0; i < num_wm; i++) {
 		rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
 			out_acquire_args->out_port_info,
+			acq_args->tasklet,
+			out_acquire_args->ctx,
 			vfe_out_res_id,
 			i,
 			out_acquire_args->split_id,
 			subscribe_irq,
 			&rsrc_data->wm_res[i],
 			&client_done_mask);
-		if (rc < 0)
+		if (rc) {
+			pr_err("VFE%d WM acquire failed for Out %d rc=%d\n",
+				rsrc_data->common_data->core_index,
+				vfe_out_res_id, rc);
 			goto release_wm;
+		}
 
 		if (rsrc_data->comp_grp)
 			cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
@@ -1352,11 +1606,21 @@
 	return rc;
 }
 
-static int cam_vfe_bus_release_vfe_out(void *bus_priv,
-	struct cam_isp_resource_node        *vfe_out)
+static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args,
+	uint32_t args_size)
 {
 	uint32_t i;
-	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = vfe_out->res_priv;
+	struct cam_isp_resource_node          *vfe_out = NULL;
+	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = NULL;
+
+	if (!bus_priv || !release_args) {
+		pr_err("Invalid input bus_priv %pK release_args %pK\n",
+			bus_priv, release_args);
+		return -EINVAL;
+	}
+
+	vfe_out = release_args;
+	rsrc_data = vfe_out->res_priv;
 
 	if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
 		pr_err("Error! Invalid resource state:%d\n",
@@ -1381,12 +1645,20 @@
 	return 0;
 }
 
-static int cam_vfe_bus_start_vfe_out(struct cam_isp_resource_node *vfe_out)
+static int cam_vfe_bus_start_vfe_out(
+	struct cam_isp_resource_node          *vfe_out)
 {
 	int rc = 0, i;
-	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = vfe_out->res_priv;
-	struct cam_vfe_bus_ver2_common_data   *common_data =
-		rsrc_data->common_data;
+	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = NULL;
+	struct cam_vfe_bus_ver2_common_data   *common_data = NULL;
+
+	if (!vfe_out) {
+		pr_err("Invalid input\n");
+		return -EINVAL;
+	}
+
+	rsrc_data = vfe_out->res_priv;
+	common_data = rsrc_data->common_data;
 
 	CDBG("Start resource index %d\n", rsrc_data->out_type);
 
@@ -1396,28 +1668,12 @@
 		return -EACCES;
 	}
 
-	/* Enable IRQ Mask */
-	cam_io_w_mb(0x00001FE0, common_data->mem_base + 0x2044);
-	cam_io_w_mb(0x000FFFE7, common_data->mem_base + 0x2048);
-	cam_io_w_mb(0x000000FF, common_data->mem_base + 0x204c);
-
 	for (i = 0; i < rsrc_data->num_wm; i++)
 		rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
 
 	if (rsrc_data->comp_grp)
 		rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
 
-	/* VFE_MODULE_BUS_CGC_OVERRIDE */
-	cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000003C);
-	/* VFE_MODULE_COLOR_CGC_OVERRIDE */
-	cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000034);
-	/* VFE_MODULE_ZOOM_CGC_OVERRIDE */
-	cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x38);
-	/* VFE_MODULE_LENS_CGC_OVERRIDE */
-	cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000002C);
-	/* VFE_MODULE_STATS_CGC_OVERRIDE */
-	cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000030);
-
 	/* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
 	cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
 	/*  BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
@@ -1440,13 +1696,22 @@
 	/* BUS_WR_TEST_BUS_CTRL */
 	cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
 
+	vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
 	return rc;
 }
 
-static int cam_vfe_bus_stop_vfe_out(struct cam_isp_resource_node *vfe_out)
+static int cam_vfe_bus_stop_vfe_out(
+	struct cam_isp_resource_node          *vfe_out)
 {
 	int rc = 0, i;
-	struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
+	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = NULL;
+
+	if (!vfe_out) {
+		pr_err("Invalid input\n");
+		return -EINVAL;
+	}
+
+	rsrc_data = vfe_out->res_priv;
 
 	if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
 		vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
@@ -1459,7 +1724,6 @@
 	for (i = 0; i < rsrc_data->num_wm; i++)
 		rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
 
-	vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
 
 	vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
 	return rc;
@@ -1533,122 +1797,39 @@
 	return 0;
 }
 
-static int cam_vfe_bus_get_evt_payload(
-	struct cam_vfe_bus_ver2_priv         *bus_priv,
-	struct cam_vfe_bus_irq_evt_payload  **evt_payload)
+static int cam_vfe_bus_deinit_vfe_out_resource(
+	struct cam_isp_resource_node    *vfe_out)
 {
-	if (list_empty(&bus_priv->free_payload_list)) {
-		*evt_payload = NULL;
-		pr_err("No free payload\n");
-		return -ENODEV;
+	struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
+
+	vfe_out->start = NULL;
+	vfe_out->stop = NULL;
+	vfe_out->top_half_handler = NULL;
+	vfe_out->bottom_half_handler = NULL;
+	vfe_out->hw_intf = NULL;
+
+	vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+	INIT_LIST_HEAD(&vfe_out->list);
+	vfe_out->res_priv = NULL;
+
+	if (!rsrc_data) {
+		pr_err("Error! vfe out priv is NULL\n");
+		return -ENOMEM;
 	}
+	kfree(rsrc_data);
 
-	*evt_payload = list_first_entry(&bus_priv->free_payload_list,
-		struct cam_vfe_bus_irq_evt_payload, list);
-	list_del_init(&(*evt_payload)->list);
-	return 0;
-}
-
-static int cam_vfe_bus_put_evt_payload(void     *core_info,
-	struct cam_vfe_bus_irq_evt_payload     **evt_payload)
-{
-	struct cam_vfe_bus_ver2_priv         *bus_priv = NULL;
-	uint32_t  *cam_ife_irq_regs = (*evt_payload)->irq_reg_val;
-	uint32_t   status_reg0, status_reg1;
-
-	status_reg0 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
-	status_reg1 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
-
-	if (status_reg0 || status_reg1) {
-		CDBG("status0 0x%x status1 0x%x\n", status_reg0, status_reg1);
-		return 0;
-	}
-
-	if (!core_info) {
-		pr_err("Invalid param core_info NULL");
-		return -EINVAL;
-	}
-	if (*evt_payload == NULL) {
-		pr_err("No payload to put\n");
-		return -EINVAL;
-	}
-	bus_priv = (*evt_payload)->bus_priv;
-	list_add_tail(&(*evt_payload)->list, &bus_priv->free_payload_list);
-	*evt_payload = NULL;
 	return 0;
 }
 
 static int cam_vfe_bus_ver2_handle_irq(uint32_t    evt_id,
 	struct cam_irq_th_payload                 *th_payload)
 {
-	int32_t                                rc;
-	int                                    i;
-	struct cam_vfe_irq_handler_priv       *handler_priv;
-	struct cam_vfe_hw_core_info           *core_info;
-	struct cam_vfe_bus_irq_evt_payload    *evt_payload;
-	struct cam_vfe_bus                    *bus_info;
 	struct cam_vfe_bus_ver2_priv          *bus_priv;
-	struct cam_irq_controller_reg_info    *reg_info;
-	uint32_t                               irq_mask;
-	int                                    found = 0;
 
-	handler_priv = th_payload->handler_priv;
-	core_info    = handler_priv->core_info;
-	bus_info     = core_info->vfe_bus;
-	bus_priv     = bus_info->bus_priv;
-	reg_info     = &bus_priv->common_data.common_reg->irq_reg_info;
-
-	/*
-	 *  add reset ack handling here once supported.
-	 *  Just clear all the bus irq status registers and ignore the reset.
-	 */
-
+	bus_priv     = th_payload->handler_priv;
 	CDBG("Enter\n");
-	rc  = cam_vfe_bus_get_evt_payload(bus_priv, &evt_payload);
-	if (rc) {
-		pr_err("No tasklet_cmd is free in queue\n");
-		return rc;
-	}
-
-	cam_isp_hw_get_timestamp(&evt_payload->ts);
-
-	evt_payload->core_index = handler_priv->core_index;
-	evt_payload->core_info  = handler_priv->core_info;
-	evt_payload->bus_priv   = bus_priv;
-	CDBG("core_idx %d, core_info %llx\n", handler_priv->core_index,
-			(uint64_t)handler_priv->core_info);
-
-	for (i = 0; i < CAM_IFE_BUS_IRQ_REGISTERS_MAX; i++) {
-		irq_mask = cam_io_r(handler_priv->mem_base +
-			irq_reg_offset[i] - (0xC * 2));
-		evt_payload->irq_reg_val[i] = irq_mask &
-			cam_io_r(handler_priv->mem_base + irq_reg_offset[i]);
-		if (evt_payload->irq_reg_val[i])
-			found = 1;
-		CDBG("irq_status%d = 0x%x\n", i, evt_payload->irq_reg_val[i]);
-	}
-	for (i = 0; i <= CAM_IFE_IRQ_BUS_REG_STATUS2; i++) {
-		cam_io_w(evt_payload->irq_reg_val[i], handler_priv->mem_base +
-			reg_info->irq_reg_set[i].clear_reg_offset);
-		CDBG("Clear irq_status%d = 0x%x offset 0x%x\n", i,
-			evt_payload->irq_reg_val[i],
-			reg_info->irq_reg_set[i].clear_reg_offset);
-	}
-	cam_io_w(reg_info->global_clear_bitmask, handler_priv->mem_base +
-		reg_info->global_clear_offset);
-	CDBG("Global clear bitmask = 0x%x offset 0x%x\n",
-			reg_info->global_clear_bitmask,
-			reg_info->global_clear_offset);
-
-	if (found)
-		th_payload->evt_payload_priv = evt_payload;
-	else {
-		cam_vfe_bus_put_evt_payload(evt_payload->core_info,
-			&evt_payload);
-		rc = -ENOMSG;
-	}
-
-	return rc;
+	return cam_irq_controller_handle_irq(evt_id,
+		bus_priv->common_data.bus_irq_controller);
 }
 
 static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
@@ -1882,6 +2063,69 @@
 	return 0;
 }
 
+static int cam_vfe_bus_start_hw(void *hw_priv,
+	void *start_hw_args, uint32_t arg_size)
+{
+	return cam_vfe_bus_start_vfe_out(hw_priv);
+}
+
+static int cam_vfe_bus_stop_hw(void *hw_priv,
+	void *stop_hw_args, uint32_t arg_size)
+{
+	return cam_vfe_bus_stop_vfe_out(hw_priv);
+}
+
+static int cam_vfe_bus_init_hw(void *hw_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_vfe_bus_ver2_priv    *bus_priv = hw_priv;
+	uint32_t                         top_irq_reg_mask[2] = {0};
+
+	if (!bus_priv) {
+		pr_err("Error! Invalid args\n");
+		return -EINVAL;
+	}
+
+	top_irq_reg_mask[0] = (1 << 9);
+
+	bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
+		bus_priv->common_data.vfe_irq_controller,
+		CAM_IRQ_PRIORITY_2,
+		top_irq_reg_mask,
+		bus_priv,
+		cam_vfe_bus_ver2_handle_irq,
+		NULL,
+		NULL,
+		NULL);
+
+	if (bus_priv->irq_handle <= 0) {
+		pr_err("Failed to subscribe BUS IRQ\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int cam_vfe_bus_deinit_hw(void *hw_priv,
+	void *deinit_hw_args, uint32_t arg_size)
+{
+	struct cam_vfe_bus_ver2_priv    *bus_priv = hw_priv;
+	int                              rc;
+
+	if (!bus_priv || (bus_priv->irq_handle <= 0)) {
+		pr_err("Error! Invalid args\n");
+		return -EINVAL;
+	}
+
+	rc = cam_irq_controller_unsubscribe_irq(
+		bus_priv->common_data.vfe_irq_controller,
+		bus_priv->irq_handle);
+	if (rc)
+		pr_err("Failed to unsubscribe irq rc=%d\n", rc);
+
+	return rc;
+}
+
 static int cam_vfe_bus_process_cmd(void *priv,
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 {
@@ -1906,7 +2150,7 @@
 }
 
 int cam_vfe_bus_ver2_init(
-	void __iomem                         *mem_base,
+	struct cam_hw_soc_info               *soc_info,
 	struct cam_hw_intf                   *hw_intf,
 	void                                 *bus_hw_info,
 	void                                 *vfe_irq_controller,
@@ -1919,11 +2163,18 @@
 
 	CDBG("Enter\n");
 
+	if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
+		pr_err("Error! Invalid params soc_info %pK hw_intf %pK hw_info %pK controller %pK\n",
+			soc_info, hw_intf, bus_hw_info, vfe_irq_controller);
+		rc = -EINVAL;
+		goto end;
+	}
+
 	vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
 	if (!vfe_bus_local) {
 		CDBG("Failed to alloc for vfe_bus\n");
 		rc = -ENOMEM;
-		goto err_alloc_bus;
+		goto end;
 	}
 
 	bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
@@ -1931,15 +2182,25 @@
 	if (!bus_priv) {
 		CDBG("Failed to alloc for vfe_bus_priv\n");
 		rc = -ENOMEM;
-		goto err_alloc_priv;
+		goto free_bus_local;
 	}
 	vfe_bus_local->bus_priv = bus_priv;
 
-	bus_priv->common_data.mem_base           = mem_base;
+	bus_priv->common_data.core_index         = soc_info->index;
+	bus_priv->common_data.mem_base           =
+		CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
 	bus_priv->common_data.hw_intf            = hw_intf;
 	bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
 	bus_priv->common_data.common_reg         = &ver2_hw_info->common_reg;
 
+	rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
+		&ver2_hw_info->common_reg.irq_reg_info,
+		&bus_priv->common_data.bus_irq_controller);
+	if (rc) {
+		pr_err("Error! cam_irq_controller_init failed\n");
+		goto free_bus_priv;
+	}
+
 	INIT_LIST_HEAD(&bus_priv->free_comp_grp);
 	INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
 	INIT_LIST_HEAD(&bus_priv->used_comp_grp);
@@ -1948,8 +2209,8 @@
 		rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
 			&bus_priv->bus_client[i]);
 		if (rc < 0) {
-			pr_err("Error! Init WM failed\n");
-			goto err_init_wm;
+			pr_err("Error! Init WM failed rc=%d\n", rc);
+			goto deinit_wm;
 		}
 	}
 
@@ -1957,8 +2218,8 @@
 		rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
 			&bus_priv->comp_grp[i]);
 		if (rc < 0) {
-			pr_err("Error! Init Comp Grp failed\n");
-			goto err_init_comp_grp;
+			pr_err("Error! Init Comp Grp failed rc=%d\n", rc);
+			goto deinit_comp_grp;
 		}
 	}
 
@@ -1966,36 +2227,119 @@
 		rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
 			&bus_priv->vfe_out[i]);
 		if (rc < 0) {
-			pr_err("Error! Init VFE Out failed\n");
-			goto err_init_vfe_out;
+			pr_err("Error! Init VFE Out failed rc=%d\n", rc);
+			goto deinit_vfe_out;
 		}
 	}
 
-	INIT_LIST_HEAD(&bus_priv->free_payload_list);
-	for (i = 0; i < 128; i++) {
-		INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
-		list_add_tail(&bus_priv->evt_payload[i].list,
-			&bus_priv->free_payload_list);
+	INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
+	for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
+		INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
+		list_add_tail(&bus_priv->common_data.evt_payload[i].list,
+			&bus_priv->common_data.free_payload_list);
 	}
 
-	vfe_bus_local->acquire_resource = cam_vfe_bus_acquire_vfe_out;
-	vfe_bus_local->release_resource = cam_vfe_bus_release_vfe_out;
-	vfe_bus_local->start_resource   = cam_vfe_bus_start_vfe_out;
-	vfe_bus_local->stop_resource    = cam_vfe_bus_stop_vfe_out;
-	vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
+	vfe_bus_local->hw_ops.reserve      = cam_vfe_bus_acquire_vfe_out;
+	vfe_bus_local->hw_ops.release      = cam_vfe_bus_release_vfe_out;
+	vfe_bus_local->hw_ops.start        = cam_vfe_bus_start_hw;
+	vfe_bus_local->hw_ops.stop         = cam_vfe_bus_stop_hw;
+	vfe_bus_local->hw_ops.init         = cam_vfe_bus_init_hw;
+	vfe_bus_local->hw_ops.deinit       = cam_vfe_bus_deinit_hw;
+	vfe_bus_local->top_half_handler    = cam_vfe_bus_ver2_handle_irq;
 	vfe_bus_local->bottom_half_handler = NULL;
-	vfe_bus_local->process_cmd      = cam_vfe_bus_process_cmd;
+	vfe_bus_local->hw_ops.process_cmd  = cam_vfe_bus_process_cmd;
 
 	*vfe_bus = vfe_bus_local;
 
+	CDBG("Exit\n");
 	return rc;
 
-err_init_vfe_out:
-err_init_comp_grp:
-err_init_wm:
+deinit_vfe_out:
+	if (i < 0)
+		i = CAM_VFE_BUS_VER2_VFE_OUT_MAX;
+	for (--i; i >= 0; i--)
+		cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
+
+deinit_comp_grp:
+	if (i < 0)
+		i = CAM_VFE_BUS_VER2_COMP_GRP_MAX;
+	for (--i; i >= 0; i--)
+		cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
+
+deinit_wm:
+	if (i < 0)
+		i = CAM_VFE_BUS_VER2_MAX_CLIENTS;
+	for (--i; i >= 0; i--)
+		cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
+
+free_bus_priv:
 	kfree(vfe_bus_local->bus_priv);
-err_alloc_priv:
+
+free_bus_local:
 	kfree(vfe_bus_local);
-err_alloc_bus:
+
+end:
 	return rc;
 }
+
+int cam_vfe_bus_ver2_deinit(
+	struct cam_vfe_bus                  **vfe_bus)
+{
+	int i, rc = 0;
+	struct cam_vfe_bus_ver2_priv    *bus_priv = NULL;
+	struct cam_vfe_bus              *vfe_bus_local;
+
+	if (!vfe_bus || !*vfe_bus) {
+		pr_err("Error! Invalid input\n");
+		return -EINVAL;
+	}
+	vfe_bus_local = *vfe_bus;
+
+	bus_priv = vfe_bus_local->bus_priv;
+	if (!bus_priv) {
+		pr_err("Error! bus_priv is NULL\n");
+		rc = -ENODEV;
+		goto free_bus_local;
+	}
+
+	INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
+	for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++)
+		INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
+
+	for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
+		rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
+		if (rc < 0)
+			pr_err("Error! Deinit WM failed rc=%d\n", rc);
+	}
+
+	for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
+		rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
+		if (rc < 0)
+			pr_err("Error! Deinit Comp Grp failed rc=%d\n", rc);
+	}
+
+	for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
+		rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
+		if (rc < 0)
+			pr_err("Error! Deinit VFE Out failed rc=%d\n", rc);
+	}
+
+	INIT_LIST_HEAD(&bus_priv->free_comp_grp);
+	INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
+	INIT_LIST_HEAD(&bus_priv->used_comp_grp);
+
+	rc = cam_irq_controller_deinit(
+		&bus_priv->common_data.bus_irq_controller);
+	if (rc)
+		pr_err("Error! Deinit IRQ Controller failed rc=%d\n", rc);
+
+	kfree(vfe_bus_local->bus_priv);
+
+free_bus_local:
+	kfree(vfe_bus_local);
+
+	*vfe_bus = NULL;
+
+	return rc;
+}
+
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
index e451174..ba98077 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
@@ -171,18 +171,34 @@
  *
  * @Brief:                   Initialize Bus layer
  *
- * @mem_base:                Mapped base address of register space
+ * @soc_info:                Soc Information for the associated HW
  * @hw_intf:                 HW Interface of HW to which this resource belongs
  * @bus_hw_info:             BUS HW info that contains details of BUS registers
  * @vfe_irq_controller:      VFE IRQ Controller to use for subscribing to Top
  *                           level IRQs
  * @vfe_bus:                 Pointer to vfe_bus structure which will be filled
  *                           and returned on successful initialize
+ *
+ * @Return:                  0: Success
+ *                           Non-zero: Failure
  */
-int cam_vfe_bus_ver2_init(void __iomem   *mem_base,
+int cam_vfe_bus_ver2_init(
+	struct cam_hw_soc_info               *soc_info,
 	struct cam_hw_intf                   *hw_intf,
 	void                                 *bus_hw_info,
 	void                                 *vfe_irq_controller,
 	struct cam_vfe_bus                  **vfe_bus);
 
+/*
+ * cam_vfe_bus_ver2_deinit()
+ *
+ * @Brief:                   Deinitialize Bus layer
+ *
+ * @vfe_bus:                 Pointer to vfe_bus structure to deinitialize
+ *
+ * @Return:                  0: Success
+ *                           Non-zero: Failure
+ */
+int cam_vfe_bus_ver2_deinit(struct cam_vfe_bus     **vfe_bus);
+
 #endif /* _CAM_VFE_BUS_VER2_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
index d202c13..c089911 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
@@ -14,6 +14,7 @@
 #define _CAM_VFE_BUS_H_
 
 #include <uapi/media/cam_isp.h>
+#include "cam_hw_intf.h"
 #include "cam_isp_hw.h"
 
 #define CAM_VFE_BUS_VER_1_0 0x1000
@@ -31,25 +32,14 @@
  * @Brief:                   Bus interface structure
  *
  * @bus_priv:                Private data of BUS
- * @acquire_resource:        Function pointer for acquiring BUS output resource
- * @release_resource:        Function pointer for releasing BUS resource
- * @start_resource:          Function for starting BUS Output resource
- * @stop_resource:           Function for stopping BUS Output resource
- * @process_cmd:             Function to process commands specific to BUS
- *                           resources
+ * @hw_ops:                  Hardware interface functions
  * @top_half_handler:        Top Half handler function
  * @bottom_half_handler:     Bottom Half handler function
  */
 struct cam_vfe_bus {
 	void               *bus_priv;
 
-	int (*acquire_resource)(void *bus_priv, void *acquire_args);
-	int (*release_resource)(void *bus_priv,
-		struct cam_isp_resource_node *vfe_out);
-	int (*start_resource)(struct cam_isp_resource_node *vfe_out);
-	int (*stop_resource)(struct cam_isp_resource_node *vfe_out);
-	int (*process_cmd)(void *priv, uint32_t cmd_type, void *cmd_args,
-		uint32_t arg_size);
+	struct cam_hw_ops              hw_ops;
 	CAM_IRQ_HANDLER_TOP_HALF       top_half_handler;
 	CAM_IRQ_HANDLER_BOTTOM_HALF    bottom_half_handler;
 };
@@ -60,19 +50,36 @@
  * @Brief:                   Initialize Bus layer
  *
  * @bus_version:             Version of BUS to initialize
- * @mem_base:                Mapped base address of register space
+ * @soc_info:                Soc Information for the associated HW
  * @hw_intf:                 HW Interface of HW to which this resource belongs
  * @bus_hw_info:             BUS HW info that contains details of BUS registers
  * @vfe_irq_controller:      VFE IRQ Controller to use for subscribing to Top
  *                           level IRQs
  * @vfe_bus:                 Pointer to vfe_bus structure which will be filled
  *                           and returned on successful initialize
+ *
+ * @Return:                  0: Success
+ *                           Non-zero: Failure
  */
 int cam_vfe_bus_init(uint32_t          bus_version,
-	void __iomem                  *mem_base,
+	struct cam_hw_soc_info        *soc_info,
 	struct cam_hw_intf            *hw_intf,
 	void                          *bus_hw_info,
 	void                          *vfe_irq_controller,
 	struct cam_vfe_bus            **vfe_bus);
 
+/*
+ * cam_vfe_bus_deinit()
+ *
+ * @Brief:                   Deinitialize Bus layer
+ *
+ * @bus_version:             Version of BUS to deinitialize
+ * @vfe_bus:                 Pointer to vfe_bus structure to deinitialize
+ *
+ * @Return:                  0: Success
+ *                           Non-zero: Failure
+ */
+int cam_vfe_bus_deinit(uint32_t        bus_version,
+	struct cam_vfe_bus           **vfe_bus);
+
 #endif /* _CAM_VFE_BUS_ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index 6dd67df..fa00769 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
@@ -229,7 +229,7 @@
 	struct cam_vfe_camif_ver2_hw_info *camif_info = camif_hw_info;
 
 	camif_priv = kzalloc(sizeof(struct cam_vfe_mux_camif_data),
-			GFP_KERNEL);
+		GFP_KERNEL);
 	if (!camif_priv) {
 		CDBG("Error! Failed to alloc for camif_priv\n");
 		return -ENOMEM;
@@ -251,3 +251,24 @@
 	return 0;
 }
 
+int cam_vfe_camif_ver2_deinit(
+	struct cam_isp_resource_node  *camif_node)
+{
+	struct cam_vfe_mux_camif_data *camif_priv = camif_node->res_priv;
+
+	camif_node->start = NULL;
+	camif_node->stop  = NULL;
+	camif_node->top_half_handler = NULL;
+	camif_node->bottom_half_handler = NULL;
+
+	camif_node->res_priv = NULL;
+
+	if (!camif_priv) {
+		pr_err("Error! camif_priv is NULL\n");
+		return -ENODEV;
+	}
+
+	kfree(camif_priv);
+
+	return 0;
+}
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h
index cc6aab0..553abf2 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.h
@@ -75,4 +75,7 @@
 	void                          *camif_hw_info,
 	struct cam_isp_resource_node  *camif_node);
 
+int cam_vfe_camif_ver2_deinit(
+	struct cam_isp_resource_node  *camif_node);
+
 #endif /* _CAM_VFE_CAMIF_VER2_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
index 5f77a7c..f96f4d9 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
@@ -187,3 +187,23 @@
 	return 0;
 }
 
+int cam_vfe_rdi_ver2_deinit(
+	struct cam_isp_resource_node  *rdi_node)
+{
+	struct cam_vfe_mux_rdi_data *rdi_priv = rdi_node->res_priv;
+
+	rdi_node->start = NULL;
+	rdi_node->stop  = NULL;
+	rdi_node->top_half_handler = NULL;
+	rdi_node->bottom_half_handler = NULL;
+
+	rdi_node->res_priv = NULL;
+
+	if (!rdi_priv) {
+		pr_err("Error! rdi_priv NULL\n");
+		return -ENODEV;
+	}
+	kfree(rdi_priv);
+
+	return 0;
+}
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h
index 967cec3..9893474 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h
@@ -43,4 +43,7 @@
 	void                          *rdi_hw_info,
 	struct cam_isp_resource_node  *rdi_node);
 
+int cam_vfe_rdi_ver2_deinit(
+	struct cam_isp_resource_node  *rdi_node);
+
 #endif /* _CAM_VFE_RDI_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c
index e2bceb8..ee608fa 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top.c
@@ -36,3 +36,20 @@
 	return rc;
 }
 
+int cam_vfe_top_deinit(uint32_t        top_version,
+	struct cam_vfe_top           **vfe_top)
+{
+	int rc = -EINVAL;
+
+	switch (top_version) {
+	case CAM_VFE_TOP_VER_2_0:
+		rc = cam_vfe_top_ver2_deinit(vfe_top);
+		break;
+	default:
+		pr_err("Error! Unsupported Version %x\n", top_version);
+		break;
+	}
+
+	return rc;
+}
+
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index 3ef4f49..ce7c63e 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -359,7 +359,7 @@
 	if (!vfe_top) {
 		CDBG("Error! Failed to alloc for vfe_top\n");
 		rc = -ENOMEM;
-		goto err_alloc_top;
+		goto end;
 	}
 
 	top_priv = kzalloc(sizeof(struct cam_vfe_top_ver2_priv),
@@ -367,7 +367,7 @@
 	if (!top_priv) {
 		CDBG("Error! Failed to alloc for vfe_top_priv\n");
 		rc = -ENOMEM;
-		goto err_alloc_priv;
+		goto free_vfe_top;
 	}
 	vfe_top->top_priv = top_priv;
 
@@ -384,16 +384,16 @@
 				&ver2_hw_info->camif_hw_info,
 				&top_priv->mux_rsrc[i]);
 			if (rc)
-				goto err_mux_init;
+				goto deinit_resources;
 		} else {
 			/* set the RDI resource id */
 			top_priv->mux_rsrc[i].res_id =
-				CAM_ISP_HW_VFE_IN_RDI0 + j;
+				CAM_ISP_HW_VFE_IN_RDI0 + j++;
+
 			rc = cam_vfe_rdi_ver2_init(hw_intf, soc_info,
 				NULL, &top_priv->mux_rsrc[i]);
 			if (rc)
 				goto deinit_resources;
-			j++;
 		}
 	}
 
@@ -416,10 +416,71 @@
 	return rc;
 
 deinit_resources:
-err_mux_init:
+	for (--i; i >= 0; i--) {
+		if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) {
+			if (cam_vfe_camif_ver2_deinit(&top_priv->mux_rsrc[i]))
+				pr_err("Camif Deinit failed\n");
+		} else {
+			if (cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]))
+				pr_err("RDI Deinit failed\n");
+		}
+		top_priv->mux_rsrc[i].res_state =
+			CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+	}
+
 	kfree(vfe_top->top_priv);
-err_alloc_priv:
+free_vfe_top:
 	kfree(vfe_top);
-err_alloc_top:
+end:
 	return rc;
 }
+
+int cam_vfe_top_ver2_deinit(struct cam_vfe_top  **vfe_top_ptr)
+{
+	int i, rc = 0;
+	struct cam_vfe_top_ver2_priv           *top_priv = NULL;
+	struct cam_vfe_top                     *vfe_top;
+
+	if (!vfe_top_ptr) {
+		pr_err("Error! Invalid input\n");
+		return -EINVAL;
+	}
+
+	vfe_top = *vfe_top_ptr;
+	if (!vfe_top) {
+		pr_err("Error! vfe_top NULL\n");
+		return -ENODEV;
+	}
+
+	top_priv = vfe_top->top_priv;
+	if (!top_priv) {
+		pr_err("Error! vfe_top_priv NULL\n");
+		rc = -ENODEV;
+		goto free_vfe_top;
+	}
+
+	for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
+		top_priv->mux_rsrc[i].res_state =
+			CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+		if (top_priv->mux_rsrc[i].res_id ==
+			CAM_ISP_HW_VFE_IN_CAMIF) {
+			rc = cam_vfe_camif_ver2_deinit(&top_priv->mux_rsrc[i]);
+			if (rc)
+				pr_err("Error! Camif deinit failed rc=%d\n",
+					rc);
+		} else {
+			rc = cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]);
+			if (rc)
+				pr_err("Error! RDI deinit failed rc=%d\n", rc);
+		}
+	}
+
+	kfree(vfe_top->top_priv);
+
+free_vfe_top:
+	kfree(vfe_top);
+	*vfe_top_ptr = NULL;
+
+	return rc;
+}
+
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
index 1038721..0813202 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
@@ -58,6 +58,8 @@
 int cam_vfe_top_ver2_init(struct cam_hw_soc_info     *soc_info,
 	struct cam_hw_intf                           *hw_intf,
 	void                                         *top_hw_info,
-	struct cam_vfe_top                           **vfe_top);
+	struct cam_vfe_top                          **vfe_top);
+
+int cam_vfe_top_ver2_deinit(struct cam_vfe_top      **vfe_top);
 
 #endif /* _CAM_VFE_TOP_VER2_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
index 44c046d..dbb211f 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
@@ -50,4 +50,7 @@
 	void                          *top_hw_info,
 	struct cam_vfe_top            **vfe_top);
 
+int cam_vfe_top_deinit(uint32_t        top_version,
+	struct cam_vfe_top           **vfe_top);
+
 #endif /* _CAM_VFE_TOP_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/Makefile b/drivers/media/platform/msm/camera/cam_req_mgr/Makefile
index e6da6ca..f514139 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/Makefile
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/Makefile
@@ -1,4 +1,6 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core/
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
 
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_req_mgr_dev.o \
 				cam_req_mgr_util.o \
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
index edfc245..2f9db97 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
@@ -735,18 +735,19 @@
 		if (tbl.bufq[idx].i_hdl && tbl.bufq[idx].kmdvaddr)
 			ion_unmap_kernel(tbl.client, tbl.bufq[idx].i_hdl);
 
-	if (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_READ_WRITE ||
-		tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) {
-
+	/* SHARED flag gets precedence, all other flags after it */
+	if (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) {
+		region = CAM_SMMU_REGION_SHARED;
+	} else {
 		if (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_READ_WRITE)
 			region = CAM_SMMU_REGION_IO;
-
-		if (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_SHARED_ACCESS)
-			region = CAM_SMMU_REGION_SHARED;
-
-		rc = cam_mem_util_unmap_hw_va(idx, region);
 	}
 
+	if (tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_READ_WRITE ||
+		tbl.bufq[idx].flags & CAM_MEM_FLAG_HW_SHARED_ACCESS)
+		rc = cam_mem_util_unmap_hw_va(idx, region);
+
+
 	mutex_lock(&tbl.bufq[idx].q_lock);
 	tbl.bufq[idx].flags = 0;
 	tbl.bufq[idx].buf_handle = -1;
@@ -820,15 +821,16 @@
 	uint32_t mem_handle;
 	int32_t smmu_hdl = 0;
 	int32_t num_hdl = 0;
-	enum cam_smmu_region_id region;
+	enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED;
 
 	if (!inp || !out) {
 		pr_err("Invalid params\n");
 		return -EINVAL;
 	}
 
-	if (inp->region != CAM_MEM_MGR_REGION_SHARED &&
-		inp->region != CAM_MEM_MGR_REGION_NON_SECURE_IO) {
+	if (!(inp->flags & CAM_MEM_FLAG_HW_READ_WRITE ||
+		inp->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS ||
+		inp->flags & CAM_MEM_FLAG_CACHE)) {
 		pr_err("Invalid flags for request mem\n");
 		return -EINVAL;
 	}
@@ -866,11 +868,13 @@
 		goto smmu_fail;
 	}
 
-	if (inp->region == CAM_MEM_MGR_REGION_SHARED)
+	/* SHARED flag gets precedence, all other flags after it */
+	if (inp->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) {
 		region = CAM_SMMU_REGION_SHARED;
-
-	if (inp->region == CAM_MEM_MGR_REGION_NON_SECURE_IO)
-		region = CAM_SMMU_REGION_IO;
+	} else {
+		if (inp->flags & CAM_MEM_FLAG_HW_READ_WRITE)
+			region = CAM_SMMU_REGION_IO;
+	}
 
 	rc = cam_smmu_map_iova(inp->smmu_hdl,
 		ion_fd,
@@ -915,13 +919,13 @@
 	out->smmu_hdl = smmu_hdl;
 	out->mem_handle = mem_handle;
 	out->len = inp->size;
-	out->region = inp->region;
+	out->region = region;
 
 	return rc;
 slot_fail:
 	cam_smmu_unmap_iova(inp->smmu_hdl,
 		ion_fd,
-		inp->region);
+		region);
 smmu_fail:
 	ion_unmap_kernel(tbl.client, hdl);
 map_fail:
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h
index 32a754e..0858b8a 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr_api.h
@@ -14,13 +14,7 @@
 #define _CAM_MEM_MGR_API_H_
 
 #include <media/cam_req_mgr.h>
-
-/* Region IDs for memory manager */
-#define CAM_MEM_MGR_REGION_FIRMWARE      0
-#define CAM_MEM_MGR_REGION_SHARED        1
-#define CAM_MEM_MGR_REGION_NON_SECURE_IO 2
-#define CAM_MEM_MGR_REGION_SECURE_IO     3
-#define CAM_MEM_MGR_REGION_SCRATCH       4
+#include "cam_smmu_api.h"
 
 /**
  * struct cam_mem_mgr_request_desc
@@ -36,7 +30,6 @@
 	uint64_t align;
 	int32_t smmu_hdl;
 	uint32_t flags;
-	uint32_t region;
 };
 
 /**
@@ -55,7 +48,7 @@
 	int32_t smmu_hdl;
 	uint32_t mem_handle;
 	uint64_t len;
-	uint32_t region;
+	enum cam_smmu_region_id region;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index ed251eb..f5dfcf2 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -19,6 +19,7 @@
 #include "cam_req_mgr_core.h"
 #include "cam_req_mgr_workq.h"
 #include "cam_req_mgr_debug.h"
+#include "cam_trace.h"
 
 static struct cam_req_mgr_core_device *g_crm_core_dev;
 
@@ -975,7 +976,7 @@
  * cam_req_mgr_process_flush_req()
  *
  * @brief: This runs in workque thread context. Call core funcs to check
- *         which requests need to be removedcancelled.
+ *         which requests need to be removed/cancelled.
  * @priv : link information.
  * @data : contains information about frame_id, link etc.
  *
@@ -1007,6 +1008,8 @@
 
 	in_q = link->req.in_q;
 
+	trace_cam_flush_req(flush_info);
+
 	mutex_lock(&link->req.lock);
 	if (flush_info->flush_type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
 		for (i = 0; i < in_q->num_slots; i++) {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/Makefile
index 8670d80..4e8ea8b 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/Makefile
@@ -1,8 +1,10 @@
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
 
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator_dev.o cam_actuator_core.o cam_actuator_soc.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
index 0a96f18..37dbf9e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -13,7 +13,8 @@
 #include <linux/module.h>
 #include <cam_sensor_cmn_header.h>
 #include "cam_actuator_core.h"
-#include <cam_sensor_util.h>
+#include "cam_sensor_util.h"
+#include "cam_trace.h"
 
 int32_t cam_actuator_slaveInfo_pkt_parser(struct cam_actuator_ctrl_t *a_ctrl,
 	uint32_t *cmd_buf)
@@ -111,6 +112,9 @@
 		return -EINVAL;
 	}
 	request_id = apply->request_id % MAX_PER_FRAME_ARRAY;
+
+	trace_cam_apply_req("Actuator", apply);
+
 	CDBG("%s:%d Request Id: %lld\n",
 		__func__, __LINE__, apply->request_id);
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
index 48e3c2e..f8ea769 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
@@ -14,6 +14,7 @@
 #include "cam_req_mgr_dev.h"
 #include "cam_actuator_soc.h"
 #include "cam_actuator_core.h"
+#include "cam_trace.h"
 
 static long cam_actuator_subdev_ioctl(struct v4l2_subdev *sd,
 	unsigned int cmd, void *arg)
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/Makefile
index 57dfed5..ba81259 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/Makefile
@@ -3,5 +3,6 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_cci_dev.o cam_cci_core.o cam_cci_soc.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/Makefile
index 0337b32..8edbea5 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/Makefile
@@ -4,5 +4,6 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_csiphy_soc.o cam_csiphy_dev.o cam_csiphy_core.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 71a88bf..6b20bcc 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -37,7 +37,7 @@
 	base = soc_info->reg_map[0].mem_base;
 
 	for (i = 0; i < size; i++) {
-		cam_io_w(
+		cam_io_w_mb(
 			csiphy_dev->ctrl_reg->
 			csiphy_reset_reg[i].reg_data,
 			base +
@@ -128,7 +128,7 @@
 		csiphy_dev->soc_info.reg_map[0].mem_base;
 
 	for (i = 0; i < csiphy_dev->num_irq_registers; i++)
-		cam_io_w(csiphy_dev->ctrl_reg->
+		cam_io_w_mb(csiphy_dev->ctrl_reg->
 			csiphy_irq_reg[i].reg_data,
 			csiphybase +
 			csiphy_dev->ctrl_reg->
@@ -142,7 +142,7 @@
 		csiphy_dev->soc_info.reg_map[0].mem_base;
 
 	for (i = 0; i < csiphy_dev->num_irq_registers; i++)
-		cam_io_w(0x0,
+		cam_io_w_mb(0x0,
 			csiphybase +
 			csiphy_dev->ctrl_reg->
 			csiphy_irq_reg[i].reg_addr);
@@ -171,22 +171,22 @@
 			base +
 			csiphy_dev->ctrl_reg->csiphy_reg.
 			mipi_csiphy_interrupt_status0_addr + 0x4*i);
-		cam_io_w(irq,
+		cam_io_w_mb(irq,
 			base +
 			csiphy_dev->ctrl_reg->csiphy_reg.
 			mipi_csiphy_interrupt_clear0_addr + 0x4*i);
 		pr_err_ratelimited(
 			"%s CSIPHY%d_IRQ_STATUS_ADDR%d = 0x%x\n",
 			__func__, soc_info->index, i, irq);
-		cam_io_w(0x0,
+		cam_io_w_mb(0x0,
 			base +
 			csiphy_dev->ctrl_reg->csiphy_reg.
 			mipi_csiphy_interrupt_clear0_addr + 0x4*i);
 	}
-	cam_io_w(0x1, base +
+	cam_io_w_mb(0x1, base +
 		csiphy_dev->ctrl_reg->
 		csiphy_reg.mipi_csiphy_glbl_irq_cmd_addr);
-	cam_io_w(0x0, base +
+	cam_io_w_mb(0x0, base +
 		csiphy_dev->ctrl_reg->
 		csiphy_reg.mipi_csiphy_glbl_irq_cmd_addr);
 
@@ -198,7 +198,8 @@
 	int32_t      rc = 0;
 	uint32_t     lane_enable = 0, mask = 1, size = 0;
 	uint16_t     lane_mask = 0, i = 0, cfg_size = 0;
-	uint8_t      settle_cnt, lane_cnt, lane_pos = 0;
+	uint8_t      lane_cnt, lane_pos = 0;
+	uint16_t     settle_cnt = 0;
 	void __iomem *csiphybase;
 	struct csiphy_reg_t (*reg_array)[MAX_SETTINGS_PER_LANE];
 
@@ -257,13 +258,13 @@
 		switch (csiphy_dev->ctrl_reg->
 			csiphy_common_reg[i].csiphy_param_type) {
 			case CSIPHY_LANE_ENABLE:
-				cam_io_w(lane_enable,
+				cam_io_w_mb(lane_enable,
 					csiphybase +
 					csiphy_dev->ctrl_reg->
 					csiphy_common_reg[i].reg_addr);
 			break;
 			case CSIPHY_DEFAULT_PARAMS:
-				cam_io_w(csiphy_dev->ctrl_reg->
+				cam_io_w_mb(csiphy_dev->ctrl_reg->
 					csiphy_common_reg[i].reg_data,
 					csiphybase +
 					csiphy_dev->ctrl_reg->
@@ -284,22 +285,22 @@
 		for (i = 0; i < cfg_size; i++) {
 			switch (reg_array[lane_pos][i].csiphy_param_type) {
 			case CSIPHY_LANE_ENABLE:
-				cam_io_w(lane_enable,
+				cam_io_w_mb(lane_enable,
 					csiphybase +
 					reg_array[lane_pos][i].reg_addr);
 			break;
 			case CSIPHY_DEFAULT_PARAMS:
-				cam_io_w(reg_array[lane_pos][i].reg_data,
+				cam_io_w_mb(reg_array[lane_pos][i].reg_data,
 					csiphybase +
 					reg_array[lane_pos][i].reg_addr);
 			break;
 			case CSIPHY_SETTLE_CNT_LOWER_BYTE:
-				cam_io_w(settle_cnt & 0xFF,
+				cam_io_w_mb(settle_cnt & 0xFF,
 					csiphybase +
 					reg_array[lane_pos][i].reg_addr);
 			break;
 			case CSIPHY_SETTLE_CNT_HIGHER_BYTE:
-				cam_io_w((settle_cnt >> 8) & 0xFF,
+				cam_io_w_mb((settle_cnt >> 8) & 0xFF,
 					csiphybase +
 					reg_array[lane_pos][i].reg_addr);
 			break;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/Makefile
index d8c75fb..5a9441f 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/Makefile
@@ -1,8 +1,10 @@
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
-ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
 
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_dev.o cam_sensor_core.o cam_sensor_soc.o
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 031c340..be8306c 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
@@ -13,8 +13,9 @@
 #include <linux/module.h>
 #include <cam_sensor_cmn_header.h>
 #include "cam_sensor_core.h"
-#include <cam_sensor_util.h>
+#include "cam_sensor_util.h"
 #include "cam_soc_util.h"
+#include "cam_trace.h"
 
 static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
 	void *arg)
@@ -1004,6 +1005,9 @@
 	}
 	CDBG("%s:%d Req Id: %lld\n", __func__, __LINE__,
 		apply->request_id);
+
+	trace_cam_apply_req("Sensor", apply);
+
 	rc = cam_sensor_apply_settings(s_ctrl, apply->request_id);
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/Makefile
index 6292a9f..4c3b8e8 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/Makefile
@@ -4,5 +4,6 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io.o cam_sensor_cci_i2c.o cam_sensor_qup_i2c.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile
index 770391c..bf61fb3 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile
@@ -2,5 +2,6 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 
 obj-$(CONFIG_SPECTRA_CAMERA) +=  cam_sensor_util.o
diff --git a/drivers/media/platform/msm/camera/cam_utils/Makefile b/drivers/media/platform/msm/camera/cam_utils/Makefile
index f22115c..370651f 100644
--- a/drivers/media/platform/msm/camera/cam_utils/Makefile
+++ b/drivers/media/platform/msm/camera/cam_utils/Makefile
@@ -1,3 +1,5 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core/
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
 
-obj-$(CONFIG_SPECTRA_CAMERA) += cam_soc_util.o cam_io_util.o cam_packet_util.o
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_soc_util.o cam_io_util.o cam_packet_util.o cam_debug_util.o cam_trace.o
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
new file mode 100644
index 0000000..eb5e7d8
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
@@ -0,0 +1,101 @@
+/* Copyright (c) 2017, The Linux Foundataion. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include "cam_debug_util.h"
+
+static const char *cam_debug_module_id_to_name(unsigned int module_id)
+{
+	const char *name = NULL;
+
+	switch (module_id) {
+	case CAM_CDM:
+		name = "CAM-CDM";
+		break;
+	case CAM_CORE:
+		name = "CAM-CORE";
+		break;
+	case CAM_CRM:
+		name = "CAM_CRM";
+		break;
+	case CAM_CPAS:
+		name = "CAM-CPAS";
+		break;
+	case CAM_ISP:
+		name = "CAM-ISP";
+		break;
+	case CAM_SENSOR:
+		name = "CAM-SENSOR";
+		break;
+	case CAM_SMMU:
+		name = "CAM-SMMU";
+		break;
+	case CAM_SYNC:
+		name = "CAM-SYNC";
+		break;
+	case CAM_ICP:
+		name = "CAM-ICP";
+		break;
+	case CAM_JPEG:
+		name = "CAM-JPEG";
+		break;
+	case CAM_FD:
+		name = "CAM-FD";
+		break;
+	case CAM_LRME:
+		name = "CAM-LRME";
+		break;
+	case CAM_FLASH:
+		name = "CAM-FLASH";
+		break;
+	default:
+		name = "CAM";
+		break;
+	}
+
+	return name;
+}
+
+void cam_debug_log(unsigned int module_id, enum cam_debug_level dbg_level,
+	const char *func, const int line, const char *fmt, ...)
+{
+	char str_buffer[STR_BUFFER_MAX_LENGTH];
+	const char *module_name;
+	va_list args;
+
+	va_start(args, fmt);
+	vsnprintf(str_buffer, STR_BUFFER_MAX_LENGTH, fmt, args);
+	va_end(args);
+
+	module_name = cam_debug_module_id_to_name(module_id);
+
+	switch (dbg_level) {
+	case CAM_LEVEL_INFO:
+		pr_info("CAM_INFO: %s: %s: %d: %s\n",
+			module_name, func, line, str_buffer);
+		break;
+	case CAM_LEVEL_WARN:
+		pr_warn("CAM_WARN: %s: %s: %d: %s\n",
+			module_name, func, line, str_buffer);
+		break;
+	case CAM_LEVEL_ERR:
+		pr_err("CAM_ERR: %s: %s: %d: %s\n",
+			module_name, func, line, str_buffer);
+		break;
+	case CAM_LEVEL_DBG:
+		pr_info("CAM_DBG: %s: %s: %d: %s\n",
+			module_name, func, line, str_buffer);
+		break;
+	default:
+		break;
+	}
+}
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
index 5989f1a..34adb0e 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundataion. All rights reserved.
+/* 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
@@ -13,7 +13,6 @@
 #ifndef _CAM_DEBUG_UTIL_H_
 #define _CAM_DEBUG_UTIL_H_
 
-#define DEFAULT     0xFFFF
 #define CAM_CDM    (1 << 0)
 #define CAM_CORE   (1 << 1)
 #define CAM_CPAS   (1 << 2)
@@ -26,32 +25,91 @@
 #define CAM_JPEG   (1 << 9)
 #define CAM_FD     (1 << 10)
 #define CAM_LRME   (1 << 11)
+#define CAM_FLASH  (1 << 12)
 
-#define GROUP      DEFAULT
-#define TRACE_ON   0
+#define STR_BUFFER_MAX_LENGTH  1024
+#define GROUP                  0x0000
 
-#define CAM_ERR(__module, fmt, args...)                                      \
-	do { if (GROUP & __module) {                                         \
-		if (TRACE_ON)                                                \
-			trace_printk(fmt, ##args);                           \
-		else                                                         \
-			pr_err(fmt, ##args);                                 \
-	} } while (0)
+enum cam_debug_level {
+	CAM_LEVEL_INFO,
+	CAM_LEVEL_WARN,
+	CAM_LEVEL_ERR,
+	CAM_LEVEL_DBG,
+};
 
-#define CAM_WARN(__module, fmt, args...)                                     \
-	do { if (GROUP & __module) {                                         \
-		if (TRACE_ON)                                                \
-			trace_printk(fmt, ##args);                           \
-		else                                                         \
-			pr_warn(fmt, ##args);                                \
-	} } while (0)
+/*
+ *  cam_debug_log()
+ *
+ * @brief:        Get the Module name form module ID and print
+ *                respective debug logs
+ *
+ * @module_id :  Respective Module ID which is calling this function
+ * @dbg_level :  Debug level from cam_module_debug_level enum entries
+ * @func :       Function which is calling to print logs
+ * @line :       Line number associated with the function which is calling
+ *               to print log
+ * @fmt  :       Formatted string which needs to be print in the log
+ *
+ */
+void cam_debug_log(unsigned int module_id, enum cam_debug_level dbg_level,
+	const char *func, const int line, const char *fmt, ...);
 
-#define CAM_INFO(__module, fmt, args...)                                     \
-	do { if (GROUP & __module) {                                         \
-		if (TRACE_ON)                                                \
-			trace_printk(fmt, ##args);                           \
-		else                                                         \
-			pr_info(fmt, ##args);                                \
-	} } while (0)
+/*
+ * CAM_ERR
+ * @brief :     This Macro will print error logs
+ *
+ * @__module :  Respective module id which is been calling this Macro
+ * @fmt :       Formatted string which needs to be print in log
+ * @args:       Arguments which needs to be print in log
+ */
+#define CAM_ERR(__module, fmt, args...)                            \
+	{                                                          \
+		cam_debug_log(__module, CAM_LEVEL_ERR,             \
+			__func__, __LINE__, fmt, ##args);          \
+	}
+
+/*
+ * CAM_WARN
+ * @brief :     This Macro will print warning logs
+ *
+ * @__module :  Respective module id which is been calling this Macro
+ * @fmt      :  Formatted string which needs to be print in log
+ * @args     :  Arguments which needs to be print in log
+ */
+#define CAM_WARN(__module, fmt, args...)                           \
+	{                                                          \
+		cam_debug_log(__module, CAM_LEVEL_WARN,            \
+			__func__, __LINE__, fmt, ##args);          \
+	}
+
+/*
+ * CAM_INFO
+ * @brief :     This Macro will print Information logs
+ *
+ * @__module :  Respective module id which is been calling this Macro
+ * @fmt      :  Formatted string which needs to be print in log
+ * @args     :  Arguments which needs to be print in log
+ */
+#define CAM_INFO(__module, fmt, args...)                           \
+	{                                                          \
+		cam_debug_log(__module, CAM_LEVEL_INFO,            \
+			__func__, __LINE__, fmt, ##args);          \
+	}
+
+/*
+ * CAM_DBG
+ * @brief :     This Macro will print debug logs when enabled using GROUP
+ *
+ * @__module :  Respective module id which is been calling this Macro
+ * @fmt      :  Formatted string which needs to be print in log
+ * @args     :  Arguments which needs to be print in log
+ */
+#define CAM_DBG(__module, fmt, args...)                            \
+	do {                                                       \
+		if (GROUP & __module) {                            \
+			cam_debug_log(__module, CAM_LEVEL_DBG,     \
+				__func__, __LINE__, fmt, ##args);  \
+		}                                                  \
+	} while (0)
 
 #endif /* _CAM_DEBUG_UTIL_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
index 0be2aaa..1d86bb1 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
@@ -574,7 +574,7 @@
 		goto free_gpio_array;
 	}
 
-	for (i = 0; i <= gpio_array_size; i++)
+	for (i = 0; i < gpio_array_size; i++)
 		gconf->cam_gpio_common_tbl[i].gpio = gpio_array[i];
 
 	gconf->cam_gpio_common_tbl_size = gpio_array_size;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_trace.c b/drivers/media/platform/msm/camera/cam_utils/cam_trace.c
new file mode 100644
index 0000000..08129f3
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_trace.c
@@ -0,0 +1,16 @@
+/* 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.
+ *
+ */
+
+/* Instantiate tracepoints */
+#define CREATE_TRACE_POINTS
+#include "cam_trace.h"
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_trace.h b/drivers/media/platform/msm/camera/cam_utils/cam_trace.h
new file mode 100644
index 0000000..f233799
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_trace.h
@@ -0,0 +1,128 @@
+/* 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.
+ *
+ */
+
+#if !defined(_CAM_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _CAM_TRACE_H
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM camera
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE cam_trace
+
+#include <linux/tracepoint.h>
+#include <media/cam_req_mgr.h>
+#include "cam_context.h"
+
+TRACE_EVENT(cam_context_state,
+	TP_PROTO(const char *name, struct cam_context *ctx),
+	TP_ARGS(name, ctx),
+	TP_STRUCT__entry(
+		__field(void*, ctx)
+		__field(uint32_t, state)
+		__string(name, name)
+	),
+	TP_fast_assign(
+		__entry->ctx = ctx;
+		__entry->state = ctx->state;
+		__assign_str(name, name);
+	),
+	TP_printk(
+		"%s: State ctx=%p ctx_state=%u",
+			__get_str(name), __entry->ctx, __entry->state
+	)
+);
+
+TRACE_EVENT(cam_isp_activated_irq,
+	TP_PROTO(struct cam_context *ctx, unsigned int substate,
+		unsigned int event, uint64_t timestamp),
+	TP_ARGS(ctx, substate, event, timestamp),
+	TP_STRUCT__entry(
+		__field(void*, ctx)
+		__field(uint32_t, state)
+		__field(uint32_t, substate)
+		__field(uint32_t, event)
+		__field(uint64_t, ts)
+	),
+	TP_fast_assign(
+		__entry->ctx = ctx;
+		__entry->state = ctx->state;
+		__entry->substate = substate;
+		__entry->event = event;
+		__entry->ts = timestamp;
+	),
+	TP_printk(
+		"ISP: IRQ ctx=%p ctx_state=%u substate=%u event=%u ts=%llu",
+			__entry->ctx, __entry->state, __entry->substate,
+			__entry->event, __entry->ts
+	)
+);
+
+TRACE_EVENT(cam_buf_done,
+	TP_PROTO(const char *ctx_type, struct cam_context *ctx,
+		struct cam_ctx_request *req),
+	TP_ARGS(ctx_type, ctx, req),
+	TP_STRUCT__entry(
+		__string(ctx_type, ctx_type)
+		__field(void*, ctx)
+		__field(uint64_t, request)
+	),
+	TP_fast_assign(
+		__assign_str(ctx_type, ctx_type);
+		__entry->ctx = ctx;
+		__entry->request = req->request_id;
+	),
+	TP_printk(
+		"%5s: BufDone ctx=%p request=%llu",
+			__get_str(ctx_type), __entry->ctx, __entry->request
+	)
+);
+
+TRACE_EVENT(cam_apply_req,
+	TP_PROTO(const char *entity, struct cam_req_mgr_apply_request *req),
+	TP_ARGS(entity, req),
+	TP_STRUCT__entry(
+		__string(entity, entity)
+		__field(uint64_t, req_id)
+	),
+	TP_fast_assign(
+		__assign_str(entity, entity);
+		__entry->req_id = req->request_id;
+	),
+	TP_printk(
+		"%8s: ApplyRequest request=%llu",
+			__get_str(entity), __entry->req_id
+	)
+);
+
+TRACE_EVENT(cam_flush_req,
+	TP_PROTO(struct cam_req_mgr_flush_info *info),
+	TP_ARGS(info),
+	TP_STRUCT__entry(
+		__field(uint32_t, type)
+		__field(int64_t, req_id)
+	),
+	TP_fast_assign(
+		__entry->type   = info->flush_type;
+		__entry->req_id = info->req_id;
+	),
+	TP_printk(
+		"FlushRequest type=%u request=%llu",
+			__entry->type, __entry->req_id
+	)
+);
+#endif /* _CAM_TRACE_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
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 a195c15..df2642c 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -2583,6 +2583,7 @@
 {
 	int ret = 0, i;
 	int usecases;
+	struct device_node *node;
 
 	mgr->data_bus.bus_scale_pdata = msm_bus_cl_get_pdata(dev);
 	if (IS_ERR_OR_NULL(mgr->data_bus.bus_scale_pdata)) {
@@ -2594,12 +2595,27 @@
 		}
 	}
 
-	mgr->reg_bus.bus_scale_pdata = &rot_reg_bus_scale_table;
-	usecases = mgr->reg_bus.bus_scale_pdata->num_usecases;
-	for (i = 0; i < usecases; i++) {
-		rot_reg_bus_usecases[i].num_paths = 1;
-		rot_reg_bus_usecases[i].vectors =
-			&rot_reg_bus_vectors[i];
+	node = of_get_child_by_name(dev->dev.of_node, "qcom,rot-reg-bus");
+	if (node) {
+		mgr->reg_bus.bus_scale_pdata
+				= msm_bus_pdata_from_node(dev, node);
+		if (IS_ERR_OR_NULL(mgr->reg_bus.bus_scale_pdata)) {
+			SDEROT_ERR("reg bus pdata parsing failed\n");
+			ret = PTR_ERR(mgr->reg_bus.bus_scale_pdata);
+			if (!mgr->reg_bus.bus_scale_pdata)
+				ret = -EINVAL;
+			mgr->reg_bus.bus_scale_pdata = NULL;
+		}
+	} else {
+		SDEROT_DBG(
+			"no DT entries, configuring default reg bus table\n");
+		mgr->reg_bus.bus_scale_pdata = &rot_reg_bus_scale_table;
+		usecases = mgr->reg_bus.bus_scale_pdata->num_usecases;
+		for (i = 0; i < usecases; i++) {
+			rot_reg_bus_usecases[i].num_paths = 1;
+			rot_reg_bus_usecases[i].vectors =
+				&rot_reg_bus_vectors[i];
+		}
 	}
 
 	return ret;
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 743d2f7..205eeef 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -1446,6 +1446,9 @@
 
 		if (bw > 0xFF)
 			bw = 0xFF;
+		else if (bw == 0)
+			bw = 1;
+
 		SDE_REGDMA_WRITE(wrptr, ROT_WB_TRAFFIC_SHAPER_WR_CLIENT,
 				BIT(31) | (cfg->prefill_bw ? BIT(27) : 0) | bw);
 		SDEROT_DBG("Enable ROT_WB Traffic Shaper:%d\n", bw);
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 9f8b341..a7b1852 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
@@ -846,10 +846,6 @@
 	if (!dev || !freq)
 		return -EINVAL;
 
-	/* Start with highest frequecy and decide correct one later*/
-
-	ab_kbps = INT_MAX;
-
 	gov = container_of(dev->governor,
 			struct governor, devfreq_gov);
 	dev->profile->get_dev_status(dev->dev.parent, &stats);
@@ -860,11 +856,11 @@
 
 	for (c = 0; c < vidc_data->data_count; ++c) {
 		if (vidc_data->data->power_mode == VIDC_POWER_TURBO) {
+			ab_kbps = INT_MAX;
 			goto exit;
 		}
 	}
 
-	ab_kbps = 0;
 	for (c = 0; c < vidc_data->data_count; ++c)
 		ab_kbps += __calculate(&vidc_data->data[c], gov->mode);
 
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 1991a34..32e79f2 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1360,11 +1360,15 @@
 		pkt->rg_property_data[0] =
 			HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR;
 		hfi = (struct hfi_conceal_color *) &pkt->rg_property_data[1];
-		if (hfi)
-			hfi->conceal_color =
+		if (hfi) {
+			hfi->conceal_color_8bit =
 				((struct hfi_conceal_color *) pdata)->
-				conceal_color;
-		pkt->size += sizeof(u32) * 2;
+				conceal_color_8bit;
+			hfi->conceal_color_10bit =
+				((struct hfi_conceal_color *) pdata)->
+				conceal_color_10bit;
+		}
+		pkt->size += sizeof(u32) + sizeof(struct hfi_conceal_color);
 		break;
 	}
 	case HAL_PARAM_VPE_ROTATION:
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index c2a93a96..e5d1576 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -337,26 +337,26 @@
 	cmd_done.device_id = device_id;
 	cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
 	cmd_done.status = hfi_map_err_status(pkt->event_data1);
+	info->response.cmd = cmd_done;
 	dprintk(VIDC_INFO, "Received: SESSION_ERROR with event id : %#x %#x\n",
 		pkt->event_data1, pkt->event_data2);
 	switch (pkt->event_data1) {
+	/* Ignore below errors */
 	case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
-	case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
-	case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
 	case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
-		cmd_done.status = VIDC_ERR_NONE;
 		dprintk(VIDC_INFO, "Non Fatal: HFI_EVENT_SESSION_ERROR\n");
 		info->response_type = HAL_RESPONSE_UNUSED;
-		info->response.cmd = cmd_done;
-		return 0;
+		break;
 	default:
+		/* All other errors are not expected and treated as sys error */
 		dprintk(VIDC_ERR,
-			"HFI_EVENT_SESSION_ERROR: data1 %#x, data2 %#x\n",
-			pkt->event_data1, pkt->event_data2);
-		info->response_type = HAL_SESSION_ERROR;
-		info->response.cmd = cmd_done;
-		return 0;
+			"%s: data1 %#x, data2 %#x, treat as sys error\n",
+			__func__, pkt->event_data1, pkt->event_data2);
+		info->response_type = HAL_SYS_ERROR;
+		break;
 	}
+
+	return 0;
 }
 
 static int hfi_process_event_notify(u32 device_id,
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index acca9f4..472beb1 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -24,7 +24,8 @@
 #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS MIN_NUM_CAPTURE_BUFFERS
 #define MIN_NUM_DEC_OUTPUT_BUFFERS 4
 #define MIN_NUM_DEC_CAPTURE_BUFFERS 4
-#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8010
+// Y=16(0-9bits), Cb(10-19bits)=Cr(20-29bits)=128, black by default
+#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010
 #define MB_SIZE_IN_PIXEL (16 * 16)
 #define OPERATING_FRAME_RATE_STEP (1 << 16)
 
@@ -264,11 +265,20 @@
 		.flags = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
 	},
 	{
-		.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR,
-		.name = "Picture concealed color",
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT,
+		.name = "Picture concealed color 8bit",
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.minimum = 0x0,
-		.maximum = 0xffffff,
+		.maximum = 0xff3fcff,
+		.default_value = DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
+		.step = 1,
+	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_10BIT,
+		.name = "Picture concealed color 10bit",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = 0x0,
+		.maximum = 0x3fffffff,
 		.default_value = DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
 		.step = 1,
 	},
@@ -804,6 +814,10 @@
 		}
 		bufreq->buffer_count_min =
 			MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+		bufreq->buffer_count_min_host =
+			MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+		bufreq->buffer_count_actual =
+			MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
 
 		if (msm_comm_get_stream_output_mode(inst) ==
 				HAL_VIDEO_DECODER_SECONDARY) {
@@ -819,6 +833,10 @@
 
 			bufreq->buffer_count_min =
 				MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS;
+			bufreq->buffer_count_min_host =
+				MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+			bufreq->buffer_count_actual =
+				MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
 
 			bufreq = get_buff_req_buffer(inst,
 					HAL_BUFFER_OUTPUT2);
@@ -831,6 +849,11 @@
 
 			bufreq->buffer_count_min =
 				MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS;
+			bufreq->buffer_count_min_host =
+				MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+			bufreq->buffer_count_actual =
+				MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+
 		} else {
 
 			bufreq = get_buff_req_buffer(inst,
@@ -843,6 +866,10 @@
 			}
 			bufreq->buffer_count_min =
 				MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS;
+			bufreq->buffer_count_min_host =
+				MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+			bufreq->buffer_count_actual =
+				MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
 
 		}
 
@@ -974,11 +1001,6 @@
 			break;
 		}
 		break;
-	case V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR:
-		property_id = HAL_PARAM_VDEC_CONCEAL_COLOR;
-		property_val = ctrl->val;
-		pdata = &property_val;
-		break;
 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_LEVEL);
 		property_id =
@@ -1067,29 +1089,37 @@
 	int rc = 0, i = 0, fourcc = 0;
 	struct v4l2_ext_control *ext_control;
 	struct v4l2_control control;
+	struct hal_conceal_color conceal_color = {0};
+	struct hfi_device *hdev;
 
-	if (!inst || !inst->core || !ctrl) {
+	if (!inst || !inst->core || !inst->core->device || !ctrl) {
 		dprintk(VIDC_ERR,
 			"%s invalid parameters\n", __func__);
 		return -EINVAL;
 	}
 
+	hdev = inst->core->device;
+
+	v4l2_try_ext_ctrls(&inst->ctrl_handler, ctrl);
+
 	ext_control = ctrl->controls;
-	control.id =
-		V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
 
 	for (i = 0; i < ctrl->count; i++) {
 		switch (ext_control[i].id) {
 		case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE:
 			control.value = ext_control[i].value;
-
+			control.id =
+				V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
 			rc = msm_comm_s_ctrl(inst, &control);
 			if (rc)
 				dprintk(VIDC_ERR,
 					"%s Failed setting stream output mode : %d\n",
 					__func__, rc);
+			rc = msm_vidc_update_host_buff_counts(inst);
 			break;
 		case V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT:
+			control.id =
+				V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
 			switch (ext_control[i].value) {
 			case V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE:
 				if (!msm_comm_g_ctrl_for_id(inst, control.id)) {
@@ -1125,6 +1155,7 @@
 						break;
 					}
 				}
+				rc = msm_vidc_update_host_buff_counts(inst);
 				inst->clk_data.dpb_fourcc = fourcc;
 				break;
 			default:
@@ -1135,6 +1166,36 @@
 				break;
 			}
 			break;
+		case V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT:
+			conceal_color.conceal_color_8bit = ext_control[i].value;
+			i++;
+			switch (ext_control[i].id) {
+			case V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_10BIT:
+				conceal_color.conceal_color_10bit =
+					ext_control[i].value;
+				dprintk(VIDC_DBG,
+					"conceal color: 8bit=0x%x 10bit=0x%x",
+					conceal_color.conceal_color_8bit,
+					conceal_color.conceal_color_10bit);
+				rc = call_hfi_op(hdev, session_set_property,
+						inst->session,
+						HAL_PARAM_VDEC_CONCEAL_COLOR,
+							&conceal_color);
+				if (rc) {
+					dprintk(VIDC_ERR,
+							"%s Failed setting conceal color",
+							__func__);
+				}
+				break;
+			default:
+				dprintk(VIDC_ERR,
+						"%s Could not find CONCEAL_COLOR_10BIT ext_control",
+						__func__);
+				rc = -ENOTSUPP;
+				break;
+			}
+
+			break;
 		default:
 			dprintk(VIDC_ERR
 				, "%s Unsupported set control %d",
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 21ad17a..427568c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -429,7 +429,7 @@
 		print_vidc_buffer(VIDC_DBG, "release buf", inst, mbuf);
 		msm_comm_unmap_vidc_buffer(inst, mbuf);
 		list_del(&mbuf->list);
-		kfree(mbuf);
+		kref_put_mbuf(mbuf);
 	}
 	mutex_unlock(&inst->registeredbufs.lock);
 
@@ -918,6 +918,10 @@
 	}
 
 fail_start:
+	if (rc) {
+		dprintk(VIDC_ERR, "%s: kill session %pK\n", __func__, inst);
+		msm_comm_kill_session(inst);
+	}
 	return rc;
 }
 
@@ -994,7 +998,7 @@
 			}
 			msm_comm_unmap_vidc_buffer(inst, temp);
 			list_del(&temp->list);
-			kfree(temp);
+			kref_put_mbuf(temp);
 		}
 		mutex_unlock(&inst->registeredbufs.lock);
 	}
@@ -1071,10 +1075,16 @@
 				inst, vb2);
 		return;
 	}
+	if (!kref_get_mbuf(inst, mbuf)) {
+		dprintk(VIDC_ERR, "%s: mbuf not found\n", __func__);
+		return;
+	}
 
 	rc = msm_comm_qbuf(inst, mbuf);
 	if (rc)
 		print_vidc_buffer(VIDC_ERR, "failed qbuf", inst, mbuf);
+
+	kref_put_mbuf(mbuf);
 }
 
 static const struct vb2_ops msm_vidc_vb2q_ops = {
@@ -1601,13 +1611,25 @@
 }
 EXPORT_SYMBOL(msm_vidc_open);
 
-static void cleanup_instance(struct msm_vidc_inst *inst)
+static void msm_vidc_cleanup_instance(struct msm_vidc_inst *inst)
 {
+	struct msm_vidc_buffer *temp, *dummy;
+
 	if (!inst) {
 		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
 		return;
 	}
 
+	mutex_lock(&inst->registeredbufs.lock);
+	list_for_each_entry_safe(temp, dummy, &inst->registeredbufs.list,
+			list) {
+		print_vidc_buffer(VIDC_ERR, "undequeud buf", inst, temp);
+		msm_comm_unmap_vidc_buffer(inst, temp);
+		list_del(&temp->list);
+		kref_put_mbuf(temp);
+	}
+	mutex_unlock(&inst->registeredbufs.lock);
+
 	msm_comm_free_freq_table(inst);
 
 	if (msm_comm_release_scratch_buffers(inst, false))
@@ -1661,18 +1683,18 @@
 
 	msm_comm_ctrl_deinit(inst);
 
-	DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
-	DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
-	DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
-	DEINIT_MSM_VIDC_LIST(&inst->outputbufs);
-	DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
-
 	v4l2_fh_del(&inst->event_handler);
 	v4l2_fh_exit(&inst->event_handler);
 
 	for (i = 0; i < MAX_PORT_NUM; i++)
 		vb2_queue_release(&inst->bufq[i].vb2_bufq);
 
+	DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
+	DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
+	DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
+	DEINIT_MSM_VIDC_LIST(&inst->outputbufs);
+	DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
+
 	mutex_destroy(&inst->sync_lock);
 	mutex_destroy(&inst->bufq[CAPTURE_PORT].lock);
 	mutex_destroy(&inst->bufq[OUTPUT_PORT].lock);
@@ -1695,7 +1717,6 @@
 int msm_vidc_close(void *instance)
 {
 	struct msm_vidc_inst *inst = instance;
-	struct msm_vidc_buffer *temp, *dummy;
 	int rc = 0;
 
 	if (!inst || !inst->core) {
@@ -1707,30 +1728,20 @@
 	 * Make sure that HW stop working on these buffers that
 	 * we are going to free.
 	 */
-	if (inst->state != MSM_VIDC_CORE_INVALID &&
-		inst->core->state != VIDC_CORE_INVALID)
-		rc = msm_comm_try_state(inst,
-				MSM_VIDC_RELEASE_RESOURCES_DONE);
-
-	mutex_lock(&inst->registeredbufs.lock);
-	list_for_each_entry_safe(temp, dummy, &inst->registeredbufs.list,
-			list) {
-		print_vidc_buffer(VIDC_ERR, "undequeud buf", inst, temp);
-		msm_comm_unmap_vidc_buffer(inst, temp);
-		list_del(&temp->list);
-		kfree(temp);
-	}
-	mutex_unlock(&inst->registeredbufs.lock);
-
-	cleanup_instance(inst);
-	if (inst->state != MSM_VIDC_CORE_INVALID &&
-		inst->core->state != VIDC_CORE_INVALID)
-		rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
-	else
-		rc = msm_comm_force_cleanup(inst);
+	rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
 	if (rc)
 		dprintk(VIDC_ERR,
-			"Failed to move video instance to uninit state\n");
+			"Failed to move inst %pK to rel resource done state\n",
+			inst);
+
+	msm_vidc_cleanup_instance(inst);
+
+	rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
+	if (rc) {
+		dprintk(VIDC_ERR,
+			"Failed to move inst %pK to uninit state\n", inst);
+		rc = msm_comm_force_cleanup(inst);
+	}
 
 	msm_comm_session_clean(inst);
 	msm_smem_delete_client(inst->mem_client);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 61c4d7b..fbef464 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1175,11 +1175,6 @@
 	if (!rc) {
 		dprintk(VIDC_ERR, "Wait interrupted or timed out: %d\n",
 				SESSION_MSG_INDEX(cmd));
-		call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
-		dprintk(VIDC_ERR,
-			"sess resp timeout can potentially crash the system\n");
-		msm_comm_print_debug_info(inst);
-		msm_vidc_handle_hw_error(inst->core);
 		msm_comm_kill_session(inst);
 		rc = -EIO;
 	} else {
@@ -1497,6 +1492,7 @@
 		break;
 	case HAL_EVENT_RELEASE_BUFFER_REFERENCE:
 	{
+		struct msm_vidc_buffer *mbuf;
 		u32 planes[VIDEO_MAX_PLANES] = {0};
 
 		dprintk(VIDC_DBG,
@@ -1506,8 +1502,15 @@
 
 		planes[0] = event_notify->packet_buffer;
 		planes[1] = event_notify->extra_data_buffer;
-		handle_release_buffer_reference(inst, planes);
-
+		mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
+		if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
+			dprintk(VIDC_ERR,
+				"%s: data_addr %x, extradata_addr %x not found\n",
+				__func__, planes[0], planes[1]);
+		} else {
+			handle_release_buffer_reference(inst, mbuf);
+			kref_put_mbuf(mbuf);
+		}
 		goto err_bad_event;
 	}
 	default:
@@ -1951,7 +1954,6 @@
 
 	hdev = inst->core->device;
 	dprintk(VIDC_WARN, "Session error received for session %pK\n", inst);
-	change_inst_state(inst, MSM_VIDC_CORE_INVALID);
 
 	if (response->status == VIDC_ERR_MAX_CLIENTS) {
 		dprintk(VIDC_WARN, "Too many clients, rejecting %pK", inst);
@@ -1989,7 +1991,6 @@
 
 	dprintk(VIDC_WARN, "%s: Core %pK\n", __func__, core);
 	mutex_lock(&core->lock);
-	core->state = VIDC_CORE_INVALID;
 
 	list_for_each_entry(inst, &core->instances, list) {
 		mutex_lock(&inst->lock);
@@ -2026,52 +2027,37 @@
 	}
 
 	mutex_lock(&core->lock);
-	if (core->state == VIDC_CORE_INVALID ||
-		core->state == VIDC_CORE_UNINIT) {
+	if (core->state == VIDC_CORE_UNINIT) {
 		dprintk(VIDC_ERR,
-			"%s: Core already moved to state %d\n",
-			 __func__, core->state);
+			"%s: Core %pK already moved to state %d\n",
+			 __func__, core, core->state);
 		mutex_unlock(&core->lock);
 		return;
 	}
-	mutex_unlock(&core->lock);
 
-	dprintk(VIDC_WARN, "SYS_ERROR %d received for core %pK\n", cmd, core);
-	msm_comm_clean_notify_client(core);
-
-	hdev = core->device;
-	mutex_lock(&core->lock);
-	if (core->state == VIDC_CORE_INVALID) {
-		dprintk(VIDC_DBG, "Calling core_release\n");
-		rc = call_hfi_op(hdev, core_release,
-						 hdev->hfi_device_data);
-		if (rc) {
-			dprintk(VIDC_ERR, "core_release failed\n");
-			mutex_unlock(&core->lock);
-			return;
-		}
-		core->state = VIDC_CORE_UNINIT;
-	}
-	mutex_unlock(&core->lock);
-
-	msm_vidc_print_running_insts(core);
+	dprintk(VIDC_WARN, "SYS_ERROR received for core %pK\n", core);
 	call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
+	list_for_each_entry(inst, &core->instances, list) {
+		dprintk(VIDC_WARN,
+			"%s: Send sys error for inst %pK\n", __func__, inst);
+		change_inst_state(inst, MSM_VIDC_CORE_INVALID);
+		msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
+		msm_comm_print_inst_info(inst);
+	}
+	hdev = core->device;
+	dprintk(VIDC_DBG, "Calling core_release\n");
+	rc = call_hfi_op(hdev, core_release, hdev->hfi_device_data);
+	if (rc) {
+		dprintk(VIDC_ERR, "core_release failed\n");
+		mutex_unlock(&core->lock);
+		return;
+	}
+	core->state = VIDC_CORE_UNINIT;
+	mutex_unlock(&core->lock);
+
 	dprintk(VIDC_ERR,
 		"SYS_ERROR can potentially crash the system\n");
 
-	/*
-	 * For SYS_ERROR, there will not be any inst pointer.
-	 * Just grab one of the inst from instances list and
-	 * use it.
-	 */
-
-	mutex_lock(&core->lock);
-	inst = list_first_entry_or_null(&core->instances,
-		struct msm_vidc_inst, list);
-	mutex_unlock(&core->lock);
-
-	msm_comm_print_debug_info(inst);
-
 	msm_vidc_handle_hw_error(core);
 }
 
@@ -2084,19 +2070,22 @@
 		dprintk(VIDC_ERR, "%s invalid params\n", __func__);
 		return;
 	}
+	if (!inst->session) {
+		dprintk(VIDC_DBG, "%s: inst %pK session already cleaned\n",
+			__func__, inst);
+		return;
+	}
 
 	hdev = inst->core->device;
 	mutex_lock(&inst->lock);
-	if (hdev && inst->session) {
-		dprintk(VIDC_DBG, "cleaning up instance: %pK\n", inst);
-		rc = call_hfi_op(hdev, session_clean,
-				(void *)inst->session);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"Session clean failed :%pK\n", inst);
-		}
-		inst->session = NULL;
+	dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
+	rc = call_hfi_op(hdev, session_clean,
+			(void *)inst->session);
+	if (rc) {
+		dprintk(VIDC_ERR,
+			"Session clean failed :%pK\n", inst);
 	}
+	inst->session = NULL;
 	mutex_unlock(&inst->lock);
 }
 
@@ -2219,7 +2208,7 @@
 	planes[1] = empty_buf_done->extra_data_buffer;
 
 	mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
-	if (!mbuf) {
+	if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
 		dprintk(VIDC_ERR,
 			"%s: data_addr %x, extradata_addr %x not found\n",
 			__func__, planes[0], planes[1]);
@@ -2261,12 +2250,11 @@
 	/*
 	 * put_buffer should be done before vb2_buffer_done else
 	 * client might queue the same buffer before it is unmapped
-	 * in put_buffer. also don't use mbuf after put_buffer
-	 * as it may be freed in put_buffer.
+	 * in put_buffer.
 	 */
 	msm_comm_put_vidc_buffer(inst, mbuf);
 	msm_comm_vb2_buffer_done(inst, vb);
-
+	kref_put_mbuf(mbuf);
 exit:
 	put_inst(inst);
 }
@@ -2345,7 +2333,7 @@
 	buffer_type = msm_comm_get_hal_output_buffer(inst);
 	if (fill_buf_done->buffer_type == buffer_type) {
 		mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
-		if (!mbuf) {
+		if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
 			dprintk(VIDC_ERR,
 				"%s: data_addr %x, extradata_addr %x not found\n",
 				__func__, planes[0], planes[1]);
@@ -2448,6 +2436,7 @@
 	 */
 	msm_comm_put_vidc_buffer(inst, mbuf);
 	msm_comm_vb2_buffer_done(inst, vb);
+	kref_put_mbuf(mbuf);
 
 exit:
 	put_inst(inst);
@@ -2586,31 +2575,26 @@
 	hdev = inst->core->device;
 	abort_completion = SESSION_MSG_INDEX(HAL_SESSION_ABORT_DONE);
 
+	dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
 	rc = call_hfi_op(hdev, session_abort, (void *)inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"%s session_abort failed rc: %d\n", __func__, rc);
-		return rc;
+		goto exit;
 	}
 	rc = wait_for_completion_timeout(
 			&inst->completions[abort_completion],
 			msecs_to_jiffies(
 				inst->core->resources.msm_vidc_hw_rsp_timeout));
 	if (!rc) {
-		dprintk(VIDC_ERR,
-				"%s: Wait interrupted or timed out [%pK]: %d\n",
-				__func__, inst, abort_completion);
-		call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
-		dprintk(VIDC_ERR,
-			"ABORT timeout can potentially crash the system\n");
-		msm_comm_print_debug_info(inst);
-
-		msm_vidc_handle_hw_error(inst->core);
+		dprintk(VIDC_ERR, "%s: inst %pK abort timed out\n",
+				__func__, inst);
+		msm_comm_generate_sys_error(inst);
 		rc = -EBUSY;
 	} else {
 		rc = 0;
 	}
-	msm_comm_session_clean(inst);
+exit:
 	return rc;
 }
 
@@ -2765,7 +2749,7 @@
 			"%s: capabilities memory is expected to be freed\n",
 			__func__);
 	}
-
+	dprintk(VIDC_DBG, "%s: core %pK\n", __func__, core);
 	rc = call_hfi_op(hdev, core_init, hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to init core, id = %d\n",
@@ -2825,13 +2809,12 @@
 		 * e.g. thumbnail generation.
 		 */
 		schedule_delayed_work(&core->fw_unload_work,
-			msecs_to_jiffies(core->state == VIDC_CORE_INVALID ?
-					0 :
-			core->resources.msm_vidc_firmware_unload_delay));
+			msecs_to_jiffies(core->state == VIDC_CORE_INIT_DONE ?
+			core->resources.msm_vidc_firmware_unload_delay : 0));
 
 		dprintk(VIDC_DBG, "firmware unload delayed by %u ms\n",
-			core->state == VIDC_CORE_INVALID ?
-			0 : core->resources.msm_vidc_firmware_unload_delay);
+			core->state == VIDC_CORE_INIT_DONE ?
+			core->resources.msm_vidc_firmware_unload_delay : 0);
 	}
 
 core_already_uninited:
@@ -2875,6 +2858,7 @@
 
 	msm_comm_init_clocks_and_bus_data(inst);
 
+	dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
 	rc = call_hfi_op(hdev, session_init, hdev->hfi_device_data,
 			inst, get_hal_domain(inst->session_type),
 			get_hal_codec(fourcc),
@@ -2940,19 +2924,17 @@
 		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
 		return -EINVAL;
 	}
-
-	core = inst->core;
-	if (core->state == VIDC_CORE_INVALID) {
-		dprintk(VIDC_ERR,
-				"Core is in bad state can't do load res\n");
-		return -EINVAL;
-	}
-
 	if (inst->state == MSM_VIDC_CORE_INVALID) {
 		dprintk(VIDC_ERR,
-				"Instance is in invalid state can't do load res\n");
+			"%s: inst %pK is in invalid state\n", __func__, inst);
 		return -EINVAL;
 	}
+	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
+		dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
+						inst, inst->state);
+		goto exit;
+	}
+	core = inst->core;
 
 	num_mbs_per_sec =
 		msm_comm_get_load(core, MSM_VIDC_DECODER, quirks) +
@@ -2965,18 +2947,12 @@
 		dprintk(VIDC_ERR, "HW is overloaded, needed: %d max: %d\n",
 			num_mbs_per_sec, max_load_adj);
 		msm_vidc_print_running_insts(core);
-		inst->state = MSM_VIDC_CORE_INVALID;
 		msm_comm_kill_session(inst);
 		return -EBUSY;
 	}
 
 	hdev = core->device;
-	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
-		dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
-						inst, inst->state);
-		goto exit;
-	}
-
+	dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
 	rc = call_hfi_op(hdev, session_load_res, (void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
@@ -2997,21 +2973,19 @@
 		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
 		return -EINVAL;
 	}
-	if (inst->state == MSM_VIDC_CORE_INVALID ||
-			inst->core->state == VIDC_CORE_INVALID) {
+	if (inst->state == MSM_VIDC_CORE_INVALID) {
 		dprintk(VIDC_ERR,
-				"Core is in bad state can't do start\n");
+			"%s: inst %pK is in invalid\n", __func__, inst);
 		return -EINVAL;
 	}
-
-	hdev = inst->core->device;
-
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_START)) {
 		dprintk(VIDC_INFO,
 			"inst: %pK is already in state: %d\n",
 			inst, inst->state);
 		goto exit;
 	}
+	hdev = inst->core->device;
+	dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
 	rc = call_hfi_op(hdev, session_start, (void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
@@ -3032,18 +3006,23 @@
 		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
 		return -EINVAL;
 	}
-	hdev = inst->core->device;
-
+	if (inst->state == MSM_VIDC_CORE_INVALID) {
+		dprintk(VIDC_ERR,
+			"%s: inst %pK is in invalid state\n", __func__, inst);
+		return -EINVAL;
+	}
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_STOP)) {
 		dprintk(VIDC_INFO,
 			"inst: %pK is already in state: %d\n",
 			inst, inst->state);
 		goto exit;
 	}
-	dprintk(VIDC_DBG, "Send Stop to hal\n");
+	hdev = inst->core->device;
+	dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
 	rc = call_hfi_op(hdev, session_stop, (void *) inst->session);
 	if (rc) {
-		dprintk(VIDC_ERR, "Failed to send stop\n");
+		dprintk(VIDC_ERR, "%s: inst %pK session_stop failed\n",
+				__func__, inst);
 		goto exit;
 	}
 	change_inst_state(inst, MSM_VIDC_STOP);
@@ -3060,16 +3039,19 @@
 		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
 		return -EINVAL;
 	}
-	hdev = inst->core->device;
-
+	if (inst->state == MSM_VIDC_CORE_INVALID) {
+		dprintk(VIDC_ERR,
+			"%s: inst %pK is in invalid state\n", __func__, inst);
+		return -EINVAL;
+	}
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_RELEASE_RESOURCES)) {
 		dprintk(VIDC_INFO,
 			"inst: %pK is already in state: %d\n",
 			inst, inst->state);
 		goto exit;
 	}
-	dprintk(VIDC_DBG,
-		"Send release res to hal\n");
+	hdev = inst->core->device;
+	dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
 	rc = call_hfi_op(hdev, session_release_res, (void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
@@ -3091,15 +3073,14 @@
 		dprintk(VIDC_ERR, "%s invalid params\n", __func__);
 		return -EINVAL;
 	}
-	hdev = inst->core->device;
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_CLOSE)) {
 		dprintk(VIDC_INFO,
 			"inst: %pK is already in state: %d\n",
 						inst, inst->state);
 		goto exit;
 	}
-	dprintk(VIDC_DBG,
-		"Send session close to hal\n");
+	hdev = inst->core->device;
+	dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
 	rc = call_hfi_op(hdev, session_end, (void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
@@ -3132,7 +3113,7 @@
 	}
 
 	mutex_lock(&core->lock);
-	if (core->state == VIDC_CORE_INVALID) {
+	if (core->state != VIDC_CORE_INIT_DONE) {
 		dprintk(VIDC_ERR,
 				"%s - fw is not in proper state, skip suspend\n",
 				__func__);
@@ -3201,6 +3182,11 @@
 			buffer_type);
 		return 0;
 	}
+
+	/* For DPB buffers, Always use FW count */
+	output_buf->buffer_count_actual = output_buf->buffer_count_min_host =
+		output_buf->buffer_count_min;
+
 	dprintk(VIDC_DBG,
 		"output: num = %d, size = %d\n",
 		output_buf->buffer_count_actual,
@@ -3490,30 +3476,23 @@
 {
 	int rc = 0;
 	int flipped_state;
-	struct msm_vidc_core *core;
 
 	if (!inst) {
-		dprintk(VIDC_ERR,
-				"Invalid instance pointer = %pK\n", inst);
+		dprintk(VIDC_ERR, "%s: invalid params %pK", __func__, inst);
 		return -EINVAL;
 	}
 	dprintk(VIDC_DBG,
 			"Trying to move inst: %pK from: %#x to %#x\n",
 			inst, inst->state, state);
-	core = inst->core;
-	if (!core) {
-		dprintk(VIDC_ERR,
-				"Invalid core pointer = %pK\n", inst);
+
+	mutex_lock(&inst->sync_lock);
+	if (inst->state == MSM_VIDC_CORE_INVALID) {
+		dprintk(VIDC_ERR, "%s: inst %pK is in invalid\n",
+			__func__, inst);
+		mutex_unlock(&inst->sync_lock);
 		return -EINVAL;
 	}
-	mutex_lock(&inst->sync_lock);
-	if (inst->state == MSM_VIDC_CORE_INVALID ||
-			core->state == VIDC_CORE_INVALID) {
-		dprintk(VIDC_ERR,
-				"Core is in bad state can't change the state\n");
-		rc = -EINVAL;
-		goto exit;
-	}
+
 	flipped_state = get_flipped_state(inst->state, state);
 	dprintk(VIDC_DBG,
 			"flipped_state = %#x\n", flipped_state);
@@ -3593,15 +3572,17 @@
 		rc = -EINVAL;
 		break;
 	}
-exit:
 	mutex_unlock(&inst->sync_lock);
-	if (rc)
+
+	if (rc) {
 		dprintk(VIDC_ERR,
 				"Failed to move from state: %d to %d\n",
 				inst->state, state);
-	else
+		msm_comm_kill_session(inst);
+	} else {
 		trace_msm_vidc_common_state_change((void *)inst,
 				inst->state, state);
+	}
 	return rc;
 }
 
@@ -3631,14 +3612,6 @@
 
 	switch (which_cmd) {
 	case V4L2_QCOM_CMD_FLUSH:
-		if (core->state != VIDC_CORE_INVALID &&
-			inst->state ==  MSM_VIDC_CORE_INVALID) {
-			rc = msm_comm_kill_session(inst);
-			if (rc)
-				dprintk(VIDC_ERR,
-					"Fail to clean session: %d\n",
-					rc);
-		}
 		rc = msm_comm_flush(inst, flags);
 		if (rc) {
 			dprintk(VIDC_ERR,
@@ -4252,13 +4225,6 @@
 			"%s: Wait interrupted or timed out [%pK]: %d\n",
 			__func__, inst,
 			SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO));
-		inst->state = MSM_VIDC_CORE_INVALID;
-		call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
-		dprintk(VIDC_ERR,
-			"SESS_PROP timeout can potentially crash the system\n");
-		msm_comm_print_debug_info(inst);
-
-		msm_vidc_handle_hw_error(inst->core);
 		msm_comm_kill_session(inst);
 		rc = -ETIMEDOUT;
 		goto exit;
@@ -4333,9 +4299,7 @@
 		buffer_info.num_buffers = 1;
 		buffer_info.align_device_addr = handle->device_addr;
 		if (inst->buffer_mode_set[CAPTURE_PORT] ==
-			HAL_BUFFER_MODE_STATIC &&
-			inst->state != MSM_VIDC_CORE_INVALID &&
-				core->state != VIDC_CORE_INVALID) {
+				HAL_BUFFER_MODE_STATIC) {
 			buffer_info.response_required = false;
 			rc = call_hfi_op(hdev, session_release_buffers,
 				(void *)inst->session, &buffer_info);
@@ -4441,26 +4405,23 @@
 		buffer_info.buffer_type = buf->buffer_type;
 		buffer_info.num_buffers = 1;
 		buffer_info.align_device_addr = handle->device_addr;
-		if (inst->state != MSM_VIDC_CORE_INVALID &&
-				core->state != VIDC_CORE_INVALID) {
-			buffer_info.response_required = true;
-			rc = call_hfi_op(hdev, session_release_buffers,
+		buffer_info.response_required = true;
+		rc = call_hfi_op(hdev, session_release_buffers,
 				(void *)inst->session, &buffer_info);
-			if (rc) {
-				dprintk(VIDC_WARN,
-					"Rel scrtch buf fail:%x, %d\n",
-					buffer_info.align_device_addr,
-					buffer_info.buffer_size);
-			}
+		if (!rc) {
 			mutex_unlock(&inst->scratchbufs.lock);
 			rc = wait_for_sess_signal_receipt(inst,
 				HAL_SESSION_RELEASE_BUFFER_DONE);
-			if (rc) {
-				change_inst_state(inst,
-					MSM_VIDC_CORE_INVALID);
-				msm_comm_kill_session(inst);
-			}
+			if (rc)
+				dprintk(VIDC_WARN,
+					"%s: wait for signal failed, rc %d\n",
+					__func__, rc);
 			mutex_lock(&inst->scratchbufs.lock);
+		} else {
+			dprintk(VIDC_WARN,
+				"Rel scrtch buf fail:%x, %d\n",
+				buffer_info.align_device_addr,
+				buffer_info.buffer_size);
 		}
 
 		/*If scratch buffers can be reused, do not free the buffers*/
@@ -4532,25 +4493,23 @@
 		buffer_info.buffer_type = buf->buffer_type;
 		buffer_info.num_buffers = 1;
 		buffer_info.align_device_addr = handle->device_addr;
-		if (inst->state != MSM_VIDC_CORE_INVALID &&
-				core->state != VIDC_CORE_INVALID) {
-			buffer_info.response_required = true;
-			rc = call_hfi_op(hdev, session_release_buffers,
+		buffer_info.response_required = true;
+		rc = call_hfi_op(hdev, session_release_buffers,
 				(void *)inst->session, &buffer_info);
-			if (rc) {
-				dprintk(VIDC_WARN,
-					"Rel prst buf fail:%x, %d\n",
-					buffer_info.align_device_addr,
-					buffer_info.buffer_size);
-			}
+		if (!rc) {
 			mutex_unlock(&inst->persistbufs.lock);
 			rc = wait_for_sess_signal_receipt(inst,
 				HAL_SESSION_RELEASE_BUFFER_DONE);
-			if (rc) {
-				change_inst_state(inst, MSM_VIDC_CORE_INVALID);
-				msm_comm_kill_session(inst);
-			}
+			if (rc)
+				dprintk(VIDC_WARN,
+					"%s: wait for signal failed, rc %d\n",
+					__func__, rc);
 			mutex_lock(&inst->persistbufs.lock);
+		} else {
+			dprintk(VIDC_WARN,
+				"Rel prst buf fail:%x, %d\n",
+				buffer_info.align_device_addr,
+				buffer_info.buffer_size);
 		}
 		list_del(&buf->list);
 		msm_comm_smem_free(inst, handle);
@@ -4803,8 +4762,7 @@
 
 		/* remove from list */
 		list_del(&mbuf->list);
-		kfree(mbuf);
-		mbuf = NULL;
+		kref_put_mbuf(mbuf);
 	}
 	mutex_unlock(&inst->registeredbufs.lock);
 
@@ -4994,6 +4952,7 @@
 {
 	u32 x_min, x_max, y_min, y_max;
 	u32 input_height, input_width, output_height, output_width;
+	u32 rotation;
 
 	input_height = inst->prop.height[OUTPUT_PORT];
 	input_width = inst->prop.width[OUTPUT_PORT];
@@ -5029,6 +4988,20 @@
 		return 0;
 	}
 
+	rotation =  msm_comm_g_ctrl_for_id(inst,
+					V4L2_CID_MPEG_VIDC_VIDEO_ROTATION);
+
+	if ((output_width != output_height) &&
+		(rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90 ||
+		rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270)) {
+
+		output_width = inst->prop.height[CAPTURE_PORT];
+		output_height = inst->prop.width[CAPTURE_PORT];
+		dprintk(VIDC_DBG,
+			"Rotation=%u Swapped Output W=%u H=%u to check scaling",
+			rotation, output_width, output_height);
+	}
+
 	x_min = (1<<16)/inst->capability.scale_x.min;
 	y_min = (1<<16)/inst->capability.scale_y.min;
 	x_max = inst->capability.scale_x.max >> 16;
@@ -5083,7 +5056,6 @@
 	core = inst->core;
 	rc = msm_vidc_load_supported(inst);
 	if (rc) {
-		change_inst_state(inst, MSM_VIDC_CORE_INVALID);
 		dprintk(VIDC_WARN,
 			"%s: Hardware is overloaded\n", __func__);
 		return rc;
@@ -5110,7 +5082,7 @@
 		if (!rc && inst->prop.width[CAPTURE_PORT] >
 			capability->width.max) {
 			dprintk(VIDC_ERR,
-				"Unsupported width = %u supported max width = %u",
+				"Unsupported width = %u supported max width = %u\n",
 				inst->prop.width[CAPTURE_PORT],
 				capability->width.max);
 				rc = -ENOTSUPP;
@@ -5132,7 +5104,6 @@
 		}
 	}
 	if (rc) {
-		change_inst_state(inst, MSM_VIDC_CORE_INVALID);
 		dprintk(VIDC_ERR,
 			"%s: Resolution unsupported\n", __func__);
 	}
@@ -5144,12 +5115,11 @@
 	enum hal_command_response cmd = HAL_SESSION_ERROR;
 	struct msm_vidc_cb_cmd_done response = {0};
 
-	dprintk(VIDC_WARN, "msm_comm_generate_session_error\n");
 	if (!inst || !inst->core) {
 		dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
 		return;
 	}
-
+	dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
 	response.session_id = inst;
 	response.status = VIDC_ERR_FAIL;
 	handle_session_error(cmd, (void *)&response);
@@ -5165,6 +5135,7 @@
 		dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
 		return;
 	}
+	dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
 	core = inst->core;
 	response.device_id = (u32) core->id;
 	handle_sys_error(cmd, (void *) &response);
@@ -5179,10 +5150,13 @@
 		dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
 		return -EINVAL;
 	} else if (!inst->session) {
-		/* There's no hfi session to kill */
+		dprintk(VIDC_ERR, "%s: no session to kill for inst %pK\n",
+			__func__, inst);
 		return 0;
 	}
 
+	dprintk(VIDC_WARN, "%s: inst %pK, state %d\n", __func__,
+			inst, inst->state);
 	/*
 	 * We're internally forcibly killing the session, if fw is aware of
 	 * the session send session_abort to firmware to clean up and release
@@ -5191,20 +5165,18 @@
 	if ((inst->state >= MSM_VIDC_OPEN_DONE &&
 			inst->state < MSM_VIDC_CLOSE_DONE) ||
 			inst->state == MSM_VIDC_CORE_INVALID) {
-		if (msm_comm_session_abort(inst)) {
-			msm_comm_generate_sys_error(inst);
-			return 0;
+		rc = msm_comm_session_abort(inst);
+		if (rc) {
+			dprintk(VIDC_WARN, "%s: inst %pK abort failed\n",
+				__func__, inst);
+			change_inst_state(inst, MSM_VIDC_CORE_INVALID);
 		}
-		change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
-		msm_comm_generate_session_error(inst);
-	} else {
-		dprintk(VIDC_WARN,
-				"Inactive session %pK, triggering an internal session error\n",
-				inst);
-		msm_comm_generate_session_error(inst);
-
 	}
 
+	change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
+	msm_comm_session_clean(inst);
+
+	dprintk(VIDC_WARN, "%s: inst %pK handled\n", __func__, inst);
 	return rc;
 }
 
@@ -5624,8 +5596,7 @@
 	hdev = inst->core->device;
 	mutex_lock(&inst->lock);
 	if (inst->state >= MSM_VIDC_RELEASE_RESOURCES_DONE ||
-			inst->state < MSM_VIDC_START_DONE ||
-			inst->core->state == VIDC_CORE_INVALID) {
+			inst->state < MSM_VIDC_START_DONE) {
 		dprintk(VIDC_DBG,
 			"Inst %pK : Not in valid state to call %s\n",
 				inst, __func__);
@@ -5979,6 +5950,7 @@
 			rc = -ENOMEM;
 			goto exit;
 		}
+		kref_init(&mbuf->kref);
 	}
 
 	vbuf = to_vb2_v4l2_buffer(vb2);
@@ -6042,11 +6014,11 @@
 	return mbuf;
 
 exit:
-	mutex_unlock(&inst->registeredbufs.lock);
 	dprintk(VIDC_ERR, "%s: rc %d\n", __func__, rc);
 	msm_comm_unmap_vidc_buffer(inst, mbuf);
 	if (!found)
-		kfree(mbuf);
+		kref_put_mbuf(mbuf);
+	mutex_unlock(&inst->registeredbufs.lock);
 
 	return ERR_PTR(rc);
 }
@@ -6098,24 +6070,26 @@
 	 */
 	if (!mbuf->smem[0].refcount) {
 		list_del(&mbuf->list);
-		kfree(mbuf);
-		mbuf = NULL;
+		kref_put_mbuf(mbuf);
 	}
 unlock:
 	mutex_unlock(&inst->registeredbufs.lock);
 }
 
-void handle_release_buffer_reference(struct msm_vidc_inst *inst, u32 *planes)
+void handle_release_buffer_reference(struct msm_vidc_inst *inst,
+		struct msm_vidc_buffer *mbuf)
 {
 	int rc = 0;
-	struct msm_vidc_buffer *mbuf = NULL;
+	struct msm_vidc_buffer *temp;
 	bool found = false;
 	int i = 0;
 
 	mutex_lock(&inst->registeredbufs.lock);
 	found = false;
-	list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
-		if (msm_comm_compare_device_planes(mbuf, planes)) {
+	/* check if mbuf was not removed by any chance */
+	list_for_each_entry(temp, &inst->registeredbufs.list, list) {
+		if (msm_comm_compare_vb2_planes(inst, mbuf,
+				&temp->vvb.vb2_buf)) {
 			found = true;
 			break;
 		}
@@ -6133,13 +6107,10 @@
 		/* refcount is not zero if client queued the same buffer */
 		if (!mbuf->smem[0].refcount) {
 			list_del(&mbuf->list);
-			kfree(mbuf);
-			mbuf = NULL;
+			kref_put_mbuf(mbuf);
 		}
 	} else {
-		dprintk(VIDC_ERR,
-			"%s: data_addr %x extradata_addr %x not found\n",
-			__func__, planes[0], planes[1]);
+		print_vidc_buffer(VIDC_ERR, "mbuf not found", inst, mbuf);
 		goto unlock;
 	}
 
@@ -6153,8 +6124,9 @@
 	 *    and if found queue it to video hw (if not flushing).
 	 */
 	found = false;
-	list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
-		if (msm_comm_compare_device_plane(mbuf, planes, 0)) {
+	list_for_each_entry(temp, &inst->registeredbufs.list, list) {
+		if (msm_comm_compare_vb2_plane(inst, mbuf,
+				&temp->vvb.vb2_buf, 0)) {
 			found = true;
 			break;
 		}
@@ -6169,8 +6141,7 @@
 		msm_comm_unmap_vidc_buffer(inst, mbuf);
 		/* remove from list */
 		list_del(&mbuf->list);
-		kfree(mbuf);
-		mbuf = NULL;
+		kref_put_mbuf(mbuf);
 
 		/* don't queue the buffer */
 		found = false;
@@ -6217,3 +6188,41 @@
 	return rc;
 }
 
+static void kref_free_mbuf(struct kref *kref)
+{
+	struct msm_vidc_buffer *mbuf = container_of(kref,
+			struct msm_vidc_buffer, kref);
+
+	kfree(mbuf);
+}
+
+void kref_put_mbuf(struct msm_vidc_buffer *mbuf)
+{
+	if (!mbuf)
+		return;
+
+	kref_put(&mbuf->kref, kref_free_mbuf);
+}
+
+bool kref_get_mbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
+{
+	struct msm_vidc_buffer *temp;
+	bool matches = false;
+	bool ret = false;
+
+	if (!inst || !mbuf)
+		return false;
+
+	mutex_lock(&inst->registeredbufs.lock);
+	list_for_each_entry(temp, &inst->registeredbufs.list, list) {
+		if (temp == mbuf) {
+			matches = true;
+			break;
+		}
+	}
+	ret = (matches && kref_get_unless_zero(&mbuf->kref)) ? true : false;
+	mutex_unlock(&inst->registeredbufs.lock);
+
+	return ret;
+}
+
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index bc881a0..18ba4a5 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -116,7 +116,8 @@
 		struct vb2_buffer *vb2);
 void msm_comm_put_vidc_buffer(struct msm_vidc_inst *inst,
 		struct msm_vidc_buffer *mbuf);
-void handle_release_buffer_reference(struct msm_vidc_inst *inst, u32 *planes);
+void handle_release_buffer_reference(struct msm_vidc_inst *inst,
+		struct msm_vidc_buffer *mbuf);
 int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst,
 		struct vb2_buffer *vb);
 int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst,
@@ -145,4 +146,7 @@
 		struct vb2_buffer *vb2);
 void print_v4l2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
 		struct v4l2_buffer *v4l2);
+void kref_put_mbuf(struct msm_vidc_buffer *mbuf);
+bool kref_get_mbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf);
+
 #endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 677ee89..e554a46 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -83,7 +83,6 @@
 	VIDC_CORE_UNINIT = 0,
 	VIDC_CORE_INIT,
 	VIDC_CORE_INIT_DONE,
-	VIDC_CORE_INVALID
 };
 
 /*
@@ -388,6 +387,7 @@
 
 struct msm_vidc_buffer {
 	struct list_head list;
+	struct kref kref;
 	struct msm_smem smem[VIDEO_MAX_PLANES];
 	struct vb2_v4l2_buffer vvb;
 	bool deferred;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index dad4b60..b430d14 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -90,6 +90,8 @@
 static int __initialize_packetization(struct venus_hfi_device *device);
 static struct hal_session *__get_session(struct venus_hfi_device *device,
 		u32 session_id);
+static bool __is_session_valid(struct venus_hfi_device *device,
+		struct hal_session *session, const char *func);
 static int __set_clocks(struct venus_hfi_device *device, u32 freq);
 static int __iface_cmdq_write(struct venus_hfi_device *device,
 					void *pkt);
@@ -1668,11 +1670,9 @@
 
 static int venus_hfi_core_init(void *device)
 {
+	int rc = 0;
 	struct hfi_cmd_sys_init_packet pkt;
 	struct hfi_cmd_sys_get_property_packet version_pkt;
-	int rc = 0;
-	struct list_head *ptr, *next;
-	struct hal_session *session = NULL;
 	struct venus_hfi_device *dev;
 
 	if (!device) {
@@ -1681,8 +1681,16 @@
 	}
 
 	dev = device;
+
+	dprintk(VIDC_DBG, "Core initializing\n");
+
 	mutex_lock(&dev->lock);
 
+	dev->bus_vote.data =
+		kzalloc(sizeof(struct vidc_bus_vote_data), GFP_KERNEL);
+	dev->bus_vote.data_count = 1;
+	dev->bus_vote.data->power_mode = VIDC_POWER_TURBO;
+
 	rc = __load_fw(dev);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to load Venus FW\n");
@@ -1691,20 +1699,6 @@
 
 	__set_state(dev, VENUS_STATE_INIT);
 
-	list_for_each_safe(ptr, next, &dev->sess_head) {
-		/*
-		 * This means that session list is not empty. Kick stale
-		 * sessions out of our valid instance list, but keep the
-		 * list_head inited so that list_del (in the future, called
-		 * by session_clean()) will be valid. When client doesn't close
-		 * them, then it is a genuine leak which driver can't fix.
-		 */
-		session = list_entry(ptr, struct hal_session, list);
-		list_del_init(&session->list);
-	}
-
-	INIT_LIST_HEAD(&dev->sess_head);
-
 	if (!dev->hal_client) {
 		dev->hal_client = msm_smem_new_client(
 				SMEM_ION, dev->res, MSM_VIDC_UNKNOWN);
@@ -1766,21 +1760,23 @@
 		pm_qos_add_request(&dev->qos, PM_QOS_CPU_DMA_LATENCY,
 				dev->res->pm_qos_latency_us);
 	}
-
+	dprintk(VIDC_DBG, "Core inited successfully\n");
 	mutex_unlock(&dev->lock);
 	return rc;
 err_core_init:
 	__set_state(dev, VENUS_STATE_DEINIT);
 	__unload_fw(dev);
 err_load_fw:
+	dprintk(VIDC_ERR, "Core init failed\n");
 	mutex_unlock(&dev->lock);
 	return rc;
 }
 
 static int venus_hfi_core_release(void *dev)
 {
-	struct venus_hfi_device *device = dev;
 	int rc = 0;
+	struct venus_hfi_device *device = dev;
+	struct hal_session *session, *next;
 
 	if (!device) {
 		dprintk(VIDC_ERR, "invalid device\n");
@@ -1788,7 +1784,7 @@
 	}
 
 	mutex_lock(&device->lock);
-
+	dprintk(VIDC_DBG, "Core releasing\n");
 	if (device->res->pm_qos_latency_us &&
 		pm_qos_request_active(&device->qos))
 		pm_qos_remove_request(&device->qos);
@@ -1797,6 +1793,11 @@
 	__set_state(device, VENUS_STATE_DEINIT);
 	__unload_fw(device);
 
+	/* unlink all sessions from device */
+	list_for_each_entry_safe(session, next, &device->sess_head, list)
+		list_del(&session->list);
+
+	dprintk(VIDC_DBG, "Core released successfully\n");
 	mutex_unlock(&device->lock);
 
 	return rc;
@@ -1937,6 +1938,10 @@
 	mutex_lock(&device->lock);
 
 	dprintk(VIDC_INFO, "in set_prop,with prop id: %#x\n", ptype);
+	if (!__is_session_valid(device, session, __func__)) {
+		rc = -EINVAL;
+		goto err_set_prop;
+	}
 
 	rc = call_hfi_pkt_op(device, session_set_property,
 			pkt, session, ptype, pdata);
@@ -1979,6 +1984,10 @@
 	mutex_lock(&device->lock);
 
 	dprintk(VIDC_INFO, "%s: property id: %d\n", __func__, ptype);
+	if (!__is_session_valid(device, session, __func__)) {
+		rc = -EINVAL;
+		goto err_create_pkt;
+	}
 
 	rc = call_hfi_pkt_op(device, session_get_property,
 				&pkt, session, ptype);
@@ -2010,8 +2019,25 @@
 
 static void __session_clean(struct hal_session *session)
 {
+	struct hal_session *temp, *next;
+	struct venus_hfi_device *device;
+
+	if (!session || !session->device) {
+		dprintk(VIDC_WARN, "%s: invalid params\n", __func__);
+		return;
+	}
+	device = session->device;
 	dprintk(VIDC_DBG, "deleted the session: %pK\n", session);
-	list_del(&session->list);
+	/*
+	 * session might have been removed from the device list in
+	 * core_release, so check and remove if it is in the list
+	 */
+	list_for_each_entry_safe(temp, next, &device->sess_head, list) {
+		if (session == temp) {
+			list_del(&session->list);
+			break;
+		}
+	}
 	/* Poison the session handle with zeros */
 	*session = (struct hal_session){ {0} };
 	kfree(session);
@@ -2105,6 +2131,9 @@
 	int rc = 0;
 	struct venus_hfi_device *device = session->device;
 
+	if (!__is_session_valid(device, session, __func__))
+		return -EINVAL;
+
 	rc = call_hfi_pkt_op(device, session_cmd,
 			&pkt, pkt_type, session);
 	if (rc == -EPERM)
@@ -2190,6 +2219,10 @@
 	device = session->device;
 	mutex_lock(&device->lock);
 
+	if (!__is_session_valid(device, session, __func__)) {
+		rc = -EINVAL;
+		goto err_create_pkt;
+	}
 	if (buffer_info->buffer_type == HAL_BUFFER_INPUT) {
 		/*
 		 * Hardware doesn't care about input buffers being
@@ -2234,6 +2267,10 @@
 	device = session->device;
 	mutex_lock(&device->lock);
 
+	if (!__is_session_valid(device, session, __func__)) {
+		rc = -EINVAL;
+		goto err_create_pkt;
+	}
 	if (buffer_info->buffer_type == HAL_BUFFER_INPUT) {
 		rc = 0;
 		goto err_create_pkt;
@@ -2368,6 +2405,9 @@
 	int rc = 0;
 	struct venus_hfi_device *device = session->device;
 
+	if (!__is_session_valid(device, session, __func__))
+		return -EINVAL;
+
 	if (session->is_decoder) {
 		struct hfi_cmd_session_empty_buffer_compressed_packet pkt;
 
@@ -2437,6 +2477,9 @@
 	struct venus_hfi_device *device = session->device;
 	struct hfi_cmd_session_fill_buffer_packet pkt;
 
+	if (!__is_session_valid(device, session, __func__))
+		return -EINVAL;
+
 	rc = call_hfi_pkt_op(device, session_ftb,
 			&pkt, session, output_frame);
 	if (rc) {
@@ -2490,6 +2533,12 @@
 	device = session->device;
 
 	mutex_lock(&device->lock);
+
+	if (!__is_session_valid(device, session, __func__)) {
+		rc = -EINVAL;
+		goto err_etbs_and_ftbs;
+	}
+
 	for (c = 0; c < num_ftbs; ++c) {
 		rc = __session_ftb(session, &ftbs[c], true);
 		if (rc) {
@@ -2537,6 +2586,10 @@
 	device = session->device;
 	mutex_lock(&device->lock);
 
+	if (!__is_session_valid(device, session, __func__)) {
+		rc = -EINVAL;
+		goto err_create_pkt;
+	}
 	rc = call_hfi_pkt_op(device, session_get_buf_req,
 			&pkt, session);
 	if (rc) {
@@ -2567,6 +2620,10 @@
 	device = session->device;
 	mutex_lock(&device->lock);
 
+	if (!__is_session_valid(device, session, __func__)) {
+		rc = -EINVAL;
+		goto err_create_pkt;
+	}
 	rc = call_hfi_pkt_op(device, session_flush,
 			&pkt, session, flush_mode);
 	if (rc) {
@@ -2844,6 +2901,24 @@
 		kfree(packet);
 }
 
+static bool __is_session_valid(struct venus_hfi_device *device,
+		struct hal_session *session, const char *func)
+{
+	struct hal_session *temp = NULL;
+
+	if (!device || !session)
+		goto invalid;
+
+	list_for_each_entry(temp, &device->sess_head, list)
+		if (session == temp)
+			return true;
+
+invalid:
+	dprintk(VIDC_WARN, "%s: device %pK, invalid session %pK\n",
+			func, device, session);
+	return false;
+}
+
 static struct hal_session *__get_session(struct venus_hfi_device *device,
 		u32 session_id)
 {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 79ce858..fbd3b02 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -996,6 +996,11 @@
 	struct hal_buffer_requirements buffer[HAL_BUFFER_MAX];
 };
 
+struct hal_conceal_color {
+	u32 conceal_color_8bit;
+	u32 conceal_color_10bit;
+};
+
 union hal_get_property {
 	struct hal_frame_rate frame_rate;
 	struct hal_uncompressed_format_select format_select;
@@ -1045,6 +1050,7 @@
 	struct hal_buffer_alloc_mode buffer_alloc_mode;
 	struct buffer_requirements buf_req;
 	enum hal_h264_entropy h264_entropy;
+	struct hal_conceal_color conceal_color;
 };
 
 /* HAL Response */
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index d5624ce..a522918 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -478,7 +478,8 @@
 };
 
 struct hfi_conceal_color {
-	u32 conceal_color;
+	u32 conceal_color_8bit;
+	u32 conceal_color_10bit;
 };
 
 struct hfi_intra_period {
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 093f28a..3e9448b 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -479,12 +479,17 @@
 	struct mmc_devfeq_clk_scaling *clk_scaling;
 	int err = 0;
 	int abort;
+	unsigned long pflags = current->flags;
+
+	/* Ensure scaling would happen even in memory pressure conditions */
+	current->flags |= PF_MEMALLOC;
 
 	if (!(host && freq)) {
 		pr_err("%s: unexpected host/freq parameter\n", __func__);
 		err = -EINVAL;
 		goto out;
 	}
+
 	clk_scaling = &host->clk_scaling;
 
 	if (!clk_scaling->enable)
@@ -548,6 +553,7 @@
 rel_host:
 	mmc_release_host(host);
 out:
+	tsk_restore_flags(current, pflags, PF_MEMALLOC);
 	return err;
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 6063cf4..410bcda 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -3133,7 +3133,7 @@
 	setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry,
 		    (unsigned long)ar);
 
-	if (QCA_REV_6174(ar))
+	if (QCA_REV_6174(ar) || QCA_REV_9377(ar))
 		ath10k_pci_override_ce_config(ar);
 
 	ret = ath10k_pci_alloc_pipes(ar);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index d3bad57..0fd7d7e 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2662,7 +2662,7 @@
 
 	tasklet_hrtimer_init(&data->beacon_timer,
 			     mac80211_hwsim_beacon,
-			     CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS);
+			     CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
 
 	spin_lock_bh(&hwsim_radio_lock);
 	list_add_tail(&data->list, &hwsim_radios);
diff --git a/drivers/pinctrl/freescale/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c
index 41b5b07..6852010 100644
--- a/drivers/pinctrl/freescale/pinctrl-mxs.c
+++ b/drivers/pinctrl/freescale/pinctrl-mxs.c
@@ -194,6 +194,16 @@
 	return 0;
 }
 
+static void mxs_pinctrl_rmwl(u32 value, u32 mask, u8 shift, void __iomem *reg)
+{
+	u32 tmp;
+
+	tmp = readl(reg);
+	tmp &= ~(mask << shift);
+	tmp |= value << shift;
+	writel(tmp, reg);
+}
+
 static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
 			       unsigned group)
 {
@@ -211,8 +221,7 @@
 		reg += bank * 0x20 + pin / 16 * 0x10;
 		shift = pin % 16 * 2;
 
-		writel(0x3 << shift, reg + CLR);
-		writel(g->muxsel[i] << shift, reg + SET);
+		mxs_pinctrl_rmwl(g->muxsel[i], 0x3, shift, reg);
 	}
 
 	return 0;
@@ -279,8 +288,7 @@
 			/* mA */
 			if (config & MA_PRESENT) {
 				shift = pin % 8 * 4;
-				writel(0x3 << shift, reg + CLR);
-				writel(ma << shift, reg + SET);
+				mxs_pinctrl_rmwl(ma, 0x3, shift, reg);
 			}
 
 			/* vol */
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index c43b1e9..0d34d8a4 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -13,6 +13,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/dmi.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -1524,10 +1525,32 @@
 	chained_irq_exit(chip, desc);
 }
 
+/*
+ * Certain machines seem to hardcode Linux IRQ numbers in their ACPI
+ * tables. Since we leave GPIOs that are not capable of generating
+ * interrupts out of the irqdomain the numbering will be different and
+ * cause devices using the hardcoded IRQ numbers fail. In order not to
+ * break such machines we will only mask pins from irqdomain if the machine
+ * is not listed below.
+ */
+static const struct dmi_system_id chv_no_valid_mask[] = {
+	{
+		/* See https://bugzilla.kernel.org/show_bug.cgi?id=194945 */
+		.ident = "Acer Chromebook (CYAN)",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Edgar"),
+			DMI_MATCH(DMI_BIOS_DATE, "05/21/2016"),
+		},
+	},
+	{}
+};
+
 static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
 {
 	const struct chv_gpio_pinrange *range;
 	struct gpio_chip *chip = &pctrl->chip;
+	bool need_valid_mask = !dmi_check_system(chv_no_valid_mask);
 	int ret, i, offset;
 
 	*chip = chv_gpio_chip;
@@ -1536,7 +1559,7 @@
 	chip->label = dev_name(pctrl->dev);
 	chip->parent = pctrl->dev;
 	chip->base = -1;
-	chip->irq_need_valid_mask = true;
+	chip->irq_need_valid_mask = need_valid_mask;
 
 	ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl);
 	if (ret) {
@@ -1567,7 +1590,7 @@
 		intsel &= CHV_PADCTRL0_INTSEL_MASK;
 		intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
 
-		if (intsel >= pctrl->community->nirqs)
+		if (need_valid_mask && intsel >= pctrl->community->nirqs)
 			clear_bit(i, chip->irq_valid_mask);
 	}
 
diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c
index 76f077f..f87ef5a 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8b.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8b.c
@@ -739,8 +739,8 @@
 static const char * const nand_groups[] = {
 	"nand_io", "nand_io_ce0", "nand_io_ce1",
 	"nand_io_rb0", "nand_ale", "nand_cle",
-	"nand_wen_clk", "nand_ren_clk", "nand_dqs0",
-	"nand_dqs1"
+	"nand_wen_clk", "nand_ren_clk", "nand_dqs_0",
+	"nand_dqs_1"
 };
 
 static const char * const nor_groups[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c
index b68ae42..743d1f4 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c
@@ -405,6 +405,36 @@
 	PINGROUP(67, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 	PINGROUP(68, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 	PINGROUP(69, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(70, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(71, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(72, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(73, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(74, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(75, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(76, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(77, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(78, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(79, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(80, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(81, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(82, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(83, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(84, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(85, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(86, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(87, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(88, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(89, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(90, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(91, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(92, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(93, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(94, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(95, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(96, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(97, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(98, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(99, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 };
 
 static const struct msm_pinctrl_soc_data ipq4019_pinctrl = {
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm670.c b/drivers/pinctrl/qcom/pinctrl-sdm670.c
index c93628e..1f742f8 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm670.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm670.c
@@ -28,6 +28,7 @@
 #define NORTH	0x00500000
 #define SOUTH	0x00900000
 #define WEST	0x00100000
+#define DUMMY	0x0
 #define REG_SIZE 0x1000
 #define PINGROUP(id, base, f1, f2, f3, f4, f5, f6, f7, f8, f9)	\
 	{						\
@@ -254,12 +255,14 @@
 	PINCTRL_PIN(147, "GPIO_147"),
 	PINCTRL_PIN(148, "GPIO_148"),
 	PINCTRL_PIN(149, "GPIO_149"),
-	PINCTRL_PIN(150, "SDC1_CLK"),
-	PINCTRL_PIN(151, "SDC1_CMD"),
-	PINCTRL_PIN(152, "SDC1_DATA"),
-	PINCTRL_PIN(153, "SDC2_CLK"),
-	PINCTRL_PIN(154, "SDC2_CMD"),
-	PINCTRL_PIN(155, "SDC2_DATA"),
+	PINCTRL_PIN(150, "SDC1_RCLK"),
+	PINCTRL_PIN(151, "SDC1_CLK"),
+	PINCTRL_PIN(152, "SDC1_CMD"),
+	PINCTRL_PIN(153, "SDC1_DATA"),
+	PINCTRL_PIN(154, "SDC2_CLK"),
+	PINCTRL_PIN(155, "SDC2_CMD"),
+	PINCTRL_PIN(156, "SDC2_DATA"),
+	PINCTRL_PIN(157, "UFS_RESET"),
 };
 
 #define DECLARE_MSM_GPIO_PINS(pin) \
@@ -322,10 +325,23 @@
 DECLARE_MSM_GPIO_PINS(55);
 DECLARE_MSM_GPIO_PINS(56);
 DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
 DECLARE_MSM_GPIO_PINS(65);
 DECLARE_MSM_GPIO_PINS(66);
 DECLARE_MSM_GPIO_PINS(67);
 DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
 DECLARE_MSM_GPIO_PINS(75);
 DECLARE_MSM_GPIO_PINS(76);
 DECLARE_MSM_GPIO_PINS(77);
@@ -355,6 +371,7 @@
 DECLARE_MSM_GPIO_PINS(101);
 DECLARE_MSM_GPIO_PINS(102);
 DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
 DECLARE_MSM_GPIO_PINS(105);
 DECLARE_MSM_GPIO_PINS(106);
 DECLARE_MSM_GPIO_PINS(107);
@@ -401,243 +418,128 @@
 DECLARE_MSM_GPIO_PINS(148);
 DECLARE_MSM_GPIO_PINS(149);
 
-static const unsigned int sdc1_clk_pins[] = { 150 };
-static const unsigned int sdc1_cmd_pins[] = { 151 };
-static const unsigned int sdc1_data_pins[] = { 152 };
-static const unsigned int sdc2_clk_pins[] = { 153 };
-static const unsigned int sdc2_cmd_pins[] = { 154 };
-static const unsigned int sdc2_data_pins[] = { 155 };
+static const unsigned int sdc1_rclk_pins[] = { 150 };
+static const unsigned int sdc1_clk_pins[] = { 151 };
+static const unsigned int sdc1_cmd_pins[] = { 152 };
+static const unsigned int sdc1_data_pins[] = { 153 };
+static const unsigned int sdc2_clk_pins[] = { 154 };
+static const unsigned int sdc2_cmd_pins[] = { 155 };
+static const unsigned int sdc2_data_pins[] = { 156 };
+static const unsigned int ufs_reset_pins[] = { 157 };
 
 enum sdm670_functions {
 	msm_mux_qup0,
 	msm_mux_gpio,
-	msm_mux_reserved0,
-	msm_mux_reserved1,
-	msm_mux_reserved2,
-	msm_mux_reserved3,
 	msm_mux_qup9,
 	msm_mux_qdss_cti,
-	msm_mux_reserved4,
-	msm_mux_reserved5,
 	msm_mux_ddr_pxi0,
-	msm_mux_reserved6,
 	msm_mux_ddr_bist,
 	msm_mux_atest_tsens2,
 	msm_mux_vsense_trigger,
 	msm_mux_atest_usb1,
-	msm_mux_reserved7,
 	msm_mux_qup_l4,
 	msm_mux_GP_PDM1,
-	msm_mux_reserved8,
 	msm_mux_qup_l5,
-	msm_mux_reserved9,
 	msm_mux_mdp_vsync,
 	msm_mux_qup_l6,
 	msm_mux_wlan2_adc1,
 	msm_mux_atest_usb11,
 	msm_mux_ddr_pxi2,
-	msm_mux_reserved10,
 	msm_mux_edp_lcd,
 	msm_mux_dbg_out,
 	msm_mux_wlan2_adc0,
 	msm_mux_atest_usb10,
-	msm_mux_reserved11,
 	msm_mux_m_voc,
 	msm_mux_tsif1_sync,
 	msm_mux_ddr_pxi3,
-	msm_mux_reserved12,
 	msm_mux_cam_mclk,
 	msm_mux_pll_bypassnl,
 	msm_mux_qdss_gpio0,
-	msm_mux_reserved13,
 	msm_mux_pll_reset,
 	msm_mux_qdss_gpio1,
-	msm_mux_reserved14,
 	msm_mux_qdss_gpio2,
-	msm_mux_reserved15,
 	msm_mux_qdss_gpio3,
-	msm_mux_reserved16,
 	msm_mux_cci_i2c,
 	msm_mux_qup1,
 	msm_mux_qdss_gpio4,
-	msm_mux_reserved17,
 	msm_mux_qdss_gpio5,
-	msm_mux_reserved18,
 	msm_mux_qdss_gpio6,
-	msm_mux_reserved19,
 	msm_mux_qdss_gpio7,
-	msm_mux_reserved20,
 	msm_mux_cci_timer0,
 	msm_mux_gcc_gp2,
 	msm_mux_qdss_gpio8,
-	msm_mux_reserved21,
 	msm_mux_cci_timer1,
 	msm_mux_gcc_gp3,
 	msm_mux_qdss_gpio,
-	msm_mux_reserved22,
 	msm_mux_cci_timer2,
 	msm_mux_qdss_gpio9,
-	msm_mux_reserved23,
 	msm_mux_cci_timer3,
 	msm_mux_cci_async,
 	msm_mux_qdss_gpio10,
-	msm_mux_reserved24,
 	msm_mux_cci_timer4,
 	msm_mux_qdss_gpio11,
-	msm_mux_reserved25,
 	msm_mux_qdss_gpio12,
 	msm_mux_JITTER_BIST,
-	msm_mux_reserved26,
 	msm_mux_qup2,
 	msm_mux_qdss_gpio13,
 	msm_mux_PLL_BIST,
-	msm_mux_reserved27,
 	msm_mux_qdss_gpio14,
 	msm_mux_AGERA_PLL,
-	msm_mux_reserved28,
 	msm_mux_phase_flag1,
 	msm_mux_qdss_gpio15,
 	msm_mux_atest_tsens,
-	msm_mux_reserved29,
 	msm_mux_phase_flag2,
-	msm_mux_reserved30,
 	msm_mux_qup11,
 	msm_mux_qup14,
-	msm_mux_reserved31,
-	msm_mux_reserved32,
-	msm_mux_reserved33,
-	msm_mux_reserved34,
 	msm_mux_pci_e0,
 	msm_mux_QUP_L4,
-	msm_mux_reserved35,
 	msm_mux_QUP_L5,
-	msm_mux_reserved36,
 	msm_mux_QUP_L6,
-	msm_mux_reserved37,
 	msm_mux_usb_phy,
-	msm_mux_reserved38,
 	msm_mux_lpass_slimbus,
-	msm_mux_reserved39,
 	msm_mux_sd_write,
 	msm_mux_tsif1_error,
-	msm_mux_reserved40,
 	msm_mux_qup3,
-	msm_mux_reserved41,
-	msm_mux_reserved42,
-	msm_mux_reserved43,
-	msm_mux_reserved44,
-	msm_mux_bt_reset,
 	msm_mux_qup6,
-	msm_mux_reserved45,
-	msm_mux_reserved46,
-	msm_mux_reserved47,
-	msm_mux_reserved124,
-	msm_mux_reserved125,
-	msm_mux_reserved126,
-	msm_mux_reserved127,
-	msm_mux_reserved128,
-	msm_mux_reserved129,
-	msm_mux_qlink_request,
-	msm_mux_reserved130,
-	msm_mux_qlink_enable,
-	msm_mux_reserved131,
-	msm_mux_reserved132,
-	msm_mux_reserved133,
-	msm_mux_reserved134,
-	msm_mux_pa_indicator,
-	msm_mux_reserved135,
-	msm_mux_reserved136,
-	msm_mux_phase_flag26,
-	msm_mux_reserved137,
-	msm_mux_phase_flag27,
-	msm_mux_reserved138,
-	msm_mux_phase_flag28,
-	msm_mux_reserved139,
-	msm_mux_phase_flag6,
-	msm_mux_reserved140,
-	msm_mux_phase_flag29,
-	msm_mux_reserved141,
-	msm_mux_phase_flag30,
-	msm_mux_reserved142,
-	msm_mux_phase_flag31,
-	msm_mux_reserved143,
-	msm_mux_mss_lte,
-	msm_mux_reserved144,
-	msm_mux_reserved145,
-	msm_mux_reserved146,
-	msm_mux_reserved147,
-	msm_mux_reserved148,
-	msm_mux_reserved149,
-	msm_mux_reserved48,
 	msm_mux_qup12,
-	msm_mux_reserved49,
-	msm_mux_reserved50,
-	msm_mux_reserved51,
 	msm_mux_phase_flag16,
-	msm_mux_reserved52,
 	msm_mux_qup10,
 	msm_mux_phase_flag11,
-	msm_mux_reserved53,
 	msm_mux_GP_PDM0,
 	msm_mux_phase_flag12,
 	msm_mux_wlan1_adc1,
 	msm_mux_atest_usb13,
 	msm_mux_ddr_pxi1,
-	msm_mux_reserved54,
 	msm_mux_phase_flag13,
 	msm_mux_wlan1_adc0,
 	msm_mux_atest_usb12,
-	msm_mux_reserved55,
 	msm_mux_phase_flag17,
-	msm_mux_reserved56,
 	msm_mux_qua_mi2s,
 	msm_mux_gcc_gp1,
 	msm_mux_phase_flag18,
-	msm_mux_reserved57,
 	msm_mux_pri_mi2s,
 	msm_mux_qup8,
 	msm_mux_wsa_clk,
-	msm_mux_reserved65,
 	msm_mux_pri_mi2s_ws,
 	msm_mux_wsa_data,
-	msm_mux_reserved66,
-	msm_mux_wsa_en,
 	msm_mux_atest_usb2,
-	msm_mux_reserved67,
 	msm_mux_atest_usb23,
-	msm_mux_reserved68,
 	msm_mux_ter_mi2s,
 	msm_mux_phase_flag8,
 	msm_mux_atest_usb22,
-	msm_mux_reserved75,
 	msm_mux_phase_flag9,
 	msm_mux_atest_usb21,
-	msm_mux_reserved76,
 	msm_mux_phase_flag4,
 	msm_mux_atest_usb20,
-	msm_mux_reserved77,
-	msm_mux_ssc_irq,
-	msm_mux_reserved78,
 	msm_mux_sec_mi2s,
 	msm_mux_GP_PDM2,
-	msm_mux_reserved79,
-	msm_mux_reserved80,
 	msm_mux_qup15,
-	msm_mux_reserved81,
-	msm_mux_reserved82,
-	msm_mux_reserved83,
-	msm_mux_reserved84,
 	msm_mux_qup5,
-	msm_mux_reserved85,
 	msm_mux_copy_gp,
-	msm_mux_reserved86,
-	msm_mux_reserved87,
-	msm_mux_reserved88,
 	msm_mux_tsif1_clk,
 	msm_mux_qup4,
 	msm_mux_tgu_ch3,
 	msm_mux_phase_flag10,
-	msm_mux_reserved89,
 	msm_mux_tsif1_en,
 	msm_mux_mdp_vsync0,
 	msm_mux_mdp_vsync1,
@@ -645,83 +547,61 @@
 	msm_mux_mdp_vsync3,
 	msm_mux_tgu_ch0,
 	msm_mux_phase_flag0,
-	msm_mux_reserved90,
 	msm_mux_tsif1_data,
 	msm_mux_sdc4_cmd,
 	msm_mux_tgu_ch1,
-	msm_mux_reserved91,
 	msm_mux_tsif2_error,
 	msm_mux_sdc43,
 	msm_mux_vfr_1,
 	msm_mux_tgu_ch2,
-	msm_mux_reserved92,
 	msm_mux_tsif2_clk,
 	msm_mux_sdc4_clk,
 	msm_mux_qup7,
-	msm_mux_reserved93,
 	msm_mux_tsif2_en,
 	msm_mux_sdc42,
-	msm_mux_reserved94,
 	msm_mux_tsif2_data,
 	msm_mux_sdc41,
-	msm_mux_reserved95,
 	msm_mux_tsif2_sync,
 	msm_mux_sdc40,
 	msm_mux_phase_flag3,
-	msm_mux_reserved96,
 	msm_mux_ldo_en,
-	msm_mux_reserved97,
 	msm_mux_ldo_update,
-	msm_mux_reserved98,
 	msm_mux_phase_flag14,
 	msm_mux_prng_rosc,
-	msm_mux_reserved99,
 	msm_mux_phase_flag15,
-	msm_mux_reserved100,
 	msm_mux_phase_flag5,
-	msm_mux_reserved101,
 	msm_mux_pci_e1,
-	msm_mux_reserved102,
 	msm_mux_COPY_PHASE,
-	msm_mux_reserved103,
 	msm_mux_uim2_data,
 	msm_mux_qup13,
-	msm_mux_reserved105,
 	msm_mux_uim2_clk,
-	msm_mux_reserved106,
 	msm_mux_uim2_reset,
-	msm_mux_reserved107,
 	msm_mux_uim2_present,
-	msm_mux_reserved108,
 	msm_mux_uim1_data,
-	msm_mux_reserved109,
 	msm_mux_uim1_clk,
-	msm_mux_reserved110,
 	msm_mux_uim1_reset,
-	msm_mux_reserved111,
 	msm_mux_uim1_present,
-	msm_mux_reserved112,
 	msm_mux_uim_batt,
 	msm_mux_edp_hot,
-	msm_mux_reserved113,
 	msm_mux_NAV_PPS,
 	msm_mux_GPS_TX,
-	msm_mux_reserved114,
-	msm_mux_reserved115,
-	msm_mux_reserved116,
 	msm_mux_atest_char,
-	msm_mux_reserved117,
 	msm_mux_adsp_ext,
 	msm_mux_atest_char3,
-	msm_mux_reserved118,
 	msm_mux_atest_char2,
-	msm_mux_reserved119,
 	msm_mux_atest_char1,
-	msm_mux_reserved120,
 	msm_mux_atest_char0,
-	msm_mux_reserved121,
-	msm_mux_reserved122,
-	msm_mux_reserved123,
+	msm_mux_qlink_request,
+	msm_mux_qlink_enable,
+	msm_mux_pa_indicator,
+	msm_mux_phase_flag26,
+	msm_mux_phase_flag27,
+	msm_mux_phase_flag28,
+	msm_mux_phase_flag6,
+	msm_mux_phase_flag29,
+	msm_mux_phase_flag30,
+	msm_mux_phase_flag31,
+	msm_mux_mss_lte,
 	msm_mux_NA,
 };
 
@@ -735,31 +615,21 @@
 	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
 	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
 	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
-	"gpio43", "gpio44", "gpio46", "gpio47", "gpio48", "gpio49", "gpio50",
-	"gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", "gpio57",
-	"gpio65", "gpio66", "gpio75", "gpio76", "gpio77", "gpio81", "gpio82",
-	"gpio83", "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89",
-	"gpio90", "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96",
-	"gpio97", "gpio98", "gpio99", "gpio100", "gpio101", "gpio102",
-	"gpio103", "gpio105", "gpio106", "gpio107", "gpio108", "gpio109",
-	"gpio110", "gpio111", "gpio112", "gpio113", "gpio114", "gpio115",
-	"gpio116", "gpio126", "gpio127", "gpio128", "gpio129", "gpio130",
-	"gpio131", "gpio132", "gpio133", "gpio134", "gpio135", "gpio136",
-	"gpio137", "gpio138", "gpio139", "gpio140", "gpio141", "gpio142",
-	"gpio143", "gpio144", "gpio145", "gpio146", "gpio147", "gpio148",
-	"gpio149",
-};
-static const char * const reserved0_groups[] = {
-	"gpio0",
-};
-static const char * const reserved1_groups[] = {
-	"gpio1",
-};
-static const char * const reserved2_groups[] = {
-	"gpio2",
-};
-static const char * const reserved3_groups[] = {
-	"gpio3",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio65", "gpio66", "gpio67", "gpio68", "gpio75", "gpio76",
+	"gpio77", "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
+	"gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90",
+	"gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97",
+	"gpio98", "gpio99", "gpio100", "gpio101", "gpio102", "gpio103",
+	"gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+	"gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+	"gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+	"gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+	"gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+	"gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+	"gpio141", "gpio142", "gpio143", "gpio144", "gpio145", "gpio146",
+	"gpio147", "gpio148", "gpio149",
 };
 static const char * const qup9_groups[] = {
 	"gpio4", "gpio5", "gpio6", "gpio7",
@@ -767,18 +637,9 @@
 static const char * const qdss_cti_groups[] = {
 	"gpio4", "gpio5", "gpio51", "gpio52", "gpio90", "gpio91",
 };
-static const char * const reserved4_groups[] = {
-	"gpio4",
-};
-static const char * const reserved5_groups[] = {
-	"gpio5",
-};
 static const char * const ddr_pxi0_groups[] = {
 	"gpio6", "gpio7",
 };
-static const char * const reserved6_groups[] = {
-	"gpio6",
-};
 static const char * const ddr_bist_groups[] = {
 	"gpio7", "gpio8", "gpio9", "gpio10",
 };
@@ -791,24 +652,15 @@
 static const char * const atest_usb1_groups[] = {
 	"gpio7",
 };
-static const char * const reserved7_groups[] = {
-	"gpio7",
-};
 static const char * const qup_l4_groups[] = {
 	"gpio8", "gpio105", "gpio123",
 };
 static const char * const GP_PDM1_groups[] = {
 	"gpio8", "gpio66",
 };
-static const char * const reserved8_groups[] = {
-	"gpio8",
-};
 static const char * const qup_l5_groups[] = {
 	"gpio9", "gpio106", "gpio124",
 };
-static const char * const reserved9_groups[] = {
-	"gpio9",
-};
 static const char * const mdp_vsync_groups[] = {
 	"gpio10", "gpio11", "gpio12", "gpio97", "gpio98",
 };
@@ -824,9 +676,6 @@
 static const char * const ddr_pxi2_groups[] = {
 	"gpio10", "gpio11",
 };
-static const char * const reserved10_groups[] = {
-	"gpio10",
-};
 static const char * const edp_lcd_groups[] = {
 	"gpio11",
 };
@@ -839,9 +688,6 @@
 static const char * const atest_usb10_groups[] = {
 	"gpio11",
 };
-static const char * const reserved11_groups[] = {
-	"gpio11",
-};
 static const char * const m_voc_groups[] = {
 	"gpio12",
 };
@@ -851,9 +697,6 @@
 static const char * const ddr_pxi3_groups[] = {
 	"gpio12", "gpio13",
 };
-static const char * const reserved12_groups[] = {
-	"gpio12",
-};
 static const char * const cam_mclk_groups[] = {
 	"gpio13", "gpio14", "gpio15", "gpio16",
 };
@@ -863,30 +706,18 @@
 static const char * const qdss_gpio0_groups[] = {
 	"gpio13", "gpio117",
 };
-static const char * const reserved13_groups[] = {
-	"gpio13",
-};
 static const char * const pll_reset_groups[] = {
 	"gpio14",
 };
 static const char * const qdss_gpio1_groups[] = {
 	"gpio14", "gpio118",
 };
-static const char * const reserved14_groups[] = {
-	"gpio14",
-};
 static const char * const qdss_gpio2_groups[] = {
 	"gpio15", "gpio119",
 };
-static const char * const reserved15_groups[] = {
-	"gpio15",
-};
 static const char * const qdss_gpio3_groups[] = {
 	"gpio16", "gpio120",
 };
-static const char * const reserved16_groups[] = {
-	"gpio16",
-};
 static const char * const cci_i2c_groups[] = {
 	"gpio17", "gpio18", "gpio19", "gpio20",
 };
@@ -896,27 +727,15 @@
 static const char * const qdss_gpio4_groups[] = {
 	"gpio17", "gpio121",
 };
-static const char * const reserved17_groups[] = {
-	"gpio17",
-};
 static const char * const qdss_gpio5_groups[] = {
 	"gpio18", "gpio122",
 };
-static const char * const reserved18_groups[] = {
-	"gpio18",
-};
 static const char * const qdss_gpio6_groups[] = {
 	"gpio19", "gpio41",
 };
-static const char * const reserved19_groups[] = {
-	"gpio19",
-};
 static const char * const qdss_gpio7_groups[] = {
 	"gpio20", "gpio42",
 };
-static const char * const reserved20_groups[] = {
-	"gpio20",
-};
 static const char * const cci_timer0_groups[] = {
 	"gpio21",
 };
@@ -926,9 +745,6 @@
 static const char * const qdss_gpio8_groups[] = {
 	"gpio21", "gpio75",
 };
-static const char * const reserved21_groups[] = {
-	"gpio21",
-};
 static const char * const cci_timer1_groups[] = {
 	"gpio22",
 };
@@ -938,18 +754,12 @@
 static const char * const qdss_gpio_groups[] = {
 	"gpio22", "gpio30", "gpio123", "gpio124",
 };
-static const char * const reserved22_groups[] = {
-	"gpio22",
-};
 static const char * const cci_timer2_groups[] = {
 	"gpio23",
 };
 static const char * const qdss_gpio9_groups[] = {
 	"gpio23", "gpio76",
 };
-static const char * const reserved23_groups[] = {
-	"gpio23",
-};
 static const char * const cci_timer3_groups[] = {
 	"gpio24",
 };
@@ -959,27 +769,18 @@
 static const char * const qdss_gpio10_groups[] = {
 	"gpio24", "gpio77",
 };
-static const char * const reserved24_groups[] = {
-	"gpio24",
-};
 static const char * const cci_timer4_groups[] = {
 	"gpio25",
 };
 static const char * const qdss_gpio11_groups[] = {
 	"gpio25", "gpio79",
 };
-static const char * const reserved25_groups[] = {
-	"gpio25",
-};
 static const char * const qdss_gpio12_groups[] = {
 	"gpio26", "gpio80",
 };
 static const char * const JITTER_BIST_groups[] = {
 	"gpio26", "gpio35",
 };
-static const char * const reserved26_groups[] = {
-	"gpio26",
-};
 static const char * const qup2_groups[] = {
 	"gpio27", "gpio28", "gpio29", "gpio30",
 };
@@ -989,18 +790,12 @@
 static const char * const PLL_BIST_groups[] = {
 	"gpio27", "gpio36",
 };
-static const char * const reserved27_groups[] = {
-	"gpio27",
-};
 static const char * const qdss_gpio14_groups[] = {
 	"gpio28", "gpio43",
 };
 static const char * const AGERA_PLL_groups[] = {
 	"gpio28", "gpio37",
 };
-static const char * const reserved28_groups[] = {
-	"gpio28",
-};
 static const char * const phase_flag1_groups[] = {
 	"gpio29",
 };
@@ -1010,246 +805,57 @@
 static const char * const atest_tsens_groups[] = {
 	"gpio29",
 };
-static const char * const reserved29_groups[] = {
-	"gpio29",
-};
 static const char * const phase_flag2_groups[] = {
 	"gpio30",
 };
-static const char * const reserved30_groups[] = {
-	"gpio30",
-};
 static const char * const qup11_groups[] = {
 	"gpio31", "gpio32", "gpio33", "gpio34",
 };
 static const char * const qup14_groups[] = {
 	"gpio31", "gpio32", "gpio33", "gpio34",
 };
-static const char * const reserved31_groups[] = {
-	"gpio31",
-};
-static const char * const reserved32_groups[] = {
-	"gpio32",
-};
-static const char * const reserved33_groups[] = {
-	"gpio33",
-};
-static const char * const reserved34_groups[] = {
-	"gpio34",
-};
 static const char * const pci_e0_groups[] = {
 	"gpio35", "gpio36",
 };
 static const char * const QUP_L4_groups[] = {
 	"gpio35", "gpio75",
 };
-static const char * const reserved35_groups[] = {
-	"gpio35",
-};
 static const char * const QUP_L5_groups[] = {
 	"gpio36", "gpio76",
 };
-static const char * const reserved36_groups[] = {
-	"gpio36",
-};
 static const char * const QUP_L6_groups[] = {
 	"gpio37", "gpio77",
 };
-static const char * const reserved37_groups[] = {
-	"gpio37",
-};
 static const char * const usb_phy_groups[] = {
 	"gpio38",
 };
-static const char * const reserved38_groups[] = {
-	"gpio38",
-};
 static const char * const lpass_slimbus_groups[] = {
 	"gpio39",
 };
-static const char * const reserved39_groups[] = {
-	"gpio39",
-};
 static const char * const sd_write_groups[] = {
 	"gpio40",
 };
 static const char * const tsif1_error_groups[] = {
 	"gpio40",
 };
-static const char * const reserved40_groups[] = {
-	"gpio40",
-};
 static const char * const qup3_groups[] = {
 	"gpio41", "gpio42", "gpio43", "gpio44",
 };
-static const char * const reserved41_groups[] = {
-	"gpio41",
-};
-static const char * const reserved42_groups[] = {
-	"gpio42",
-};
-static const char * const reserved43_groups[] = {
-	"gpio43",
-};
-static const char * const reserved44_groups[] = {
-	"gpio44",
-};
-static const char * const bt_reset_groups[] = {
-	"gpio45",
-};
 static const char * const qup6_groups[] = {
 	"gpio45", "gpio46", "gpio47", "gpio48",
 };
-static const char * const reserved45_groups[] = {
-	"gpio45",
-};
-static const char * const reserved46_groups[] = {
-	"gpio46",
-};
-static const char * const reserved47_groups[] = {
-	"gpio47",
-};
-static const char * const reserved124_groups[] = {
-	"gpio124",
-};
-static const char * const reserved125_groups[] = {
-	"gpio125",
-};
-static const char * const reserved126_groups[] = {
-	"gpio126",
-};
-static const char * const reserved127_groups[] = {
-	"gpio127",
-};
-static const char * const reserved128_groups[] = {
-	"gpio128",
-};
-static const char * const reserved129_groups[] = {
-	"gpio129",
-};
-static const char * const qlink_request_groups[] = {
-	"gpio130",
-};
-static const char * const reserved130_groups[] = {
-	"gpio130",
-};
-static const char * const qlink_enable_groups[] = {
-	"gpio131",
-};
-static const char * const reserved131_groups[] = {
-	"gpio131",
-};
-static const char * const reserved132_groups[] = {
-	"gpio132",
-};
-static const char * const reserved133_groups[] = {
-	"gpio133",
-};
-static const char * const reserved134_groups[] = {
-	"gpio134",
-};
-static const char * const pa_indicator_groups[] = {
-	"gpio135",
-};
-static const char * const reserved135_groups[] = {
-	"gpio135",
-};
-static const char * const reserved136_groups[] = {
-	"gpio136",
-};
-static const char * const phase_flag26_groups[] = {
-	"gpio137",
-};
-static const char * const reserved137_groups[] = {
-	"gpio137",
-};
-static const char * const phase_flag27_groups[] = {
-	"gpio138",
-};
-static const char * const reserved138_groups[] = {
-	"gpio138",
-};
-static const char * const phase_flag28_groups[] = {
-	"gpio139",
-};
-static const char * const reserved139_groups[] = {
-	"gpio139",
-};
-static const char * const phase_flag6_groups[] = {
-	"gpio140",
-};
-static const char * const reserved140_groups[] = {
-	"gpio140",
-};
-static const char * const phase_flag29_groups[] = {
-	"gpio141",
-};
-static const char * const reserved141_groups[] = {
-	"gpio141",
-};
-static const char * const phase_flag30_groups[] = {
-	"gpio142",
-};
-static const char * const reserved142_groups[] = {
-	"gpio142",
-};
-static const char * const phase_flag31_groups[] = {
-	"gpio143",
-};
-static const char * const reserved143_groups[] = {
-	"gpio143",
-};
-static const char * const mss_lte_groups[] = {
-	"gpio144", "gpio145",
-};
-static const char * const reserved144_groups[] = {
-	"gpio144",
-};
-static const char * const reserved145_groups[] = {
-	"gpio145",
-};
-static const char * const reserved146_groups[] = {
-	"gpio146",
-};
-static const char * const reserved147_groups[] = {
-	"gpio147",
-};
-static const char * const reserved148_groups[] = {
-	"gpio148",
-};
-static const char * const reserved149_groups[] = {
-	"gpio149", "gpio149",
-};
-static const char * const reserved48_groups[] = {
-	"gpio48",
-};
 static const char * const qup12_groups[] = {
 	"gpio49", "gpio50", "gpio51", "gpio52",
 };
-static const char * const reserved49_groups[] = {
-	"gpio49",
-};
-static const char * const reserved50_groups[] = {
-	"gpio50",
-};
-static const char * const reserved51_groups[] = {
-	"gpio51",
-};
 static const char * const phase_flag16_groups[] = {
 	"gpio52",
 };
-static const char * const reserved52_groups[] = {
-	"gpio52",
-};
 static const char * const qup10_groups[] = {
 	"gpio53", "gpio54", "gpio55", "gpio56",
 };
 static const char * const phase_flag11_groups[] = {
 	"gpio53",
 };
-static const char * const reserved53_groups[] = {
-	"gpio53",
-};
 static const char * const GP_PDM0_groups[] = {
 	"gpio54", "gpio95",
 };
@@ -1265,9 +871,6 @@
 static const char * const ddr_pxi1_groups[] = {
 	"gpio54", "gpio55",
 };
-static const char * const reserved54_groups[] = {
-	"gpio54",
-};
 static const char * const phase_flag13_groups[] = {
 	"gpio55",
 };
@@ -1277,15 +880,9 @@
 static const char * const atest_usb12_groups[] = {
 	"gpio55",
 };
-static const char * const reserved55_groups[] = {
-	"gpio55",
-};
 static const char * const phase_flag17_groups[] = {
 	"gpio56",
 };
-static const char * const reserved56_groups[] = {
-	"gpio56",
-};
 static const char * const qua_mi2s_groups[] = {
 	"gpio57",
 };
@@ -1295,9 +892,6 @@
 static const char * const phase_flag18_groups[] = {
 	"gpio57",
 };
-static const char * const reserved57_groups[] = {
-	"gpio57",
-};
 static const char * const pri_mi2s_groups[] = {
 	"gpio65", "gpio67", "gpio68",
 };
@@ -1307,33 +901,18 @@
 static const char * const wsa_clk_groups[] = {
 	"gpio65",
 };
-static const char * const reserved65_groups[] = {
-	"gpio65",
-};
 static const char * const pri_mi2s_ws_groups[] = {
 	"gpio66",
 };
 static const char * const wsa_data_groups[] = {
 	"gpio66",
 };
-static const char * const reserved66_groups[] = {
-	"gpio66",
-};
-static const char * const wsa_en_groups[] = {
-	"gpio67", "gpio68",
-};
 static const char * const atest_usb2_groups[] = {
 	"gpio67",
 };
-static const char * const reserved67_groups[] = {
-	"gpio67",
-};
 static const char * const atest_usb23_groups[] = {
 	"gpio68",
 };
-static const char * const reserved68_groups[] = {
-	"gpio68",
-};
 static const char * const ter_mi2s_groups[] = {
 	"gpio75", "gpio76", "gpio77", "gpio78",
 };
@@ -1343,79 +922,33 @@
 static const char * const atest_usb22_groups[] = {
 	"gpio75",
 };
-static const char * const reserved75_groups[] = {
-	"gpio75",
-};
 static const char * const phase_flag9_groups[] = {
 	"gpio76",
 };
 static const char * const atest_usb21_groups[] = {
 	"gpio76",
 };
-static const char * const reserved76_groups[] = {
-	"gpio76",
-};
 static const char * const phase_flag4_groups[] = {
 	"gpio77",
 };
 static const char * const atest_usb20_groups[] = {
 	"gpio77",
 };
-static const char * const reserved77_groups[] = {
-	"gpio77",
-};
-static const char * const ssc_irq_groups[] = {
-	"gpio78", "gpio79", "gpio80", "gpio117", "gpio118", "gpio119",
-	"gpio120", "gpio121", "gpio122", "gpio123", "gpio124", "gpio125",
-};
-static const char * const reserved78_groups[] = {
-	"gpio78",
-};
 static const char * const sec_mi2s_groups[] = {
 	"gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
 };
 static const char * const GP_PDM2_groups[] = {
 	"gpio79",
 };
-static const char * const reserved79_groups[] = {
-	"gpio79",
-};
-static const char * const reserved80_groups[] = {
-	"gpio80",
-};
 static const char * const qup15_groups[] = {
 	"gpio81", "gpio82", "gpio83", "gpio84",
 };
-static const char * const reserved81_groups[] = {
-	"gpio81",
-};
-static const char * const reserved82_groups[] = {
-	"gpio82",
-};
-static const char * const reserved83_groups[] = {
-	"gpio83",
-};
-static const char * const reserved84_groups[] = {
-	"gpio84",
-};
 static const char * const qup5_groups[] = {
 	"gpio85", "gpio86", "gpio87", "gpio88",
 };
-static const char * const reserved85_groups[] = {
-	"gpio85",
-};
 static const char * const copy_gp_groups[] = {
 	"gpio86",
 };
-static const char * const reserved86_groups[] = {
-	"gpio86",
-};
-static const char * const reserved87_groups[] = {
-	"gpio87",
-};
-static const char * const reserved88_groups[] = {
-	"gpio88",
-};
 static const char * const tsif1_clk_groups[] = {
 	"gpio89",
 };
@@ -1428,9 +961,6 @@
 static const char * const phase_flag10_groups[] = {
 	"gpio89",
 };
-static const char * const reserved89_groups[] = {
-	"gpio89",
-};
 static const char * const tsif1_en_groups[] = {
 	"gpio90",
 };
@@ -1452,9 +982,6 @@
 static const char * const phase_flag0_groups[] = {
 	"gpio90",
 };
-static const char * const reserved90_groups[] = {
-	"gpio90",
-};
 static const char * const tsif1_data_groups[] = {
 	"gpio91",
 };
@@ -1464,9 +991,6 @@
 static const char * const tgu_ch1_groups[] = {
 	"gpio91",
 };
-static const char * const reserved91_groups[] = {
-	"gpio91",
-};
 static const char * const tsif2_error_groups[] = {
 	"gpio92",
 };
@@ -1479,9 +1003,6 @@
 static const char * const tgu_ch2_groups[] = {
 	"gpio92",
 };
-static const char * const reserved92_groups[] = {
-	"gpio92",
-};
 static const char * const tsif2_clk_groups[] = {
 	"gpio93",
 };
@@ -1491,27 +1012,18 @@
 static const char * const qup7_groups[] = {
 	"gpio93", "gpio94", "gpio95", "gpio96",
 };
-static const char * const reserved93_groups[] = {
-	"gpio93",
-};
 static const char * const tsif2_en_groups[] = {
 	"gpio94",
 };
 static const char * const sdc42_groups[] = {
 	"gpio94",
 };
-static const char * const reserved94_groups[] = {
-	"gpio94",
-};
 static const char * const tsif2_data_groups[] = {
 	"gpio95",
 };
 static const char * const sdc41_groups[] = {
 	"gpio95",
 };
-static const char * const reserved95_groups[] = {
-	"gpio95",
-};
 static const char * const tsif2_sync_groups[] = {
 	"gpio96",
 };
@@ -1521,114 +1033,63 @@
 static const char * const phase_flag3_groups[] = {
 	"gpio96",
 };
-static const char * const reserved96_groups[] = {
-	"gpio96",
-};
 static const char * const ldo_en_groups[] = {
 	"gpio97",
 };
-static const char * const reserved97_groups[] = {
-	"gpio97",
-};
 static const char * const ldo_update_groups[] = {
 	"gpio98",
 };
-static const char * const reserved98_groups[] = {
-	"gpio98",
-};
 static const char * const phase_flag14_groups[] = {
 	"gpio99",
 };
 static const char * const prng_rosc_groups[] = {
 	"gpio99", "gpio102",
 };
-static const char * const reserved99_groups[] = {
-	"gpio99",
-};
 static const char * const phase_flag15_groups[] = {
 	"gpio100",
 };
-static const char * const reserved100_groups[] = {
-	"gpio100",
-};
 static const char * const phase_flag5_groups[] = {
 	"gpio101",
 };
-static const char * const reserved101_groups[] = {
-	"gpio101",
-};
 static const char * const pci_e1_groups[] = {
 	"gpio102", "gpio103",
 };
-static const char * const reserved102_groups[] = {
-	"gpio102",
-};
 static const char * const COPY_PHASE_groups[] = {
 	"gpio103",
 };
-static const char * const reserved103_groups[] = {
-	"gpio103",
-};
 static const char * const uim2_data_groups[] = {
 	"gpio105",
 };
 static const char * const qup13_groups[] = {
 	"gpio105", "gpio106", "gpio107", "gpio108",
 };
-static const char * const reserved105_groups[] = {
-	"gpio105",
-};
 static const char * const uim2_clk_groups[] = {
 	"gpio106",
 };
-static const char * const reserved106_groups[] = {
-	"gpio106",
-};
 static const char * const uim2_reset_groups[] = {
 	"gpio107",
 };
-static const char * const reserved107_groups[] = {
-	"gpio107",
-};
 static const char * const uim2_present_groups[] = {
 	"gpio108",
 };
-static const char * const reserved108_groups[] = {
-	"gpio108",
-};
 static const char * const uim1_data_groups[] = {
 	"gpio109",
 };
-static const char * const reserved109_groups[] = {
-	"gpio109",
-};
 static const char * const uim1_clk_groups[] = {
 	"gpio110",
 };
-static const char * const reserved110_groups[] = {
-	"gpio110",
-};
 static const char * const uim1_reset_groups[] = {
 	"gpio111",
 };
-static const char * const reserved111_groups[] = {
-	"gpio111",
-};
 static const char * const uim1_present_groups[] = {
 	"gpio112",
 };
-static const char * const reserved112_groups[] = {
-	"gpio112",
-};
 static const char * const uim_batt_groups[] = {
 	"gpio113",
 };
 static const char * const edp_hot_groups[] = {
 	"gpio113",
 };
-static const char * const reserved113_groups[] = {
-	"gpio113",
-};
 static const char * const NAV_PPS_groups[] = {
 	"gpio114", "gpio114", "gpio115", "gpio115", "gpio128", "gpio128",
 	"gpio129", "gpio129", "gpio143", "gpio143",
@@ -1636,285 +1097,171 @@
 static const char * const GPS_TX_groups[] = {
 	"gpio114", "gpio115", "gpio128", "gpio129", "gpio143", "gpio145",
 };
-static const char * const reserved114_groups[] = {
-	"gpio114",
-};
-static const char * const reserved115_groups[] = {
-	"gpio115",
-};
-static const char * const reserved116_groups[] = {
-	"gpio116",
-};
 static const char * const atest_char_groups[] = {
 	"gpio117",
 };
-static const char * const reserved117_groups[] = {
-	"gpio117",
-};
 static const char * const adsp_ext_groups[] = {
 	"gpio118",
 };
 static const char * const atest_char3_groups[] = {
 	"gpio118",
 };
-static const char * const reserved118_groups[] = {
-	"gpio118",
-};
 static const char * const atest_char2_groups[] = {
 	"gpio119",
 };
-static const char * const reserved119_groups[] = {
-	"gpio119",
-};
 static const char * const atest_char1_groups[] = {
 	"gpio120",
 };
-static const char * const reserved120_groups[] = {
-	"gpio120",
-};
 static const char * const atest_char0_groups[] = {
 	"gpio121",
 };
-static const char * const reserved121_groups[] = {
-	"gpio121",
+static const char * const qlink_request_groups[] = {
+	"gpio130",
 };
-static const char * const reserved122_groups[] = {
-	"gpio122",
+static const char * const qlink_enable_groups[] = {
+	"gpio131",
 };
-static const char * const reserved123_groups[] = {
-	"gpio123",
+static const char * const pa_indicator_groups[] = {
+	"gpio135",
+};
+static const char * const phase_flag26_groups[] = {
+	"gpio137",
+};
+static const char * const phase_flag27_groups[] = {
+	"gpio138",
+};
+static const char * const phase_flag28_groups[] = {
+	"gpio139",
+};
+static const char * const phase_flag6_groups[] = {
+	"gpio140",
+};
+static const char * const phase_flag29_groups[] = {
+	"gpio141",
+};
+static const char * const phase_flag30_groups[] = {
+	"gpio142",
+};
+static const char * const phase_flag31_groups[] = {
+	"gpio143",
+};
+static const char * const mss_lte_groups[] = {
+	"gpio144", "gpio145",
 };
 
 static const struct msm_function sdm670_functions[] = {
 	FUNCTION(qup0),
 	FUNCTION(gpio),
-	FUNCTION(reserved0),
-	FUNCTION(reserved1),
-	FUNCTION(reserved2),
-	FUNCTION(reserved3),
 	FUNCTION(qup9),
 	FUNCTION(qdss_cti),
-	FUNCTION(reserved4),
-	FUNCTION(reserved5),
 	FUNCTION(ddr_pxi0),
-	FUNCTION(reserved6),
 	FUNCTION(ddr_bist),
 	FUNCTION(atest_tsens2),
 	FUNCTION(vsense_trigger),
 	FUNCTION(atest_usb1),
-	FUNCTION(reserved7),
 	FUNCTION(qup_l4),
 	FUNCTION(GP_PDM1),
-	FUNCTION(reserved8),
 	FUNCTION(qup_l5),
-	FUNCTION(reserved9),
 	FUNCTION(mdp_vsync),
 	FUNCTION(qup_l6),
 	FUNCTION(wlan2_adc1),
 	FUNCTION(atest_usb11),
 	FUNCTION(ddr_pxi2),
-	FUNCTION(reserved10),
 	FUNCTION(edp_lcd),
 	FUNCTION(dbg_out),
 	FUNCTION(wlan2_adc0),
 	FUNCTION(atest_usb10),
-	FUNCTION(reserved11),
 	FUNCTION(m_voc),
 	FUNCTION(tsif1_sync),
 	FUNCTION(ddr_pxi3),
-	FUNCTION(reserved12),
 	FUNCTION(cam_mclk),
 	FUNCTION(pll_bypassnl),
 	FUNCTION(qdss_gpio0),
-	FUNCTION(reserved13),
 	FUNCTION(pll_reset),
 	FUNCTION(qdss_gpio1),
-	FUNCTION(reserved14),
 	FUNCTION(qdss_gpio2),
-	FUNCTION(reserved15),
 	FUNCTION(qdss_gpio3),
-	FUNCTION(reserved16),
 	FUNCTION(cci_i2c),
 	FUNCTION(qup1),
 	FUNCTION(qdss_gpio4),
-	FUNCTION(reserved17),
 	FUNCTION(qdss_gpio5),
-	FUNCTION(reserved18),
 	FUNCTION(qdss_gpio6),
-	FUNCTION(reserved19),
 	FUNCTION(qdss_gpio7),
-	FUNCTION(reserved20),
 	FUNCTION(cci_timer0),
 	FUNCTION(gcc_gp2),
 	FUNCTION(qdss_gpio8),
-	FUNCTION(reserved21),
 	FUNCTION(cci_timer1),
 	FUNCTION(gcc_gp3),
 	FUNCTION(qdss_gpio),
-	FUNCTION(reserved22),
 	FUNCTION(cci_timer2),
 	FUNCTION(qdss_gpio9),
-	FUNCTION(reserved23),
 	FUNCTION(cci_timer3),
 	FUNCTION(cci_async),
 	FUNCTION(qdss_gpio10),
-	FUNCTION(reserved24),
 	FUNCTION(cci_timer4),
 	FUNCTION(qdss_gpio11),
-	FUNCTION(reserved25),
 	FUNCTION(qdss_gpio12),
 	FUNCTION(JITTER_BIST),
-	FUNCTION(reserved26),
 	FUNCTION(qup2),
 	FUNCTION(qdss_gpio13),
 	FUNCTION(PLL_BIST),
-	FUNCTION(reserved27),
 	FUNCTION(qdss_gpio14),
 	FUNCTION(AGERA_PLL),
-	FUNCTION(reserved28),
 	FUNCTION(phase_flag1),
 	FUNCTION(qdss_gpio15),
 	FUNCTION(atest_tsens),
-	FUNCTION(reserved29),
 	FUNCTION(phase_flag2),
-	FUNCTION(reserved30),
 	FUNCTION(qup11),
 	FUNCTION(qup14),
-	FUNCTION(reserved31),
-	FUNCTION(reserved32),
-	FUNCTION(reserved33),
-	FUNCTION(reserved34),
 	FUNCTION(pci_e0),
 	FUNCTION(QUP_L4),
-	FUNCTION(reserved35),
 	FUNCTION(QUP_L5),
-	FUNCTION(reserved36),
 	FUNCTION(QUP_L6),
-	FUNCTION(reserved37),
 	FUNCTION(usb_phy),
-	FUNCTION(reserved38),
 	FUNCTION(lpass_slimbus),
-	FUNCTION(reserved39),
 	FUNCTION(sd_write),
 	FUNCTION(tsif1_error),
-	FUNCTION(reserved40),
 	FUNCTION(qup3),
-	FUNCTION(reserved41),
-	FUNCTION(reserved42),
-	FUNCTION(reserved43),
-	FUNCTION(reserved44),
-	FUNCTION(bt_reset),
 	FUNCTION(qup6),
-	FUNCTION(reserved45),
-	FUNCTION(reserved46),
-	FUNCTION(reserved47),
-	FUNCTION(reserved124),
-	FUNCTION(reserved125),
-	FUNCTION(reserved126),
-	FUNCTION(reserved127),
-	FUNCTION(reserved128),
-	FUNCTION(reserved129),
-	FUNCTION(qlink_request),
-	FUNCTION(reserved130),
-	FUNCTION(qlink_enable),
-	FUNCTION(reserved131),
-	FUNCTION(reserved132),
-	FUNCTION(reserved133),
-	FUNCTION(reserved134),
-	FUNCTION(pa_indicator),
-	FUNCTION(reserved135),
-	FUNCTION(reserved136),
-	FUNCTION(phase_flag26),
-	FUNCTION(reserved137),
-	FUNCTION(phase_flag27),
-	FUNCTION(reserved138),
-	FUNCTION(phase_flag28),
-	FUNCTION(reserved139),
-	FUNCTION(phase_flag6),
-	FUNCTION(reserved140),
-	FUNCTION(phase_flag29),
-	FUNCTION(reserved141),
-	FUNCTION(phase_flag30),
-	FUNCTION(reserved142),
-	FUNCTION(phase_flag31),
-	FUNCTION(reserved143),
-	FUNCTION(mss_lte),
-	FUNCTION(reserved144),
-	FUNCTION(reserved145),
-	FUNCTION(reserved146),
-	FUNCTION(reserved147),
-	FUNCTION(reserved148),
-	FUNCTION(reserved149),
-	FUNCTION(reserved48),
 	FUNCTION(qup12),
-	FUNCTION(reserved49),
-	FUNCTION(reserved50),
-	FUNCTION(reserved51),
 	FUNCTION(phase_flag16),
-	FUNCTION(reserved52),
 	FUNCTION(qup10),
 	FUNCTION(phase_flag11),
-	FUNCTION(reserved53),
 	FUNCTION(GP_PDM0),
 	FUNCTION(phase_flag12),
 	FUNCTION(wlan1_adc1),
 	FUNCTION(atest_usb13),
 	FUNCTION(ddr_pxi1),
-	FUNCTION(reserved54),
 	FUNCTION(phase_flag13),
 	FUNCTION(wlan1_adc0),
 	FUNCTION(atest_usb12),
-	FUNCTION(reserved55),
 	FUNCTION(phase_flag17),
-	FUNCTION(reserved56),
 	FUNCTION(qua_mi2s),
 	FUNCTION(gcc_gp1),
 	FUNCTION(phase_flag18),
-	FUNCTION(reserved57),
 	FUNCTION(pri_mi2s),
 	FUNCTION(qup8),
 	FUNCTION(wsa_clk),
-	FUNCTION(reserved65),
 	FUNCTION(pri_mi2s_ws),
 	FUNCTION(wsa_data),
-	FUNCTION(reserved66),
-	FUNCTION(wsa_en),
 	FUNCTION(atest_usb2),
-	FUNCTION(reserved67),
 	FUNCTION(atest_usb23),
-	FUNCTION(reserved68),
 	FUNCTION(ter_mi2s),
 	FUNCTION(phase_flag8),
 	FUNCTION(atest_usb22),
-	FUNCTION(reserved75),
 	FUNCTION(phase_flag9),
 	FUNCTION(atest_usb21),
-	FUNCTION(reserved76),
 	FUNCTION(phase_flag4),
 	FUNCTION(atest_usb20),
-	FUNCTION(reserved77),
-	FUNCTION(ssc_irq),
-	FUNCTION(reserved78),
 	FUNCTION(sec_mi2s),
 	FUNCTION(GP_PDM2),
-	FUNCTION(reserved79),
-	FUNCTION(reserved80),
 	FUNCTION(qup15),
-	FUNCTION(reserved81),
-	FUNCTION(reserved82),
-	FUNCTION(reserved83),
-	FUNCTION(reserved84),
 	FUNCTION(qup5),
-	FUNCTION(reserved85),
 	FUNCTION(copy_gp),
-	FUNCTION(reserved86),
-	FUNCTION(reserved87),
-	FUNCTION(reserved88),
 	FUNCTION(tsif1_clk),
 	FUNCTION(qup4),
 	FUNCTION(tgu_ch3),
 	FUNCTION(phase_flag10),
-	FUNCTION(reserved89),
 	FUNCTION(tsif1_en),
 	FUNCTION(mdp_vsync0),
 	FUNCTION(mdp_vsync1),
@@ -1922,326 +1269,320 @@
 	FUNCTION(mdp_vsync3),
 	FUNCTION(tgu_ch0),
 	FUNCTION(phase_flag0),
-	FUNCTION(reserved90),
 	FUNCTION(tsif1_data),
 	FUNCTION(sdc4_cmd),
 	FUNCTION(tgu_ch1),
-	FUNCTION(reserved91),
 	FUNCTION(tsif2_error),
 	FUNCTION(sdc43),
 	FUNCTION(vfr_1),
 	FUNCTION(tgu_ch2),
-	FUNCTION(reserved92),
 	FUNCTION(tsif2_clk),
 	FUNCTION(sdc4_clk),
 	FUNCTION(qup7),
-	FUNCTION(reserved93),
 	FUNCTION(tsif2_en),
 	FUNCTION(sdc42),
-	FUNCTION(reserved94),
 	FUNCTION(tsif2_data),
 	FUNCTION(sdc41),
-	FUNCTION(reserved95),
 	FUNCTION(tsif2_sync),
 	FUNCTION(sdc40),
 	FUNCTION(phase_flag3),
-	FUNCTION(reserved96),
 	FUNCTION(ldo_en),
-	FUNCTION(reserved97),
 	FUNCTION(ldo_update),
-	FUNCTION(reserved98),
 	FUNCTION(phase_flag14),
 	FUNCTION(prng_rosc),
-	FUNCTION(reserved99),
 	FUNCTION(phase_flag15),
-	FUNCTION(reserved100),
 	FUNCTION(phase_flag5),
-	FUNCTION(reserved101),
 	FUNCTION(pci_e1),
-	FUNCTION(reserved102),
 	FUNCTION(COPY_PHASE),
-	FUNCTION(reserved103),
 	FUNCTION(uim2_data),
 	FUNCTION(qup13),
-	FUNCTION(reserved105),
 	FUNCTION(uim2_clk),
-	FUNCTION(reserved106),
 	FUNCTION(uim2_reset),
-	FUNCTION(reserved107),
 	FUNCTION(uim2_present),
-	FUNCTION(reserved108),
 	FUNCTION(uim1_data),
-	FUNCTION(reserved109),
 	FUNCTION(uim1_clk),
-	FUNCTION(reserved110),
 	FUNCTION(uim1_reset),
-	FUNCTION(reserved111),
 	FUNCTION(uim1_present),
-	FUNCTION(reserved112),
 	FUNCTION(uim_batt),
 	FUNCTION(edp_hot),
-	FUNCTION(reserved113),
 	FUNCTION(NAV_PPS),
 	FUNCTION(GPS_TX),
-	FUNCTION(reserved114),
-	FUNCTION(reserved115),
-	FUNCTION(reserved116),
 	FUNCTION(atest_char),
-	FUNCTION(reserved117),
 	FUNCTION(adsp_ext),
 	FUNCTION(atest_char3),
-	FUNCTION(reserved118),
 	FUNCTION(atest_char2),
-	FUNCTION(reserved119),
 	FUNCTION(atest_char1),
-	FUNCTION(reserved120),
 	FUNCTION(atest_char0),
-	FUNCTION(reserved121),
-	FUNCTION(reserved122),
-	FUNCTION(reserved123),
+	FUNCTION(qlink_request),
+	FUNCTION(qlink_enable),
+	FUNCTION(pa_indicator),
+	FUNCTION(phase_flag26),
+	FUNCTION(phase_flag27),
+	FUNCTION(phase_flag28),
+	FUNCTION(phase_flag6),
+	FUNCTION(phase_flag29),
+	FUNCTION(phase_flag30),
+	FUNCTION(phase_flag31),
+	FUNCTION(mss_lte),
 };
 
+/* Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
 static const struct msm_pingroup sdm670_groups[] = {
-	PINGROUP(0, SOUTH, qup0, NA, reserved0, NA, NA, NA, NA, NA, NA),
-	PINGROUP(1, SOUTH, qup0, NA, reserved1, NA, NA, NA, NA, NA, NA),
-	PINGROUP(2, SOUTH, qup0, NA, reserved2, NA, NA, NA, NA, NA, NA),
-	PINGROUP(3, SOUTH, qup0, NA, reserved3, NA, NA, NA, NA, NA, NA),
-	PINGROUP(4, NORTH, qup9, qdss_cti, reserved4, NA, NA, NA, NA, NA, NA),
-	PINGROUP(5, NORTH, qup9, qdss_cti, reserved5, NA, NA, NA, NA, NA, NA),
-	PINGROUP(6, NORTH, qup9, NA, ddr_pxi0, reserved6, NA, NA, NA, NA, NA),
-	PINGROUP(7, NORTH, qup9, ddr_bist, NA, atest_tsens2, vsense_trigger,
-		 atest_usb1, ddr_pxi0, reserved7, NA),
-	PINGROUP(8, WEST, qup_l4, GP_PDM1, ddr_bist, NA, reserved8, NA, NA, NA,
-		 NA),
-	PINGROUP(9, WEST, qup_l5, ddr_bist, reserved9, NA, NA, NA, NA, NA, NA),
-	PINGROUP(10, NORTH, mdp_vsync, qup_l6, ddr_bist, wlan2_adc1,
-		 atest_usb11, ddr_pxi2, reserved10, NA, NA),
-	PINGROUP(11, NORTH, mdp_vsync, edp_lcd, dbg_out, wlan2_adc0,
-		 atest_usb10, ddr_pxi2, reserved11, NA, NA),
-	PINGROUP(12, SOUTH, mdp_vsync, m_voc, tsif1_sync, ddr_pxi3, reserved12,
-		 NA, NA, NA, NA),
-	PINGROUP(13, WEST, cam_mclk, pll_bypassnl, qdss_gpio0, ddr_pxi3,
-		 reserved13, NA, NA, NA, NA),
-	PINGROUP(14, WEST, cam_mclk, pll_reset, qdss_gpio1, reserved14, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(15, WEST, cam_mclk, qdss_gpio2, reserved15, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(16, WEST, cam_mclk, qdss_gpio3, reserved16, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(17, WEST, cci_i2c, qup1, qdss_gpio4, reserved17, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(18, WEST, cci_i2c, qup1, NA, qdss_gpio5, reserved18, NA, NA,
-		 NA, NA),
-	PINGROUP(19, WEST, cci_i2c, qup1, NA, qdss_gpio6, reserved19, NA, NA,
-		 NA, NA),
-	PINGROUP(20, WEST, cci_i2c, qup1, NA, qdss_gpio7, reserved20, NA, NA,
-		 NA, NA),
-	PINGROUP(21, WEST, cci_timer0, gcc_gp2, qdss_gpio8, NA, reserved21, NA,
-		 NA, NA, NA),
-	PINGROUP(22, WEST, cci_timer1, gcc_gp3, qdss_gpio, NA, reserved22, NA,
-		 NA, NA, NA),
-	PINGROUP(23, WEST, cci_timer2, qdss_gpio9, NA, reserved23, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(24, WEST, cci_timer3, cci_async, qdss_gpio10, reserved24, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(25, WEST, cci_timer4, cci_async, qdss_gpio11, NA, reserved25,
-		 NA, NA, NA, NA),
-	PINGROUP(26, WEST, cci_async, qdss_gpio12, JITTER_BIST, NA, reserved26,
-		 NA, NA, NA, NA),
-	PINGROUP(27, WEST, qup2, qdss_gpio13, PLL_BIST, NA, reserved27, NA, NA,
-		 NA, NA),
-	PINGROUP(28, WEST, qup2, qdss_gpio14, AGERA_PLL, NA, reserved28, NA,
-		 NA, NA, NA),
-	PINGROUP(29, WEST, qup2, NA, phase_flag1, qdss_gpio15, atest_tsens,
-		 reserved29, NA, NA, NA),
-	PINGROUP(30, WEST, qup2, phase_flag2, qdss_gpio, reserved30, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(31, WEST, qup11, qup14, reserved31, NA, NA, NA, NA, NA, NA),
-	PINGROUP(32, WEST, qup11, qup14, NA, reserved32, NA, NA, NA, NA, NA),
-	PINGROUP(33, WEST, qup11, qup14, NA, reserved33, NA, NA, NA, NA, NA),
-	PINGROUP(34, WEST, qup11, qup14, NA, reserved34, NA, NA, NA, NA, NA),
-	PINGROUP(35, NORTH, pci_e0, QUP_L4, JITTER_BIST, NA, reserved35, NA,
-		 NA, NA, NA),
-	PINGROUP(36, NORTH, pci_e0, QUP_L5, PLL_BIST, NA, reserved36, NA, NA,
-		 NA, NA),
-	PINGROUP(37, NORTH, QUP_L6, AGERA_PLL, NA, reserved37, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(38, NORTH, usb_phy, NA, reserved38, NA, NA, NA, NA, NA, NA),
-	PINGROUP(39, NORTH, lpass_slimbus, NA, reserved39, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(40, NORTH, sd_write, tsif1_error, NA, reserved40, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(41, SOUTH, qup3, NA, qdss_gpio6, reserved41, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(42, SOUTH, qup3, NA, qdss_gpio7, reserved42, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(43, SOUTH, qup3, NA, qdss_gpio14, reserved43, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(44, SOUTH, qup3, NA, qdss_gpio15, reserved44, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(45, SOUTH, qup6, NA, reserved45, NA, NA, NA, NA, NA, NA),
-	PINGROUP(46, SOUTH, qup6, NA, reserved46, NA, NA, NA, NA, NA, NA),
-	PINGROUP(47, SOUTH, qup6, reserved47, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(48, SOUTH, qup6, reserved48, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(49, NORTH, qup12, reserved49, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(50, NORTH, qup12, reserved50, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(51, NORTH, qup12, qdss_cti, reserved51, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(52, NORTH, qup12, phase_flag16, qdss_cti, reserved52, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(53, NORTH, qup10, phase_flag11, reserved53, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(54, NORTH, qup10, GP_PDM0, phase_flag12, NA, wlan1_adc1,
-		 atest_usb13, ddr_pxi1, reserved54, NA),
-	PINGROUP(55, NORTH, qup10, phase_flag13, NA, wlan1_adc0, atest_usb12,
-		 ddr_pxi1, reserved55, NA, NA),
-	PINGROUP(56, NORTH, qup10, phase_flag17, reserved56, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(57, NORTH, qua_mi2s, gcc_gp1, phase_flag18, reserved57, NA,
-		 NA, NA, NA, NA),
-	PINGROUP(65, NORTH, pri_mi2s, qup8, wsa_clk, NA, reserved65, NA, NA,
-		 NA, NA),
-	PINGROUP(66, NORTH, pri_mi2s_ws, qup8, wsa_data, GP_PDM1, NA,
-		 reserved66, NA, NA, NA),
-	PINGROUP(67, NORTH, pri_mi2s, qup8, NA, atest_usb2, reserved67, NA, NA,
-		 NA, NA),
-	PINGROUP(68, NORTH, pri_mi2s, qup8, NA, atest_usb23, reserved68, NA,
-		 NA, NA, NA),
-	PINGROUP(75, NORTH, ter_mi2s, phase_flag8, qdss_gpio8, atest_usb22,
-		 QUP_L4, reserved75, NA, NA, NA),
-	PINGROUP(76, NORTH, ter_mi2s, phase_flag9, qdss_gpio9, atest_usb21,
-		 QUP_L5, reserved76, NA, NA, NA),
-	PINGROUP(77, NORTH, ter_mi2s, phase_flag4, qdss_gpio10, atest_usb20,
-		 QUP_L6, reserved77, NA, NA, NA),
-	PINGROUP(78, NORTH, ter_mi2s, gcc_gp1, NA, reserved78, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(79, NORTH, sec_mi2s, GP_PDM2, NA, qdss_gpio11, NA, reserved79,
-		 NA, NA, NA),
-	PINGROUP(80, NORTH, sec_mi2s, NA, qdss_gpio12, reserved80, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(81, NORTH, sec_mi2s, qup15, NA, reserved81, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(82, NORTH, sec_mi2s, qup15, NA, reserved82, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(83, NORTH, sec_mi2s, qup15, NA, reserved83, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(84, NORTH, qup15, NA, reserved84, NA, NA, NA, NA, NA, NA),
-	PINGROUP(85, SOUTH, qup5, NA, reserved85, NA, NA, NA, NA, NA, NA),
-	PINGROUP(86, SOUTH, qup5, copy_gp, NA, reserved86, NA, NA, NA, NA, NA),
-	PINGROUP(87, SOUTH, qup5, NA, reserved87, NA, NA, NA, NA, NA, NA),
-	PINGROUP(88, SOUTH, qup5, NA, reserved88, NA, NA, NA, NA, NA, NA),
-	PINGROUP(89, SOUTH, tsif1_clk, qup4, tgu_ch3, phase_flag10, reserved89,
-		 NA, NA, NA, NA),
-	PINGROUP(90, SOUTH, tsif1_en, mdp_vsync0, qup4, mdp_vsync1, mdp_vsync2,
-		 mdp_vsync3, tgu_ch0, phase_flag0, qdss_cti),
-	PINGROUP(91, SOUTH, tsif1_data, sdc4_cmd, qup4, tgu_ch1, NA, qdss_cti,
-		 reserved91, NA, NA),
-	PINGROUP(92, SOUTH, tsif2_error, sdc43, qup4, vfr_1, tgu_ch2, NA,
-		 reserved92, NA, NA),
-	PINGROUP(93, SOUTH, tsif2_clk, sdc4_clk, qup7, NA, qdss_gpio13,
-		 reserved93, NA, NA, NA),
-	PINGROUP(94, SOUTH, tsif2_en, sdc42, qup7, NA, reserved94, NA, NA, NA,
-		 NA),
-	PINGROUP(95, SOUTH, tsif2_data, sdc41, qup7, GP_PDM0, NA, reserved95,
-		 NA, NA, NA),
-	PINGROUP(96, SOUTH, tsif2_sync, sdc40, qup7, phase_flag3, reserved96,
-		 NA, NA, NA, NA),
-	PINGROUP(97, WEST, NA, NA, mdp_vsync, ldo_en, reserved97, NA, NA, NA,
-		 NA),
-	PINGROUP(98, WEST, NA, mdp_vsync, ldo_update, reserved98, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(99, NORTH, phase_flag14, prng_rosc, reserved99, NA, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(100, WEST, phase_flag15, reserved100, NA, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(101, WEST, NA, phase_flag5, reserved101, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(102, WEST, pci_e1, prng_rosc, reserved102, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(103, WEST, pci_e1, COPY_PHASE, reserved103, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(105, NORTH, uim2_data, qup13, qup_l4, NA, reserved105, NA, NA,
-		 NA, NA),
-	PINGROUP(106, NORTH, uim2_clk, qup13, qup_l5, NA, reserved106, NA, NA,
-		 NA, NA),
-	PINGROUP(107, NORTH, uim2_reset, qup13, qup_l6, reserved107, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(108, NORTH, uim2_present, qup13, reserved108, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(109, NORTH, uim1_data, reserved109, NA, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(110, NORTH, uim1_clk, reserved110, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(111, NORTH, uim1_reset, reserved111, NA, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(112, NORTH, uim1_present, reserved112, NA, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(113, NORTH, uim_batt, edp_hot, reserved113, NA, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(114, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, reserved114, NA,
-		 NA, NA),
-	PINGROUP(115, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, reserved115, NA,
-		 NA, NA),
-	PINGROUP(116, SOUTH, NA, reserved116, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(117, NORTH, NA, qdss_gpio0, atest_char, reserved117, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(118, NORTH, adsp_ext, NA, qdss_gpio1, atest_char3,
-		 reserved118, NA, NA, NA, NA),
-	PINGROUP(119, NORTH, NA, qdss_gpio2, atest_char2, reserved119, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(120, NORTH, NA, qdss_gpio3, atest_char1, reserved120, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(121, NORTH, NA, qdss_gpio4, atest_char0, reserved121, NA, NA,
-		 NA, NA, NA),
-	PINGROUP(122, NORTH, NA, qdss_gpio5, reserved122, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(123, NORTH, qup_l4, NA, qdss_gpio, reserved123, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(124, NORTH, qup_l5, NA, qdss_gpio, reserved124, NA, NA, NA,
-		 NA, NA),
-	PINGROUP(125, NORTH, qup_l6, NA, reserved125, NA, NA, NA, NA, NA, NA),
-	PINGROUP(126, NORTH, NA, reserved126, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(127, WEST, NA, NA, reserved127, NA, NA, NA, NA, NA, NA),
-	PINGROUP(128, WEST, NAV_PPS, NAV_PPS, GPS_TX, NA, reserved128, NA, NA,
-		 NA, NA),
-	PINGROUP(129, WEST, NAV_PPS, NAV_PPS, GPS_TX, NA, reserved129, NA, NA,
-		 NA, NA),
-	PINGROUP(130, WEST, qlink_request, NA, reserved130, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(131, WEST, qlink_enable, NA, reserved131, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(132, WEST, NA, NA, reserved132, NA, NA, NA, NA, NA, NA),
-	PINGROUP(133, NORTH, NA, reserved133, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(134, NORTH, NA, reserved134, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(135, WEST, NA, pa_indicator, NA, reserved135, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(136, WEST, NA, NA, reserved136, NA, NA, NA, NA, NA, NA),
-	PINGROUP(137, WEST, NA, NA, phase_flag26, reserved137, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(138, WEST, NA, NA, phase_flag27, reserved138, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(139, WEST, NA, phase_flag28, reserved139, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(140, WEST, NA, NA, phase_flag6, reserved140, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(141, WEST, NA, phase_flag29, reserved141, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(142, WEST, NA, phase_flag30, reserved142, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(143, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, phase_flag31,
-		 reserved143, NA, NA, NA),
-	PINGROUP(144, SOUTH, mss_lte, reserved144, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(145, SOUTH, mss_lte, GPS_TX, reserved145, NA, NA, NA, NA, NA,
-		 NA),
-	PINGROUP(146, WEST, NA, NA, reserved146, NA, NA, NA, NA, NA, NA),
-	PINGROUP(147, WEST, NA, NA, reserved147, NA, NA, NA, NA, NA, NA),
-	PINGROUP(148, WEST, NA, reserved148, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(149, WEST, NA, reserved149, NA, NA, NA, NA, NA, NA, NA),
-	SDC_QDSD_PINGROUP(sdc1_clk, 0x599000, 13, 6),
-	SDC_QDSD_PINGROUP(sdc1_cmd, 0x599000, 11, 3),
-	SDC_QDSD_PINGROUP(sdc1_data, 0x599000, 9, 0),
-	SDC_QDSD_PINGROUP(sdc2_clk, 0x99a000, 14, 6),
-	SDC_QDSD_PINGROUP(sdc2_cmd, 0x99a000, 11, 3),
-	SDC_QDSD_PINGROUP(sdc2_data, 0x99a000, 9, 0),
+	[0] = PINGROUP(0, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[1] = PINGROUP(1, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[2] = PINGROUP(2, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[3] = PINGROUP(3, SOUTH, qup0, NA, NA, NA, NA, NA, NA, NA, NA),
+	[4] = PINGROUP(4, NORTH, qup9, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[5] = PINGROUP(5, NORTH, qup9, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[6] = PINGROUP(6, NORTH, qup9, NA, ddr_pxi0, NA, NA, NA, NA, NA, NA),
+	[7] = PINGROUP(7, NORTH, qup9, ddr_bist, NA, atest_tsens2,
+		       vsense_trigger, atest_usb1, ddr_pxi0, NA, NA),
+	[8] = PINGROUP(8, WEST, qup_l4, GP_PDM1, ddr_bist, NA, NA, NA, NA, NA,
+		       NA),
+	[9] = PINGROUP(9, WEST, qup_l5, ddr_bist, NA, NA, NA, NA, NA, NA, NA),
+	[10] = PINGROUP(10, NORTH, mdp_vsync, qup_l6, ddr_bist, wlan2_adc1,
+			atest_usb11, ddr_pxi2, NA, NA, NA),
+	[11] = PINGROUP(11, NORTH, mdp_vsync, edp_lcd, dbg_out, wlan2_adc0,
+			atest_usb10, ddr_pxi2, NA, NA, NA),
+	[12] = PINGROUP(12, SOUTH, mdp_vsync, m_voc, tsif1_sync, ddr_pxi3, NA,
+			NA, NA, NA, NA),
+	[13] = PINGROUP(13, WEST, cam_mclk, pll_bypassnl, qdss_gpio0, ddr_pxi3,
+			NA, NA, NA, NA, NA),
+	[14] = PINGROUP(14, WEST, cam_mclk, pll_reset, qdss_gpio1, NA, NA, NA,
+			NA, NA, NA),
+	[15] = PINGROUP(15, WEST, cam_mclk, qdss_gpio2, NA, NA, NA, NA, NA, NA,
+			NA),
+	[16] = PINGROUP(16, WEST, cam_mclk, qdss_gpio3, NA, NA, NA, NA, NA, NA,
+			NA),
+	[17] = PINGROUP(17, WEST, cci_i2c, qup1, qdss_gpio4, NA, NA, NA, NA,
+			NA, NA),
+	[18] = PINGROUP(18, WEST, cci_i2c, qup1, NA, qdss_gpio5, NA, NA, NA,
+			NA, NA),
+	[19] = PINGROUP(19, WEST, cci_i2c, qup1, NA, qdss_gpio6, NA, NA, NA,
+			NA, NA),
+	[20] = PINGROUP(20, WEST, cci_i2c, qup1, NA, qdss_gpio7, NA, NA, NA,
+			NA, NA),
+	[21] = PINGROUP(21, WEST, cci_timer0, gcc_gp2, qdss_gpio8, NA, NA, NA,
+			NA, NA, NA),
+	[22] = PINGROUP(22, WEST, cci_timer1, gcc_gp3, qdss_gpio, NA, NA, NA,
+			NA, NA, NA),
+	[23] = PINGROUP(23, WEST, cci_timer2, qdss_gpio9, NA, NA, NA, NA, NA,
+			NA, NA),
+	[24] = PINGROUP(24, WEST, cci_timer3, cci_async, qdss_gpio10, NA, NA,
+			NA, NA, NA, NA),
+	[25] = PINGROUP(25, WEST, cci_timer4, cci_async, qdss_gpio11, NA, NA,
+			NA, NA, NA, NA),
+	[26] = PINGROUP(26, WEST, cci_async, qdss_gpio12, JITTER_BIST, NA, NA,
+			NA, NA, NA, NA),
+	[27] = PINGROUP(27, WEST, qup2, qdss_gpio13, PLL_BIST, NA, NA, NA, NA,
+			NA, NA),
+	[28] = PINGROUP(28, WEST, qup2, qdss_gpio14, AGERA_PLL, NA, NA, NA, NA,
+			NA, NA),
+	[29] = PINGROUP(29, WEST, qup2, NA, phase_flag1, qdss_gpio15,
+			atest_tsens, NA, NA, NA, NA),
+	[30] = PINGROUP(30, WEST, qup2, phase_flag2, qdss_gpio, NA, NA, NA, NA,
+			NA, NA),
+	[31] = PINGROUP(31, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[32] = PINGROUP(32, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[33] = PINGROUP(33, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[34] = PINGROUP(34, WEST, qup11, qup14, NA, NA, NA, NA, NA, NA, NA),
+	[35] = PINGROUP(35, NORTH, pci_e0, QUP_L4, JITTER_BIST, NA, NA, NA, NA,
+			NA, NA),
+	[36] = PINGROUP(36, NORTH, pci_e0, QUP_L5, PLL_BIST, NA, NA, NA, NA,
+			NA, NA),
+	[37] = PINGROUP(37, NORTH, QUP_L6, AGERA_PLL, NA, NA, NA, NA, NA, NA,
+			NA),
+	[38] = PINGROUP(38, NORTH, usb_phy, NA, NA, NA, NA, NA, NA, NA, NA),
+	[39] = PINGROUP(39, NORTH, lpass_slimbus, NA, NA, NA, NA, NA, NA, NA,
+			NA),
+	[40] = PINGROUP(40, NORTH, sd_write, tsif1_error, NA, NA, NA, NA, NA,
+			NA, NA),
+	[41] = PINGROUP(41, SOUTH, qup3, NA, qdss_gpio6, NA, NA, NA, NA, NA,
+			NA),
+	[42] = PINGROUP(42, SOUTH, qup3, NA, qdss_gpio7, NA, NA, NA, NA, NA,
+			NA),
+	[43] = PINGROUP(43, SOUTH, qup3, NA, qdss_gpio14, NA, NA, NA, NA, NA,
+			NA),
+	[44] = PINGROUP(44, SOUTH, qup3, NA, qdss_gpio15, NA, NA, NA, NA, NA,
+			NA),
+	[45] = PINGROUP(45, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[46] = PINGROUP(46, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[47] = PINGROUP(47, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[48] = PINGROUP(48, SOUTH, qup6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[49] = PINGROUP(49, NORTH, qup12, NA, NA, NA, NA, NA, NA, NA, NA),
+	[50] = PINGROUP(50, NORTH, qup12, NA, NA, NA, NA, NA, NA, NA, NA),
+	[51] = PINGROUP(51, NORTH, qup12, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[52] = PINGROUP(52, NORTH, qup12, phase_flag16, qdss_cti, NA, NA, NA,
+			NA, NA, NA),
+	[53] = PINGROUP(53, NORTH, qup10, phase_flag11, NA, NA, NA, NA, NA, NA,
+			NA),
+	[54] = PINGROUP(54, NORTH, qup10, GP_PDM0, phase_flag12, NA,
+			wlan1_adc1, atest_usb13, ddr_pxi1, NA, NA),
+	[55] = PINGROUP(55, NORTH, qup10, phase_flag13, NA, wlan1_adc0,
+			atest_usb12, ddr_pxi1, NA, NA, NA),
+	[56] = PINGROUP(56, NORTH, qup10, phase_flag17, NA, NA, NA, NA, NA, NA,
+			NA),
+	[57] = PINGROUP(57, NORTH, qua_mi2s, gcc_gp1, phase_flag18, NA, NA, NA,
+			NA, NA, NA),
+	[58] = PINGROUP(58, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[59] = PINGROUP(59, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[60] = PINGROUP(60, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[61] = PINGROUP(61, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[62] = PINGROUP(62, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[63] = PINGROUP(63, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[64] = PINGROUP(64, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[65] = PINGROUP(65, NORTH, pri_mi2s, qup8, wsa_clk, NA, NA, NA, NA, NA,
+			NA),
+	[66] = PINGROUP(66, NORTH, pri_mi2s_ws, qup8, wsa_data, GP_PDM1, NA,
+			NA, NA, NA, NA),
+	[67] = PINGROUP(67, NORTH, pri_mi2s, qup8, NA, atest_usb2, NA, NA, NA,
+			NA, NA),
+	[68] = PINGROUP(68, NORTH, pri_mi2s, qup8, NA, atest_usb23, NA, NA, NA,
+			NA, NA),
+	[69] = PINGROUP(69, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[70] = PINGROUP(70, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[71] = PINGROUP(71, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[72] = PINGROUP(72, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[73] = PINGROUP(73, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[74] = PINGROUP(74, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[75] = PINGROUP(75, NORTH, ter_mi2s, phase_flag8, qdss_gpio8,
+			atest_usb22, QUP_L4, NA, NA, NA, NA),
+	[76] = PINGROUP(76, NORTH, ter_mi2s, phase_flag9, qdss_gpio9,
+			atest_usb21, QUP_L5, NA, NA, NA, NA),
+	[77] = PINGROUP(77, NORTH, ter_mi2s, phase_flag4, qdss_gpio10,
+			atest_usb20, QUP_L6, NA, NA, NA, NA),
+	[78] = PINGROUP(78, NORTH, ter_mi2s, gcc_gp1, NA, NA, NA, NA, NA, NA,
+			NA),
+	[79] = PINGROUP(79, NORTH, sec_mi2s, GP_PDM2, NA, qdss_gpio11, NA, NA,
+			NA, NA, NA),
+	[80] = PINGROUP(80, NORTH, sec_mi2s, NA, qdss_gpio12, NA, NA, NA, NA,
+			NA, NA),
+	[81] = PINGROUP(81, NORTH, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
+	[82] = PINGROUP(82, NORTH, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
+	[83] = PINGROUP(83, NORTH, sec_mi2s, qup15, NA, NA, NA, NA, NA, NA, NA),
+	[84] = PINGROUP(84, NORTH, qup15, NA, NA, NA, NA, NA, NA, NA, NA),
+	[85] = PINGROUP(85, SOUTH, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
+	[86] = PINGROUP(86, SOUTH, qup5, copy_gp, NA, NA, NA, NA, NA, NA, NA),
+	[87] = PINGROUP(87, SOUTH, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
+	[88] = PINGROUP(88, SOUTH, qup5, NA, NA, NA, NA, NA, NA, NA, NA),
+	[89] = PINGROUP(89, SOUTH, tsif1_clk, qup4, tgu_ch3, phase_flag10, NA,
+			NA, NA, NA, NA),
+	[90] = PINGROUP(90, SOUTH, tsif1_en, mdp_vsync0, qup4, mdp_vsync1,
+			mdp_vsync2, mdp_vsync3, tgu_ch0, phase_flag0, qdss_cti),
+	[91] = PINGROUP(91, SOUTH, tsif1_data, sdc4_cmd, qup4, tgu_ch1, NA,
+			qdss_cti, NA, NA, NA),
+	[92] = PINGROUP(92, SOUTH, tsif2_error, sdc43, qup4, vfr_1, tgu_ch2,
+			NA, NA, NA, NA),
+	[93] = PINGROUP(93, SOUTH, tsif2_clk, sdc4_clk, qup7, NA, qdss_gpio13,
+			NA, NA, NA, NA),
+	[94] = PINGROUP(94, SOUTH, tsif2_en, sdc42, qup7, NA, NA, NA, NA, NA,
+			NA),
+	[95] = PINGROUP(95, SOUTH, tsif2_data, sdc41, qup7, GP_PDM0, NA, NA,
+			NA, NA, NA),
+	[96] = PINGROUP(96, SOUTH, tsif2_sync, sdc40, qup7, phase_flag3, NA,
+			NA, NA, NA, NA),
+	[97] = PINGROUP(97, WEST, NA, NA, mdp_vsync, ldo_en, NA, NA, NA, NA,
+			NA),
+	[98] = PINGROUP(98, WEST, NA, mdp_vsync, ldo_update, NA, NA, NA, NA,
+			NA, NA),
+	[99] = PINGROUP(99, NORTH, phase_flag14, prng_rosc, NA, NA, NA, NA, NA,
+			NA, NA),
+	[100] = PINGROUP(100, WEST, phase_flag15, NA, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[101] = PINGROUP(101, WEST, NA, phase_flag5, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[102] = PINGROUP(102, WEST, pci_e1, prng_rosc, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[103] = PINGROUP(103, WEST, pci_e1, COPY_PHASE, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[104] = PINGROUP(104, DUMMY, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[105] = PINGROUP(105, NORTH, uim2_data, qup13, qup_l4, NA, NA, NA, NA,
+			 NA, NA),
+	[106] = PINGROUP(106, NORTH, uim2_clk, qup13, qup_l5, NA, NA, NA, NA,
+			 NA, NA),
+	[107] = PINGROUP(107, NORTH, uim2_reset, qup13, qup_l6, NA, NA, NA, NA,
+			 NA, NA),
+	[108] = PINGROUP(108, NORTH, uim2_present, qup13, NA, NA, NA, NA, NA,
+			 NA, NA),
+	[109] = PINGROUP(109, NORTH, uim1_data, NA, NA, NA, NA, NA, NA, NA, NA),
+	[110] = PINGROUP(110, NORTH, uim1_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+	[111] = PINGROUP(111, NORTH, uim1_reset, NA, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[112] = PINGROUP(112, NORTH, uim1_present, NA, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[113] = PINGROUP(113, NORTH, uim_batt, edp_hot, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[114] = PINGROUP(114, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA,
+			 NA, NA),
+	[115] = PINGROUP(115, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA,
+			 NA, NA),
+	[116] = PINGROUP(116, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[117] = PINGROUP(117, NORTH, NA, qdss_gpio0, atest_char, NA, NA, NA,
+			 NA, NA, NA),
+	[118] = PINGROUP(118, NORTH, adsp_ext, NA, qdss_gpio1, atest_char3, NA,
+			 NA, NA, NA, NA),
+	[119] = PINGROUP(119, NORTH, NA, qdss_gpio2, atest_char2, NA, NA, NA,
+			 NA, NA, NA),
+	[120] = PINGROUP(120, NORTH, NA, qdss_gpio3, atest_char1, NA, NA, NA,
+			 NA, NA, NA),
+	[121] = PINGROUP(121, NORTH, NA, qdss_gpio4, atest_char0, NA, NA, NA,
+			 NA, NA, NA),
+	[122] = PINGROUP(122, NORTH, NA, qdss_gpio5, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[123] = PINGROUP(123, NORTH, qup_l4, NA, qdss_gpio, NA, NA, NA, NA, NA,
+			 NA),
+	[124] = PINGROUP(124, NORTH, qup_l5, NA, qdss_gpio, NA, NA, NA, NA, NA,
+			 NA),
+	[125] = PINGROUP(125, NORTH, qup_l6, NA, NA, NA, NA, NA, NA, NA, NA),
+	[126] = PINGROUP(126, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[127] = PINGROUP(127, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[128] = PINGROUP(128, WEST, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, NA,
+			 NA, NA),
+	[129] = PINGROUP(129, WEST, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, NA, NA,
+			 NA, NA),
+	[130] = PINGROUP(130, WEST, qlink_request, NA, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[131] = PINGROUP(131, WEST, qlink_enable, NA, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[132] = PINGROUP(132, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[133] = PINGROUP(133, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[134] = PINGROUP(134, NORTH, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[135] = PINGROUP(135, WEST, NA, pa_indicator, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[136] = PINGROUP(136, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[137] = PINGROUP(137, WEST, NA, NA, phase_flag26, NA, NA, NA, NA, NA,
+			 NA),
+	[138] = PINGROUP(138, WEST, NA, NA, phase_flag27, NA, NA, NA, NA, NA,
+			 NA),
+	[139] = PINGROUP(139, WEST, NA, phase_flag28, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[140] = PINGROUP(140, WEST, NA, NA, phase_flag6, NA, NA, NA, NA, NA,
+			 NA),
+	[141] = PINGROUP(141, WEST, NA, phase_flag29, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[142] = PINGROUP(142, WEST, NA, phase_flag30, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[143] = PINGROUP(143, WEST, NA, NAV_PPS, NAV_PPS, GPS_TX, phase_flag31,
+			 NA, NA, NA, NA),
+	[144] = PINGROUP(144, SOUTH, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA),
+	[145] = PINGROUP(145, SOUTH, mss_lte, GPS_TX, NA, NA, NA, NA, NA, NA,
+			 NA),
+	[146] = PINGROUP(146, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[147] = PINGROUP(147, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[148] = PINGROUP(148, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[149] = PINGROUP(149, WEST, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	[150] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x599000, 15, 0),
+	[151] = SDC_QDSD_PINGROUP(sdc1_clk, 0x599000, 13, 6),
+	[152] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x599000, 11, 3),
+	[153] = SDC_QDSD_PINGROUP(sdc1_data, 0x599000, 9, 0),
+	[154] = SDC_QDSD_PINGROUP(sdc2_clk, 0x99a000, 14, 6),
+	[155] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x99a000, 11, 3),
+	[156] = SDC_QDSD_PINGROUP(sdc2_data, 0x99a000, 9, 0),
+	[157] = UFS_RESET(ufs_reset, 0x99f000),
 };
 
 static const struct msm_pinctrl_soc_data sdm670_pinctrl = {
@@ -2251,7 +1592,7 @@
 	.nfunctions = ARRAY_SIZE(sdm670_functions),
 	.groups = sdm670_groups,
 	.ngroups = ARRAY_SIZE(sdm670_groups),
-	.ngpios = 136,
+	.ngpios = 150,
 };
 
 static int sdm670_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index cf80ce1..4a5a0fe 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -586,6 +586,9 @@
 		ret = info->ops->init(pfc);
 		if (ret < 0)
 			return ret;
+
+		/* .init() may have overridden pfc->info */
+		info = pfc->info;
 	}
 
 	/* Enable dummy states for those platforms without pinctrl support */
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
index 7ca37c3..baa98d7 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -203,7 +203,7 @@
 
 	/* IPSR6 */
 	FN_AUDIO_CLKB, FN_STP_OPWM_0_B, FN_MSIOF1_SCK_B,
-	FN_SCIF_CLK, FN_BPFCLK_E,
+	FN_SCIF_CLK, FN_DVC_MUTE, FN_BPFCLK_E,
 	FN_AUDIO_CLKC, FN_SCIFB0_SCK_C, FN_MSIOF1_SYNC_B, FN_RX2,
 	FN_SCIFA2_RXD, FN_FMIN_E,
 	FN_AUDIO_CLKOUT, FN_MSIOF1_SS1_B, FN_TX2, FN_SCIFA2_TXD,
@@ -573,7 +573,7 @@
 
 	/* IPSR6 */
 	AUDIO_CLKB_MARK, STP_OPWM_0_B_MARK, MSIOF1_SCK_B_MARK,
-	SCIF_CLK_MARK, BPFCLK_E_MARK,
+	SCIF_CLK_MARK, DVC_MUTE_MARK, BPFCLK_E_MARK,
 	AUDIO_CLKC_MARK, SCIFB0_SCK_C_MARK, MSIOF1_SYNC_B_MARK, RX2_MARK,
 	SCIFA2_RXD_MARK, FMIN_E_MARK,
 	AUDIO_CLKOUT_MARK, MSIOF1_SS1_B_MARK, TX2_MARK, SCIFA2_TXD_MARK,
@@ -1010,14 +1010,17 @@
 	PINMUX_IPSR_MSEL(IP4_12_10, SCL2, SEL_IIC2_0),
 	PINMUX_IPSR_MSEL(IP4_12_10, GPS_CLK_B, SEL_GPS_1),
 	PINMUX_IPSR_MSEL(IP4_12_10, GLO_Q0_D, SEL_GPS_3),
+	PINMUX_IPSR_MSEL(IP4_12_10, HSCK1_E, SEL_HSCIF1_4),
 	PINMUX_IPSR_GPSR(IP4_15_13, SSI_WS2),
 	PINMUX_IPSR_MSEL(IP4_15_13, SDA2, SEL_IIC2_0),
 	PINMUX_IPSR_MSEL(IP4_15_13, GPS_SIGN_B, SEL_GPS_1),
 	PINMUX_IPSR_MSEL(IP4_15_13, RX2_E, SEL_SCIF2_4),
 	PINMUX_IPSR_MSEL(IP4_15_13, GLO_Q1_D, SEL_GPS_3),
+	PINMUX_IPSR_MSEL(IP4_15_13, HCTS1_N_E, SEL_HSCIF1_4),
 	PINMUX_IPSR_GPSR(IP4_18_16, SSI_SDATA2),
 	PINMUX_IPSR_MSEL(IP4_18_16, GPS_MAG_B, SEL_GPS_1),
 	PINMUX_IPSR_MSEL(IP4_18_16, TX2_E, SEL_SCIF2_4),
+	PINMUX_IPSR_MSEL(IP4_18_16, HRTS1_N_E, SEL_HSCIF1_4),
 	PINMUX_IPSR_GPSR(IP4_19, SSI_SCK34),
 	PINMUX_IPSR_GPSR(IP4_20, SSI_WS34),
 	PINMUX_IPSR_GPSR(IP4_21, SSI_SDATA3),
@@ -1090,6 +1093,7 @@
 	PINMUX_IPSR_MSEL(IP6_2_0, STP_OPWM_0_B, SEL_SSP_1),
 	PINMUX_IPSR_MSEL(IP6_2_0, MSIOF1_SCK_B, SEL_SOF1_1),
 	PINMUX_IPSR_MSEL(IP6_2_0, SCIF_CLK, SEL_SCIF_0),
+	PINMUX_IPSR_GPSR(IP6_2_0, DVC_MUTE),
 	PINMUX_IPSR_MSEL(IP6_2_0, BPFCLK_E, SEL_FM_4),
 	PINMUX_IPSR_GPSR(IP6_5_3, AUDIO_CLKC),
 	PINMUX_IPSR_MSEL(IP6_5_3, SCIFB0_SCK_C, SEL_SCIFB_2),
@@ -1099,7 +1103,7 @@
 	PINMUX_IPSR_MSEL(IP6_5_3, FMIN_E, SEL_FM_4),
 	PINMUX_IPSR_GPSR(IP6_7_6, AUDIO_CLKOUT),
 	PINMUX_IPSR_MSEL(IP6_7_6, MSIOF1_SS1_B, SEL_SOF1_1),
-	PINMUX_IPSR_MSEL(IP6_5_3, TX2, SEL_SCIF2_0),
+	PINMUX_IPSR_MSEL(IP6_7_6, TX2, SEL_SCIF2_0),
 	PINMUX_IPSR_MSEL(IP6_7_6, SCIFA2_TXD, SEL_SCIFA2_0),
 	PINMUX_IPSR_GPSR(IP6_9_8, IRQ0),
 	PINMUX_IPSR_MSEL(IP6_9_8, SCIFB1_RXD_D, SEL_SCIFB1_3),
@@ -5810,7 +5814,7 @@
 		0, 0,
 		/* IP6_2_0 [3] */
 		FN_AUDIO_CLKB, FN_STP_OPWM_0_B, FN_MSIOF1_SCK_B,
-		FN_SCIF_CLK, 0, FN_BPFCLK_E,
+		FN_SCIF_CLK, FN_DVC_MUTE, FN_BPFCLK_E,
 		0, 0, }
 	},
 	{ PINMUX_CFG_REG_VAR("IPSR7", 0xE606003C, 32,
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
index ed734f56..ef093ac 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
@@ -281,8 +281,8 @@
 	FN_AVB_AVTP_CAPTURE, FN_ETH_CRS_DV_B, FN_SSI_WS1, FN_SCIF1_TXD_B,
 	FN_IIC1_SDA_C, FN_VI1_DATA0, FN_CAN0_TX_D, FN_AVB_AVTP_MATCH,
 	FN_ETH_RX_ER_B, FN_SSI_SDATA1, FN_HSCIF1_HRX_B, FN_SDATA, FN_VI1_DATA1,
-	FN_ATAG0_N, FN_ETH_RXD0_B, FN_SSI_SCK2, FN_HSCIF1_HTX_B, FN_VI1_DATA2,
-	FN_MDATA, FN_ATAWR0_N, FN_ETH_RXD1_B,
+	FN_ATAWR0_N, FN_ETH_RXD0_B, FN_SSI_SCK2, FN_HSCIF1_HTX_B, FN_VI1_DATA2,
+	FN_MDATA, FN_ATAG0_N, FN_ETH_RXD1_B,
 
 	/* IPSR13 */
 	FN_SSI_WS2, FN_HSCIF1_HCTS_N_B, FN_SCIFA0_RXD_D, FN_VI1_DATA3, FN_SCKZ,
@@ -575,8 +575,8 @@
 	ETH_CRS_DV_B_MARK, SSI_WS1_MARK, SCIF1_TXD_B_MARK, IIC1_SDA_C_MARK,
 	VI1_DATA0_MARK, CAN0_TX_D_MARK, AVB_AVTP_MATCH_MARK, ETH_RX_ER_B_MARK,
 	SSI_SDATA1_MARK, HSCIF1_HRX_B_MARK, VI1_DATA1_MARK, SDATA_MARK,
-	ATAG0_N_MARK, ETH_RXD0_B_MARK, SSI_SCK2_MARK, HSCIF1_HTX_B_MARK,
-	VI1_DATA2_MARK, MDATA_MARK, ATAWR0_N_MARK, ETH_RXD1_B_MARK,
+	ATAWR0_N_MARK, ETH_RXD0_B_MARK, SSI_SCK2_MARK, HSCIF1_HTX_B_MARK,
+	VI1_DATA2_MARK, MDATA_MARK, ATAG0_N_MARK, ETH_RXD1_B_MARK,
 
 	/* IPSR13 */
 	SSI_WS2_MARK, HSCIF1_HCTS_N_B_MARK, SCIFA0_RXD_D_MARK, VI1_DATA3_MARK,
@@ -1413,13 +1413,13 @@
 	PINMUX_IPSR_MSEL(IP12_26_24, HSCIF1_HRX_B, SEL_HSCIF1_1),
 	PINMUX_IPSR_GPSR(IP12_26_24, VI1_DATA1),
 	PINMUX_IPSR_MSEL(IP12_26_24, SDATA, SEL_FSN_0),
-	PINMUX_IPSR_GPSR(IP12_26_24, ATAG0_N),
+	PINMUX_IPSR_GPSR(IP12_26_24, ATAWR0_N),
 	PINMUX_IPSR_MSEL(IP12_26_24, ETH_RXD0_B, SEL_ETH_1),
 	PINMUX_IPSR_MSEL(IP12_29_27, SSI_SCK2, SEL_SSI2_0),
 	PINMUX_IPSR_MSEL(IP12_29_27, HSCIF1_HTX_B, SEL_HSCIF1_1),
 	PINMUX_IPSR_GPSR(IP12_29_27, VI1_DATA2),
 	PINMUX_IPSR_MSEL(IP12_29_27, MDATA, SEL_FSN_0),
-	PINMUX_IPSR_GPSR(IP12_29_27, ATAWR0_N),
+	PINMUX_IPSR_GPSR(IP12_29_27, ATAG0_N),
 	PINMUX_IPSR_MSEL(IP12_29_27, ETH_RXD1_B, SEL_ETH_1),
 
 	/* IPSR13 */
@@ -4938,10 +4938,10 @@
 		0, 0, 0, 0,
 		/* IP12_29_27 [3] */
 		FN_SSI_SCK2, FN_HSCIF1_HTX_B, FN_VI1_DATA2, FN_MDATA,
-		FN_ATAWR0_N, FN_ETH_RXD1_B, 0, 0,
+		FN_ATAG0_N, FN_ETH_RXD1_B, 0, 0,
 		/* IP12_26_24 [3] */
 		FN_SSI_SDATA1, FN_HSCIF1_HRX_B, FN_VI1_DATA1, FN_SDATA,
-		FN_ATAG0_N, FN_ETH_RXD0_B, 0, 0,
+		FN_ATAWR0_N, FN_ETH_RXD0_B, 0, 0,
 		/* IP12_23_21 [3] */
 		FN_SSI_WS1, FN_SCIF1_TXD_B, FN_IIC1_SDA_C, FN_VI1_DATA0,
 		FN_CAN0_TX_D, FN_AVB_AVTP_MATCH, FN_ETH_RX_ER_B, 0,
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
index 84cee66..0acb0a7 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
@@ -2056,7 +2056,7 @@
 	RCAR_GP_PIN(6, 21),
 };
 static const unsigned int hscif2_clk_b_mux[] = {
-	HSCK1_B_MARK,
+	HSCK2_B_MARK,
 };
 static const unsigned int hscif2_ctrl_b_pins[] = {
 	/* RTS, CTS */
@@ -2129,7 +2129,7 @@
 	RCAR_GP_PIN(1, 15), RCAR_GP_PIN(1, 14),
 };
 static const unsigned int hscif4_ctrl_mux[] = {
-	HRTS4_N_MARK, HCTS3_N_MARK,
+	HRTS4_N_MARK, HCTS4_N_MARK,
 };
 
 static const unsigned int hscif4_data_b_pins[] = {
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index efc4371..a36fd4b 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -798,7 +798,7 @@
 		break;
 	case PIN_CONFIG_OUTPUT:
 		__stm32_gpio_set(bank, offset, arg);
-		ret = stm32_pmx_gpio_set_direction(pctldev, NULL, pin, false);
+		ret = stm32_pmx_gpio_set_direction(pctldev, range, pin, false);
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
index 90b973e..a7c81e9 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
@@ -394,7 +394,7 @@
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 18),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x3, "owa")),		/* DOUT */
+		  SUNXI_FUNCTION(0x3, "spdif")),	/* DOUT */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 19),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out")),
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 23103da..808391f 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -422,7 +422,7 @@
 /**
  * ipa_cfg_ep_nat() - IPA end-point NAT configuration
  * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
- * @ipa_ep_cfg:	[in] IPA end-point configuration params
+ * @ep_nat:	[in] IPA NAT end-point configuration params
  *
  * Returns:	0 on success, negative on failure
  *
@@ -439,6 +439,27 @@
 EXPORT_SYMBOL(ipa_cfg_ep_nat);
 
 /**
+* ipa_cfg_ep_conn_track() - IPA end-point IPv6CT configuration
+* @clnt_hdl:		[in] opaque client handle assigned by IPA to client
+* @ep_conn_track:	[in] IPA IPv6CT end-point configuration params
+*
+* Returns:	0 on success, negative on failure
+*
+* Note:	Should not be called from atomic context
+*/
+int ipa_cfg_ep_conn_track(u32 clnt_hdl,
+	const struct ipa_ep_cfg_conn_track *ep_conn_track)
+{
+	int ret;
+
+	IPA_API_DISPATCH_RETURN(ipa_cfg_ep_conn_track, clnt_hdl,
+		ep_conn_track);
+
+	return ret;
+}
+EXPORT_SYMBOL(ipa_cfg_ep_conn_track);
+
+/**
  * ipa_cfg_ep_hdr() -  IPA end-point header configuration
  * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
  * @ipa_ep_cfg:	[in] IPA end-point configuration params
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index bfe1608..d3d4178 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -34,6 +34,9 @@
 	int (*ipa_cfg_ep_nat)(u32 clnt_hdl,
 		const struct ipa_ep_cfg_nat *ipa_ep_cfg);
 
+	int (*ipa_cfg_ep_conn_track)(u32 clnt_hdl,
+		const struct ipa_ep_cfg_conn_track *ipa_ep_cfg);
+
 	int (*ipa_cfg_ep_hdr)(u32 clnt_hdl,
 		const struct ipa_ep_cfg_hdr *ipa_ep_cfg);
 
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index 50804ee..69c83d4 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -26,7 +26,8 @@
 		log_info.file = __FILENAME__; \
 		log_info.line = __LINE__; \
 		log_info.type = EP; \
-		log_info.id_string = ipa_clients_strings[client]
+		log_info.id_string = (client < 0 || client >= IPA_CLIENT_MAX) \
+			? "Invalid Client" : ipa_clients_strings[client]
 
 #define IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info) \
 		log_info.file = __FILENAME__; \
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
index 4b62927..dc27636 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
@@ -516,15 +516,15 @@
 	char __user *start;
 	struct ipa_push_msg *msg = NULL;
 	int ret;
-	DEFINE_WAIT(wait);
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 	int locked;
 
 	start = buf;
 
+	add_wait_queue(&ipa_ctx->msg_waitq, &wait);
 	while (1) {
 		mutex_lock(&ipa_ctx->msg_lock);
 		locked = 1;
-		prepare_to_wait(&ipa_ctx->msg_waitq, &wait, TASK_INTERRUPTIBLE);
 		if (!list_empty(&ipa_ctx->msg_list)) {
 			msg = list_first_entry(&ipa_ctx->msg_list,
 					struct ipa_push_msg, link);
@@ -576,10 +576,10 @@
 
 		locked = 0;
 		mutex_unlock(&ipa_ctx->msg_lock);
-		schedule();
+		wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
 	}
 
-	finish_wait(&ipa_ctx->msg_waitq, &wait);
+	remove_wait_queue(&ipa_ctx->msg_waitq, &wait);
 	if (start != buf && ret != -EFAULT)
 		ret = buf - start;
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 1e2b200..a5fb576 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -745,7 +745,7 @@
 			retval = -EFAULT;
 			break;
 		}
-		if (ipa4_nat_mdfy_pdn(&mdfy_pdn)) {
+		if (ipa3_nat_mdfy_pdn(&mdfy_pdn)) {
 			retval = -EFAULT;
 			break;
 		}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index 2d08767..1af968e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -644,6 +644,12 @@
 	}
 
 	gsi_ep_cfg_ptr = ipa3_get_gsi_ep_info(ep->client);
+	if (gsi_ep_cfg_ptr == NULL) {
+		IPAERR("Error ipa3_get_gsi_ep_info ret NULL\n");
+		result = -EFAULT;
+		goto write_evt_scratch_fail;
+	}
+
 	params->chan_params.evt_ring_hdl = ep->gsi_evt_ring_hdl;
 	params->chan_params.ch_id = gsi_ep_cfg_ptr->ipa_gsi_chan_num;
 	gsi_res = gsi_alloc_channel(&params->chan_params, gsi_dev_hdl,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index 5e789af..24c3d62 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -264,6 +264,7 @@
 	return scnprintf(
 		dbg_buff, IPA_MAX_MSG_LEN,
 		"IPA_ENDP_INIT_NAT_%u=0x%x\n"
+		"IPA_ENDP_INIT_CONN_TRACK_n%u=0x%x\n"
 		"IPA_ENDP_INIT_HDR_%u=0x%x\n"
 		"IPA_ENDP_INIT_HDR_EXT_%u=0x%x\n"
 		"IPA_ENDP_INIT_MODE_%u=0x%x\n"
@@ -274,6 +275,7 @@
 		"IPA_ENDP_INIT_DEAGGR_%u=0x%x\n"
 		"IPA_ENDP_INIT_CFG_%u=0x%x\n",
 		pipe, ipahal_read_reg_n(IPA_ENDP_INIT_NAT_n, pipe),
+		pipe, ipahal_read_reg_n(IPA_ENDP_INIT_CONN_TRACK_n, pipe),
 		pipe, ipahal_read_reg_n(IPA_ENDP_INIT_HDR_n, pipe),
 		pipe, ipahal_read_reg_n(IPA_ENDP_INIT_HDR_EXT_n, pipe),
 		pipe, ipahal_read_reg_n(IPA_ENDP_INIT_MODE_n, pipe),
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 4fb4da8..b41bab7 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -1549,6 +1549,8 @@
 	struct ipa3_rx_pkt_wrapper *rx_pkt;
 	struct ipa3_rx_pkt_wrapper *tmp;
 
+	spin_lock_bh(&ipa3_ctx->wc_memb.wlan_spinlock);
+
 	list_for_each_entry_safe(rx_pkt, tmp,
 		&ipa3_ctx->wc_memb.wlan_comm_desc_list, link) {
 		list_del(&rx_pkt->link);
@@ -1569,6 +1571,8 @@
 		IPAERR("wlan comm buff total cnt: %d\n",
 			ipa3_ctx->wc_memb.wlan_comm_total_cnt);
 
+	spin_unlock_bh(&ipa3_ctx->wc_memb.wlan_spinlock);
+
 }
 
 static void ipa3_alloc_wlan_rx_common_cache(u32 size)
@@ -1606,11 +1610,13 @@
 			goto fail_dma_mapping;
 		}
 
+		spin_lock_bh(&ipa3_ctx->wc_memb.wlan_spinlock);
 		list_add_tail(&rx_pkt->link,
 			&ipa3_ctx->wc_memb.wlan_comm_desc_list);
 		rx_len_cached = ++ipa3_ctx->wc_memb.wlan_comm_total_cnt;
 
 		ipa3_ctx->wc_memb.wlan_comm_free_cnt++;
+		spin_unlock_bh(&ipa3_ctx->wc_memb.wlan_spinlock);
 
 	}
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 6a5ec31..fcb7c72 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1495,6 +1495,9 @@
 
 int ipa3_cfg_ep_nat(u32 clnt_hdl, const struct ipa_ep_cfg_nat *ipa_ep_cfg);
 
+int ipa3_cfg_ep_conn_track(u32 clnt_hdl,
+	const struct ipa_ep_cfg_conn_track *ep_conn_track);
+
 int ipa3_cfg_ep_hdr(u32 clnt_hdl, const struct ipa_ep_cfg_hdr *ipa_ep_cfg);
 
 int ipa3_cfg_ep_hdr_ext(u32 clnt_hdl,
@@ -1597,7 +1600,7 @@
 
 int ipa3_nat_del_cmd(struct ipa_ioc_v4_nat_del *del);
 
-int ipa4_nat_mdfy_pdn(struct ipa_ioc_nat_pdn_entry *mdfy_pdn);
+int ipa3_nat_mdfy_pdn(struct ipa_ioc_nat_pdn_entry *mdfy_pdn);
 
 /*
  * Messaging
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
index da965e7..fe6d245 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
@@ -522,17 +522,15 @@
 	char __user *start;
 	struct ipa3_push_msg *msg = NULL;
 	int ret;
-	DEFINE_WAIT(wait);
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 	int locked;
 
 	start = buf;
 
+	add_wait_queue(&ipa3_ctx->msg_waitq, &wait);
 	while (1) {
 		mutex_lock(&ipa3_ctx->msg_lock);
 		locked = 1;
-		prepare_to_wait(&ipa3_ctx->msg_waitq,
-				&wait,
-				TASK_INTERRUPTIBLE);
 
 		if (!list_empty(&ipa3_ctx->msg_list)) {
 			msg = list_first_entry(&ipa3_ctx->msg_list,
@@ -585,10 +583,10 @@
 
 		locked = 0;
 		mutex_unlock(&ipa3_ctx->msg_lock);
-		schedule();
+		wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
 	}
 
-	finish_wait(&ipa3_ctx->msg_waitq, &wait);
+	remove_wait_queue(&ipa3_ctx->msg_waitq, &wait);
 	if (start != buf && ret != -EFAULT)
 		ret = buf - start;
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index 0dd86fa..b19ef8b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
@@ -191,7 +191,7 @@
 static int ipa_mhi_start_gsi_channel(enum ipa_client_type client,
 	int ipa_ep_idx, struct start_gsi_channel *params)
 {
-	int res;
+	int res = 0;
 	struct gsi_evt_ring_props ev_props;
 	struct ipa_mhi_msi_info *msi;
 	struct gsi_chan_props ch_props;
@@ -241,7 +241,6 @@
 		if (res) {
 			IPA_MHI_ERR("gsi_alloc_evt_ring failed %d\n", res);
 			goto fail_alloc_evt;
-			return res;
 		}
 		IPA_MHI_DBG("client %d, caching event ring hdl %lu\n",
 				client,
@@ -259,7 +258,6 @@
 		IPA_MHI_ERR("event ring wp is not updated. base=wp=0x%llx\n",
 			params->ev_ctx_host->wp);
 		goto fail_alloc_ch;
-		return res;
 	}
 
 	IPA_MHI_DBG("Ring event db: evt_ring_hdl=%lu host_wp=0x%llx\n",
@@ -270,7 +268,6 @@
 		IPA_MHI_ERR("fail to ring evt ring db %d. hdl=%lu wp=0x%llx\n",
 			res, ep->gsi_evt_ring_hdl, params->ev_ctx_host->wp);
 		goto fail_alloc_ch;
-		return res;
 	}
 
 	memset(&ch_props, 0, sizeof(ch_props));
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
index 6acc4d8..a153f2d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
@@ -643,14 +643,14 @@
 }
 
 /**
-* ipa4_nat_mdfy_pdn() - Modify a PDN entry in PDN config table in IPA SRAM
+* ipa3_nat_mdfy_pdn() - Modify a PDN entry in PDN config table in IPA SRAM
 * @mdfy_pdn:	[in] PDN info to be written to SRAM
 *
 * Called by NAT client driver to modify an entry in the PDN config table
 *
 * Returns:	0 on success, negative on failure
 */
-int ipa4_nat_mdfy_pdn(struct ipa_ioc_nat_pdn_entry *mdfy_pdn)
+int ipa3_nat_mdfy_pdn(struct ipa_ioc_nat_pdn_entry *mdfy_pdn)
 {
 	struct ipahal_imm_cmd_dma_shared_mem mem_cmd = { 0 };
 	struct ipa3_desc desc;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
index 73738bf..80c3996 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
@@ -1178,10 +1178,13 @@
 	}
 
 	/* clean the QMI msg cache */
+	mutex_lock(&ipa3_qmi_lock);
 	if (ipa3_qmi_ctx != NULL) {
 		vfree(ipa3_qmi_ctx);
 		ipa3_qmi_ctx = NULL;
 	}
+	mutex_unlock(&ipa3_qmi_lock);
+
 	ipa3_svc_handle = 0;
 	ipa3_qmi_modem_init_fin = false;
 	ipa3_qmi_indication_fin = false;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index edd5b54..11da6b3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -2487,8 +2487,8 @@
  * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
  * @ipa_ep_cfg:	[in] IPA end-point configuration params
  *
- * This includes nat, header, mode, aggregation and route settings and is a one
- * shot API to configure the IPA end-point fully
+ * This includes nat, IPv6CT, header, mode, aggregation and route settings and
+ * is a one shot API to configure the IPA end-point fully
  *
  * Returns:	0 on success, negative on failure
  *
@@ -2525,6 +2525,13 @@
 		if (result)
 			return result;
 
+		if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
+			result = ipa3_cfg_ep_conn_track(clnt_hdl,
+				&ipa_ep_cfg->conn_track);
+			if (result)
+				return result;
+		}
+
 		result = ipa3_cfg_ep_mode(clnt_hdl, &ipa_ep_cfg->mode);
 		if (result)
 			return result;
@@ -2550,7 +2557,7 @@
 	return 0;
 }
 
-const char *ipa3_get_nat_en_str(enum ipa_nat_en_type nat_en)
+static const char *ipa3_get_nat_en_str(enum ipa_nat_en_type nat_en)
 {
 	switch (nat_en) {
 	case (IPA_BYPASS_NAT):
@@ -2564,10 +2571,22 @@
 	return "undefined";
 }
 
+static const char *ipa3_get_ipv6ct_en_str(enum ipa_ipv6ct_en_type ipv6ct_en)
+{
+	switch (ipv6ct_en) {
+	case (IPA_BYPASS_IPV6CT):
+		return "ipv6ct disabled";
+	case (IPA_ENABLE_IPV6CT):
+		return "ipv6ct enabled";
+	}
+
+	return "undefined";
+}
+
 /**
  * ipa3_cfg_ep_nat() - IPA end-point NAT configuration
  * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
- * @ipa_ep_cfg:	[in] IPA end-point configuration params
+ * @ep_nat:	[in] IPA NAT end-point configuration params
  *
  * Returns:	0 on success, negative on failure
  *
@@ -2605,6 +2624,49 @@
 	return 0;
 }
 
+/**
+ * ipa3_cfg_ep_conn_track() - IPA end-point IPv6CT configuration
+ * @clnt_hdl:		[in] opaque client handle assigned by IPA to client
+ * @ep_conn_track:	[in] IPA IPv6CT end-point configuration params
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa3_cfg_ep_conn_track(u32 clnt_hdl,
+	const struct ipa_ep_cfg_conn_track *ep_conn_track)
+{
+	if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
+		ipa3_ctx->ep[clnt_hdl].valid == 0 || ep_conn_track == NULL) {
+		IPAERR("bad parm, clnt_hdl = %d , ep_valid = %d\n",
+			clnt_hdl,
+			ipa3_ctx->ep[clnt_hdl].valid);
+		return -EINVAL;
+	}
+
+	if (IPA_CLIENT_IS_CONS(ipa3_ctx->ep[clnt_hdl].client)) {
+		IPAERR("IPv6CT does not apply to IPA out EP %d\n", clnt_hdl);
+		return -EINVAL;
+	}
+
+	IPADBG("pipe=%d, conn_track_en=%d(%s)\n",
+		clnt_hdl,
+		ep_conn_track->conn_track_en,
+		ipa3_get_ipv6ct_en_str(ep_conn_track->conn_track_en));
+
+	/* copy over EP cfg */
+	ipa3_ctx->ep[clnt_hdl].cfg.conn_track = *ep_conn_track;
+
+	IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl));
+
+	ipahal_write_reg_n_fields(IPA_ENDP_INIT_CONN_TRACK_n, clnt_hdl,
+		ep_conn_track);
+
+	IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl));
+
+	return 0;
+}
+
 
 /**
  * ipa3_cfg_ep_status() - IPA end-point status configuration
@@ -4286,6 +4348,7 @@
 	api_ctrl->ipa_disable_endpoint = NULL;
 	api_ctrl->ipa_cfg_ep = ipa3_cfg_ep;
 	api_ctrl->ipa_cfg_ep_nat = ipa3_cfg_ep_nat;
+	api_ctrl->ipa_cfg_ep_conn_track = ipa3_cfg_ep_conn_track;
 	api_ctrl->ipa_cfg_ep_hdr = ipa3_cfg_ep_hdr;
 	api_ctrl->ipa_cfg_ep_hdr_ext = ipa3_cfg_ep_hdr_ext;
 	api_ctrl->ipa_cfg_ep_mode = ipa3_cfg_ep_mode;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index ae1b989..57d44e3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -45,6 +45,7 @@
 	__stringify(IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS),
 	__stringify(IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT),
 	__stringify(IPAHAL_PKT_STATUS_EXCEPTION_NAT),
+	__stringify(IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT),
 };
 
 #define IPAHAL_MEM_ALLOC(__size, __is_atomic_ctx) \
@@ -838,10 +839,13 @@
 {
 	enum ipahal_pkt_status_opcode opcode = 0;
 	enum ipahal_pkt_status_exception exception_type = 0;
+	bool is_ipv6;
 
 	struct ipa_pkt_status_hw *hw_status =
 		(struct ipa_pkt_status_hw *)unparsed_status;
 
+	is_ipv6 = (hw_status->status_mask & 0x80) ? false : true;
+
 	status->pkt_len = hw_status->pkt_len;
 	status->endp_src_idx = hw_status->endp_src_idx;
 	status->endp_dest_idx = hw_status->endp_dest_idx;
@@ -933,7 +937,10 @@
 		exception_type = IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT;
 		break;
 	case 64:
-		exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NAT;
+		if (is_ipv6)
+			exception_type = IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT;
+		else
+			exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NAT;
 		break;
 	default:
 		IPAHAL_ERR("unsupported Status Exception type 0x%x\n",
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
index 724cdec..0f322b5 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
@@ -434,7 +434,12 @@
 	IPAHAL_PKT_STATUS_EXCEPTION_PACKET_THRESHOLD,
 	IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS,
 	IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT,
+	/*
+	 * NAT and IPv6CT have the same value at HW.
+	 * NAT for IPv4 and IPv6CT for IPv6 exceptions
+	 */
 	IPAHAL_PKT_STATUS_EXCEPTION_NAT,
+	IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT,
 	IPAHAL_PKT_STATUS_EXCEPTION_MAX,
 };
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index af717cd..0dccb5b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -43,6 +43,7 @@
 	__stringify(IPA_ENDP_INIT_ROUTE_n),
 	__stringify(IPA_ENDP_INIT_MODE_n),
 	__stringify(IPA_ENDP_INIT_NAT_n),
+	__stringify(IPA_ENDP_INIT_CONN_TRACK_n),
 	__stringify(IPA_ENDP_INIT_CTRL_n),
 	__stringify(IPA_ENDP_INIT_CTRL_SCND_n),
 	__stringify(IPA_ENDP_INIT_HOL_BLOCK_EN_n),
@@ -724,6 +725,17 @@
 		IPA_ENDP_INIT_NAT_n_NAT_EN_BMSK);
 }
 
+static void ipareg_construct_endp_init_conn_track_n(enum ipahal_reg_name reg,
+	const void *fields, u32 *val)
+{
+	struct ipa_ep_cfg_conn_track *ep_ipv6ct =
+		(struct ipa_ep_cfg_conn_track *)fields;
+
+	IPA_SETFIELD_IN_REG(*val, ep_ipv6ct->conn_track_en,
+		IPA_ENDP_INIT_CONN_TRACK_n_CONN_TRACK_EN_SHFT,
+		IPA_ENDP_INIT_CONN_TRACK_n_CONN_TRACK_EN_BMSK);
+}
+
 static void ipareg_construct_endp_init_mode_n(enum ipahal_reg_name reg,
 		const void *fields, u32 *val)
 {
@@ -1494,6 +1506,10 @@
 	[IPA_HW_v4_0][IPA_CLKON_CFG] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
 		0x00000044, 0},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_CONN_TRACK_n] = {
+		ipareg_construct_endp_init_conn_track_n,
+		ipareg_parse_dummy,
+		0x00000850, 0x70},
 };
 
 /*
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
index 79e2b9c..3df49ce 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -46,6 +46,7 @@
 	IPA_ENDP_INIT_ROUTE_n,
 	IPA_ENDP_INIT_MODE_n,
 	IPA_ENDP_INIT_NAT_n,
+	IPA_ENDP_INIT_CONN_TRACK_n,
 	IPA_ENDP_INIT_CTRL_n,
 	IPA_ENDP_INIT_CTRL_SCND_n,
 	IPA_ENDP_INIT_HOL_BLOCK_EN_n,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
index 17bad03..664d254 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
@@ -118,6 +118,10 @@
 #define IPA_ENDP_INIT_NAT_n_NAT_EN_BMSK 0x3
 #define IPA_ENDP_INIT_NAT_n_NAT_EN_SHFT 0x0
 
+/* IPA_ENDP_INIT_CONN_TRACK_n register */
+#define IPA_ENDP_INIT_CONN_TRACK_n_CONN_TRACK_EN_BMSK 0x1
+#define IPA_ENDP_INIT_CONN_TRACK_n_CONN_TRACK_EN_SHFT 0x0
+
 /* IPA_ENDP_INIT_CTRL_n register */
 #define IPA_ENDP_INIT_CTRL_n_ENDP_SUSPEND_BMSK 0x1
 #define IPA_ENDP_INIT_CTRL_n_ENDP_SUSPEND_SHFT 0x0
diff --git a/drivers/platform/msm/seemp_core/seemp_logk.c b/drivers/platform/msm/seemp_core/seemp_logk.c
index a528e16..e55260d 100644
--- a/drivers/platform/msm/seemp_core/seemp_logk.c
+++ b/drivers/platform/msm/seemp_core/seemp_logk.c
@@ -13,6 +13,11 @@
 
 #define pr_fmt(fmt) "seemp: %s: " fmt, __func__
 
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/seemp_instrumentation.h>
+#include <soc/qcom/scm.h>
+
 #include "seemp_logk.h"
 #include "seemp_ringbuf.h"
 
@@ -24,6 +29,8 @@
 #define FOUR_MB 4
 #define YEAR_BASE 1900
 
+#define EL2_SCM_ID 0x02001902
+
 static struct seemp_logk_dev *slogk_dev;
 
 static unsigned int ring_sz = FOUR_MB;
@@ -49,11 +56,15 @@
 static struct seemp_source_mask *pmask;
 static unsigned int num_sources;
 
+static void *el2_shared_mem;
+static struct task_struct *rtic_thread;
+
 static long seemp_logk_reserve_rdblks(
 		struct seemp_logk_dev *sdev, unsigned long arg);
 static long seemp_logk_set_mask(unsigned long arg);
 static long seemp_logk_set_mapping(unsigned long arg);
 static long seemp_logk_check_filter(unsigned long arg);
+static int seemp_logk_rtic_thread(void *data);
 
 void* (*seemp_logk_kernel_begin)(char **buf);
 
@@ -569,6 +580,15 @@
 		}
 	}
 
+	if (!rtic_thread && el2_shared_mem) {
+		rtic_thread = kthread_run(seemp_logk_rtic_thread,
+				NULL, "seemp_logk_rtic_thread");
+		if (IS_ERR(rtic_thread)) {
+			pr_err("rtic_thread creation failed");
+			rtic_thread = NULL;
+		}
+	}
+
 	return 0;
 }
 
@@ -580,10 +600,59 @@
 	.mmap = seemp_logk_mmap,
 };
 
+static int seemp_logk_rtic_thread(void *data)
+{
+	struct el2_report_header_t *header;
+	__u64 last_sequence_number = 0;
+	int last_pos = -1;
+	int i;
+	int num_entries = (PAGE_SIZE - sizeof(struct el2_report_header_t))
+		/ sizeof(struct el2_report_data_t);
+	header = (struct el2_report_header_t *) el2_shared_mem;
+
+	while (!kthread_should_stop()) {
+		for (i = 1; i < num_entries + 1; i++) {
+			struct el2_report_data_t *report;
+			int cur_pos = last_pos + i;
+
+			if (cur_pos >= num_entries)
+				cur_pos -= num_entries;
+
+			report = el2_shared_mem +
+				sizeof(struct el2_report_header_t) +
+				cur_pos * sizeof(struct el2_report_data_t);
+
+			/* determine legitimacy of report */
+			if (report->report_valid &&
+				report->sequence_number <=
+					header->num_incidents &&
+				(last_sequence_number == 0
+					|| report->sequence_number >
+						last_sequence_number)) {
+				seemp_logk_rtic(report->report_type,
+					report->report.incident.actor,
+					report->report.incident.asset_id,
+					report->report.incident.asset_category,
+					report->report.incident.response);
+				last_sequence_number = report->sequence_number;
+			} else {
+				last_pos = cur_pos - 1;
+				break;
+			}
+		}
+
+		/* periodically check el2 report every second */
+		ssleep(1);
+	}
+
+	return 0;
+}
+
 __init int seemp_logk_init(void)
 {
 	int ret;
 	int devno = 0;
+	struct scm_desc desc = {0};
 
 	num_sources = 0;
 	kmalloc_flag = 0;
@@ -650,6 +719,21 @@
 	init_waitqueue_head(&slogk_dev->readers_wq);
 	init_waitqueue_head(&slogk_dev->writers_wq);
 	rwlock_init(&filter_lock);
+
+	el2_shared_mem = (void *) __get_free_page(GFP_KERNEL);
+	if (el2_shared_mem) {
+		desc.arginfo = SCM_ARGS(2, SCM_RW, SCM_VAL);
+		desc.args[0] = (uint64_t) virt_to_phys(el2_shared_mem);
+		desc.args[1] = PAGE_SIZE;
+		ret = scm_call2(EL2_SCM_ID, &desc);
+		if (ret || desc.ret[0] || desc.ret[1]) {
+			pr_err("SCM call failed with ret val = %d %d %d",
+				ret, (int)desc.ret[0], (int)desc.ret[1]);
+			free_page((unsigned long) el2_shared_mem);
+			el2_shared_mem = NULL;
+		}
+	}
+
 	return 0;
 class_destroy_fail:
 	class_destroy(cl);
@@ -666,6 +750,11 @@
 {
 	dev_t devno = MKDEV(slogk_dev->major, slogk_dev->minor);
 
+	if (rtic_thread) {
+		kthread_stop(rtic_thread);
+		rtic_thread = NULL;
+	}
+
 	seemp_logk_detach();
 
 	cdev_del(&slogk_dev->cdev);
diff --git a/drivers/platform/msm/seemp_core/seemp_logk.h b/drivers/platform/msm/seemp_core/seemp_logk.h
index 1a41d4c..871de0e 100644
--- a/drivers/platform/msm/seemp_core/seemp_logk.h
+++ b/drivers/platform/msm/seemp_core/seemp_logk.h
@@ -158,4 +158,45 @@
 	__u32       hash;
 	bool        isOn;
 };
+
+/* report region header */
+struct el2_report_header_t {
+	__u64 report_version;     /* Version of the EL2 report */
+	__u64 mp_catalog_version;
+		/* Version of MP catalogue used for kernel protection */
+	__u8 protection_enabled;  /* Kernel Assets protected by EL2 */
+	__u8 pad1;
+	__u8 pad2;
+	__u8 pad3;
+	__u32 pad4;
+	__u64 num_incidents;      /* Number of Incidents Observed by EL2 */
+};
+
+/* individual report contents */
+union el2_report {
+	struct {
+		__u8 asset_id[0x20]; /* Asset Identifier */
+		__u64 actor;
+			/* Actor that caused the Incident.  */
+		__u8 asset_category; /* Asset Category */
+		__u8 response;       /* Response From EL2 */
+		__u16 pad1;
+		__u32 pad2;
+	} incident;
+	struct {
+		__u64 reserved;      /* TBD */
+	} info;
+};
+
+/* individual report */
+struct el2_report_data_t {
+	__u8 report_valid;
+		/* Flag to indicate whether report instance is valid */
+	__u8 report_type;        /* Report Type */
+	__u8 pad1;
+	__u8 pad2;
+	__u64 sequence_number;   /* Sequence number of the report */
+	union el2_report report;       /* Report Contents */
+};
+
 #endif
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 4c67c80..ae44f01 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -3688,6 +3688,7 @@
 	vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
 	vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
 	vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
+	vote(chg->usb_icl_votable, OTG_VOTER, false, 0);
 
 	/* reset hvdcp voters */
 	vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0);
@@ -3849,6 +3850,12 @@
 		smblib_handle_typec_removal(chg);
 	}
 
+	/* suspend usb if sink */
+	if (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT)
+		vote(chg->usb_icl_votable, OTG_VOTER, true, 0);
+	else
+		vote(chg->usb_icl_votable, OTG_VOTER, false, 0);
+
 	smblib_dbg(chg, PR_INTERRUPT, "IRQ: cc-state-change; Type-C %s detected\n",
 				smblib_typec_mode_name[chg->typec_mode]);
 }
@@ -3896,6 +3903,12 @@
 		return IRQ_HANDLED;
 	}
 
+	if (chg->pr_swap_in_progress) {
+		smblib_dbg(chg, PR_INTERRUPT,
+				"Ignoring since pr_swap_in_progress\n");
+		return IRQ_HANDLED;
+	}
+
 	mutex_lock(&chg->lock);
 	smblib_usb_typec_change(chg);
 	mutex_unlock(&chg->lock);
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index a2168f0..5c7819e 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -65,6 +65,7 @@
 #define OTG_DELAY_VOTER			"OTG_DELAY_VOTER"
 #define USBIN_I_VOTER			"USBIN_I_VOTER"
 #define WEAK_CHARGER_VOTER		"WEAK_CHARGER_VOTER"
+#define OTG_VOTER			"OTG_VOTER"
 
 #define VCONN_MAX_ATTEMPTS	3
 #define OTG_MAX_ATTEMPTS	3
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 7ad650e..d75f157 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2408,6 +2408,14 @@
 	count = rdev->deferred_disables;
 	rdev->deferred_disables = 0;
 
+	/*
+	 * Workqueue functions queue the new work instance while the previous
+	 * work instance is being processed. Cancel the queued work instance
+	 * as the work instance under processing does the job of the queued
+	 * work instance.
+	 */
+	cancel_delayed_work(&rdev->disable_work);
+
 	for (i = 0; i < count; i++) {
 		ret = _regulator_disable(rdev);
 		if (ret != 0)
@@ -2451,10 +2459,10 @@
 
 	mutex_lock(&rdev->mutex);
 	rdev->deferred_disables++;
+	mod_delayed_work(system_power_efficient_wq, &rdev->disable_work,
+			 msecs_to_jiffies(ms));
 	mutex_unlock(&rdev->mutex);
 
-	queue_delayed_work(system_power_efficient_wq, &rdev->disable_work,
-			   msecs_to_jiffies(ms));
 	return 0;
 }
 EXPORT_SYMBOL_GPL(regulator_disable_deferred);
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index d8c5ea8..01779f9 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -182,6 +182,9 @@
 	if (!ctrl_dev->iommu_desc.cb_dev)
 		return 0;
 
+	if (!IS_ERR_OR_NULL(ctrl_dev->iommu_desc.iommu_map))
+		return 0;
+
 	dev = ctrl_dev->iommu_desc.cb_dev;
 	iommu_map = arm_iommu_create_mapping(&platform_bus_type,
 						va_start, va_size);
@@ -1299,6 +1302,13 @@
 		if (dev->pipes[i].connected)
 			msm_slim_disconn_pipe_port(dev, i);
 	}
+
+	if (!IS_ERR_OR_NULL(dev->iommu_desc.iommu_map)) {
+		arm_iommu_detach_device(dev->iommu_desc.cb_dev);
+		arm_iommu_release_mapping(dev->iommu_desc.iommu_map);
+		dev->iommu_desc.iommu_map = NULL;
+	}
+
 	if (dereg) {
 		for (i = 0; i < dev->port_nums; i++) {
 			if (dev->pipes[i].connected)
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e6c2aa3..1f7286b 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -632,6 +632,14 @@
 	   between MSM and WCD DSP over glink transport protocol. This driver
 	   provides read and write interface via char device.
 
+config QCOM_SMCINVOKE
+	bool "Secure QSEE Support"
+	help
+	  Enable SMCInvoke driver which supports capability based secure
+	  communication between QTI Secure Execution Environment (QSEE)
+          and high level operating system. It exposes APIs for both
+          userspace and kernel clients.
+
 config MSM_EVENT_TIMER
 	bool "Event timer"
         help
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 64fb7a0..7820f8b 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -77,3 +77,4 @@
 obj-$(CONFIG_APSS_CORE_EA)	+= msm-core.o debug_core.o
 obj-$(CONFIG_QCOM_DCC_V2) += dcc_v2.o
 obj-$(CONFIG_QTI_RPM_STATS_LOG) += rpm_stats.o
+obj-$(CONFIG_QCOM_SMCINVOKE) += smcinvoke.o
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 28f89bf..405d05c 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -13,6 +13,7 @@
 #define pr_fmt(fmt) "icnss: " fmt
 
 #include <asm/dma-iommu.h>
+#include <linux/of_address.h>
 #include <linux/clk.h>
 #include <linux/iommu.h>
 #include <linux/export.h>
@@ -357,6 +358,7 @@
 	uint32_t vbatt_req;
 	uint32_t vbatt_resp;
 	uint32_t vbatt_req_err;
+	u32 rejuvenate_ind;
 	uint32_t rejuvenate_ack_req;
 	uint32_t rejuvenate_ack_resp;
 	uint32_t rejuvenate_ack_err;
@@ -434,6 +436,10 @@
 	bool is_wlan_mac_set;
 	struct icnss_wlan_mac_addr wlan_mac_addr;
 	bool bypass_s1_smmu;
+	u8 cause_for_rejuvenation;
+	u8 requesting_sub_system;
+	u16 line_number;
+	char function_name[QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1];
 } *penv;
 
 #ifdef CONFIG_ICNSS_DEBUG
@@ -1669,6 +1675,60 @@
 	return ret;
 }
 
+static int icnss_decode_rejuvenate_ind(void *msg, unsigned int msg_len)
+{
+	struct msg_desc ind_desc;
+	struct wlfw_rejuvenate_ind_msg_v01 ind_msg;
+	int ret = 0;
+
+	if (!penv || !penv->wlfw_clnt) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	memset(&ind_msg, 0, sizeof(ind_msg));
+
+	ind_desc.msg_id = QMI_WLFW_REJUVENATE_IND_V01;
+	ind_desc.max_msg_len = WLFW_REJUVENATE_IND_MSG_V01_MAX_MSG_LEN;
+	ind_desc.ei_array = wlfw_rejuvenate_ind_msg_v01_ei;
+
+	ret = qmi_kernel_decode(&ind_desc, &ind_msg, msg, msg_len);
+	if (ret < 0) {
+		icnss_pr_err("Failed to decode rejuvenate ind message: ret %d, msg_len %u\n",
+			     ret, msg_len);
+		goto out;
+	}
+
+	if (ind_msg.cause_for_rejuvenation_valid)
+		penv->cause_for_rejuvenation = ind_msg.cause_for_rejuvenation;
+	else
+		penv->cause_for_rejuvenation = 0;
+	if (ind_msg.requesting_sub_system_valid)
+		penv->requesting_sub_system = ind_msg.requesting_sub_system;
+	else
+		penv->requesting_sub_system = 0;
+	if (ind_msg.line_number_valid)
+		penv->line_number = ind_msg.line_number;
+	else
+		penv->line_number = 0;
+	if (ind_msg.function_name_valid)
+		memcpy(penv->function_name, ind_msg.function_name,
+		       QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1);
+	else
+		memset(penv->function_name, 0,
+		       QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1);
+
+	icnss_pr_info("Cause for rejuvenation: 0x%x, requesting sub-system: 0x%x, line number: %u, function name: %s\n",
+		      penv->cause_for_rejuvenation,
+		      penv->requesting_sub_system,
+		      penv->line_number,
+		      penv->function_name);
+
+	penv->stats.rejuvenate_ind++;
+out:
+	return ret;
+}
+
 static int wlfw_rejuvenate_ack_send_sync_msg(struct icnss_priv *priv)
 {
 	int ret;
@@ -1862,6 +1922,7 @@
 			     msg_id, penv->state);
 
 		icnss_ignore_qmi_timeout(true);
+		icnss_decode_rejuvenate_ind(msg, msg_len);
 		event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
 		if (event_data == NULL)
 			return;
@@ -3616,9 +3677,6 @@
 	if (ret)
 		return ret;
 
-	if (ret == 0)
-		memset(&priv->stats, 0, sizeof(priv->stats));
-
 	return count;
 }
 
@@ -3742,6 +3800,26 @@
 	return 0;
 }
 
+static int icnss_stats_show_rejuvenate_info(struct seq_file *s,
+					    struct icnss_priv *priv)
+{
+	if (priv->stats.rejuvenate_ind)  {
+		seq_puts(s, "\n<---------------- Rejuvenate Info ----------------->\n");
+		seq_printf(s, "Number of Rejuvenations: %u\n",
+			   priv->stats.rejuvenate_ind);
+		seq_printf(s, "Cause for Rejuvenation: 0x%x\n",
+			   priv->cause_for_rejuvenation);
+		seq_printf(s, "Requesting Sub-System: 0x%x\n",
+			   priv->requesting_sub_system);
+		seq_printf(s, "Line Number: %u\n",
+			   priv->line_number);
+		seq_printf(s, "Function Name: %s\n",
+			   priv->function_name);
+	}
+
+	return 0;
+}
+
 static int icnss_stats_show_events(struct seq_file *s, struct icnss_priv *priv)
 {
 	int i;
@@ -3807,6 +3885,7 @@
 	ICNSS_STATS_DUMP(s, priv, vbatt_req);
 	ICNSS_STATS_DUMP(s, priv, vbatt_resp);
 	ICNSS_STATS_DUMP(s, priv, vbatt_req_err);
+	ICNSS_STATS_DUMP(s, priv, rejuvenate_ind);
 	ICNSS_STATS_DUMP(s, priv, rejuvenate_ack_req);
 	ICNSS_STATS_DUMP(s, priv, rejuvenate_ack_resp);
 	ICNSS_STATS_DUMP(s, priv, rejuvenate_ack_err);
@@ -3828,6 +3907,8 @@
 
 	icnss_stats_show_capability(s, priv);
 
+	icnss_stats_show_rejuvenate_info(s, priv);
+
 	icnss_stats_show_events(s, priv);
 
 	icnss_stats_show_state(s, priv);
@@ -4160,6 +4241,9 @@
 	int i;
 	struct device *dev = &pdev->dev;
 	struct icnss_priv *priv;
+	const __be32 *addrp;
+	u64 prop_size = 0;
+	struct device_node *np;
 
 	if (penv) {
 		icnss_pr_err("Driver is already initialized\n");
@@ -4231,24 +4315,53 @@
 		}
 	}
 
-	ret = of_property_read_u32(dev->of_node, "qcom,wlan-msa-memory",
-				   &priv->msa_mem_size);
+	np = of_parse_phandle(dev->of_node,
+			      "qcom,wlan-msa-fixed-region", 0);
+	if (np) {
+		addrp = of_get_address(np, 0, &prop_size, NULL);
+		if (!addrp) {
+			icnss_pr_err("Failed to get assigned-addresses or property\n");
+			ret = -EINVAL;
+			goto out;
+		}
 
-	if (ret || priv->msa_mem_size == 0) {
-		icnss_pr_err("Fail to get MSA Memory Size: %u, ret: %d\n",
-			     priv->msa_mem_size, ret);
-		goto out;
+		priv->msa_pa = of_translate_address(np, addrp);
+		if (priv->msa_pa == OF_BAD_ADDR) {
+			icnss_pr_err("Failed to translate MSA PA from device-tree\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		priv->msa_va = memremap(priv->msa_pa,
+					(unsigned long)prop_size, MEMREMAP_WT);
+		if (!priv->msa_va) {
+			icnss_pr_err("MSA PA ioremap failed: phy addr: %pa\n",
+				     &priv->msa_pa);
+			ret = -EINVAL;
+			goto out;
+		}
+		priv->msa_mem_size = prop_size;
+	} else {
+		ret = of_property_read_u32(dev->of_node, "qcom,wlan-msa-memory",
+					   &priv->msa_mem_size);
+		if (ret || priv->msa_mem_size == 0) {
+			icnss_pr_err("Fail to get MSA Memory Size: %u ret: %d\n",
+				     priv->msa_mem_size, ret);
+			goto out;
+		}
+
+		priv->msa_va = dmam_alloc_coherent(&pdev->dev,
+				priv->msa_mem_size, &priv->msa_pa, GFP_KERNEL);
+
+		if (!priv->msa_va) {
+			icnss_pr_err("DMA alloc failed for MSA\n");
+			ret = -ENOMEM;
+			goto out;
+		}
 	}
 
-	priv->msa_va = dmam_alloc_coherent(&pdev->dev, priv->msa_mem_size,
-					   &priv->msa_pa, GFP_KERNEL);
-	if (!priv->msa_va) {
-		icnss_pr_err("DMA alloc failed for MSA\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-	icnss_pr_dbg("MSA pa: %pa, MSA va: 0x%p\n", &priv->msa_pa,
-		     priv->msa_va);
+	icnss_pr_dbg("MSA pa: %pa, MSA va: 0x%p MSA Memory Size: 0x%x\n",
+		     &priv->msa_pa, (void *)priv->msa_va, priv->msa_mem_size);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 					   "smmu_iova_base");
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index 36c0154..ed78af7 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -746,18 +746,16 @@
 
 static int msm_bus_disable_node_qos_clk(struct msm_bus_node_device_type *node)
 {
-	struct msm_bus_node_device_type *bus_node = NULL;
 	int i;
 	int ret = 0;
 
-	if (!node || (!to_msm_bus_node(node->node_info->bus_device))) {
+	if (!node) {
 		ret = -ENXIO;
 		goto exit_disable_node_qos_clk;
 	}
-	bus_node = to_msm_bus_node(node->node_info->bus_device);
 
-	for (i = 0; i < bus_node->num_node_qos_clks; i++)
-		ret = disable_nodeclk(&bus_node->node_qos_clks[i]);
+	for (i = 0; i < node->num_node_qos_clks; i++)
+		ret = disable_nodeclk(&node->node_qos_clks[i]);
 
 exit_disable_node_qos_clk:
 	return ret;
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 9a98063..17e0a4c 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -32,6 +32,7 @@
 #define RPMH_MAX_MBOXES			2
 #define RPMH_MAX_FAST_RES		32
 #define RPMH_MAX_REQ_IN_BATCH		10
+#define RPMH_TIMEOUT			msecs_to_jiffies(10000)
 
 #define DEFINE_RPMH_MSG_ONSTACK(rc, s, q, c, name)	\
 	struct rpmh_msg name = {			\
@@ -166,6 +167,41 @@
 			complete(compl);
 }
 
+/**
+ * wait_for_tx_done: Wait forever until the response is received.
+ *
+ * @rc: The RPMH client
+ * @compl: The completion object
+ * @addr: An addr that we sent in that request
+ * @data: The data for the address in that request
+ *
+ */
+static inline void wait_for_tx_done(struct rpmh_client *rc,
+		struct completion *compl, u32 addr, u32 data)
+{
+	int ret;
+	int count = 4;
+
+	do {
+		ret = wait_for_completion_timeout(compl, RPMH_TIMEOUT);
+		if (ret) {
+			if (count != 4)
+			dev_notice(rc->dev,
+				"RPMH response received addr=0x%x data=0x%x\n",
+				addr, data);
+			return;
+		}
+		if (!count) {
+			mbox_chan_debug(rc->chan);
+		} else {
+			dev_err(rc->dev,
+			"RPMH response timeout (%d) addr=0x%x,data=0x%x\n",
+			count, addr, data);
+			count--;
+		}
+	} while (true);
+}
+
 static struct rpmh_req *__find_req(struct rpmh_client *rc, u32 addr)
 {
 	struct rpmh_req *p, *req = NULL;
@@ -365,7 +401,7 @@
 	if (ret < 0)
 		return ret;
 
-	wait_for_completion(&compl);
+	wait_for_tx_done(rc, &compl, addr, data);
 
 	return rpm_msg.err;
 }
@@ -469,7 +505,7 @@
 	if (ret)
 		return ret;
 
-	wait_for_completion(&compl);
+	wait_for_tx_done(rc, &compl, cmd[0].addr, cmd[0].data);
 
 	return rpm_msg.err;
 }
@@ -500,6 +536,7 @@
 	int count = 0;
 	int ret, i, j, k;
 	bool complete_set;
+	u32 addr, data;
 
 	if (IS_ERR_OR_NULL(rc) || !cmd || !n)
 		return -EINVAL;
@@ -537,6 +574,8 @@
 		}
 	}
 
+	addr = cmd[0].addr;
+	data = cmd[0].data;
 	/* Create async request batches */
 	for (i = 0; i < count; i++) {
 		rpm_msg[i] = __get_rpmh_msg_async(rc, state, cmd, n[i]);
@@ -566,7 +605,7 @@
 		/* For those unsent requests, spoof tx_done */
 		for (j = i; j < count; j++)
 			rpmh_tx_done(&rc->client, &rpm_msg[j]->msg, ret);
-		wait_for_completion(&compl);
+		wait_for_tx_done(rc, &compl, addr, data);
 	} else {
 		/* Send Sleep requests to the controller, expect no response */
 		for (i = 0; i < count; i++) {
@@ -719,7 +758,7 @@
 		return ret;
 
 	/* Wait until the response is received from RPMH */
-	wait_for_completion(&compl);
+	wait_for_tx_done(rc, &compl, addr, 0);
 
 	/* Read the data back from the tcs_mbox_msg structrure */
 	*resp = rpm_msg.cmd[0].data;
diff --git a/drivers/soc/qcom/secure_buffer.c b/drivers/soc/qcom/secure_buffer.c
index 63cce5c..d337b7a 100644
--- a/drivers/soc/qcom/secure_buffer.c
+++ b/drivers/soc/qcom/secure_buffer.c
@@ -416,6 +416,8 @@
 		return "VMID_CP_SPSS_SP";
 	case VMID_CP_SPSS_SP_SHARED:
 		return "VMID_CP_SPSS_SP_SHARED";
+	case VMID_CP_SPSS_HLOS_SHARED:
+		return "VMID_CP_SPSS_HLOS_SHARED";
 	case VMID_INVAL:
 		return "VMID_INVAL";
 	default:
diff --git a/drivers/soc/qcom/smcinvoke.c b/drivers/soc/qcom/smcinvoke.c
new file mode 100644
index 0000000..3f31fb1
--- /dev/null
+++ b/drivers/soc/qcom/smcinvoke.c
@@ -0,0 +1,575 @@
+/*
+ * SMC Invoke driver
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/anon_inodes.h>
+#include <linux/smcinvoke.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+
+#include <soc/qcom/scm.h>
+#include <asm/cacheflush.h>
+#include <soc/qcom/qseecomi.h>
+
+#include "smcinvoke_object.h"
+#include "../../misc/qseecom_kernel.h"
+
+#define SMCINVOKE_DEV			"smcinvoke"
+#define SMCINVOKE_TZ_PARAM_ID		0x224
+#define SMCINVOKE_TZ_CMD		0x32000600
+#define SMCINVOKE_TZ_ROOT_OBJ		1
+#define SMCINVOKE_TZ_MIN_BUF_SIZE	4096
+#define SMCINVOKE_ARGS_ALIGN_SIZE	(sizeof(uint64_t))
+#define SMCINVOKE_TZ_OBJ_NULL		0
+
+#define FOR_ARGS(ndxvar, counts, section)			\
+	for (ndxvar = object_counts_index_##section(counts);	\
+		ndxvar < (object_counts_index_##section(counts)	\
+		+ object_counts_num_##section(counts));		\
+		++ndxvar)
+
+static long smcinvoke_ioctl(struct file *, unsigned int, unsigned long);
+static int smcinvoke_open(struct inode *, struct file *);
+static int smcinvoke_release(struct inode *, struct file *);
+
+static const struct file_operations smcinvoke_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= smcinvoke_ioctl,
+	.compat_ioctl	= smcinvoke_ioctl,
+	.open		= smcinvoke_open,
+	.release	= smcinvoke_release,
+};
+
+struct smcinvoke_buf_hdr {
+	uint32_t offset;
+	uint32_t size;
+};
+
+union smcinvoke_tz_args {
+	struct smcinvoke_buf_hdr b;
+	uint32_t		 tzhandle;
+};
+struct smcinvoke_msg_hdr {
+	uint32_t	tzhandle;
+	uint32_t	op;
+	uint32_t	counts;
+};
+
+struct smcinvoke_tzobj_context {
+	uint32_t	tzhandle;
+};
+
+static dev_t smcinvoke_device_no;
+struct cdev smcinvoke_cdev;
+struct class *driver_class;
+struct device *class_dev;
+
+/*
+ * size_add saturates at SIZE_MAX. If integer overflow is detected,
+ * this function would return SIZE_MAX otherwise normal a+b is returned.
+ */
+static inline size_t size_add(size_t a, size_t b)
+{
+	return (b > (SIZE_MAX - a)) ? SIZE_MAX : a + b;
+}
+
+/*
+ * pad_size is used along with size_align to define a buffer overflow
+ * protected version of ALIGN
+ */
+static inline size_t pad_size(size_t a, size_t b)
+{
+	return (~a + 1) % b;
+}
+
+/*
+ * size_align saturates at SIZE_MAX. If integer overflow is detected, this
+ * function would return SIZE_MAX otherwise next aligned size is returned.
+ */
+static inline size_t size_align(size_t a, size_t b)
+{
+	return size_add(a, pad_size(a, b));
+}
+
+/*
+ * This function retrieves file pointer corresponding to FD provided. It stores
+ * retrived file pointer until IOCTL call is concluded. Once call is completed,
+ * all stored file pointers are released. file pointers are stored to prevent
+ * other threads from releasing that FD while IOCTL is in progress.
+ */
+static int get_tzhandle_from_fd(int64_t fd, struct file **filp,
+				uint32_t *tzhandle)
+{
+	int ret = -EBADF;
+	struct file *tmp_filp = NULL;
+	struct smcinvoke_tzobj_context *tzobj = NULL;
+
+	if (fd == SMCINVOKE_USERSPACE_OBJ_NULL) {
+		*tzhandle = SMCINVOKE_TZ_OBJ_NULL;
+		ret = 0;
+		goto out;
+	} else if (fd < SMCINVOKE_USERSPACE_OBJ_NULL) {
+		goto out;
+	}
+
+	tmp_filp = fget(fd);
+	if (!tmp_filp)
+		goto out;
+
+	/* Verify if filp is smcinvoke device's file pointer */
+	if (!tmp_filp->f_op || !tmp_filp->private_data ||
+		(tmp_filp->f_op != &smcinvoke_fops)) {
+		fput(tmp_filp);
+		goto out;
+	}
+
+	tzobj = tmp_filp->private_data;
+	*tzhandle = tzobj->tzhandle;
+	*filp = tmp_filp;
+	ret = 0;
+out:
+	return ret;
+}
+
+static int get_fd_from_tzhandle(uint32_t tzhandle, int64_t *fd)
+{
+	int unused_fd = -1, ret = -1;
+	struct file *f = NULL;
+	struct smcinvoke_tzobj_context *cxt = NULL;
+
+	if (tzhandle == SMCINVOKE_TZ_OBJ_NULL) {
+		*fd = SMCINVOKE_USERSPACE_OBJ_NULL;
+		ret = 0;
+		goto out;
+	}
+
+	cxt = kzalloc(sizeof(*cxt), GFP_KERNEL);
+	if (!cxt) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	unused_fd = get_unused_fd_flags(O_RDWR);
+	if (unused_fd < 0)
+		goto out;
+
+	f = anon_inode_getfile(SMCINVOKE_DEV, &smcinvoke_fops, cxt, O_RDWR);
+	if (IS_ERR(f))
+		goto out;
+
+	*fd = unused_fd;
+	fd_install(*fd, f);
+	((struct smcinvoke_tzobj_context *)
+			(f->private_data))->tzhandle = tzhandle;
+	return 0;
+out:
+	if (unused_fd >= 0)
+		put_unused_fd(unused_fd);
+	kfree(cxt);
+
+	return ret;
+}
+
+static int prepare_send_scm_msg(const uint8_t *in_buf, size_t in_buf_len,
+				const uint8_t *out_buf, size_t out_buf_len,
+				int32_t *smcinvoke_result)
+{
+	int ret = 0;
+	struct scm_desc desc = {0};
+	size_t inbuf_flush_size = (1UL << get_order(in_buf_len)) * PAGE_SIZE;
+	size_t outbuf_flush_size = (1UL << get_order(out_buf_len)) * PAGE_SIZE;
+
+	desc.arginfo = SMCINVOKE_TZ_PARAM_ID;
+	desc.args[0] = (uint64_t)virt_to_phys(in_buf);
+	desc.args[1] = inbuf_flush_size;
+	desc.args[2] = (uint64_t)virt_to_phys(out_buf);
+	desc.args[3] = outbuf_flush_size;
+
+	dmac_flush_range(in_buf, in_buf + inbuf_flush_size);
+	dmac_flush_range(out_buf, out_buf + outbuf_flush_size);
+
+	ret = scm_call2(SMCINVOKE_TZ_CMD, &desc);
+
+	/* process listener request */
+	if (!ret && (desc.ret[0] == QSEOS_RESULT_INCOMPLETE ||
+		desc.ret[0] == QSEOS_RESULT_BLOCKED_ON_LISTENER))
+		ret = qseecom_process_listener_from_smcinvoke(&desc);
+
+	*smcinvoke_result = (int32_t)desc.ret[1];
+	if (ret || desc.ret[1] || desc.ret[2] || desc.ret[0])
+		pr_err("SCM call failed with ret val = %d %d %d %d\n",
+						ret, (int)desc.ret[0],
+				(int)desc.ret[1], (int)desc.ret[2]);
+
+	dmac_inv_range(in_buf, in_buf + inbuf_flush_size);
+	dmac_inv_range(out_buf, out_buf + outbuf_flush_size);
+	return ret;
+}
+
+static int marshal_out(void *buf, uint32_t buf_size,
+				struct smcinvoke_cmd_req *req,
+				union smcinvoke_arg *args_buf)
+{
+	int ret = -EINVAL, i = 0;
+	union smcinvoke_tz_args *tz_args = NULL;
+	size_t offset = sizeof(struct smcinvoke_msg_hdr) +
+				object_counts_total(req->counts) *
+					sizeof(union smcinvoke_tz_args);
+
+	if (offset > buf_size)
+		goto out;
+
+	tz_args = (union smcinvoke_tz_args *)
+				(buf + sizeof(struct smcinvoke_msg_hdr));
+
+	tz_args += object_counts_num_BI(req->counts);
+
+	FOR_ARGS(i, req->counts, BO) {
+		args_buf[i].b.size = tz_args->b.size;
+		if ((buf_size - tz_args->b.offset < tz_args->b.size) ||
+			tz_args->b.offset > buf_size) {
+			pr_err("%s: buffer overflow detected\n", __func__);
+			goto out;
+		}
+		if (copy_to_user((void __user *)(uintptr_t)(args_buf[i].b.addr),
+			(uint8_t *)(buf) + tz_args->b.offset,
+						tz_args->b.size)) {
+			pr_err("Error %d copying ctxt to user\n", ret);
+			goto out;
+		}
+		tz_args++;
+	}
+	tz_args += object_counts_num_OI(req->counts);
+
+	FOR_ARGS(i, req->counts, OO) {
+		/*
+		 * create a new FD and assign to output object's
+		 * context
+		 */
+		ret = get_fd_from_tzhandle(tz_args->tzhandle,
+						&(args_buf[i].o.fd));
+		if (ret)
+			goto out;
+		tz_args++;
+	}
+	ret = 0;
+out:
+	return ret;
+}
+
+/*
+ * SMC expects arguments in following format
+ * ---------------------------------------------------------------------------
+ * | cxt | op | counts | ptr|size |ptr|size...|ORef|ORef|...| rest of payload |
+ * ---------------------------------------------------------------------------
+ * cxt: target, op: operation, counts: total arguments
+ * offset: offset is from beginning of buffer i.e. cxt
+ * size: size is 8 bytes aligned value
+ */
+static size_t compute_in_msg_size(const struct smcinvoke_cmd_req *req,
+					const union smcinvoke_arg *args_buf)
+{
+	uint32_t i = 0;
+
+	size_t total_size = sizeof(struct smcinvoke_msg_hdr) +
+				object_counts_total(req->counts) *
+					sizeof(union smcinvoke_tz_args);
+
+	/* Computed total_size should be 8 bytes aligned from start of buf */
+	total_size = ALIGN(total_size, SMCINVOKE_ARGS_ALIGN_SIZE);
+
+	/* each buffer has to be 8 bytes aligned */
+	while (i < object_counts_num_buffers(req->counts))
+		total_size = size_add(total_size,
+		size_align(args_buf[i++].b.size, SMCINVOKE_ARGS_ALIGN_SIZE));
+
+	/* Since we're using get_free_pages, no need for explicit PAGE align */
+	return total_size;
+}
+
+static int marshal_in(const struct smcinvoke_cmd_req *req,
+			const union smcinvoke_arg *args_buf, uint32_t tzhandle,
+			uint8_t *buf, size_t buf_size, struct file **arr_filp)
+{
+	int ret = -EINVAL, i = 0;
+	union smcinvoke_tz_args *tz_args = NULL;
+	struct smcinvoke_msg_hdr msg_hdr = {tzhandle, req->op, req->counts};
+	uint32_t offset = sizeof(struct smcinvoke_msg_hdr) +
+				sizeof(union smcinvoke_tz_args) *
+				object_counts_total(req->counts);
+
+	if (buf_size < offset)
+		goto out;
+
+	*(struct smcinvoke_msg_hdr *)buf = msg_hdr;
+	tz_args = (union smcinvoke_tz_args *)
+			(buf + sizeof(struct smcinvoke_msg_hdr));
+
+	FOR_ARGS(i, req->counts, BI) {
+		offset = size_align(offset, SMCINVOKE_ARGS_ALIGN_SIZE);
+		if ((offset > buf_size) ||
+			(args_buf[i].b.size > (buf_size - offset)))
+			goto out;
+
+		tz_args->b.offset = offset;
+		tz_args->b.size = args_buf[i].b.size;
+		tz_args++;
+
+		if (copy_from_user(buf+offset,
+			(void __user *)(uintptr_t)(args_buf[i].b.addr),
+						args_buf[i].b.size))
+			goto out;
+
+		offset += args_buf[i].b.size;
+	}
+	FOR_ARGS(i, req->counts, BO) {
+		offset = size_align(offset, SMCINVOKE_ARGS_ALIGN_SIZE);
+		if ((offset > buf_size) ||
+			(args_buf[i].b.size > (buf_size - offset)))
+			goto out;
+
+		tz_args->b.offset = offset;
+		tz_args->b.size = args_buf[i].b.size;
+		tz_args++;
+
+		offset += args_buf[i].b.size;
+	}
+	FOR_ARGS(i, req->counts, OI) {
+		if (get_tzhandle_from_fd(args_buf[i].o.fd,
+					&arr_filp[i], &(tz_args->tzhandle)))
+			goto out;
+		tz_args++;
+	}
+	ret = 0;
+out:
+	return ret;
+}
+
+long smcinvoke_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	int    ret = -1, i = 0, nr_args = 0;
+	struct smcinvoke_cmd_req req = {0};
+	void   *in_msg = NULL;
+	size_t inmsg_size = 0;
+	void   *out_msg = NULL;
+	union  smcinvoke_arg *args_buf = NULL;
+	struct file *filp_to_release[object_counts_max_OO] = {NULL};
+	struct smcinvoke_tzobj_context *tzobj = filp->private_data;
+
+	switch (cmd) {
+	case SMCINVOKE_IOCTL_INVOKE_REQ:
+		if (_IOC_SIZE(cmd) != sizeof(req)) {
+			ret =  -EINVAL;
+			goto out;
+		}
+		ret = copy_from_user(&req, (void __user *)arg, sizeof(req));
+		if (ret) {
+			ret =  -EFAULT;
+			goto out;
+		}
+
+		nr_args = object_counts_num_buffers(req.counts) +
+				object_counts_num_objects(req.counts);
+
+		if (req.argsize != sizeof(union smcinvoke_arg)) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		if (nr_args) {
+
+			args_buf = kzalloc(nr_args * req.argsize, GFP_KERNEL);
+			if (!args_buf) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			ret = copy_from_user(args_buf,
+					(void __user *)(uintptr_t)(req.args),
+						nr_args * req.argsize);
+
+			if (ret) {
+				ret = -EFAULT;
+				goto out;
+			}
+		}
+
+		inmsg_size = compute_in_msg_size(&req, args_buf);
+		in_msg = (void *)__get_free_pages(GFP_KERNEL,
+						get_order(inmsg_size));
+		if (!in_msg) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		out_msg = (void *)__get_free_page(GFP_KERNEL);
+		if (!out_msg) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		ret = marshal_in(&req, args_buf, tzobj->tzhandle, in_msg,
+					inmsg_size, filp_to_release);
+		if (ret)
+			goto out;
+
+		ret = prepare_send_scm_msg(in_msg, inmsg_size, out_msg,
+				SMCINVOKE_TZ_MIN_BUF_SIZE, &req.result);
+		if (ret)
+			goto out;
+
+		/*
+		 * if invoke op results in an err, no need to marshal_out and
+		 * copy args buf to user space
+		 */
+		if (!req.result) {
+			ret = marshal_out(in_msg, inmsg_size, &req, args_buf);
+
+			ret |=  copy_to_user(
+					(void __user *)(uintptr_t)(req.args),
+					args_buf, nr_args * req.argsize);
+		}
+		ret |=  copy_to_user((void __user *)arg, &req, sizeof(req));
+		if (ret)
+			goto out;
+
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+out:
+	free_page((long)out_msg);
+	free_pages((long)in_msg, get_order(inmsg_size));
+	kfree(args_buf);
+	for (i = 0; i < object_counts_max_OO; i++) {
+		if (filp_to_release[i])
+			fput(filp_to_release[i]);
+	}
+
+	return ret;
+}
+
+static int smcinvoke_open(struct inode *nodp, struct file *filp)
+{
+	struct smcinvoke_tzobj_context *tzcxt = NULL;
+
+	tzcxt = kzalloc(sizeof(*tzcxt), GFP_KERNEL);
+	if (!tzcxt)
+		return -ENOMEM;
+
+	tzcxt->tzhandle = SMCINVOKE_TZ_ROOT_OBJ;
+	filp->private_data = tzcxt;
+
+	return 0;
+}
+
+static int smcinvoke_release(struct inode *nodp, struct file *filp)
+{
+	int ret = 0, smcinvoke_result = 0;
+	uint8_t *in_buf = NULL;
+	uint8_t *out_buf = NULL;
+	struct smcinvoke_msg_hdr hdr = {0};
+	struct smcinvoke_tzobj_context *tzobj = filp->private_data;
+	uint32_t tzhandle = tzobj->tzhandle;
+
+	/* Root object is special in sense it is indestructible */
+	if (!tzhandle || tzhandle == SMCINVOKE_TZ_ROOT_OBJ)
+		goto out;
+
+	in_buf = (uint8_t *)__get_free_page(GFP_KERNEL);
+	out_buf = (uint8_t *)__get_free_page(GFP_KERNEL);
+	if (!in_buf || !out_buf)
+		goto out;
+
+	hdr.tzhandle = tzhandle;
+	hdr.op = object_op_RELEASE;
+	hdr.counts = 0;
+	*(struct smcinvoke_msg_hdr *)in_buf = hdr;
+
+	ret = prepare_send_scm_msg(in_buf, SMCINVOKE_TZ_MIN_BUF_SIZE,
+			out_buf, SMCINVOKE_TZ_MIN_BUF_SIZE, &smcinvoke_result);
+out:
+	kfree(filp->private_data);
+	free_page((long)in_buf);
+	free_page((long)out_buf);
+
+	return ret;
+}
+
+static int __init smcinvoke_init(void)
+{
+	unsigned int baseminor = 0;
+	unsigned int count = 1;
+	int rc = 0;
+
+	rc = alloc_chrdev_region(&smcinvoke_device_no, baseminor, count,
+							SMCINVOKE_DEV);
+	if (rc < 0) {
+		pr_err("chrdev_region failed %d for %s\n", rc, SMCINVOKE_DEV);
+		return rc;
+	}
+	driver_class = class_create(THIS_MODULE, SMCINVOKE_DEV);
+	if (IS_ERR(driver_class)) {
+		rc = -ENOMEM;
+		pr_err("class_create failed %d\n", rc);
+		goto exit_unreg_chrdev_region;
+	}
+	class_dev = device_create(driver_class, NULL, smcinvoke_device_no,
+						NULL, SMCINVOKE_DEV);
+	if (!class_dev) {
+		pr_err("class_device_create failed %d\n", rc);
+		rc = -ENOMEM;
+		goto exit_destroy_class;
+	}
+
+	cdev_init(&smcinvoke_cdev, &smcinvoke_fops);
+	smcinvoke_cdev.owner = THIS_MODULE;
+
+	rc = cdev_add(&smcinvoke_cdev, MKDEV(MAJOR(smcinvoke_device_no), 0),
+								count);
+	if (rc < 0) {
+		pr_err("cdev_add failed %d for %s\n", rc, SMCINVOKE_DEV);
+		goto exit_destroy_device;
+	}
+	return  0;
+
+exit_destroy_device:
+	device_destroy(driver_class, smcinvoke_device_no);
+exit_destroy_class:
+	class_destroy(driver_class);
+exit_unreg_chrdev_region:
+	unregister_chrdev_region(smcinvoke_device_no, count);
+
+	return rc;
+}
+
+static void __exit smcinvoke_exit(void)
+{
+	int count = 1;
+
+	cdev_del(&smcinvoke_cdev);
+	device_destroy(driver_class, smcinvoke_device_no);
+	class_destroy(driver_class);
+	unregister_chrdev_region(smcinvoke_device_no, count);
+}
+device_initcall(smcinvoke_init);
+module_exit(smcinvoke_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("SMC Invoke driver");
diff --git a/drivers/soc/qcom/smcinvoke_object.h b/drivers/soc/qcom/smcinvoke_object.h
new file mode 100644
index 0000000..670b425
--- /dev/null
+++ b/drivers/soc/qcom/smcinvoke_object.h
@@ -0,0 +1,51 @@
+/* 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.
+ */
+#ifndef __SMCINVOKE_OBJECT_H
+#define __SMCINVOKE_OBJECT_H
+
+#include <linux/types.h>
+
+#define object_op_METHOD_MASK   ((uint32_t)0x0000FFFFu)
+#define object_op_RELEASE       (object_op_METHOD_MASK - 0)
+#define object_op_RETAIN        (object_op_METHOD_MASK - 1)
+
+#define object_counts_max_BI   0xF
+#define object_counts_max_BO   0xF
+#define object_counts_max_OI   0xF
+#define object_counts_max_OO   0xF
+
+/* unpack counts */
+
+#define object_counts_num_BI(k)  ((size_t) (((k) >> 0) & object_counts_max_BI))
+#define object_counts_num_BO(k)  ((size_t) (((k) >> 4) & object_counts_max_BO))
+#define object_counts_num_OI(k)  ((size_t) (((k) >> 8) & object_counts_max_OI))
+#define object_counts_num_OO(k)  ((size_t) (((k) >> 12) & object_counts_max_OO))
+#define object_counts_num_buffers(k)	\
+			(object_counts_num_BI(k) + object_counts_num_BO(k))
+
+#define object_counts_num_objects(k)	\
+			(object_counts_num_OI(k) + object_counts_num_OO(k))
+
+/* Indices into args[] */
+
+#define object_counts_index_BI(k)   0
+#define object_counts_index_BO(k)		\
+			(object_counts_index_BI(k) + object_counts_num_BI(k))
+#define object_counts_index_OI(k)		\
+			(object_counts_index_BO(k) + object_counts_num_BO(k))
+#define object_counts_index_OO(k)		\
+			(object_counts_index_OI(k) + object_counts_num_OI(k))
+#define object_counts_total(k)		\
+			(object_counts_index_OO(k) + object_counts_num_OO(k))
+
+
+#endif /* __SMCINVOKE_OBJECT_H */
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 9ea4a9f..4082a7d 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -3,7 +3,7 @@
  * drivers/staging/android/ion/ion.c
  *
  * Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-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
@@ -76,7 +76,7 @@
  * @dev:		backpointer to ion device
  * @handles:		an rb tree of all the handles in this client
  * @idr:		an idr space for allocating handle ids
- * @lock:		lock protecting the tree of handles
+ * @lock:		lock protecting the tree of handles and idr
  * @name:		used for debugging
  * @display_name:	used for debugging (unique version of @name)
  * @display_serial:	used for debugging (to make display_name unique)
@@ -91,7 +91,6 @@
 	struct ion_device *dev;
 	struct rb_root handles;
 	struct idr idr;
-	/* Protects idr */
 	struct mutex lock;
 	char *name;
 	char *display_name;
@@ -671,8 +670,8 @@
 		mutex_unlock(&client->lock);
 		return -ENODEV;
 	}
-	mutex_unlock(&client->lock);
 	ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len);
+	mutex_unlock(&client->lock);
 	return ret;
 }
 EXPORT_SYMBOL(ion_phys);
@@ -777,33 +776,7 @@
 }
 EXPORT_SYMBOL(ion_unmap_kernel);
 
-static struct mutex debugfs_mutex;
 static struct rb_root *ion_root_client;
-static int is_client_alive(struct ion_client *client)
-{
-	struct rb_node *node;
-	struct ion_client *tmp;
-	struct ion_device *dev;
-
-	node = ion_root_client->rb_node;
-	dev = container_of(ion_root_client, struct ion_device, clients);
-
-	down_read(&dev->lock);
-	while (node) {
-		tmp = rb_entry(node, struct ion_client, node);
-		if (client < tmp) {
-			node = node->rb_left;
-		} else if (client > tmp) {
-			node = node->rb_right;
-		} else {
-			up_read(&dev->lock);
-			return 1;
-		}
-	}
-
-	up_read(&dev->lock);
-	return 0;
-}
 
 static int ion_debug_client_show(struct seq_file *s, void *unused)
 {
@@ -814,14 +787,6 @@
 		   "heap_name", "size_in_bytes", "handle refcount",
 		   "buffer");
 
-	mutex_lock(&debugfs_mutex);
-	if (!is_client_alive(client)) {
-		seq_printf(s, "ion_client 0x%p dead, can't dump its buffers\n",
-			   client);
-		mutex_unlock(&debugfs_mutex);
-		return 0;
-	}
-
 	mutex_lock(&client->lock);
 	for (n = rb_first(&client->handles); n; n = rb_next(n)) {
 		struct ion_handle *handle = rb_entry(n, struct ion_handle,
@@ -836,7 +801,6 @@
 		seq_puts(s, "\n");
 	}
 	mutex_unlock(&client->lock);
-	mutex_unlock(&debugfs_mutex);
 	return 0;
 }
 
@@ -967,27 +931,27 @@
 	struct rb_node *n;
 
 	pr_debug("%s: %d\n", __func__, __LINE__);
-	mutex_lock(&debugfs_mutex);
+	down_write(&dev->lock);
+	rb_erase(&client->node, &dev->clients);
+	up_write(&dev->lock);
+
+	/* After this completes, there are no more references to client */
+	debugfs_remove_recursive(client->debug_root);
+
+	mutex_lock(&client->lock);
 	while ((n = rb_first(&client->handles))) {
 		struct ion_handle *handle = rb_entry(n, struct ion_handle,
 						     node);
 		ion_handle_destroy(&handle->ref);
 	}
+	mutex_unlock(&client->lock);
 
 	idr_destroy(&client->idr);
-
-	down_write(&dev->lock);
 	if (client->task)
 		put_task_struct(client->task);
-	rb_erase(&client->node, &dev->clients);
-	debugfs_remove_recursive(client->debug_root);
-
-	up_write(&dev->lock);
-
 	kfree(client->display_name);
 	kfree(client->name);
 	kfree(client);
-	mutex_unlock(&debugfs_mutex);
 }
 EXPORT_SYMBOL(ion_client_destroy);
 
@@ -1794,7 +1758,7 @@
 	seq_printf(s, "%16s %16s %16s\n", "client", "pid", "size");
 	seq_puts(s, "----------------------------------------------------\n");
 
-	mutex_lock(&debugfs_mutex);
+	down_read(&dev->lock);
 	for (n = rb_first(&dev->clients); n; n = rb_next(n)) {
 		struct ion_client *client = rb_entry(n, struct ion_client,
 						     node);
@@ -1813,7 +1777,7 @@
 				   client->pid, size);
 		}
 	}
-	mutex_unlock(&debugfs_mutex);
+	up_read(&dev->lock);
 
 	seq_puts(s, "----------------------------------------------------\n");
 	seq_puts(s, "orphaned allocations (info is from last known client):\n");
@@ -2048,7 +2012,6 @@
 	plist_head_init(&idev->heaps);
 	idev->clients = RB_ROOT;
 	ion_root_client = &idev->clients;
-	mutex_init(&debugfs_mutex);
 	return idev;
 }
 EXPORT_SYMBOL(ion_device_create);
diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c
index 52926f0..a9ebfed 100644
--- a/drivers/staging/android/ion/msm/msm_ion.c
+++ b/drivers/staging/android/ion/msm/msm_ion.c
@@ -621,7 +621,8 @@
 		vmid == VMID_CP_APP ||
 		vmid == VMID_CP_CAMERA_PREVIEW ||
 		vmid == VMID_CP_SPSS_SP ||
-		vmid == VMID_CP_SPSS_SP_SHARED);
+		vmid == VMID_CP_SPSS_SP_SHARED ||
+		vmid == VMID_CP_SPSS_HLOS_SHARED);
 }
 
 unsigned int count_set_bits(unsigned long val)
@@ -669,6 +670,8 @@
 		return VMID_CP_SPSS_SP;
 	if (flags & ION_FLAG_CP_SPSS_SP_SHARED)
 		return VMID_CP_SPSS_SP_SHARED;
+	if (flags & ION_FLAG_CP_SPSS_HLOS_SHARED)
+		return VMID_CP_SPSS_HLOS_SHARED;
 	return -EINVAL;
 }
 /* fix up the cases where the ioctl direction bits are incorrect */
diff --git a/drivers/staging/android/uapi/msm_ion.h b/drivers/staging/android/uapi/msm_ion.h
index 7381ee9..84598db 100644
--- a/drivers/staging/android/uapi/msm_ion.h
+++ b/drivers/staging/android/uapi/msm_ion.h
@@ -89,6 +89,7 @@
 #define ION_FLAG_CP_SEC_DISPLAY		ION_BIT(25)
 #define ION_FLAG_CP_APP			ION_BIT(26)
 #define ION_FLAG_CP_CAMERA_PREVIEW	ION_BIT(27)
+#define ION_FLAG_CP_SPSS_HLOS_SHARED	ION_BIT(30)
 
 
 /**
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 68d9feb..95ef027 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -897,6 +897,60 @@
 }
 
 static ssize_t
+polling_delay_show(struct device *dev, struct device_attribute *attr,
+		   char *buf)
+{
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", tz->polling_delay);
+}
+
+static ssize_t
+polling_delay_store(struct device *dev, struct device_attribute *attr,
+		    const char *buf, size_t count)
+{
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+	int delay;
+
+	if (kstrtoint(buf, 10, &delay))
+		return -EINVAL;
+
+	mutex_lock(&tz->lock);
+	tz->polling_delay = delay;
+	mutex_unlock(&tz->lock);
+	thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+	return count;
+}
+
+static ssize_t
+passive_delay_show(struct device *dev, struct device_attribute *attr,
+		   char *buf)
+{
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", tz->passive_delay);
+}
+
+static ssize_t
+passive_delay_store(struct device *dev, struct device_attribute *attr,
+		    const char *buf, size_t count)
+{
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+	int delay;
+
+	if (kstrtoint(buf, 10, &delay))
+		return -EINVAL;
+
+	mutex_lock(&tz->lock);
+	tz->passive_delay = delay;
+	mutex_unlock(&tz->lock);
+	thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+	return count;
+}
+
+static ssize_t
 policy_store(struct device *dev, struct device_attribute *attr,
 		    const char *buf, size_t count)
 {
@@ -1167,6 +1221,10 @@
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
 static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
 static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL);
+static DEVICE_ATTR(passive_delay, 0644, passive_delay_show,
+			passive_delay_store);
+static DEVICE_ATTR(polling_delay, 0644, polling_delay_show,
+			polling_delay_store);
 
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)	\
@@ -1324,6 +1382,54 @@
 		return sprintf(buf, "%d\n", instance->trip);
 }
 
+static ssize_t
+thermal_cooling_device_upper_limit_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+	struct thermal_instance *instance;
+	int ret, upper_limit;
+
+	instance =
+	    container_of(attr, struct thermal_instance, upper_attr);
+
+	ret = kstrtoint(buf, 0, &upper_limit);
+	if (ret)
+		return ret;
+	if (upper_limit < instance->lower)
+		return -EINVAL;
+
+	instance->upper = upper_limit;
+	thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+	return count;
+}
+
+static ssize_t
+thermal_cooling_device_lower_limit_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+	struct thermal_instance *instance;
+	int ret, lower_limit;
+
+	instance =
+	    container_of(attr, struct thermal_instance, lower_attr);
+
+	ret = kstrtoint(buf, 0, &lower_limit);
+	if (ret)
+		return ret;
+	if (lower_limit > instance->upper)
+		return -EINVAL;
+
+	instance->lower = lower_limit;
+	thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+	return count;
+}
+
 static struct attribute *cooling_device_attrs[] = {
 	&dev_attr_cdev_type.attr,
 	&dev_attr_max_state.attr,
@@ -1484,8 +1590,9 @@
 			"cdev%d_upper_limit", dev->id);
 	sysfs_attr_init(&dev->upper_attr.attr);
 	dev->upper_attr.attr.name = dev->upper_attr_name;
-	dev->upper_attr.attr.mode = 0444;
+	dev->upper_attr.attr.mode = 0644;
 	dev->upper_attr.show = thermal_cooling_device_upper_limit_show;
+	dev->upper_attr.store = thermal_cooling_device_upper_limit_store;
 	result = device_create_file(&tz->device, &dev->upper_attr);
 	if (result)
 		goto remove_trip_file;
@@ -1494,8 +1601,9 @@
 			"cdev%d_lower_limit", dev->id);
 	sysfs_attr_init(&dev->lower_attr.attr);
 	dev->lower_attr.attr.name = dev->lower_attr_name;
-	dev->lower_attr.attr.mode = 0444;
+	dev->lower_attr.attr.mode = 0644;
 	dev->lower_attr.show = thermal_cooling_device_lower_limit_show;
+	dev->lower_attr.store = thermal_cooling_device_lower_limit_store;
 	result = device_create_file(&tz->device, &dev->lower_attr);
 	if (result)
 		goto remove_upper_file;
@@ -2084,6 +2192,13 @@
 		if (result)
 			goto unregister;
 	}
+	result = device_create_file(&tz->device, &dev_attr_passive_delay);
+	if (result)
+		goto unregister;
+
+	result = device_create_file(&tz->device, &dev_attr_polling_delay);
+	if (result)
+		goto unregister;
 
 	if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) {
 		result = device_create_file(&tz->device, &dev_attr_emul_temp);
@@ -2207,6 +2322,8 @@
 		device_remove_file(&tz->device, &dev_attr_mode);
 	device_remove_file(&tz->device, &dev_attr_policy);
 	device_remove_file(&tz->device, &dev_attr_available_policies);
+	device_remove_file(&tz->device, &dev_attr_passive_delay);
+	device_remove_file(&tz->device, &dev_attr_polling_delay);
 	remove_trip_attrs(tz);
 	thermal_set_governor(tz, NULL);
 
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 94ba2c3e..d1cde1b 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -1069,6 +1069,14 @@
 						SE_GENI_TX_PACKING_CFG0);
 		geni_write_reg_nolog(cfg1, uport->membase,
 						SE_GENI_TX_PACKING_CFG1);
+		msm_port->handle_rx = handle_rx_hs;
+		msm_port->rx_fifo = devm_kzalloc(uport->dev,
+				sizeof(msm_port->rx_fifo_depth * sizeof(u32)),
+								GFP_KERNEL);
+		if (!msm_port->rx_fifo) {
+			ret = -ENOMEM;
+			goto exit_portsetup;
+		}
 	} else {
 		/*
 		 * Make an unconditional cancel on the main sequencer to reset
@@ -1166,12 +1174,12 @@
 		goto exit_startup;
 	}
 
+	get_tx_fifo_size(msm_port);
 	if (!msm_port->port_setup) {
 		if (msm_geni_serial_port_setup(uport))
 			goto exit_startup;
 	}
 
-	get_tx_fifo_size(msm_port);
 	msm_geni_serial_start_rx(uport);
 	/*
 	 * Ensure that all the port configuration writes complete
@@ -1790,10 +1798,6 @@
 		dev_port->rx_fifo = devm_kzalloc(uport->dev, sizeof(u32),
 								GFP_KERNEL);
 	} else {
-		dev_port->handle_rx = handle_rx_hs;
-		dev_port->rx_fifo = devm_kzalloc(uport->dev,
-				sizeof(dev_port->rx_fifo_depth * sizeof(u32)),
-								GFP_KERNEL);
 		pm_runtime_set_suspended(&pdev->dev);
 		pm_runtime_enable(&pdev->dev);
 	}
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 96b21b0..3116edf 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -223,6 +223,10 @@
 	/* Blackmagic Design UltraStudio SDI */
 	{ USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },
 
+	/* Hauppauge HVR-950q */
+	{ USB_DEVICE(0x2040, 0x7200), .driver_info =
+			USB_QUIRK_CONFIG_INTF_STRINGS },
+
 	/* INTEL VALUE SSD */
 	{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
 
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 7272f9a..92e5d13 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -279,6 +279,8 @@
 
 	usb_destroy_configuration(udev);
 	usb_release_bos_descriptor(udev);
+	if (udev->parent)
+		of_node_put(dev->of_node);
 	usb_put_hcd(hcd);
 	kfree(udev->product);
 	kfree(udev->manufacturer);
diff --git a/drivers/usb/dwc3/dbm.c b/drivers/usb/dwc3/dbm.c
index 285cd5a..3860a1a 100644
--- a/drivers/usb/dwc3/dbm.c
+++ b/drivers/usb/dwc3/dbm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-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
@@ -129,7 +129,7 @@
 					      enum dbm_reg reg, int ep,
 					      const u32 mask, u32 val)
 {
-	u32 shift = find_first_bit((void *)&mask, 32);
+	u32 shift = __ffs(mask);
 	u32 offset = dbm->reg_table[reg].offset +
 			(dbm->reg_table[reg].ep_mult * ep);
 	u32 tmp = ioread32(dbm->base + offset);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index a496468..81f3384 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -319,7 +319,7 @@
 					  u32 offset,
 					  const u32 mask)
 {
-	u32 shift = ffs(mask);
+	u32 shift = __ffs(mask);
 	u32 val = ioread32(base + offset);
 
 	val &= mask;		/* clear other bits */
@@ -353,7 +353,7 @@
 static inline void dwc3_msm_write_reg_field(void __iomem *base, u32 offset,
 					    const u32 mask, u32 val)
 {
-	u32 shift = find_first_bit((void *)&mask, 32);
+	u32 shift = __ffs(mask);
 	u32 tmp = ioread32(base + offset);
 
 	tmp &= ~mask;		/* clear written bits */
diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index aaaf256..4cf5381 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -231,7 +231,7 @@
 
 	dwc3_data->syscfg_reg_off = res->start;
 
-	dev_vdbg(&pdev->dev, "glue-logic addr 0x%p, syscfg-reg offset 0x%x\n",
+	dev_vdbg(&pdev->dev, "glue-logic addr 0x%pK, syscfg-reg offset 0x%x\n",
 		 dwc3_data->glue_base, dwc3_data->syscfg_reg_off);
 
 	dwc3_data->rstc_pwrdn =
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7d8566f..edd000b 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1211,9 +1211,9 @@
 		return -ESHUTDOWN;
 	}
 
-	if (WARN(req->dep != dep, "request %p belongs to '%s'\n",
+	if (WARN(req->dep != dep, "request %pK belongs to '%s'\n",
 				&req->request, req->dep->name)) {
-		dwc3_trace(trace_dwc3_gadget, "request %p belongs to '%s'",
+		dwc3_trace(trace_dwc3_gadget, "request %pK belongs to '%s'",
 				&req->request, req->dep->name);
 		return -EINVAL;
 	}
@@ -1405,7 +1405,7 @@
 			dwc3_stop_active_transfer(dwc, dep->number, true);
 			goto out1;
 		}
-		dev_err(dwc->dev, "request %p was not queued to %s\n",
+		dev_err(dwc->dev, "request %pK was not queued to %s\n",
 				request, ep->name);
 		ret = -EINVAL;
 		goto out0;
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index e9e8f46..af3ce4f 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -19,6 +19,39 @@
 
 #include "core.h"
 
+static int dwc3_host_get_irq(struct dwc3 *dwc)
+{
+	struct platform_device	*dwc3_pdev = to_platform_device(dwc->dev);
+	int irq;
+
+	irq = platform_get_irq_byname(dwc3_pdev, "host");
+	if (irq > 0)
+		goto out;
+
+	if (irq == -EPROBE_DEFER)
+		goto out;
+
+	irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3");
+	if (irq > 0)
+		goto out;
+
+	if (irq == -EPROBE_DEFER)
+		goto out;
+
+	irq = platform_get_irq(dwc3_pdev, 0);
+	if (irq > 0)
+		goto out;
+
+	if (irq != -EPROBE_DEFER)
+		dev_err(dwc->dev, "missing host IRQ\n");
+
+	if (!irq)
+		irq = -EINVAL;
+
+out:
+	return irq;
+}
+
 int dwc3_host_init(struct dwc3 *dwc)
 {
 	struct property_entry	props[3];
@@ -28,39 +61,18 @@
 	struct platform_device	*dwc3_pdev = to_platform_device(dwc->dev);
 	int			prop_idx = 0;
 
-	irq = platform_get_irq_byname(dwc3_pdev, "host");
-	if (irq == -EPROBE_DEFER)
+	irq = dwc3_host_get_irq(dwc);
+	if (irq < 0)
 		return irq;
 
-	if (irq <= 0) {
-		irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3");
-		if (irq == -EPROBE_DEFER)
-			return irq;
-
-		if (irq <= 0) {
-			irq = platform_get_irq(dwc3_pdev, 0);
-			if (irq <= 0) {
-				if (irq != -EPROBE_DEFER) {
-					dev_err(dwc->dev,
-						"missing host IRQ\n");
-				}
-				if (!irq)
-					irq = -EINVAL;
-				return irq;
-			} else {
-				res = platform_get_resource(dwc3_pdev,
-							    IORESOURCE_IRQ, 0);
-			}
-		} else {
-			res = platform_get_resource_byname(dwc3_pdev,
-							   IORESOURCE_IRQ,
-							   "dwc_usb3");
-		}
-
-	} else {
+	res = platform_get_resource_byname(dwc3_pdev, IORESOURCE_IRQ, "host");
+	if (!res)
 		res = platform_get_resource_byname(dwc3_pdev, IORESOURCE_IRQ,
-						   "host");
-	}
+				"dwc_usb3");
+	if (!res)
+		res = platform_get_resource(dwc3_pdev, IORESOURCE_IRQ, 0);
+	if (!res)
+		return -ENOMEM;
 
 	dwc->xhci_resources[1].start = irq;
 	dwc->xhci_resources[1].end = irq;
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 32aa45e..b0c4f12 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1535,6 +1535,9 @@
 				t2 |= PORT_WKOC_E | PORT_WKCONN_E;
 				t2 &= ~PORT_WKDISC_E;
 			}
+			if ((xhci->quirks & XHCI_U2_DISABLE_WAKE) &&
+			    (hcd->speed < HCD_USB3))
+				t2 &= ~PORT_WAKE_BITS;
 		} else
 			t2 &= ~PORT_WAKE_BITS;
 
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 69864ba..672751e 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -54,6 +54,11 @@
 #define PCI_DEVICE_ID_INTEL_APL_XHCI			0x5aa8
 #define PCI_DEVICE_ID_INTEL_DNV_XHCI			0x19d0
 
+#define PCI_DEVICE_ID_AMD_PROMONTORYA_4			0x43b9
+#define PCI_DEVICE_ID_AMD_PROMONTORYA_3			0x43ba
+#define PCI_DEVICE_ID_AMD_PROMONTORYA_2			0x43bb
+#define PCI_DEVICE_ID_AMD_PROMONTORYA_1			0x43bc
+
 static const char hcd_name[] = "xhci_hcd";
 
 static struct hc_driver __read_mostly xhci_pci_hc_driver;
@@ -135,6 +140,13 @@
 	if (pdev->vendor == PCI_VENDOR_ID_AMD)
 		xhci->quirks |= XHCI_TRUST_TX_LENGTH;
 
+	if ((pdev->vendor == PCI_VENDOR_ID_AMD) &&
+		((pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4) ||
+		(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_3) ||
+		(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_2) ||
+		(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_1)))
+		xhci->quirks |= XHCI_U2_DISABLE_WAKE;
+
 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
 		xhci->quirks |= XHCI_LPM_SUPPORT;
 		xhci->quirks |= XHCI_INTEL_HOST;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 86d578e..3a7fb29 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1668,6 +1668,7 @@
 /* For controller with a broken Port Disable implementation */
 #define XHCI_BROKEN_PORT_PED	(1 << 25)
 #define XHCI_LIMIT_ENDPOINT_INTERVAL_7	(1 << 26)
+#define XHCI_U2_DISABLE_WAKE	(1 << 27)
 
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 2682d29..f232f2d 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -182,7 +182,7 @@
 #define PS_HARD_RESET_TIME	25
 #define PS_SOURCE_ON		400
 #define PS_SOURCE_OFF		750
-#define SWAP_SOURCE_START_TIME	20
+#define FIRST_SOURCE_CAP_TIME	200
 #define VDM_BUSY_TIME		50
 #define VCONN_ON_TIME		100
 
@@ -796,17 +796,27 @@
 			pd->pd_phy_opened = true;
 		}
 
-		pd->current_state = PE_SRC_SEND_CAPABILITIES;
 		if (pd->in_pr_swap) {
-			kick_sm(pd, SWAP_SOURCE_START_TIME);
 			pd->in_pr_swap = false;
 			val.intval = 0;
 			power_supply_set_property(pd->usb_psy,
 					POWER_SUPPLY_PROP_PR_SWAP, &val);
-			break;
 		}
 
-		/* fall-through */
+		/*
+		 * A sink might remove its terminations (during some Type-C
+		 * compliance tests or a sink attempting to do Try.SRC)
+		 * at this point just after we enabled VBUS. Sending PD
+		 * messages now would delay detecting the detach beyond the
+		 * required timing. Instead, delay sending out the first
+		 * source capabilities to allow for the other side to
+		 * completely settle CC debounce and allow HW to detect detach
+		 * sooner in the meantime. PD spec allows up to
+		 * tFirstSourceCap (250ms).
+		 */
+		pd->current_state = PE_SRC_SEND_CAPABILITIES;
+		kick_sm(pd, FIRST_SOURCE_CAP_TIME);
+		break;
 
 	case PE_SRC_SEND_CAPABILITIES:
 		kick_sm(pd, 0);
diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c
index 1210188e..675e50e 100644
--- a/drivers/usb/phy/phy-msm-qusb-v2.c
+++ b/drivers/usb/phy/phy-msm-qusb-v2.c
@@ -27,29 +27,23 @@
 #include <linux/usb/phy.h>
 #include <linux/reset.h>
 
-#define QUSB2PHY_PWR_CTRL1		0x210
+/* QUSB2PHY_PWR_CTRL1 register related bits */
 #define PWR_CTRL1_POWR_DOWN		BIT(0)
 
-#define QUSB2PHY_PLL_COMMON_STATUS_ONE	0x1A0
+/* QUSB2PHY_PLL_COMMON_STATUS_ONE register related bits */
 #define CORE_READY_STATUS		BIT(0)
 
 /* Get TUNE value from efuse bit-mask */
 #define TUNE_VAL_MASK(val, pos, mask)	((val >> pos) & mask)
 
-#define QUSB2PHY_INTR_CTRL		0x22C
+/* QUSB2PHY_INTR_CTRL register related bits */
 #define DMSE_INTR_HIGH_SEL              BIT(4)
 #define DPSE_INTR_HIGH_SEL              BIT(3)
 #define CHG_DET_INTR_EN                 BIT(2)
 #define DMSE_INTR_EN                    BIT(1)
 #define DPSE_INTR_EN                    BIT(0)
 
-#define QUSB2PHY_INTR_STAT		0x230
-#define DMSE_INTERRUPT			BIT(1)
-#define DPSE_INTERRUPT			BIT(0)
-
-#define QUSB2PHY_PORT_TUNE1		0x23c
-
-#define QUSB2PHY_PLL_CORE_INPUT_OVERRIDE 0x0a8
+/* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE register related bits */
 #define CORE_PLL_RATE			BIT(0)
 #define CORE_PLL_RATE_MUX		BIT(1)
 #define CORE_PLL_EN			BIT(2)
@@ -73,6 +67,16 @@
 module_param(phy_tune1, uint, 0644);
 MODULE_PARM_DESC(phy_tune1, "QUSB PHY v2 TUNE1");
 
+enum qusb_phy_reg {
+	PORT_TUNE1,
+	PLL_COMMON_STATUS_ONE,
+	PWR_CTRL1,
+	INTR_CTRL,
+	PLL_CORE_INPUT_OVERRIDE,
+	TEST1,
+	USB2_PHY_REG_MAX,
+};
+
 struct qusb_phy {
 	struct usb_phy		phy;
 	void __iomem		*base;
@@ -92,8 +96,10 @@
 	int			host_init_seq_len;
 	int			*qusb_phy_host_init_seq;
 
+	unsigned int		*phy_reg;
+	int			qusb_phy_reg_offset_cnt;
+
 	u32			tune_val;
-	u32			phy_auto_resume_offset;
 	int			efuse_bit_pos;
 	int			efuse_num_of_bits;
 
@@ -316,7 +322,7 @@
 
 	qphy->tune_val = TUNE_VAL_MASK(qphy->tune_val,
 				qphy->efuse_bit_pos, bit_mask);
-	reg = readb_relaxed(qphy->base + QUSB2PHY_PORT_TUNE1);
+	reg = readb_relaxed(qphy->base + qphy->phy_reg[PORT_TUNE1]);
 	if (qphy->tune_val) {
 		reg = reg & 0x0f;
 		reg |= (qphy->tune_val << 4);
@@ -372,7 +378,7 @@
 	/* Require to get phy pll lock successfully */
 	usleep_range(150, 160);
 
-	reg = readb_relaxed(qphy->base + QUSB2PHY_PLL_COMMON_STATUS_ONE);
+	reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]);
 	dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
 	if (!(reg & CORE_READY_STATUS)) {
 		dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
@@ -421,9 +427,9 @@
 	}
 
 	/* Disable the PHY */
-	writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) |
+	writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) |
 			PWR_CTRL1_POWR_DOWN,
-			qphy->base + QUSB2PHY_PWR_CTRL1);
+			qphy->base + qphy->phy_reg[PWR_CTRL1]);
 
 	if (qphy->qusb_phy_init_seq)
 		qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq,
@@ -435,7 +441,7 @@
 		pr_debug("%s(): Programming TUNE1 parameter as:%x\n", __func__,
 				qphy->tune_val);
 		writel_relaxed(qphy->tune_val,
-				qphy->base + QUSB2PHY_PORT_TUNE1);
+				qphy->base + qphy->phy_reg[PORT_TUNE1]);
 	}
 
 	/* If phy_tune1 modparam set, override tune1 value */
@@ -443,16 +449,16 @@
 		pr_debug("%s(): (modparam) TUNE1 val:0x%02x\n",
 						__func__, phy_tune1);
 		writel_relaxed(phy_tune1,
-				qphy->base + QUSB2PHY_PORT_TUNE1);
+				qphy->base + qphy->phy_reg[PORT_TUNE1]);
 	}
 
 	/* ensure above writes are completed before re-enabling PHY */
 	wmb();
 
 	/* Enable the PHY */
-	writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) &
+	writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) &
 			~PWR_CTRL1_POWR_DOWN,
-			qphy->base + QUSB2PHY_PWR_CTRL1);
+			qphy->base + qphy->phy_reg[PWR_CTRL1]);
 
 	/* Ensure above write is completed before turning ON ref clk */
 	wmb();
@@ -460,7 +466,7 @@
 	/* Require to get phy pll lock successfully */
 	usleep_range(150, 160);
 
-	reg = readb_relaxed(qphy->base + QUSB2PHY_PLL_COMMON_STATUS_ONE);
+	reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]);
 	dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
 	if (!(reg & CORE_READY_STATUS)) {
 		dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
@@ -478,9 +484,9 @@
 	qusb_phy_enable_clocks(qphy, true);
 
 	/* Disable the PHY */
-	writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) |
+	writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) |
 			PWR_CTRL1_POWR_DOWN,
-			qphy->base + QUSB2PHY_PWR_CTRL1);
+			qphy->base + qphy->phy_reg[PWR_CTRL1]);
 
 	/* Makes sure that above write goes through */
 	wmb();
@@ -525,7 +531,7 @@
 			(qphy->phy.flags & PHY_HOST_MODE)) {
 			/* Disable all interrupts */
 			writel_relaxed(0x00,
-				qphy->base + QUSB2PHY_INTR_CTRL);
+				qphy->base + qphy->phy_reg[INTR_CTRL]);
 
 			linestate = qusb_phy_get_linestate(qphy);
 			/*
@@ -537,29 +543,27 @@
 			 * e.g. if currently D+ high, D- low (HS 'J'/Suspend),
 			 * configure the mask to trigger on D+ low OR D- high
 			 */
-			intr_mask = DMSE_INTERRUPT | DPSE_INTERRUPT;
+			intr_mask = DPSE_INTR_EN | DMSE_INTR_EN;
 			if (!(linestate & LINESTATE_DP)) /* D+ low */
 				intr_mask |= DPSE_INTR_HIGH_SEL;
 			if (!(linestate & LINESTATE_DM)) /* D- low */
 				intr_mask |= DMSE_INTR_HIGH_SEL;
 
 			writel_relaxed(intr_mask,
-				qphy->base + QUSB2PHY_INTR_CTRL);
+				qphy->base + qphy->phy_reg[INTR_CTRL]);
 
 			/* hold core PLL into reset */
 			writel_relaxed(CORE_PLL_EN_FROM_RESET |
 				CORE_RESET | CORE_RESET_MUX,
-				qphy->base + QUSB2PHY_PLL_CORE_INPUT_OVERRIDE);
+				qphy->base +
+				qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
 
-			if (qphy->phy_auto_resume_offset) {
-				/* enable phy auto-resume */
-				writel_relaxed(0x91,
-				qphy->base + qphy->phy_auto_resume_offset);
-				/* flush the previous write before next write */
-				wmb();
-				writel_relaxed(0x90,
-				qphy->base + qphy->phy_auto_resume_offset);
-			}
+			/* enable phy auto-resume */
+			writel_relaxed(0x91, qphy->base + qphy->phy_reg[TEST1]);
+			/* flush the previous write before next write */
+			wmb();
+			writel_relaxed(0x90, qphy->base + qphy->phy_reg[TEST1]);
+
 			dev_dbg(phy->dev, "%s: intr_mask = %x\n",
 			__func__, intr_mask);
 
@@ -569,7 +573,7 @@
 		} else { /* Cable disconnect case */
 			/* Disable all interrupts */
 			writel_relaxed(0x00,
-				qphy->base + QUSB2PHY_INTR_CTRL);
+				qphy->base + qphy->phy_reg[INTR_CTRL]);
 			qusb_phy_reset(qphy);
 			qusb_phy_enable_clocks(qphy, false);
 			qusb_phy_enable_power(qphy, false, true);
@@ -582,11 +586,11 @@
 			qusb_phy_enable_clocks(qphy, true);
 			/* Clear all interrupts on resume */
 			writel_relaxed(0x00,
-				qphy->base + QUSB2PHY_INTR_CTRL);
+				qphy->base + qphy->phy_reg[INTR_CTRL]);
 
 			/* bring core PLL out of reset */
-			writel_relaxed(CORE_PLL_EN_FROM_RESET,
-				qphy->base + QUSB2PHY_PLL_CORE_INPUT_OVERRIDE);
+			writel_relaxed(CORE_PLL_EN_FROM_RESET, qphy->base +
+				qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
 
 			/* Makes sure that above write goes through */
 			wmb();
@@ -870,6 +874,31 @@
 	}
 
 	size = 0;
+	of_get_property(dev->of_node, "qcom,qusb-phy-reg-offset", &size);
+	if (size) {
+		qphy->phy_reg = devm_kzalloc(dev, size, GFP_KERNEL);
+		if (qphy->phy_reg) {
+			qphy->qusb_phy_reg_offset_cnt =
+				size / sizeof(*qphy->phy_reg);
+			if (qphy->qusb_phy_reg_offset_cnt > USB2_PHY_REG_MAX) {
+				dev_err(dev, "invalid reg offset count\n");
+				return -EINVAL;
+			}
+
+			of_property_read_u32_array(dev->of_node,
+					"qcom,qusb-phy-reg-offset",
+					qphy->phy_reg,
+					qphy->qusb_phy_reg_offset_cnt);
+		} else {
+			dev_err(dev, "err mem alloc for qusb_phy_reg_offset\n");
+			return -ENOMEM;
+		}
+	} else {
+		dev_err(dev, "err provide qcom,qmp-phy-reg-offset\n");
+		return -EINVAL;
+	}
+
+	size = 0;
 	of_get_property(dev->of_node, "qcom,qusb-phy-init-seq", &size);
 	if (size) {
 		qphy->qusb_phy_init_seq = devm_kzalloc(dev,
@@ -917,12 +946,6 @@
 		return ret;
 	}
 
-	ret = of_property_read_u32(dev->of_node, "qcom,phy-auto-resume-offset",
-			&qphy->phy_auto_resume_offset);
-	if (ret)
-		dev_dbg(dev, "error reading qcom,phy-auto-resume-offset %d\n",
-				ret);
-
 	qphy->vdd = devm_regulator_get(dev, "vdd");
 	if (IS_ERR(qphy->vdd)) {
 		dev_err(dev, "unable to get vdd supply\n");
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 8bb4875..84b444f 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -135,6 +135,7 @@
 	{ USB_DEVICE(0x10C4, 0x8977) },	/* CEL MeshWorks DevKit Device */
 	{ USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */
 	{ USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */
+	{ USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 3bf61ac..ebe51f11 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1877,6 +1877,10 @@
 	  .driver_info = (kernel_ulong_t)&four_g_w100_blacklist
 	},
 	{ USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, SPEEDUP_PRODUCT_SU9800, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9801, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+	{ USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9803, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
 	{ USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
 	{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index fd509ed6c..652b433 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -158,6 +158,7 @@
 	{DEVICE_SWI(0x1199, 0x9056)},	/* Sierra Wireless Modem */
 	{DEVICE_SWI(0x1199, 0x9060)},	/* Sierra Wireless Modem */
 	{DEVICE_SWI(0x1199, 0x9061)},	/* Sierra Wireless Modem */
+	{DEVICE_SWI(0x1199, 0x9063)},	/* Sierra Wireless EM7305 */
 	{DEVICE_SWI(0x1199, 0x9070)},	/* Sierra Wireless MC74xx */
 	{DEVICE_SWI(0x1199, 0x9071)},	/* Sierra Wireless MC74xx */
 	{DEVICE_SWI(0x1199, 0x9078)},	/* Sierra Wireless EM74xx */
diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c
index 44ab43f..af10f7b 100644
--- a/drivers/usb/usbip/stub_main.c
+++ b/drivers/usb/usbip/stub_main.c
@@ -262,7 +262,11 @@
 		kmem_cache_free(stub_priv_cache, priv);
 
 		kfree(urb->transfer_buffer);
+		urb->transfer_buffer = NULL;
+
 		kfree(urb->setup_packet);
+		urb->setup_packet = NULL;
+
 		usb_free_urb(urb);
 	}
 }
diff --git a/drivers/usb/usbip/stub_tx.c b/drivers/usb/usbip/stub_tx.c
index 6b1e8c3..be50cef 100644
--- a/drivers/usb/usbip/stub_tx.c
+++ b/drivers/usb/usbip/stub_tx.c
@@ -28,7 +28,11 @@
 	struct urb *urb = priv->urb;
 
 	kfree(urb->setup_packet);
+	urb->setup_packet = NULL;
+
 	kfree(urb->transfer_buffer);
+	urb->transfer_buffer = NULL;
+
 	list_del(&priv->list);
 	kmem_cache_free(stub_priv_cache, priv);
 	usb_free_urb(urb);
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 1afa111..aca0d88 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -315,7 +315,7 @@
 	struct ceph_mds_client *mdsc = fsc->mdsc;
 	int i;
 	int err;
-	u32 ftype;
+	unsigned frag = -1;
 	struct ceph_mds_reply_info_parsed *rinfo;
 
 	dout("readdir %p file %p pos %llx\n", inode, file, ctx->pos);
@@ -362,7 +362,6 @@
 	/* do we have the correct frag content buffered? */
 	if (need_send_readdir(fi, ctx->pos)) {
 		struct ceph_mds_request *req;
-		unsigned frag;
 		int op = ceph_snap(inode) == CEPH_SNAPDIR ?
 			CEPH_MDS_OP_LSSNAP : CEPH_MDS_OP_READDIR;
 
@@ -373,8 +372,11 @@
 		}
 
 		if (is_hash_order(ctx->pos)) {
-			frag = ceph_choose_frag(ci, fpos_hash(ctx->pos),
-						NULL, NULL);
+			/* fragtree isn't always accurate. choose frag
+			 * based on previous reply when possible. */
+			if (frag == (unsigned)-1)
+				frag = ceph_choose_frag(ci, fpos_hash(ctx->pos),
+							NULL, NULL);
 		} else {
 			frag = fpos_frag(ctx->pos);
 		}
@@ -497,6 +499,7 @@
 		struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i;
 		struct ceph_vino vino;
 		ino_t ino;
+		u32 ftype;
 
 		BUG_ON(rde->offset < ctx->pos);
 
@@ -519,15 +522,17 @@
 		ctx->pos++;
 	}
 
+	ceph_mdsc_put_request(fi->last_readdir);
+	fi->last_readdir = NULL;
+
 	if (fi->next_offset > 2) {
-		ceph_mdsc_put_request(fi->last_readdir);
-		fi->last_readdir = NULL;
+		frag = fi->frag;
 		goto more;
 	}
 
 	/* more frags? */
 	if (!ceph_frag_is_rightmost(fi->frag)) {
-		unsigned frag = ceph_frag_next(fi->frag);
+		frag = ceph_frag_next(fi->frag);
 		if (is_hash_order(ctx->pos)) {
 			loff_t new_pos = ceph_make_fpos(ceph_frag_value(frag),
 							fi->next_offset, true);
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 350a2c8..1493ceb 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -741,16 +741,10 @@
 	 * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
 	 * is defined as O_NONBLOCK on some platforms and not on others.
 	 */
-	BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
-		O_RDONLY	| O_WRONLY	| O_RDWR	|
-		O_CREAT		| O_EXCL	| O_NOCTTY	|
-		O_TRUNC		| O_APPEND	| /* O_NONBLOCK	| */
-		__O_SYNC	| O_DSYNC	| FASYNC	|
-		O_DIRECT	| O_LARGEFILE	| O_DIRECTORY	|
-		O_NOFOLLOW	| O_NOATIME	| O_CLOEXEC	|
-		__FMODE_EXEC	| O_PATH	| __O_TMPFILE	|
-		__FMODE_NONOTIFY
-		));
+	BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
+		HWEIGHT32(
+			(VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
+			__FMODE_EXEC | __FMODE_NONOTIFY));
 
 	fasync_cache = kmem_cache_create("fasync_cache",
 		sizeof(struct fasync_struct), 0, SLAB_PANIC, NULL);
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 6528724..7bff6f4 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -80,9 +80,9 @@
 
 static struct rhashtable gl_hash_table;
 
-void gfs2_glock_free(struct gfs2_glock *gl)
+static void gfs2_glock_dealloc(struct rcu_head *rcu)
 {
-	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+	struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);
 
 	if (gl->gl_ops->go_flags & GLOF_ASPACE) {
 		kmem_cache_free(gfs2_glock_aspace_cachep, gl);
@@ -90,6 +90,13 @@
 		kfree(gl->gl_lksb.sb_lvbptr);
 		kmem_cache_free(gfs2_glock_cachep, gl);
 	}
+}
+
+void gfs2_glock_free(struct gfs2_glock *gl)
+{
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+
+	call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
 	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
 		wake_up(&sdp->sd_glock_wait);
 }
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 51519c2..a04bf95 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -370,6 +370,7 @@
 			loff_t end;
 		} gl_vm;
 	};
+	struct rcu_head gl_rcu;
 	struct rhash_head gl_node;
 };
 
diff --git a/fs/open.c b/fs/open.c
index 568749b..73b7d19 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -915,6 +915,12 @@
 	int lookup_flags = 0;
 	int acc_mode = ACC_MODE(flags);
 
+	/*
+	 * Clear out all open flags we don't know about so that we don't report
+	 * them in fcntl(F_GETFD) or similar interfaces.
+	 */
+	flags &= VALID_OPEN_FLAGS;
+
 	if (flags & (O_CREAT | __O_TMPFILE))
 		op->mode = (mode & S_IALLUGO) | S_IFREG;
 	else
diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c
index 3c5b51d..80825b2 100644
--- a/fs/sdcardfs/main.c
+++ b/fs/sdcardfs/main.c
@@ -364,41 +364,34 @@
 	return err;
 }
 
-/* A feature which supports mount_nodev() with options */
-static struct dentry *mount_nodev_with_options(struct vfsmount *mnt,
-			struct file_system_type *fs_type, int flags,
-			const char *dev_name, void *data,
-			int (*fill_super)(struct vfsmount *, struct super_block *,
-						const char *, void *, int))
+struct sdcardfs_mount_private {
+	struct vfsmount *mnt;
+	const char *dev_name;
+	void *raw_data;
+};
 
+static int __sdcardfs_fill_super(
+	struct super_block *sb,
+	void *_priv, int silent)
 {
-	int error;
-	struct super_block *s = sget(fs_type, NULL, set_anon_super, flags, NULL);
+	struct sdcardfs_mount_private *priv = _priv;
 
-	if (IS_ERR(s))
-		return ERR_CAST(s);
-
-	s->s_flags = flags;
-
-	error = fill_super(mnt, s, dev_name, data, flags & MS_SILENT ? 1 : 0);
-	if (error) {
-		deactivate_locked_super(s);
-		return ERR_PTR(error);
-	}
-	s->s_flags |= MS_ACTIVE;
-	return dget(s->s_root);
+	return sdcardfs_read_super(priv->mnt,
+		sb, priv->dev_name, priv->raw_data, silent);
 }
 
 static struct dentry *sdcardfs_mount(struct vfsmount *mnt,
 		struct file_system_type *fs_type, int flags,
 			    const char *dev_name, void *raw_data)
 {
-	/*
-	 * dev_name is a lower_path_name,
-	 * raw_data is a option string.
-	 */
-	return mount_nodev_with_options(mnt, fs_type, flags, dev_name,
-						raw_data, sdcardfs_read_super);
+	struct sdcardfs_mount_private priv = {
+		.mnt = mnt,
+		.dev_name = dev_name,
+		.raw_data = raw_data
+	};
+
+	return mount_nodev(fs_type, flags,
+		&priv, __sdcardfs_fill_super);
 }
 
 static struct dentry *sdcardfs_mount_wrn(struct file_system_type *fs_type,
@@ -423,7 +416,7 @@
 		list_del(&sbi->list);
 		mutex_unlock(&sdcardfs_super_list_lock);
 	}
-	generic_shutdown_super(sb);
+	kill_anon_super(sb);
 }
 
 static struct file_system_type sdcardfs_fs_type = {
diff --git a/include/dt-bindings/msm/msm-bus-ids.h b/include/dt-bindings/msm/msm-bus-ids.h
index 8bd30d4..bc87beb 100644
--- a/include/dt-bindings/msm/msm-bus-ids.h
+++ b/include/dt-bindings/msm/msm-bus-ids.h
@@ -250,7 +250,8 @@
 #define	MSM_BUS_MASTER_CAMNOC_HF0_UNCOMP 146
 #define	MSM_BUS_MASTER_CAMNOC_HF1_UNCOMP 147
 #define	MSM_BUS_MASTER_CAMNOC_SF_UNCOMP 148
-#define	MSM_BUS_MASTER_MASTER_LAST 149
+#define	MSM_BUS_MASTER_GIC 149
+#define	MSM_BUS_MASTER_MASTER_LAST 150
 
 #define MSM_BUS_MASTER_LLCC_DISPLAY 20000
 #define MSM_BUS_MASTER_MNOC_HF_MEM_NOC_DISPLAY 20001
@@ -330,7 +331,8 @@
 #define	MSM_BUS_A2NOC_SNOC_SLV 10065
 #define	MSM_BUS_SNOC_INT_2 10066
 #define	MSM_BUS_A0NOC_QDSS_INT	10067
-#define	MSM_BUS_INT_LAST 10068
+#define MSM_BUS_SLAVE_ANOC_PCIE_A1NOC_SNOC 10068
+#define	MSM_BUS_INT_LAST 10069
 
 #define	MSM_BUS_INT_TEST_ID	20000
 #define	MSM_BUS_INT_TEST_LAST	20050
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 76ce329..1b48d9c 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -3,6 +3,12 @@
 
 #include <uapi/linux/fcntl.h>
 
+/* list of all valid flags for the open/openat flags argument: */
+#define VALID_OPEN_FLAGS \
+	(O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \
+	 O_APPEND | O_NDELAY | O_NONBLOCK | O_NDELAY | __O_SYNC | O_DSYNC | \
+	 FASYNC	| O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \
+	 O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE)
 
 #ifndef force_o_largefile
 #define force_o_largefile() (BITS_PER_LONG != 32)
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index 0668534..6e664f6 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -40,6 +40,14 @@
 };
 
 /**
+* enum ipa_ipv6ct_en_type - IPv6CT setting type in IPA end-point
+*/
+enum ipa_ipv6ct_en_type {
+	IPA_BYPASS_IPV6CT,
+	IPA_ENABLE_IPV6CT,
+};
+
+/**
  * enum ipa_mode_type - mode setting type in IPA end-point
  * @BASIC: basic mode
  * @ENABLE_FRAMING_HDLC: not currently supported
@@ -119,6 +127,19 @@
 };
 
 /**
+ * struct ipa_ep_cfg_conn_track - IPv6 Connection tracking configuration in
+ *	IPA end-point
+ * @conn_track_en: Defines speculative conn_track action, means if specific
+ *		   pipe needs to have UL/DL IPv6 Connection Tracking or Bybass
+ *		   IPv6 Connection Tracking. 0: Bypass IPv6 Connection Tracking
+ *					     1: IPv6 UL/DL Connection Tracking.
+ *		  Valid for Input Pipes only (IPA consumer)
+ */
+struct ipa_ep_cfg_conn_track {
+	enum ipa_ipv6ct_en_type conn_track_en;
+};
+
+/**
  * struct ipa_ep_cfg_hdr - header configuration in IPA end-point
  *
  * @hdr_len:Header length in bytes to be added/removed. Assuming
@@ -387,6 +408,7 @@
 /**
  * struct ipa_ep_cfg - configuration of IPA end-point
  * @nat:		NAT parmeters
+ * @conn_track:		IPv6CT parmeters
  * @hdr:		Header parameters
  * @hdr_ext:		Extended header parameters
  * @mode:		Mode parameters
@@ -400,6 +422,7 @@
  */
 struct ipa_ep_cfg {
 	struct ipa_ep_cfg_nat nat;
+	struct ipa_ep_cfg_conn_track conn_track;
 	struct ipa_ep_cfg_hdr hdr;
 	struct ipa_ep_cfg_hdr_ext hdr_ext;
 	struct ipa_ep_cfg_mode mode;
@@ -1172,6 +1195,9 @@
 
 int ipa_cfg_ep_nat(u32 clnt_hdl, const struct ipa_ep_cfg_nat *ipa_ep_cfg);
 
+int ipa_cfg_ep_conn_track(u32 clnt_hdl,
+	const struct ipa_ep_cfg_conn_track *ep_conn_track);
+
 int ipa_cfg_ep_hdr(u32 clnt_hdl, const struct ipa_ep_cfg_hdr *ipa_ep_cfg);
 
 int ipa_cfg_ep_hdr_ext(u32 clnt_hdl,
@@ -1558,6 +1584,12 @@
 	return -EPERM;
 }
 
+static inline int ipa_cfg_ep_conn_track(u32 clnt_hdl,
+	const struct ipa_ep_cfg_conn_track *ep_conn_track)
+{
+	return -EPERM
+}
+
 static inline int ipa_cfg_ep_hdr(u32 clnt_hdl,
 		const struct ipa_ep_cfg_hdr *ipa_ep_cfg)
 {
diff --git a/include/linux/mailbox_client.h b/include/linux/mailbox_client.h
index 78f01ea..86a2dc6 100644
--- a/include/linux/mailbox_client.h
+++ b/include/linux/mailbox_client.h
@@ -49,5 +49,6 @@
 bool mbox_client_peek_data(struct mbox_chan *chan); /* atomic */
 void mbox_free_channel(struct mbox_chan *chan); /* may sleep */
 bool mbox_controller_is_idle(struct mbox_chan *chan); /* atomic */
+void mbox_chan_debug(struct mbox_chan *chan);
 
 #endif /* __MAILBOX_CLIENT_H */
diff --git a/include/linux/mailbox_controller.h b/include/linux/mailbox_controller.h
index 30a4ed2..7827c68 100644
--- a/include/linux/mailbox_controller.h
+++ b/include/linux/mailbox_controller.h
@@ -49,6 +49,8 @@
  *		  Used only if txdone_poll:=true && txdone_irq:=false
  * @peek_data: Atomic check for any received data. Return true if controller
  *		  has some data to push to the client. False otherwise.
+ * @debug:	Allow chan to be debugged when the client detects a channel is
+ * 		locked up.
  */
 struct mbox_chan_ops {
 	int (*send_data)(struct mbox_chan *chan, void *data);
@@ -90,6 +92,7 @@
 	struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox,
 				      const struct of_phandle_args *sp);
 	bool (*is_idle)(struct mbox_controller *mbox);
+	void (*debug)(struct mbox_chan *chan);
 	/* Internal to API */
 	struct hrtimer poll_hrt;
 	struct list_head node;
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index d6ebc01..37e5178 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -415,6 +415,11 @@
 	for (idx = 0, rgn = &memblock_type->regions[0];			\
 	     idx < memblock_type->cnt;					\
 	     idx++, rgn = &memblock_type->regions[idx])
+#define for_each_memblock_rev(memblock_type, region)	\
+	for (region = memblock.memblock_type.regions + \
+			memblock.memblock_type.cnt - 1;	\
+	     region >= memblock.memblock_type.regions;	\
+	     region--)
 
 #ifdef CONFIG_MEMTEST
 extern void early_memtest(phys_addr_t start, phys_addr_t end);
diff --git a/include/linux/restart_block.h b/include/linux/restart_block.h
new file mode 100644
index 0000000..0d905d8
--- /dev/null
+++ b/include/linux/restart_block.h
@@ -0,0 +1,51 @@
+/*
+ * Common syscall restarting data
+ */
+#ifndef __LINUX_RESTART_BLOCK_H
+#define __LINUX_RESTART_BLOCK_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+struct timespec;
+struct compat_timespec;
+struct pollfd;
+
+/*
+ * System call restart block.
+ */
+struct restart_block {
+	long (*fn)(struct restart_block *);
+	union {
+		/* For futex_wait and futex_wait_requeue_pi */
+		struct {
+			u32 __user *uaddr;
+			u32 val;
+			u32 flags;
+			u32 bitset;
+			u64 time;
+			u32 __user *uaddr2;
+		} futex;
+		/* For nanosleep */
+		struct {
+			clockid_t clockid;
+			struct timespec __user *rmtp;
+#ifdef CONFIG_COMPAT
+			struct compat_timespec __user *compat_rmtp;
+#endif
+			u64 expires;
+		} nanosleep;
+		/* For poll */
+		struct {
+			struct pollfd __user *ufds;
+			int nfds;
+			int has_timeout;
+			unsigned long tv_sec;
+			unsigned long tv_nsec;
+		} poll;
+	};
+};
+
+extern long do_no_restart_syscall(struct restart_block *parm);
+
+#endif /* __LINUX_RESTART_BLOCK_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 864c7d7..ff65b44 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1499,6 +1499,7 @@
 	 */
 	u64 mark_start;
 	u32 sum, demand;
+	u32 coloc_demand;
 	u32 sum_history[RAVG_HIST_SIZE_MAX];
 	u32 *curr_window_cpu, *prev_window_cpu;
 	u32 curr_window, prev_window;
diff --git a/include/linux/seemp_instrumentation.h b/include/linux/seemp_instrumentation.h
index 21bc436..ff09bd2 100644
--- a/include/linux/seemp_instrumentation.h
+++ b/include/linux/seemp_instrumentation.h
@@ -15,6 +15,8 @@
 
 #ifdef CONFIG_SEEMP_CORE
 #include <linux/kernel.h>
+#include <linux/seemp_api.h>
+#include <linux/socket.h>
 
 #define MAX_BUF_SIZE 188
 
@@ -66,11 +68,33 @@
 
 	seemp_logk_kernel_end(blck);
 }
+
+static inline void seemp_logk_rtic(__u8 type, __u64 actor, __u8 asset_id[0x20],
+		__u8 asset_category, __u8 response)
+{
+	char *buf = NULL;
+	void *blck = NULL;
+
+	blck = seemp_setup_buf(&buf);
+	if (!blck)
+		return;
+
+	SEEMP_LOGK_RECORD(SEEMP_API_kernel__rtic,
+		"app_pid=%llu,rtic_type=%u,asset_id=%s,asset_category=%u,response=%u",
+		actor, type, asset_id, asset_category, response);
+
+	seemp_logk_kernel_end(blck);
+}
 #else
 static inline void seemp_logk_sendto(int fd, void __user *buff,
 		size_t len, unsigned int flags, struct sockaddr __user *addr,
 		int addr_len)
 {
 }
+
+static inline void seemp_logk_rtic(__u8 type, __u64 actor, __u8 asset_id[0x20],
+		__u8 asset_category, __u8 response)
+{
+}
 #endif
 #endif
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index 2873baf..5837387 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -9,51 +9,18 @@
 
 #include <linux/types.h>
 #include <linux/bug.h>
-
-struct timespec;
-struct compat_timespec;
+#include <linux/restart_block.h>
 
 #ifdef CONFIG_THREAD_INFO_IN_TASK
+/*
+ * For CONFIG_THREAD_INFO_IN_TASK kernels we need <asm/current.h> for the
+ * definition of current, but for !CONFIG_THREAD_INFO_IN_TASK kernels,
+ * including <asm/current.h> can cause a circular dependency on some platforms.
+ */
+#include <asm/current.h>
 #define current_thread_info() ((struct thread_info *)current)
 #endif
 
-/*
- * System call restart block.
- */
-struct restart_block {
-	long (*fn)(struct restart_block *);
-	union {
-		/* For futex_wait and futex_wait_requeue_pi */
-		struct {
-			u32 __user *uaddr;
-			u32 val;
-			u32 flags;
-			u32 bitset;
-			u64 time;
-			u32 __user *uaddr2;
-		} futex;
-		/* For nanosleep */
-		struct {
-			clockid_t clockid;
-			struct timespec __user *rmtp;
-#ifdef CONFIG_COMPAT
-			struct compat_timespec __user *compat_rmtp;
-#endif
-			u64 expires;
-		} nanosleep;
-		/* For poll */
-		struct {
-			struct pollfd __user *ufds;
-			int nfds;
-			int has_timeout;
-			unsigned long tv_sec;
-			unsigned long tv_nsec;
-		} poll;
-	};
-};
-
-extern long do_no_restart_syscall(struct restart_block *parm);
-
 #include <linux/bitops.h>
 #include <asm/thread_info.h>
 
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 5c0b3fa..b305b0e 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -582,9 +582,9 @@
 	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
 
 #define EndpointRequest \
-	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8)
 #define EndpointOutRequest \
-	((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+	((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8)
 
 /* class requests from the USB 2.0 hub spec, table 11-15 */
 /* GetBusState and SetHubDescriptor are optional, omitted */
diff --git a/include/soc/qcom/secure_buffer.h b/include/soc/qcom/secure_buffer.h
index a08cfe1..6afaf67 100644
--- a/include/soc/qcom/secure_buffer.h
+++ b/include/soc/qcom/secure_buffer.h
@@ -40,6 +40,7 @@
 	VMID_CP_SPSS_SP = 0x1A,
 	VMID_CP_CAMERA_PREVIEW = 0x1D,
 	VMID_CP_SPSS_SP_SHARED = 0x22,
+	VMID_CP_SPSS_HLOS_SHARED = 0x24,
 	VMID_LAST,
 	VMID_INVAL = -1
 };
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index bf8f149..e94a82b 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -236,6 +236,7 @@
 		__field(	 int,	samples			)
 		__field(enum task_event,	evt		)
 		__field(unsigned int,	demand			)
+		__field(unsigned int,	coloc_demand		)
 		__field(unsigned int,	pred_demand		)
 		__array(	 u32,	hist, RAVG_HIST_SIZE_MAX)
 		__field(unsigned int,	nr_big_tasks		)
@@ -249,6 +250,7 @@
 		__entry->samples        = samples;
 		__entry->evt            = evt;
 		__entry->demand         = p->ravg.demand;
+		__entry->coloc_demand   = p->ravg.coloc_demand;
 		__entry->pred_demand     = p->ravg.pred_demand;
 		memcpy(__entry->hist, p->ravg.sum_history,
 					RAVG_HIST_SIZE_MAX * sizeof(u32));
@@ -256,12 +258,12 @@
 		__entry->cpu            = rq->cpu;
 	),
 
-	TP_printk("%d (%s): runtime %u samples %d event %s demand %u pred_demand %u"
+	TP_printk("%d (%s): runtime %u samples %d event %s demand %u coloc_demand %u pred_demand %u"
 		" (hist: %u %u %u %u %u) cpu %d nr_big %u",
 		__entry->pid, __entry->comm,
 		__entry->runtime, __entry->samples,
 		task_event_names[__entry->evt],
-		__entry->demand, __entry->pred_demand,
+		__entry->demand, __entry->coloc_demand, __entry->pred_demand,
 		__entry->hist[0], __entry->hist[1],
 		__entry->hist[2], __entry->hist[3],
 		__entry->hist[4], __entry->cpu, __entry->nr_big_tasks)
@@ -317,6 +319,7 @@
 		__field(	u64,	irqtime			)
 		__field(enum task_event,	evt		)
 		__field(unsigned int,	demand			)
+		__field(unsigned int,	coloc_demand		)
 		__field(unsigned int,	sum			)
 		__field(	 int,	cpu			)
 		__field(unsigned int,	pred_demand		)
@@ -350,6 +353,7 @@
 		__entry->mark_start     = p->ravg.mark_start;
 		__entry->delta_m        = (wallclock - p->ravg.mark_start);
 		__entry->demand         = p->ravg.demand;
+		__entry->coloc_demand	= p->ravg.coloc_demand;
 		__entry->sum            = p->ravg.sum;
 		__entry->irqtime        = irqtime;
 		__entry->pred_demand     = p->ravg.pred_demand;
@@ -370,12 +374,12 @@
 		__entry->prev_top	= rq->prev_top;
 	),
 
-	TP_printk("wc %llu ws %llu delta %llu event %s cpu %d cur_freq %u cur_pid %d task %d (%s) ms %llu delta %llu demand %u sum %u irqtime %llu pred_demand %u rq_cs %llu rq_ps %llu cur_window %u (%s) prev_window %u (%s) nt_cs %llu nt_ps %llu active_wins %u grp_cs %lld grp_ps %lld, grp_nt_cs %llu, grp_nt_ps: %llu curr_top %u prev_top %u",
+	TP_printk("wc %llu ws %llu delta %llu event %s cpu %d cur_freq %u cur_pid %d task %d (%s) ms %llu delta %llu demand %u coloc_demand: %u sum %u irqtime %llu pred_demand %u rq_cs %llu rq_ps %llu cur_window %u (%s) prev_window %u (%s) nt_cs %llu nt_ps %llu active_wins %u grp_cs %lld grp_ps %lld, grp_nt_cs %llu, grp_nt_ps: %llu curr_top %u prev_top %u",
 		__entry->wallclock, __entry->win_start, __entry->delta,
 		task_event_names[__entry->evt], __entry->cpu,
 		__entry->cur_freq, __entry->cur_pid,
 		__entry->pid, __entry->comm, __entry->mark_start,
-		__entry->delta_m, __entry->demand,
+		__entry->delta_m, __entry->demand, __entry->coloc_demand,
 		__entry->sum, __entry->irqtime, __entry->pred_demand,
 		__entry->rq_cs, __entry->rq_ps, __entry->curr_window,
 		__window_print(p, __get_dynamic_array(curr_sum), nr_cpu_ids),
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index eb7e0c6..71c2c9e 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -322,6 +322,7 @@
 #define DRM_EVENT_AD_BACKLIGHT 0x80000001
 #define DRM_EVENT_CRTC_POWER 0x80000002
 #define DRM_EVENT_SYS_BACKLIGHT 0x80000003
+#define DRM_EVENT_SDE_POWER 0x80000004
 
 #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 7945af0..c7f2308 100644
--- a/include/uapi/drm/msm_drm_pp.h
+++ b/include/uapi/drm/msm_drm_pp.h
@@ -28,17 +28,35 @@
 
 /**
  * struct drm_msm_pcc - pcc feature structure
- * flags: for customizing operations
- * r: red coefficients.
- * g: green coefficients.
- * b: blue coefficients.
+ * @flags: for customizing operations
+ * @r: red coefficients.
+ * @g: green coefficients.
+ * @b: blue coefficients.
+ * @r_rr: second order coefficients
+ * @r_gg: second order coefficients
+ * @r_bb: second order coefficients
+ * @g_rr: second order coefficients
+ * @g_gg: second order coefficients
+ * @g_bb: second order coefficients
+ * @b_rr: second order coefficients
+ * @b_gg: second order coefficients
+ * @b_bb: second order coefficients
  */
-
+#define DRM_MSM_PCC3
 struct drm_msm_pcc {
 	__u64 flags;
 	struct drm_msm_pcc_coeff r;
 	struct drm_msm_pcc_coeff g;
 	struct drm_msm_pcc_coeff b;
+	__u32 r_rr;
+	__u32 r_gg;
+	__u32 r_bb;
+	__u32 g_rr;
+	__u32 g_gg;
+	__u32 g_bb;
+	__u32 b_rr;
+	__u32 b_gg;
+	__u32 b_bb;
 };
 
 /* struct drm_msm_pa_vlut - picture adjustment vLUT structure
@@ -135,6 +153,26 @@
 	__u32 c2[PGC_TBL_LEN];
 };
 
+#define IGC_TBL_LEN 256
+#define IGC_DITHER_ENABLE (1 << 0)
+/**
+ * struct drm_msm_igc_lut - igc lut feature structure
+ * @flags: flags for the feature customization, values can be:
+ *             - IGC_DITHER_ENABLE: Enable dither functionality
+ * @c0: color0 component lut
+ * @c1: color1 component lut
+ * @c2: color2 component lut
+ * @strength: dither strength, considered valid when IGC_DITHER_ENABLE
+ *            is set in flags. Strength value based on source bit width.
+ */
+struct drm_msm_igc_lut {
+	__u64 flags;
+	__u32 c0[IGC_TBL_LEN];
+	__u32 c1[IGC_TBL_LEN];
+	__u32 c2[IGC_TBL_LEN];
+	__u32 strength;
+};
+
 #define AD4_LUT_GRP0_SIZE 33
 #define AD4_LUT_GRP1_SIZE 32
 /*
diff --git a/include/uapi/linux/seemp_api.h b/include/uapi/linux/seemp_api.h
index 4dfc257..a42ad4b 100644
--- a/include/uapi/linux/seemp_api.h
+++ b/include/uapi/linux/seemp_api.h
@@ -1,6 +1,8 @@
 #ifndef _SEEMP_API_H_
 #define _SEEMP_API_H_
 
+#define SEEMP_API_kernel__rtic                                            100000
+
 #define SEEMP_API_kernel__oom_adjust_write                                     0
 #define SEEMP_API_kernel__sendto                                               1
 #define SEEMP_API_kernel__recvfrom                                             2
diff --git a/include/uapi/linux/seemp_param_id.h b/include/uapi/linux/seemp_param_id.h
index c72c579..d8b9f78 100644
--- a/include/uapi/linux/seemp_param_id.h
+++ b/include/uapi/linux/seemp_param_id.h
@@ -15,7 +15,11 @@
 #define PARAM_ID_SENSOR 8
 #define PARAM_ID_WINDOW_TYPE 9
 #define PARAM_ID_WINDOW_FLAG 10
-#define NUM_PARAM_IDS 11
+#define PARAM_ID_RTIC_TYPE 11
+#define PARAM_ID_RTIC_ASSET_ID 12
+#define PARAM_ID_RTIC_ASSET_CATEGORY 13
+#define PARAM_ID_RTIC_RESPONSE 14
+#define NUM_PARAM_IDS 15
 
 static inline int param_id_index(const char *param, const char *end)
 {
@@ -44,6 +48,14 @@
 		id = 9;
 	else if ((len == 11) && !memcmp(param, "window_flag", 11))
 		id = 10;
+	else if ((len == 9) && !memcmp(param, "rtic_type", 9))
+		id = 11;
+	else if ((len == 8) && !memcmp(param, "asset_id", 8))
+		id = 12;
+	else if ((len == 14) && !memcmp(param, "asset_category", 14))
+		id = 13;
+	else if ((len == 8) && !memcmp(param, "response", 8))
+		id = 14;
 
 	return id;
 }
@@ -86,6 +98,18 @@
 	case 10:
 		name = "window_flag";
 		break;
+	case 11:
+		name = "rtic_type";
+		break;
+	case 12:
+		name = "asset_id";
+		break;
+	case 13:
+		name = "asset_category";
+		break;
+	case 14:
+		name = "response";
+		break;
 	}
 	return name;
 }
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index e5c4ddf..731b2f0 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -1074,6 +1074,11 @@
 	V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED,
 };
 
+#define V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT	\
+	(V4L2_CID_MPEG_MSM_VIDC_BASE + 109)
+#define V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_10BIT \
+	(V4L2_CID_MPEG_MSM_VIDC_BASE + 110)
+
 /*  Camera class control IDs */
 
 #define V4L2_CID_CAMERA_CLASS_BASE 	(V4L2_CTRL_CLASS_CAMERA | 0x900)
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index e6c1a45..e073c5c 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -43,6 +43,10 @@
 #define V4L_EVENT_CAM_REQ_MGR_ERROR       1
 #define V4L_EVENT_CAM_REQ_MGR_MAX         2
 
+/* SOF Event status */
+#define CAM_REQ_MGR_SOF_EVENT_SUCCESS           0
+#define CAM_REQ_MGR_SOF_EVENT_ERROR             1
+
 /**
  * Request Manager : flush_type
  * @CAM_REQ_MGR_FLUSH_TYPE_ALL: Req mgr will remove all the pending
@@ -353,14 +357,18 @@
 
 /**
  * struct cam_req_mgr_frame_msg
- * @request_id: request id of frame
- * @frame_count: running count of frames
- * @timestamp: timestamp of frame
+ * @request_id: request id of the frame
+ * @frame_id: frame id of the frame
+ * @timestamp: timestamp of the frame
+ * @link_hdl: link handle associated with this message
+ * @sof_status: sof status success or fail
  */
 struct cam_req_mgr_frame_msg {
 	uint64_t request_id;
-	uint64_t frame_count;
+	uint64_t frame_id;
 	uint64_t timestamp;
+	int32_t  link_hdl;
+	uint32_t sof_status;
 };
 
 /**
diff --git a/kernel/configs/android-base.config b/kernel/configs/android-base.config
index 301e1a6..80df048 100644
--- a/kernel/configs/android-base.config
+++ b/kernel/configs/android-base.config
@@ -17,7 +17,6 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CGROUPS=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_CGROUP_DEBUG=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_CGROUP_BPF=y
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 3577ec6a..7e3dfa6 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -409,12 +409,25 @@
 	cpu_notify(CPU_ONLINE, cpu);
 	return 0;
 }
+static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st);
 
 static int bringup_wait_for_ap(unsigned int cpu)
 {
 	struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
 
+	/* Wait for the CPU to reach CPUHP_AP_ONLINE_IDLE */
 	wait_for_completion(&st->done);
+	BUG_ON(!cpu_online(cpu));
+
+	/* Unpark the stopper thread and the hotplug thread of the target cpu */
+	stop_machine_unpark(cpu);
+	kthread_unpark(st->thread);
+
+	/* Should we go further up ? */
+	if (st->target > CPUHP_AP_ONLINE_IDLE) {
+		__cpuhp_kick_ap_work(st);
+		wait_for_completion(&st->done);
+	}
 	return st->result;
 }
 
@@ -437,9 +450,7 @@
 		cpu_notify(CPU_UP_CANCELED, cpu);
 		return ret;
 	}
-	ret = bringup_wait_for_ap(cpu);
-	BUG_ON(!cpu_online(cpu));
-	return ret;
+	return bringup_wait_for_ap(cpu);
 }
 
 /*
@@ -979,31 +990,20 @@
 }
 
 /*
- * Called from the idle task. We need to set active here, so we can kick off
- * the stopper thread and unpark the smpboot threads. If the target state is
- * beyond CPUHP_AP_ONLINE_IDLE we kick cpuhp thread and let it bring up the
- * cpu further.
+ * Called from the idle task. Wake up the controlling task which brings the
+ * stopper and the hotplug thread of the upcoming CPU up and then delegates
+ * the rest of the online bringup to the hotplug thread.
  */
 void cpuhp_online_idle(enum cpuhp_state state)
 {
 	struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
-	unsigned int cpu = smp_processor_id();
 
 	/* Happens for the boot cpu */
 	if (state != CPUHP_AP_ONLINE_IDLE)
 		return;
 
 	st->state = CPUHP_AP_ONLINE_IDLE;
-
-	/* Unpark the stopper thread and the hotplug thread of this cpu */
-	stop_machine_unpark(cpu);
-	kthread_unpark(st->thread);
-
-	/* Should we go further up ? */
-	if (st->target > CPUHP_AP_ONLINE_IDLE)
-		__cpuhp_kick_ap_work(st);
-	else
-		complete(&st->done);
+	complete(&st->done);
 }
 
 /* Requires cpu_add_remove_lock to be held */
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 80bf7ba..b65854c 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -160,11 +160,9 @@
 {
 	__set_current_state(TASK_PARKED);
 	while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) {
-		preempt_disable();
 		if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags))
 			complete(&self->parked);
-		schedule_preempt_disabled();
-		preempt_enable();
+		schedule();
 		__set_current_state(TASK_PARKED);
 	}
 	clear_bit(KTHREAD_IS_PARKED, &self->flags);
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index b6a639b..dce76d1 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -404,12 +404,13 @@
 static void sugov_work(struct kthread_work *work)
 {
 	struct sugov_policy *sg_policy = container_of(work, struct sugov_policy, work);
+	unsigned long flags;
 
 	mutex_lock(&sg_policy->work_lock);
-	raw_spin_lock(&sg_policy->update_lock);
+	raw_spin_lock_irqsave(&sg_policy->update_lock, flags);
 	sugov_track_cycles(sg_policy, sg_policy->policy->cur,
 			   sched_ktime_clock());
-	raw_spin_unlock(&sg_policy->update_lock);
+	raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags);
 	__cpufreq_driver_target(sg_policy->policy, sg_policy->next_freq,
 				CPUFREQ_RELATION_L);
 	mutex_unlock(&sg_policy->work_lock);
@@ -488,18 +489,19 @@
 	unsigned int val;
 	struct sugov_policy *sg_policy;
 	unsigned long hs_util;
+	unsigned long flags;
 
 	if (kstrtouint(buf, 10, &val))
 		return -EINVAL;
 
 	tunables->hispeed_freq = val;
 	list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) {
-		raw_spin_lock(&sg_policy->update_lock);
+		raw_spin_lock_irqsave(&sg_policy->update_lock, flags);
 		hs_util = freq_to_util(sg_policy,
 					sg_policy->tunables->hispeed_freq);
 		hs_util = mult_frac(hs_util, TARGET_LOAD, 100);
 		sg_policy->hispeed_util = hs_util;
-		raw_spin_unlock(&sg_policy->update_lock);
+		raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags);
 	}
 
 	return count;
@@ -784,13 +786,14 @@
 static void sugov_limits(struct cpufreq_policy *policy)
 {
 	struct sugov_policy *sg_policy = policy->governor_data;
+	unsigned long flags;
 
 	if (!policy->fast_switch_enabled) {
 		mutex_lock(&sg_policy->work_lock);
-		raw_spin_lock(&sg_policy->update_lock);
+		raw_spin_lock_irqsave(&sg_policy->update_lock, flags);
 		sugov_track_cycles(sg_policy, sg_policy->policy->cur,
 				   sched_ktime_clock());
-		raw_spin_unlock(&sg_policy->update_lock);
+		raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags);
 		cpufreq_policy_apply_limits(policy);
 		mutex_unlock(&sg_policy->work_lock);
 	}
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index d06ac7d..1c5bb37 100755
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -5407,10 +5407,13 @@
 }
 
 static inline bool
-bias_to_waker_cpu(struct task_struct *p, int cpu)
+bias_to_waker_cpu(struct task_struct *p, int cpu, struct cpumask *rtg_target)
 {
+	int rtg_target_cpu = rtg_target ? cpumask_first(rtg_target) : cpu;
+
 	return cpumask_test_cpu(cpu, tsk_cpus_allowed(p)) &&
 	       cpu_active(cpu) && !cpu_isolated(cpu) &&
+	       capacity_orig_of(cpu) >= capacity_orig_of(rtg_target_cpu) &&
 	       task_fits_max(p, cpu);
 }
 
@@ -6730,6 +6733,7 @@
 	bool need_idle;
 	enum sched_boost_policy placement_boost = task_sched_boost(p) ?
 				sched_boost_policy() : SCHED_BOOST_NONE;
+	struct related_thread_group *grp;
 
 	sd = rcu_dereference(per_cpu(sd_ea, task_cpu(p)));
 
@@ -6745,22 +6749,17 @@
 
 	need_idle = wake_to_idle(p);
 
-	if (sync && bias_to_waker_cpu(p, cpu)) {
+	grp = task_related_thread_group(p);
+	if (grp && grp->preferred_cluster)
+		rtg_target = &grp->preferred_cluster->cpus;
+
+	if (sync && bias_to_waker_cpu(p, cpu, rtg_target)) {
 		trace_sched_task_util_bias_to_waker(p, task_cpu(p),
 					task_util(p), cpu, cpu, 0, need_idle);
 		return cpu;
 	}
 
 	if (sysctl_sched_is_big_little) {
-		struct related_thread_group *grp;
-
-		rcu_read_lock();
-		grp = task_related_thread_group(p);
-		rcu_read_unlock();
-
-		if (grp && grp->preferred_cluster)
-			rtg_target = &grp->preferred_cluster->cpus;
-
 		task_util_boosted = boosted_task_util(p);
 
 		/*
@@ -7080,8 +7079,12 @@
 	return select_best_cpu(p, prev_cpu, 0, sync);
 #endif
 
-	if (energy_aware())
-		return energy_aware_wake_cpu(p, prev_cpu, sync);
+	if (energy_aware()) {
+		rcu_read_lock();
+		new_cpu = energy_aware_wake_cpu(p, prev_cpu, sync);
+		rcu_read_unlock();
+		return new_cpu;
+	}
 
 	if (sd_flag & SD_BALANCE_WAKE) {
 		record_wakee(p);
@@ -12296,7 +12299,9 @@
 		    rq->curr->nr_cpus_allowed == 1)
 			return;
 
+		rcu_read_lock();
 		new_cpu = energy_aware_wake_cpu(p, cpu, 0);
+		rcu_read_unlock();
 		if (capacity_orig_of(new_cpu) > capacity_orig_of(cpu)) {
 			active_balance = kick_active_balance(rq, p, new_cpu);
 			if (active_balance) {
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index ae45283..69bbce2 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -1704,6 +1704,7 @@
 						      pred_demand);
 
 	p->ravg.demand = demand;
+	p->ravg.coloc_demand = div64_u64(sum, sched_ravg_hist_size);
 	p->ravg.pred_demand = pred_demand;
 
 	if (__task_in_cum_window_demand(rq, p))
@@ -1982,6 +1983,7 @@
 			  (u64)sched_ravg_window, 100);
 
 	p->ravg.demand = init_load_windows;
+	p->ravg.coloc_demand = init_load_windows;
 	p->ravg.pred_demand = 0;
 	for (i = 0; i < RAVG_HIST_SIZE_MAX; ++i)
 		p->ravg.sum_history[i] = init_load_windows;
@@ -2505,7 +2507,7 @@
 		    (sched_ravg_window * sched_ravg_hist_size))
 			continue;
 
-		combined_demand += p->ravg.demand;
+		combined_demand += p->ravg.coloc_demand;
 
 	}
 
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index b076cba..674bbd82 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2463,9 +2463,12 @@
 	if (write) {
 		if (*negp)
 			return -EINVAL;
+		if (*lvalp > UINT_MAX)
+			return -EINVAL;
 		*valp = *lvalp;
 	} else {
 		unsigned int val = *valp;
+		*negp = false;
 		*lvalp = (unsigned long)val;
 	}
 	return 0;
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 8d2b4d8..5ff45ca 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -667,30 +667,25 @@
 		pr_info("Probe point is not specified.\n");
 		return -EINVAL;
 	}
-	if (isdigit(argv[1][0])) {
-		if (is_return) {
-			pr_info("Return probe point must be a symbol.\n");
-			return -EINVAL;
-		}
-		/* an address specified */
-		ret = kstrtoul(&argv[1][0], 0, (unsigned long *)&addr);
-		if (ret) {
-			pr_info("Failed to parse address.\n");
-			return ret;
-		}
-	} else {
+
+	/* try to parse an address. if that fails, try to read the
+	 * input as a symbol. */
+	if (kstrtoul(argv[1], 0, (unsigned long *)&addr)) {
 		/* a symbol specified */
 		symbol = argv[1];
 		/* TODO: support .init module functions */
 		ret = traceprobe_split_symbol_offset(symbol, &offset);
 		if (ret) {
-			pr_info("Failed to parse symbol.\n");
+			pr_info("Failed to parse either an address or a symbol.\n");
 			return ret;
 		}
 		if (offset && is_return) {
 			pr_info("Return probe must be used without offset.\n");
 			return -EINVAL;
 		}
+	} else if (is_return) {
+		pr_info("Return probe point must be a symbol.\n");
+		return -EINVAL;
 	}
 	argc -= 2; argv += 2;
 
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 195de42..f590cb0 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1422,16 +1422,27 @@
  */
 struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
 {
+#ifdef CONFIG_ENABLE_VMALLOC_SAVING
+	return __get_vm_area_node(size, 1, flags, PAGE_OFFSET, VMALLOC_END,
+				  NUMA_NO_NODE, GFP_KERNEL,
+				  __builtin_return_address(0));
+#else
 	return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
 				  NUMA_NO_NODE, GFP_KERNEL,
 				  __builtin_return_address(0));
+#endif
 }
 
 struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
 				const void *caller)
 {
+#ifdef CONFIG_ENABLE_VMALLOC_SAVING
+	return __get_vm_area_node(size, 1, flags, PAGE_OFFSET, VMALLOC_END,
+				  NUMA_NO_NODE, GFP_KERNEL, caller);
+#else
 	return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
 				  NUMA_NO_NODE, GFP_KERNEL, caller);
+#endif
 }
 
 /**
diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c
index 04a1b97..14e3d85 100644
--- a/net/netfilter/xt_IDLETIMER.c
+++ b/net/netfilter/xt_IDLETIMER.c
@@ -76,6 +76,7 @@
 	bool send_nl_msg;
 	bool active;
 	uid_t uid;
+	bool suspend_time_valid;
 };
 
 static LIST_HEAD(idletimer_tg_list);
@@ -245,8 +246,13 @@
 	switch (pm_event) {
 	case PM_SUSPEND_PREPARE:
 		get_monotonic_boottime(&timer->last_suspend_time);
+		timer->suspend_time_valid = true;
 		break;
 	case PM_POST_SUSPEND:
+		if (!timer->suspend_time_valid)
+			break;
+		timer->suspend_time_valid = false;
+
 		spin_lock_bh(&timestamp_lock);
 		if (!timer->active) {
 			spin_unlock_bh(&timestamp_lock);
@@ -281,7 +287,7 @@
 {
 	int ret;
 
-	info->timer = kmalloc(sizeof(*info->timer), GFP_KERNEL);
+	info->timer = kzalloc(sizeof(*info->timer), GFP_KERNEL);
 	if (!info->timer) {
 		ret = -ENOMEM;
 		goto out;
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 56c458d..8d9330a 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -437,7 +437,7 @@
 static struct key *request_master_key(struct encrypted_key_payload *epayload,
 				      const u8 **master_key, size_t *master_keylen)
 {
-	struct key *mkey = NULL;
+	struct key *mkey = ERR_PTR(-EINVAL);
 
 	if (!strncmp(epayload->master_desc, KEY_TRUSTED_PREFIX,
 		     KEY_TRUSTED_PREFIX_LEN)) {
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f800858..f9a0a47 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -882,7 +882,6 @@
         tristate
 	depends on WCD9XXX_CODEC_CORE
 	select SND_SOC_WCD9XXX
-	select SND_SOC_WCD_MBHC
 	select SND_SOC_WCD_MBHC_LEGACY
 	select SND_SOC_WCD_CPE
 
@@ -900,7 +899,6 @@
 config SND_SOC_WCD934X_MBHC
         tristate
 	depends on SND_SOC_WCD934X
-	select SND_SOC_WCD_MBHC
 	select SND_SOC_WCD_MBHC_ADC
 
 config REGMAP_SWR
@@ -933,9 +931,11 @@
 
 config SND_SOC_WCD_MBHC_LEGACY
 	tristate
+	select SND_SOC_WCD_MBHC
 
 config SND_SOC_WCD_MBHC_ADC
 	tristate
+	select SND_SOC_WCD_MBHC
 
 config SND_SOC_WCD_DSP_MGR
 	tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index d5e4ab2..5cf93b1 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -172,10 +172,12 @@
 endif
 snd-soc-wcd-cpe-objs := wcd_cpe_services.o wcd_cpe_core.o
 snd-soc-wsa881x-objs := wsa881x.o wsa881x-tables.o wsa881x-regmap.o wsa881x-temp-sensor.o
+snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o
 ifneq (,$(filter $(CONFIG_SND_SOC_WCD_MBHC_LEGACY),y m))
-	snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o wcd-mbhc-legacy.o
-else ifneq (,$(filter $(CONFIG_SND_SOC_WCD_MBHC_ADC),y m))
-	snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o wcd-mbhc-adc.o
+	snd-soc-wcd-mbhc-objs += wcd-mbhc-legacy.o
+endif
+ifneq (,$(filter $(CONFIG_SND_SOC_WCD_MBHC_ADC),y m))
+	snd-soc-wcd-mbhc-objs += wcd-mbhc-adc.o
 endif
 snd-soc-wsa881x-analog-objs := wsa881x-analog.o wsa881x-tables-analog.o
 snd-soc-wsa881x-analog-objs += wsa881x-regmap-analog.o wsa881x-irq.o
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 9c365a7..7899a2c 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -1108,6 +1108,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Kabylake Client platform")
 		}
 	},
+	{
+		.ident = "Thinkpad Helix 2nd",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix 2nd")
+		}
+	},
 
 	{ }
 };
diff --git a/sound/soc/codecs/sdm660_cdc/Kconfig b/sound/soc/codecs/sdm660_cdc/Kconfig
index 2f36c39..e618258 100644
--- a/sound/soc/codecs/sdm660_cdc/Kconfig
+++ b/sound/soc/codecs/sdm660_cdc/Kconfig
@@ -1,5 +1,4 @@
 
 config SND_SOC_SDM660_CDC
 	tristate "MSM Internal PMIC based codec"
-	select SND_SOC_WCD_MBHC
 	select SND_SOC_WCD_MBHC_LEGACY
diff --git a/sound/soc/codecs/wcd-dsp-mgr.c b/sound/soc/codecs/wcd-dsp-mgr.c
index 661db2b..a6d46ae 100644
--- a/sound/soc/codecs/wcd-dsp-mgr.c
+++ b/sound/soc/codecs/wcd-dsp-mgr.c
@@ -26,7 +26,8 @@
 static char *wdsp_get_cmpnt_type_string(enum wdsp_cmpnt_type);
 
 /* Component related macros */
-#define WDSP_GET_COMPONENT(wdsp, x) (&(wdsp->cmpnts[x]))
+#define WDSP_GET_COMPONENT(wdsp, x) ((x >= WDSP_CMPNT_TYPE_MAX || x < 0) ? \
+					NULL : (&(wdsp->cmpnts[x])))
 #define WDSP_GET_CMPNT_TYPE_STR(x) wdsp_get_cmpnt_type_string(x)
 
 /*
diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c
index 3b2426d..d9bdf05 100644
--- a/sound/soc/codecs/wcd-mbhc-v2.c
+++ b/sound/soc/codecs/wcd-mbhc-v2.c
@@ -1108,7 +1108,7 @@
 	 * For ADC MBHC, ADC_COMPLETE interrupt will be generated
 	 * in this case. So skip the check here.
 	 */
-	if (!WCD_MBHC_DETECTION &&
+	if (mbhc->mbhc_detection_logic == WCD_DETECTION_LEGACY &&
 		mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) {
 		wcd_mbhc_find_plug_and_report(mbhc, MBHC_PLUG_TYPE_HEADSET);
 		goto exit;
@@ -1922,7 +1922,7 @@
 	init_waitqueue_head(&mbhc->wait_btn_press);
 	mutex_init(&mbhc->codec_resource_lock);
 
-	switch (WCD_MBHC_DETECTION) {
+	switch (mbhc->mbhc_detection_logic) {
 	case WCD_DETECTION_LEGACY:
 		wcd_mbhc_legacy_init(mbhc);
 		break;
@@ -1931,7 +1931,7 @@
 		break;
 	default:
 		pr_err("%s: Unknown detection logic type %d\n",
-			__func__, WCD_MBHC_DETECTION);
+			__func__, mbhc->mbhc_detection_logic);
 		break;
 	}
 
diff --git a/sound/soc/codecs/wcd-mbhc-v2.h b/sound/soc/codecs/wcd-mbhc-v2.h
index 7ed06c3..a7655d2 100644
--- a/sound/soc/codecs/wcd-mbhc-v2.h
+++ b/sound/soc/codecs/wcd-mbhc-v2.h
@@ -157,12 +157,6 @@
 	WCD_DETECTION_ADC,
 };
 
-#ifdef CONFIG_SND_SOC_WCD_MBHC_ADC
-#define WCD_MBHC_DETECTION	WCD_DETECTION_ADC
-#else
-#define WCD_MBHC_DETECTION	WCD_DETECTION_LEGACY
-#endif
-
 enum wcd_mbhc_cs_mb_en_flag {
 	WCD_MBHC_EN_CS = 0,
 	WCD_MBHC_EN_MB,
@@ -565,6 +559,9 @@
 	struct mutex hphl_pa_lock;
 	struct mutex hphr_pa_lock;
 
+	/* Holds mbhc detection method - ADC/Legacy */
+	unsigned int mbhc_detection_logic;
+
 	unsigned long intr_status;
 	bool is_hph_ocp_pending;
 
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 329aa7a..f8cd9e2 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -348,7 +348,6 @@
 	AUDIO_NOMINAL,
 	CPE_NOMINAL,
 	HPH_PA_DELAY,
-	SB_CLK_GEAR,
 	ANC_MIC_AMIC1,
 	ANC_MIC_AMIC2,
 	ANC_MIC_AMIC3,
@@ -818,7 +817,10 @@
 	int rx_8_count;
 	bool clk_mode;
 	bool clk_internal;
-
+	/* Lock to prevent multiple functions voting at same time */
+	struct mutex sb_clk_gear_lock;
+	/* Count for functions voting or un-voting */
+	u32 ref_count;
 	/* Lock to protect mclk enablement */
 	struct mutex mclk_lock;
 };
@@ -2948,10 +2950,7 @@
 					      &dai->grph);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
-		if (!test_bit(SB_CLK_GEAR, &tasha_p->status_mask)) {
-			tasha_codec_vote_max_bw(codec, true);
-			set_bit(SB_CLK_GEAR, &tasha_p->status_mask);
-		}
+		tasha_codec_vote_max_bw(codec, true);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		ret = wcd9xxx_disconnect_port(core, &dai->wcd9xxx_ch_list,
@@ -5263,10 +5262,7 @@
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		if (!test_bit(SB_CLK_GEAR, &tasha->status_mask)) {
-			tasha_codec_vote_max_bw(codec, true);
-			set_bit(SB_CLK_GEAR, &tasha->status_mask);
-		}
+		tasha_codec_vote_max_bw(codec, true);
 		/* Reset if needed */
 		tasha_codec_enable_prim_interpolator(codec, reg, event);
 		break;
@@ -11127,11 +11123,8 @@
 	if (tasha->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
 		return;
 
-	if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
-	    test_bit(SB_CLK_GEAR, &tasha->status_mask)) {
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		tasha_codec_vote_max_bw(dai->codec, false);
-		clear_bit(SB_CLK_GEAR, &tasha->status_mask);
-	}
 }
 
 static int tasha_set_decimator_rate(struct snd_soc_dai *dai,
@@ -11366,15 +11359,11 @@
 static int tasha_prepare(struct snd_pcm_substream *substream,
 			 struct snd_soc_dai *dai)
 {
-	struct tasha_priv *tasha = snd_soc_codec_get_drvdata(dai->codec);
-
 	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
 		 substream->name, substream->stream);
-	if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
-	    test_bit(SB_CLK_GEAR, &tasha->status_mask)) {
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		tasha_codec_vote_max_bw(dai->codec, false);
-		clear_bit(SB_CLK_GEAR, &tasha->status_mask);
-	}
 	return 0;
 }
 
@@ -13082,13 +13071,29 @@
 	if (tasha->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
 		return 0;
 
-	if (vote)
-		bw_ops = SLIM_BW_CLK_GEAR_9;
-	else
-		bw_ops = SLIM_BW_UNVOTE;
+	mutex_lock(&tasha->sb_clk_gear_lock);
+	if (vote) {
+		tasha->ref_count++;
+		if (tasha->ref_count == 1) {
+			bw_ops = SLIM_BW_CLK_GEAR_9;
+			tasha_codec_slim_reserve_bw(codec,
+				bw_ops, true);
+		}
+	} else if (!vote && tasha->ref_count > 0) {
+		tasha->ref_count--;
+		if (tasha->ref_count == 0) {
+			bw_ops = SLIM_BW_UNVOTE;
+			tasha_codec_slim_reserve_bw(codec,
+				bw_ops, true);
+		}
+	};
 
-	return tasha_codec_slim_reserve_bw(codec,
-			bw_ops, true);
+	dev_dbg(codec->dev, "%s Value of counter after vote or un-vote is %d\n",
+		__func__, tasha->ref_count);
+
+	mutex_unlock(&tasha->sb_clk_gear_lock);
+
+	return 0;
 }
 
 static int tasha_cpe_err_irq_control(struct snd_soc_codec *codec,
@@ -13271,6 +13276,8 @@
 	if (ret < 0)
 		dev_err(codec->dev, "%s: invalid pdata\n", __func__);
 
+	/* Reset reference counter for voting for max bw */
+	tasha->ref_count = 0;
 	/* MBHC Init */
 	wcd_mbhc_deinit(&tasha->mbhc);
 	tasha->mbhc_started = false;
@@ -14053,6 +14060,7 @@
 	mutex_init(&tasha->swr_read_lock);
 	mutex_init(&tasha->swr_write_lock);
 	mutex_init(&tasha->swr_clk_lock);
+	mutex_init(&tasha->sb_clk_gear_lock);
 	mutex_init(&tasha->mclk_lock);
 
 	cdc_pwr = devm_kzalloc(&pdev->dev, sizeof(struct wcd9xxx_power_region),
@@ -14157,6 +14165,7 @@
 	mutex_destroy(&tasha->mclk_lock);
 	devm_kfree(&pdev->dev, tasha);
 	snd_soc_unregister_codec(&pdev->dev);
+	mutex_destroy(&tasha->sb_clk_gear_lock);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/wcd934x/wcd934x-mbhc.c b/sound/soc/codecs/wcd934x/wcd934x-mbhc.c
index a1a5e2d..76316af 100644
--- a/sound/soc/codecs/wcd934x/wcd934x-mbhc.c
+++ b/sound/soc/codecs/wcd934x/wcd934x-mbhc.c
@@ -998,19 +998,26 @@
 			     struct snd_soc_codec *codec)
 {
 	int ret;
+	struct wcd_mbhc *wcd_mbhc;
 
 	if (!mbhc || !codec)
 		return -EINVAL;
 
-	wcd_mbhc_deinit(&mbhc->wcd_mbhc);
-	ret = wcd_mbhc_init(&mbhc->wcd_mbhc, codec, &mbhc_cb, &intr_ids,
+	wcd_mbhc = &mbhc->wcd_mbhc;
+	if (wcd_mbhc == NULL) {
+		pr_err("%s: wcd_mbhc is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	wcd_mbhc_deinit(wcd_mbhc);
+	ret = wcd_mbhc_init(wcd_mbhc, codec, &mbhc_cb, &intr_ids,
 			    wcd_mbhc_registers, TAVIL_ZDET_SUPPORTED);
 	if (ret) {
 		dev_err(codec->dev, "%s: mbhc initialization failed\n",
 			__func__);
 		goto done;
 	}
-	if (!WCD_MBHC_DETECTION) {
+	if (wcd_mbhc->mbhc_detection_logic == WCD_DETECTION_LEGACY) {
 		snd_soc_update_bits(codec, WCD934X_MBHC_NEW_CTL_1, 0x04, 0x04);
 		snd_soc_update_bits(codec, WCD934X_MBHC_CTL_BCS, 0x01, 0x01);
 	}
@@ -1033,6 +1040,7 @@
 {
 	struct regulator *supply;
 	struct wcd934x_mbhc *wcd934x_mbhc;
+	struct wcd_mbhc *wcd_mbhc;
 	int ret;
 
 	wcd934x_mbhc = devm_kzalloc(codec->dev, sizeof(struct wcd934x_mbhc),
@@ -1043,8 +1051,18 @@
 	wcd934x_mbhc->wcd9xxx = dev_get_drvdata(codec->dev->parent);
 	wcd934x_mbhc->fw_data = fw_data;
 	BLOCKING_INIT_NOTIFIER_HEAD(&wcd934x_mbhc->notifier);
+	wcd_mbhc = &wcd934x_mbhc->wcd_mbhc;
+	if (wcd_mbhc == NULL) {
+		pr_err("%s: wcd_mbhc is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
 
-	ret = wcd_mbhc_init(&wcd934x_mbhc->wcd_mbhc, codec, &mbhc_cb,
+
+	/* Setting default mbhc detection logic to ADC for Tavil */
+	wcd_mbhc->mbhc_detection_logic = WCD_DETECTION_ADC;
+
+	ret = wcd_mbhc_init(wcd_mbhc, codec, &mbhc_cb,
 				&intr_ids, wcd_mbhc_registers,
 				TAVIL_ZDET_SUPPORTED);
 	if (ret) {
@@ -1070,7 +1088,7 @@
 	snd_soc_add_codec_controls(codec, hph_type_detect_controls,
 				   ARRAY_SIZE(hph_type_detect_controls));
 
-	if (!WCD_MBHC_DETECTION) {
+	if (wcd_mbhc->mbhc_detection_logic == WCD_DETECTION_LEGACY) {
 		snd_soc_update_bits(codec, WCD934X_MBHC_NEW_CTL_1, 0x04, 0x04);
 		snd_soc_update_bits(codec, WCD934X_MBHC_CTL_BCS, 0x01, 0x01);
 	}
diff --git a/sound/soc/codecs/wcd934x/wcd934x-routing.h b/sound/soc/codecs/wcd934x/wcd934x-routing.h
index afd93b2..93a1ad3 100644
--- a/sound/soc/codecs/wcd934x/wcd934x-routing.h
+++ b/sound/soc/codecs/wcd934x/wcd934x-routing.h
@@ -117,6 +117,70 @@
 
 const struct snd_soc_dapm_route tavil_audio_map[] = {
 
+	/* WDMA3 */
+	{"WDMA3 PORT0 MUX", "DEC0", "ADC MUX0"},
+	{"WDMA3 PORT0 MUX", "RX_MIX_TX0", "RX MIX TX0 MUX"},
+	{"WDMA3 PORT1 MUX", "DEC1", "ADC MUX1"},
+	{"WDMA3 PORT1 MUX", "RX_MIX_TX1", "RX MIX TX1 MUX"},
+	{"WDMA3 PORT2 MUX", "DEC2", "ADC MUX2"},
+	{"WDMA3 PORT2 MUX", "RX_MIX_TX2", "RX MIX TX2 MUX"},
+	{"WDMA3 PORT3 MUX", "DEC3", "ADC MUX3"},
+	{"WDMA3 PORT3 MUX", "RX_MIX_TX3", "RX MIX TX3 MUX"},
+	{"WDMA3 PORT4 MUX", "DEC4", "ADC MUX4"},
+	{"WDMA3 PORT4 MUX", "RX_MIX_TX4", "RX MIX TX4 MUX"},
+	{"WDMA3 PORT5 MUX", "DEC5", "ADC MUX5"},
+	{"WDMA3 PORT5 MUX", "RX_MIX_TX5", "RX MIX TX5 MUX"},
+	{"WDMA3 PORT6 MUX", "DEC6", "ADC MUX6"},
+	{"WDMA3 PORT6 MUX", "RX_MIX_TX6", "RX MIX TX6 MUX"},
+
+	{"WDMA3 CH0 MUX", "PORT_0", "WDMA3 PORT0 MUX"},
+	{"WDMA3 CH0 MUX", "PORT_1", "WDMA3 PORT1 MUX"},
+	{"WDMA3 CH0 MUX", "PORT_2", "WDMA3 PORT2 MUX"},
+	{"WDMA3 CH0 MUX", "PORT_3", "WDMA3 PORT3 MUX"},
+	{"WDMA3 CH0 MUX", "PORT_4", "WDMA3 PORT4 MUX"},
+	{"WDMA3 CH0 MUX", "PORT_5", "WDMA3 PORT5 MUX"},
+	{"WDMA3 CH0 MUX", "PORT_6", "WDMA3 PORT6 MUX"},
+	{"WDMA3 CH0 MUX", "PORT_7", "ADC MUX7"},
+	{"WDMA3 CH0 MUX", "PORT_8", "ADC MUX8"},
+
+	{"WDMA3 CH1 MUX", "PORT_0", "WDMA3 PORT0 MUX"},
+	{"WDMA3 CH1 MUX", "PORT_1", "WDMA3 PORT1 MUX"},
+	{"WDMA3 CH1 MUX", "PORT_2", "WDMA3 PORT2 MUX"},
+	{"WDMA3 CH1 MUX", "PORT_3", "WDMA3 PORT3 MUX"},
+	{"WDMA3 CH1 MUX", "PORT_4", "WDMA3 PORT4 MUX"},
+	{"WDMA3 CH1 MUX", "PORT_5", "WDMA3 PORT5 MUX"},
+	{"WDMA3 CH1 MUX", "PORT_6", "WDMA3 PORT6 MUX"},
+	{"WDMA3 CH1 MUX", "PORT_7", "ADC MUX7"},
+	{"WDMA3 CH1 MUX", "PORT_8", "ADC MUX8"},
+
+	{"WDMA3 CH2 MUX", "PORT_0", "WDMA3 PORT0 MUX"},
+	{"WDMA3 CH2 MUX", "PORT_1", "WDMA3 PORT1 MUX"},
+	{"WDMA3 CH2 MUX", "PORT_2", "WDMA3 PORT2 MUX"},
+	{"WDMA3 CH2 MUX", "PORT_3", "WDMA3 PORT3 MUX"},
+	{"WDMA3 CH2 MUX", "PORT_4", "WDMA3 PORT4 MUX"},
+	{"WDMA3 CH2 MUX", "PORT_5", "WDMA3 PORT5 MUX"},
+	{"WDMA3 CH2 MUX", "PORT_6", "WDMA3 PORT6 MUX"},
+	{"WDMA3 CH2 MUX", "PORT_7", "ADC MUX7"},
+	{"WDMA3 CH2 MUX", "PORT_8", "ADC MUX8"},
+
+	{"WDMA3 CH3 MUX", "PORT_0", "WDMA3 PORT0 MUX"},
+	{"WDMA3 CH3 MUX", "PORT_1", "WDMA3 PORT1 MUX"},
+	{"WDMA3 CH3 MUX", "PORT_2", "WDMA3 PORT2 MUX"},
+	{"WDMA3 CH3 MUX", "PORT_3", "WDMA3 PORT3 MUX"},
+	{"WDMA3 CH3 MUX", "PORT_4", "WDMA3 PORT4 MUX"},
+	{"WDMA3 CH3 MUX", "PORT_5", "WDMA3 PORT5 MUX"},
+	{"WDMA3 CH3 MUX", "PORT_6", "WDMA3 PORT6 MUX"},
+	{"WDMA3 CH3 MUX", "PORT_7", "ADC MUX7"},
+	{"WDMA3 CH3 MUX", "PORT_8", "ADC MUX8"},
+
+	{"WDMA3_CH_MIXER", NULL, "WDMA3 CH0 MUX"},
+	{"WDMA3_CH_MIXER", NULL, "WDMA3 CH1 MUX"},
+	{"WDMA3_CH_MIXER", NULL, "WDMA3 CH2 MUX"},
+	{"WDMA3_CH_MIXER", NULL, "WDMA3 CH3 MUX"},
+
+	{"WDMA3_ON_OFF", "Switch", "WDMA3_CH_MIXER"},
+	{"WDMA3_OUT", NULL, "WDMA3_ON_OFF"},
+
 	/* MAD */
 	{"MAD_SEL MUX", "SPE", "MAD_CPE_INPUT"},
 	{"MAD_SEL MUX", "MSM", "MADINPUT"},
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index ca16ed8..3079cca 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -180,6 +180,8 @@
 	ANC_MIC_AMIC2,
 	ANC_MIC_AMIC3,
 	ANC_MIC_AMIC4,
+	CLK_INTERNAL,
+	CLK_MODE,
 };
 
 enum {
@@ -1071,6 +1073,40 @@
 	return ret;
 }
 
+static int tavil_get_clkmode(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
+
+	if (test_bit(CLK_MODE, &tavil_p->status_mask))
+		ucontrol->value.enumerated.item[0] = 1;
+	else
+		ucontrol->value.enumerated.item[0] = 0;
+
+	dev_dbg(codec->dev, "%s: is_low_power_clock: %s\n", __func__,
+		test_bit(CLK_MODE, &tavil_p->status_mask) ? "true" : "false");
+
+	return 0;
+}
+
+static int tavil_put_clkmode(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
+
+	if (ucontrol->value.enumerated.item[0])
+		set_bit(CLK_MODE, &tavil_p->status_mask);
+	else
+		clear_bit(CLK_MODE, &tavil_p->status_mask);
+
+	dev_dbg(codec->dev, "%s: is_low_power_clock: %s\n", __func__,
+		test_bit(CLK_MODE, &tavil_p->status_mask) ? "true" : "false");
+
+	return 0;
+}
+
 static int tavil_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_value *ucontrol)
 {
@@ -2809,6 +2845,35 @@
 	return asrc_mode;
 }
 
+static int tavil_codec_wdma3_ctl(struct snd_soc_dapm_widget *w,
+				   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Fix to 16KHz */
+		snd_soc_update_bits(codec, WCD934X_DMA_WDMA_CTL_3,
+				    0xF0, 0x10);
+		/* Select mclk_1 */
+		snd_soc_update_bits(codec, WCD934X_DMA_WDMA_CTL_3,
+				    0x02, 0x00);
+		/* Enable DMA */
+		snd_soc_update_bits(codec, WCD934X_DMA_WDMA_CTL_3,
+				    0x01, 0x01);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		/* Disable DMA */
+		snd_soc_update_bits(codec, WCD934X_DMA_WDMA_CTL_3,
+				    0x01, 0x00);
+		break;
+
+	};
+
+	return 0;
+}
+
 static int tavil_codec_enable_asrc(struct snd_soc_codec *codec,
 				   int asrc_in, int event)
 {
@@ -5547,6 +5612,9 @@
 static const struct soc_enum tavil_anc_func_enum =
 	SOC_ENUM_SINGLE_EXT(2, tavil_anc_func_text);
 
+static const char *const tavil_clkmode_text[] = {"EXTERNAL", "INTERNAL"};
+static SOC_ENUM_SINGLE_EXT_DECL(tavil_clkmode_enum, tavil_clkmode_text);
+
 /* Cutoff frequency for high pass filter */
 static const char * const cf_text[] = {
 	"CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
@@ -5726,6 +5794,9 @@
 	SOC_ENUM_EXT("ANC Function", tavil_anc_func_enum, tavil_get_anc_func,
 		tavil_put_anc_func),
 
+	SOC_ENUM_EXT("CLK MODE", tavil_clkmode_enum, tavil_get_clkmode,
+		     tavil_put_clkmode),
+
 	SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
 	SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
 	SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
@@ -6165,6 +6236,39 @@
 	"OFF", "ON",
 };
 
+static const char *const wdma3_port0_text[] = {
+	"RX_MIX_TX0", "DEC0"
+};
+
+static const char *const wdma3_port1_text[] = {
+	"RX_MIX_TX1", "DEC1"
+};
+
+static const char *const wdma3_port2_text[] = {
+	"RX_MIX_TX2", "DEC2"
+};
+
+static const char *const wdma3_port3_text[] = {
+	"RX_MIX_TX3", "DEC3"
+};
+
+static const char *const wdma3_port4_text[] = {
+	"RX_MIX_TX4", "DEC4"
+};
+
+static const char *const wdma3_port5_text[] = {
+	"RX_MIX_TX5", "DEC5"
+};
+
+static const char *const wdma3_port6_text[] = {
+	"RX_MIX_TX6", "DEC6"
+};
+
+static const char *const wdma3_ch_text[] = {
+	"PORT_0", "PORT_1", "PORT_2", "PORT_3", "PORT_4",
+	"PORT_5", "PORT_6", "PORT_7", "PORT_8",
+};
+
 static const struct snd_kcontrol_new aif4_vi_mixer[] = {
 	SOC_SINGLE_EXT("SPKR_VI_1", SND_SOC_NOPM, WCD934X_TX14, 1, 0,
 			tavil_vi_feed_mixer_get, tavil_vi_feed_mixer_put),
@@ -6570,6 +6674,20 @@
 WCD_DAPM_ENUM(anc0_fb, WCD934X_CDC_RX_INP_MUX_ANC_CFG0, 0, anc0_fb_mux_text);
 WCD_DAPM_ENUM(anc1_fb, WCD934X_CDC_RX_INP_MUX_ANC_CFG0, 3, anc1_fb_mux_text);
 
+
+WCD_DAPM_ENUM(wdma3_port0, WCD934X_DMA_WDMA3_PRT_CFG, 0, wdma3_port0_text);
+WCD_DAPM_ENUM(wdma3_port1, WCD934X_DMA_WDMA3_PRT_CFG, 1, wdma3_port1_text);
+WCD_DAPM_ENUM(wdma3_port2, WCD934X_DMA_WDMA3_PRT_CFG, 2, wdma3_port2_text);
+WCD_DAPM_ENUM(wdma3_port3, WCD934X_DMA_WDMA3_PRT_CFG, 3, wdma3_port3_text);
+WCD_DAPM_ENUM(wdma3_port4, WCD934X_DMA_WDMA3_PRT_CFG, 4, wdma3_port4_text);
+WCD_DAPM_ENUM(wdma3_port5, WCD934X_DMA_WDMA3_PRT_CFG, 5, wdma3_port5_text);
+WCD_DAPM_ENUM(wdma3_port6, WCD934X_DMA_WDMA3_PRT_CFG, 6, wdma3_port6_text);
+
+WCD_DAPM_ENUM(wdma3_ch0, WCD934X_DMA_CH_0_1_CFG_WDMA_3, 0, wdma3_ch_text);
+WCD_DAPM_ENUM(wdma3_ch1, WCD934X_DMA_CH_0_1_CFG_WDMA_3, 4, wdma3_ch_text);
+WCD_DAPM_ENUM(wdma3_ch2, WCD934X_DMA_CH_2_3_CFG_WDMA_3, 0, wdma3_ch_text);
+WCD_DAPM_ENUM(wdma3_ch3, WCD934X_DMA_CH_2_3_CFG_WDMA_3, 4, wdma3_ch_text);
+
 static const struct snd_kcontrol_new anc_ear_switch =
 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
 
@@ -6637,6 +6755,9 @@
 	SOC_DAPM_SINGLE("LO2 Switch", SND_SOC_NOPM, 0, 1, 0),
 };
 
+static const struct snd_kcontrol_new wdma3_onoff_switch =
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
+
 static int tavil_dsd_mixer_get(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
@@ -7319,6 +7440,28 @@
 	SND_SOC_DAPM_MUX_E("ASRC3 MUX", SND_SOC_NOPM, ASRC3, 0,
 		&asrc3_mux, tavil_codec_enable_asrc_resampler,
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* WDMA3 widgets */
+	WCD_DAPM_MUX("WDMA3 PORT0 MUX", 0, wdma3_port0),
+	WCD_DAPM_MUX("WDMA3 PORT1 MUX", 1, wdma3_port1),
+	WCD_DAPM_MUX("WDMA3 PORT2 MUX", 2, wdma3_port2),
+	WCD_DAPM_MUX("WDMA3 PORT3 MUX", 3, wdma3_port3),
+	WCD_DAPM_MUX("WDMA3 PORT4 MUX", 4, wdma3_port4),
+	WCD_DAPM_MUX("WDMA3 PORT5 MUX", 5, wdma3_port5),
+	WCD_DAPM_MUX("WDMA3 PORT6 MUX", 6, wdma3_port6),
+
+	WCD_DAPM_MUX("WDMA3 CH0 MUX", 0, wdma3_ch0),
+	WCD_DAPM_MUX("WDMA3 CH1 MUX", 4, wdma3_ch1),
+	WCD_DAPM_MUX("WDMA3 CH2 MUX", 0, wdma3_ch2),
+	WCD_DAPM_MUX("WDMA3 CH3 MUX", 4, wdma3_ch3),
+
+	SND_SOC_DAPM_MIXER("WDMA3_CH_MIXER", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_SWITCH_E("WDMA3_ON_OFF", SND_SOC_NOPM, 0, 0,
+			      &wdma3_onoff_switch, tavil_codec_wdma3_ctl,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_OUTPUT("WDMA3_OUT"),
 };
 
 static int tavil_get_channel_map(struct snd_soc_dai *dai,
@@ -8316,6 +8459,50 @@
 	return ret;
 }
 
+/*
+ * tavil_cdc_mclk_tx_enable: Enable/Disable codec's clock for TX path
+ * @codec: Handle to codec
+ * @enable: Indicates whether clock should be enabled or disabled
+ */
+int tavil_cdc_mclk_tx_enable(struct snd_soc_codec *codec, bool enable)
+{
+	struct tavil_priv *tavil_p;
+	int ret = 0;
+	bool clk_mode;
+	bool clk_internal;
+
+	if (!codec)
+		return -EINVAL;
+
+	tavil_p = snd_soc_codec_get_drvdata(codec);
+	clk_mode = test_bit(CLK_MODE, &tavil_p->status_mask);
+	clk_internal = test_bit(CLK_INTERNAL, &tavil_p->status_mask);
+
+	dev_dbg(codec->dev, "%s: clkmode: %d, enable: %d, clk_internal: %d\n",
+		__func__, clk_mode, enable, clk_internal);
+
+	if (clk_mode || clk_internal) {
+		if (enable) {
+			wcd_resmgr_enable_master_bias(tavil_p->resmgr);
+			tavil_dig_core_power_collapse(tavil_p, POWER_RESUME);
+			tavil_vote_svs(tavil_p, true);
+			ret = tavil_codec_internal_rco_ctrl(codec, enable);
+			set_bit(CLK_INTERNAL, &tavil_p->status_mask);
+		} else {
+			clear_bit(CLK_INTERNAL, &tavil_p->status_mask);
+			tavil_codec_internal_rco_ctrl(codec, enable);
+			tavil_vote_svs(tavil_p, false);
+			tavil_dig_core_power_collapse(tavil_p, POWER_COLLAPSE);
+			wcd_resmgr_disable_master_bias(tavil_p->resmgr);
+		}
+	} else {
+		ret = __tavil_cdc_mclk_enable(tavil_p, enable);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(tavil_cdc_mclk_tx_enable);
+
 static const struct wcd_resmgr_cb tavil_resmgr_cb = {
 	.cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl,
 };
diff --git a/sound/soc/codecs/wcd934x/wcd934x.h b/sound/soc/codecs/wcd934x/wcd934x.h
index c3bf50a..27c21f1 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.h
+++ b/sound/soc/codecs/wcd934x/wcd934x.h
@@ -137,6 +137,7 @@
 extern void *tavil_get_afe_config(struct snd_soc_codec *codec,
 				  enum afe_config_type config_type);
 extern int tavil_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable);
+extern int tavil_cdc_mclk_tx_enable(struct snd_soc_codec *codec, bool enable);
 extern int tavil_set_spkr_mode(struct snd_soc_codec *codec, int mode);
 extern int tavil_set_spkr_gain_offset(struct snd_soc_codec *codec, int offset);
 extern struct wcd_dsp_cntl *tavil_get_wcd_dsp_cntl(struct device *dev);
diff --git a/sound/soc/msm/qdsp6v2/audio_calibration.c b/sound/soc/msm/qdsp6v2/audio_calibration.c
index 808a0e4..d709b09 100644
--- a/sound/soc/msm/qdsp6v2/audio_calibration.c
+++ b/sound/soc/msm/qdsp6v2/audio_calibration.c
@@ -460,6 +460,12 @@
 			data->cal_type.cal_hdr.buffer_number);
 		ret = -EINVAL;
 		goto done;
+	} else if ((data->hdr.cal_type_size + sizeof(data->hdr)) > size) {
+		pr_err("%s: cal type hdr size %zd + cal type size %d is greater than user buffer size %d\n",
+			__func__, sizeof(data->hdr), data->hdr.cal_type_size,
+			size);
+		ret = -EFAULT;
+		goto done;
 	}
 
 
@@ -497,13 +503,7 @@
 			goto unlock;
 		if (data == NULL)
 			goto unlock;
-		if ((sizeof(data->hdr) + data->hdr.cal_type_size) > size) {
-			pr_err("%s: header size %zd plus cal type size %d are greater than data buffer size %d\n",
-				__func__, sizeof(data->hdr),
-				data->hdr.cal_type_size, size);
-			ret = -EFAULT;
-			goto unlock;
-		} else if (copy_to_user((void *)arg, data,
+		if (copy_to_user(arg, data,
 			sizeof(data->hdr) + data->hdr.cal_type_size)) {
 			pr_err("%s: Could not copy cal type to user\n",
 				__func__);
diff --git a/sound/soc/msm/sdm845.c b/sound/soc/msm/sdm845.c
index d3c4e05..3be194c 100644
--- a/sound/soc/msm/sdm845.c
+++ b/sound/soc/msm/sdm845.c
@@ -495,6 +495,8 @@
 static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_chs, mi2s_ch_text);
 static SOC_ENUM_SINGLE_EXT_DECL(mi2s_rx_format, bit_format_text);
 static SOC_ENUM_SINGLE_EXT_DECL(mi2s_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_tx_format, bit_format_text);
 static SOC_ENUM_SINGLE_EXT_DECL(hifi_function, hifi_text);
 
 static struct platform_device *spdev;
@@ -538,10 +540,10 @@
 };
 
 static struct snd_soc_dapm_route wcd_audio_paths[] = {
-	{"MIC BIAS1", NULL, "MCLK"},
-	{"MIC BIAS2", NULL, "MCLK"},
-	{"MIC BIAS3", NULL, "MCLK"},
-	{"MIC BIAS4", NULL, "MCLK"},
+	{"MIC BIAS1", NULL, "MCLK TX"},
+	{"MIC BIAS2", NULL, "MCLK TX"},
+	{"MIC BIAS3", NULL, "MCLK TX"},
+	{"MIC BIAS4", NULL, "MCLK TX"},
 };
 
 static struct afe_clk_set mi2s_clk[MI2S_MAX] = {
@@ -2252,7 +2254,7 @@
 	return sample_rate;
 }
 
-static int mi2s_get_format(int value)
+static int mi2s_auxpcm_get_format(int value)
 {
 	int format;
 
@@ -2276,7 +2278,7 @@
 	return format;
 }
 
-static int mi2s_get_format_value(int format)
+static int mi2s_auxpcm_get_format_value(int format)
 {
 	int value;
 
@@ -2441,7 +2443,7 @@
 		return idx;
 
 	ucontrol->value.enumerated.item[0] =
-		mi2s_get_format_value(mi2s_rx_cfg[idx].bit_format);
+		mi2s_auxpcm_get_format_value(mi2s_rx_cfg[idx].bit_format);
 
 	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
 		idx, mi2s_rx_cfg[idx].bit_format,
@@ -2459,7 +2461,7 @@
 		return idx;
 
 	mi2s_rx_cfg[idx].bit_format =
-		mi2s_get_format(ucontrol->value.enumerated.item[0]);
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
 
 	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
 		  idx, mi2s_rx_cfg[idx].bit_format,
@@ -2477,7 +2479,7 @@
 		return idx;
 
 	ucontrol->value.enumerated.item[0] =
-		mi2s_get_format_value(mi2s_tx_cfg[idx].bit_format);
+		mi2s_auxpcm_get_format_value(mi2s_tx_cfg[idx].bit_format);
 
 	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
 		idx, mi2s_tx_cfg[idx].bit_format,
@@ -2495,7 +2497,7 @@
 		return idx;
 
 	mi2s_tx_cfg[idx].bit_format =
-		mi2s_get_format(ucontrol->value.enumerated.item[0]);
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
 
 	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
 		  idx, mi2s_tx_cfg[idx].bit_format,
@@ -2504,6 +2506,78 @@
 	return 0;
 }
 
+static int msm_aux_pcm_rx_format_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_auxpcm_get_format_value(aux_pcm_rx_cfg[idx].bit_format);
+
+	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+		idx, aux_pcm_rx_cfg[idx].bit_format,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_rx_format_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	aux_pcm_rx_cfg[idx].bit_format =
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+		  idx, aux_pcm_rx_cfg[idx].bit_format,
+		  ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_tx_format_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_auxpcm_get_format_value(aux_pcm_tx_cfg[idx].bit_format);
+
+	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
+		idx, aux_pcm_tx_cfg[idx].bit_format,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_tx_format_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	aux_pcm_tx_cfg[idx].bit_format =
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
+		  idx, aux_pcm_tx_cfg[idx].bit_format,
+		  ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
 static int msm_hifi_ctrl(struct snd_soc_codec *codec)
 {
 	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
@@ -2765,6 +2839,22 @@
 			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
 	SOC_ENUM_EXT("QUAT_MI2S_TX Format", mi2s_tx_format,
 			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("SEC_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("SEC_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("TERT_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("TERT_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("QUAT_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("QUAT_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
 	SOC_ENUM_EXT("HiFi Function", hifi_function, msm_hifi_get,
 			msm_hifi_put),
 };
@@ -2784,6 +2874,38 @@
 	return ret;
 }
 
+static int msm_snd_enable_codec_ext_tx_clk(struct snd_soc_codec *codec,
+					   int enable, bool dapm)
+{
+	int ret = 0;
+
+	if (!strcmp(dev_name(codec->dev), "tavil_codec")) {
+		ret = tavil_cdc_mclk_tx_enable(codec, enable);
+	} else {
+		dev_err(codec->dev, "%s: unknown codec to enable TX ext clk\n",
+			__func__);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int msm_mclk_tx_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+	pr_debug("%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		return msm_snd_enable_codec_ext_tx_clk(codec, 1, true);
+	case SND_SOC_DAPM_POST_PMD:
+		return msm_snd_enable_codec_ext_tx_clk(codec, 0, true);
+	}
+	return 0;
+}
+
 static int msm_mclk_event(struct snd_soc_dapm_widget *w,
 				 struct snd_kcontrol *kcontrol, int event)
 {
@@ -2840,7 +2962,7 @@
 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_SUPPLY("MCLK TX",  SND_SOC_NOPM, 0, 0,
-	NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	msm_mclk_tx_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_SPK("Lineout_1 amp", NULL),
 	SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
@@ -3134,6 +3256,8 @@
 		break;
 
 	case MSM_BACKEND_DAI_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[PRIM_AUX_PCM].bit_format);
 		rate->min = rate->max =
 			aux_pcm_rx_cfg[PRIM_AUX_PCM].sample_rate;
 		channels->min = channels->max =
@@ -3141,6 +3265,8 @@
 		break;
 
 	case MSM_BACKEND_DAI_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[PRIM_AUX_PCM].bit_format);
 		rate->min = rate->max =
 			aux_pcm_tx_cfg[PRIM_AUX_PCM].sample_rate;
 		channels->min = channels->max =
@@ -3148,6 +3274,8 @@
 		break;
 
 	case MSM_BACKEND_DAI_SEC_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[SEC_AUX_PCM].bit_format);
 		rate->min = rate->max =
 			aux_pcm_rx_cfg[SEC_AUX_PCM].sample_rate;
 		channels->min = channels->max =
@@ -3155,6 +3283,8 @@
 		break;
 
 	case MSM_BACKEND_DAI_SEC_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[SEC_AUX_PCM].bit_format);
 		rate->min = rate->max =
 			aux_pcm_tx_cfg[SEC_AUX_PCM].sample_rate;
 		channels->min = channels->max =
@@ -3162,6 +3292,8 @@
 		break;
 
 	case MSM_BACKEND_DAI_TERT_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[TERT_AUX_PCM].bit_format);
 		rate->min = rate->max =
 			aux_pcm_rx_cfg[TERT_AUX_PCM].sample_rate;
 		channels->min = channels->max =
@@ -3169,6 +3301,8 @@
 		break;
 
 	case MSM_BACKEND_DAI_TERT_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[TERT_AUX_PCM].bit_format);
 		rate->min = rate->max =
 			aux_pcm_tx_cfg[TERT_AUX_PCM].sample_rate;
 		channels->min = channels->max =
@@ -3176,6 +3310,8 @@
 		break;
 
 	case MSM_BACKEND_DAI_QUAT_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[QUAT_AUX_PCM].bit_format);
 		rate->min = rate->max =
 			aux_pcm_rx_cfg[QUAT_AUX_PCM].sample_rate;
 		channels->min = channels->max =
@@ -3183,6 +3319,8 @@
 		break;
 
 	case MSM_BACKEND_DAI_QUAT_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[QUAT_AUX_PCM].bit_format);
 		rate->min = rate->max =
 			aux_pcm_tx_cfg[QUAT_AUX_PCM].sample_rate;
 		channels->min = channels->max =