Merge "msm: camera: Refactor ISP stream request functions"
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 5fa7c08..3e65b8a 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -247,7 +247,7 @@
 				<85 512 40000 160000>,
 				<85 512 40000 320000>,
 				<85 512 40000 480000>,
-				<85 512 40000 640000>;
+				<85 512 40000 800000>;
 	};
 };
 
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index aea092e..ba36df1 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -370,6 +370,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_SHIRQ=y
+CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index dda9bd3..5885c6e 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -428,6 +428,7 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index f90e5f3..6c18a97 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -510,6 +510,7 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index bae4ee9..72032dc 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -459,6 +459,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_TIMER_STATS=y
+CONFIG_SCHEDSTATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 0eecffd..be0daf3 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -145,7 +145,7 @@
 	select CPU_V7
 	select GPIO_MSM_V2
 	select MSM_GPIOMUX
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_DIRECT_SCLK_ACCESS
 	select REGULATOR
 	select MSM_RPM_REGULATOR
@@ -187,7 +187,7 @@
 	select CPU_V7
 	select GPIO_MSM_V2
 	select MSM_GPIOMUX
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_DIRECT_SCLK_ACCESS
 	select REGULATOR
 	select MSM_RPM_REGULATOR
@@ -223,7 +223,7 @@
 	select GPIO_MSM_V2
 	select ARM_GIC
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_GPIOMUX
 	select MSM_REMOTE_SPINLOCK_SFPB
 	select MSM_PIL
@@ -257,7 +257,7 @@
 	select GPIO_MSM_V3
 	select ARM_GIC
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
 	select MSM_MULTIMEDIA_USE_ION
@@ -292,7 +292,7 @@
 	select GPIO_MSM_V3
 	select ARM_GIC
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
 	select MSM_NATIVE_RESTART
@@ -317,6 +317,25 @@
 	select SPARSE_IRQ
 	select MSM_NOPM
 
+config ARCH_FSM9900
+	bool "FSM9900"
+	select ARCH_MSM_KRAITMP
+	select GPIO_MSM_V3
+	select ARM_GIC
+	select CPU_V7
+	select MSM_SCM
+	select MSM_GPIOMUX
+	select MULTI_IRQ_HANDLER
+	select MSM_PIL
+	select MSM_NATIVE_RESTART
+	select MSM_RESTART_V2
+	select MAY_HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
+	select REGULATOR
+	select ARM_HAS_SG_CHAIN
+	select MSM_RUN_QUEUE_STATS
+	select MSM_NOPM
+
 config ARCH_FSM9XXX
 	bool "FSM9XXX"
 	select ARCH_MSM_SCORPION
@@ -378,7 +397,6 @@
 	select MSM_RESTART_V2
 	select MSM_SPM_V2
 	select MSM_PM8X60 if PM
-	select MSM_SCM if SMP
 	select MULTI_IRQ_HANDLER
 	select GPIO_MSM_V3
 	select MAY_HAVE_SPARSE_IRQ
@@ -414,7 +432,7 @@
 	select GIC_SECURE
 	select ARCH_MSM_CORTEXMP
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MAY_HAVE_SPARSE_IRQ
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
@@ -456,7 +474,7 @@
 	select GIC_SECURE
 	select ARCH_MSM_CORTEXMP
 	select CPU_V7
-	select MSM_SCM if SMP
+	select MSM_SCM
 	select MAY_HAVE_SPARSE_IRQ
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
@@ -1094,6 +1112,7 @@
 	default "0x00000000" if ARCH_MSM8226
 	default "0x00000000" if ARCH_MSM8610
 	default "0x10000000" if ARCH_FSM9XXX
+	default "0x00000000" if ARCH_FSM9900
 	default "0x00200000" if ARCH_MSM9625
 	default "0x00000000" if ARCH_MSMKRYPTON
 	default "0x00200000" if !MSM_STACKED_MEMORY
@@ -1257,6 +1276,14 @@
                 help
                   Say Y here if you want the debug print routines to direct
                   their output to the serial port on MSM9625 devices.
+
+	config DEBUG_FSM9900_UART
+		bool "Kernel low-level debugging messages via FSM9900 UART"
+		depends on ARCH_FSM9900
+		select MSM_HAS_DEBUG_UART_HS_V14
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on FSM9900 devices.
 endchoice
 
 choice
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 400f859..f53b7fe 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -121,6 +121,7 @@
 ifndef CONFIG_ARCH_MSM8610
 ifndef CONFIG_ARCH_APQ8084
 ifndef CONFIG_ARCH_MSMKRYPTON
+ifndef CONFIG_ARCH_FSM9900
 	obj-y += nand_partitions.o
 endif
 endif
@@ -132,6 +133,7 @@
 endif
 endif
 endif
+endif
 obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
 obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
 obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
@@ -230,6 +232,7 @@
 obj-$(CONFIG_ARCH_FSM9XXX) += clock-fsm9xxx.o clock-local.o acpuclock-fsm9xxx.o
 obj-$(CONFIG_ARCH_FSM9XXX) += dfe-fsm9xxx.o rfic-fsm9xxx.o
 obj-$(CONFIG_ARCH_FSM9XXX) += restart-fsm9xxx.o xo-fsm9xxx.o
+obj-$(CONFIG_ARCH_FSM9900) += board-fsm9900.o board-fsm9900-gpiomux.o
 
 obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog.o
 obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog_asm.o
@@ -377,6 +380,7 @@
 obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_APQ8084) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_FSM9900) += gpiomux-v2.o gpiomux.o
 
 obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
 obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_mpdecision.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 2827e65..07969e0 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -93,6 +93,11 @@
 params_phys-$(CONFIG_ARCH_FSM9XXX)	:= 0x10000100
 initrd_phys-$(CONFIG_ARCH_FSM9XXX)	:= 0x12000000
 
+# FSM9900
+   zreladdr-$(CONFIG_ARCH_FSM9900)	:= 0x00008000
+        dtb-$(CONFIG_ARCH_FSM9900)	:= fsm9900-rumi.dtb
+        dtb-$(CONFIG_ARCH_FSM9900)	:= fsm9900-sim.dtb
+
 # MPQ8092
    zreladdr-$(CONFIG_ARCH_MPQ8092)	:= 0x00008000
 
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
index da7c039..5ecc63b 100644
--- a/arch/arm/mach-msm/include/mach/usb_bam.h
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -101,6 +101,7 @@
 * @desc_mem_buf: descriptor fifo buffer.
 * @event: event for wakeup.
 * @enabled: true if pipe is enabled.
+* @ipa_clnt_hdl : pipe handle to ipa api.
 * @priv: private data to return upon activity_notify
 *	or inactivity_notify callbacks.
 * @activity_notify: callback to invoke on activity on one of the in pipes.
@@ -125,6 +126,7 @@
 	struct sps_mem_buffer desc_mem_buf;
 	struct usb_bam_event_info event;
 	bool enabled;
+	int ipa_clnt_hdl;
 	void *priv;
 	int (*activity_notify)(void *priv);
 	int (*inactivity_notify)(void *priv);
@@ -195,6 +197,14 @@
 		struct usb_bam_connect_ipa_params *ipa_params);
 
 /**
+ * Wait for Consumer granted from Resource Manager.
+ *
+ * @ipa_params - in/out parameters
+ *
+ */
+void usb_bam_wait_for_cons_granted(
+	struct usb_bam_connect_ipa_params *ipa_params);
+/**
  * Register a wakeup callback from peer BAM.
  *
  * @idx - Connection index.
@@ -221,6 +231,39 @@
 int usb_bam_register_peer_reset_cb(int (*callback)(void *), void *param);
 
 /**
+ * Register callbacks for start/stop of transfers.
+ *
+ * @start - the callback function that will be called in USB
+ *				driver to start transfers
+ * @stop - the callback function that will be called in USB
+ *				driver to stop transfers
+ *
+ * @param - context that the caller can supply
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int usb_bam_register_start_stop_cbs(
+	void (*start)(void *, enum usb_bam_pipe_dir),
+	void (*stop)(void *, enum usb_bam_pipe_dir),
+	void *param);
+
+/**
+ * Start usb suspend sequence
+ *
+ * @ipa_params -  in/out parameters
+ *
+ */
+void usb_bam_suspend(struct usb_bam_connect_ipa_params *ipa_params);
+
+/**
+ * Start usb resume sequence
+ *
+ * @ipa_params -  in/out parameters
+ *
+ */
+void usb_bam_resume(struct usb_bam_connect_ipa_params *ipa_params);
+/**
  * Disconnect USB-to-Periperal SPS connection.
  *
  * @idx - Connection index.
@@ -315,6 +358,12 @@
 	return -ENODEV;
 }
 
+static inline void usb_bam_wait_for_cons_granted(
+			struct usb_bam_connect_ipa_params *ipa_params)
+{
+	return;
+}
+
 static inline int usb_bam_register_wake_cb(u8 idx,
 	int (*callback)(void *), void* param)
 {
@@ -327,6 +376,20 @@
 	return -ENODEV;
 }
 
+static inline int usb_bam_register_start_stop_cbs(
+	void (*start)(void *, enum usb_bam_pipe_dir),
+	void (*stop)(void *, enum usb_bam_pipe_dir),
+	void *param)
+{
+	return -ENODEV;
+}
+
+static inline void usb_bam_suspend(
+	struct usb_bam_connect_ipa_params *ipa_params){}
+
+static inline void usb_bam_resume(
+	struct usb_bam_connect_ipa_params *ipa_params) {}
+
 static inline int usb_bam_disconnect_pipe(u8 idx)
 {
 	return -ENODEV;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 2c7ceab..62da5ac 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -364,7 +364,7 @@
 {
 	struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
 	void *sel_cdata;
-	int i;
+	long rounded_rate;
 
 	sel_cdata = fabric->cdata[ctx];
 
@@ -379,8 +379,17 @@
 	}
 
 	/* Enable clocks before accessing QoS registers */
-	for (i = 0; i < NUM_CTX; i++)
-		clk_prepare_enable(fabric->info.nodeclk[i].clk);
+	if (fabric->info.nodeclk[DUAL_CTX].clk)
+		if (fabric->info.nodeclk[DUAL_CTX].rate == 0) {
+			rounded_rate = clk_round_rate(fabric->
+				info.nodeclk[DUAL_CTX].clk, 1);
+		if (clk_set_rate(fabric->info.nodeclk[DUAL_CTX].clk,
+				rounded_rate))
+			MSM_BUS_ERR("Error: clk: en: Node: %d rate: %ld",
+				fabric->fabdev.id, rounded_rate);
+
+		clk_prepare_enable(fabric->info.nodeclk[DUAL_CTX].clk);
+	}
 
 	if (info->iface_clk.clk)
 		clk_prepare_enable(info->iface_clk.clk);
@@ -392,8 +401,9 @@
 		master_tiers, add_bw);
 
 	/* Disable clocks after accessing QoS registers */
-	for (i = 0; i < NUM_CTX; i++)
-		clk_disable_unprepare(fabric->info.nodeclk[i].clk);
+	if (fabric->info.nodeclk[DUAL_CTX].clk &&
+			fabric->info.nodeclk[DUAL_CTX].rate == 0)
+		clk_disable_unprepare(fabric->info.nodeclk[DUAL_CTX].clk);
 
 	if (info->iface_clk.clk) {
 		MSM_BUS_DBG("Commented: Will disable clock for info: %d\n",
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 30168b8..098cbd5 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -330,12 +330,13 @@
 
 	drv->crash = true;
 
+	disable_irq_nosync(drv->irq);
+
 	if (drv->restart_inprogress) {
 		pr_err("Ignoring wcnss bite irq, restart in progress\n");
 		return IRQ_HANDLED;
 	}
 
-	disable_irq_nosync(drv->irq);
 	drv->restart_inprogress = true;
 	restart_wcnss(drv);
 
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 9a5883f..19b5671 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -410,12 +410,6 @@
 	drv->err_fatal_irq = ret;
 
 	ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
-					    "qcom,gpio-err-ready", 0));
-	if (ret < 0)
-		return ret;
-	drv->subsys_desc.err_ready_irq = ret;
-
-	ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
 					    "qcom,gpio-proxy-unvote", 0));
 	if (ret < 0)
 		return ret;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 1945651..a177593 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -3939,12 +3939,11 @@
 	}
 
 	registered = true;
-	rc = remote_spin_lock_init(&remote_spinlock, SMEM_SPINLOCK_SMEM_ALLOC);
+	rc = init_smem_remote_spinlock();
 	if (rc) {
 		pr_err("%s: remote spinlock init failed %d\n", __func__, rc);
 		return rc;
 	}
-	spinlocks_initialized = 1;
 
 	rc = platform_driver_register(&msm_smd_driver);
 	if (rc) {
diff --git a/arch/arm/mach-msm/smem.c b/arch/arm/mach-msm/smem.c
index c00f96f..2204609 100644
--- a/arch/arm/mach-msm/smem.c
+++ b/arch/arm/mach-msm/smem.c
@@ -56,6 +56,7 @@
 struct ramdump_segment *smem_ramdump_segments;
 
 static void *smem_ramdump_dev;
+static DEFINE_MUTEX(spinlock_init_lock);
 
 struct restart_notifier_block {
 	unsigned processor;
@@ -215,6 +216,7 @@
 	struct smem_heap_entry *toc = shared->heap_toc;
 	unsigned long flags;
 	void *ret = NULL;
+	int rc;
 
 	if (!shared->heap_info.initialized) {
 		pr_err("%s: smem heap info not initialized\n", __func__);
@@ -224,6 +226,15 @@
 	if (id >= SMEM_NUM_ITEMS)
 		return NULL;
 
+	if (unlikely(!spinlocks_initialized)) {
+		rc = init_smem_remote_spinlock();
+		if (unlikely(rc)) {
+			pr_err("%s: remote spinlock init failed %d\n",
+								__func__, rc);
+			return NULL;
+		}
+	}
+
 	size_in = ALIGN(size_in, 8);
 	remote_spin_lock_irqsave(&remote_spinlock, flags);
 	if (toc[id].allocated) {
@@ -301,6 +312,35 @@
 }
 EXPORT_SYMBOL(smem_get_remote_spinlock);
 
+/**
+ * init_smem_remote_spinlock - Reentrant remote spinlock initialization
+ *
+ * @returns: sucess or error code for failure
+ */
+int init_smem_remote_spinlock(void)
+{
+	int rc = 0;
+
+	/*
+	 * Optimistic locking.  Init only needs to be done once by the first
+	 * caller.  After that, serializing inits between different callers
+	 * is unnecessary.  The second check after the lock ensures init
+	 * wasn't previously completed by someone else before the lock could
+	 * be grabbed.
+	 */
+	if (!spinlocks_initialized) {
+		mutex_lock(&spinlock_init_lock);
+		if (!spinlocks_initialized) {
+			rc = remote_spin_lock_init(&remote_spinlock,
+						SMEM_SPINLOCK_SMEM_ALLOC);
+			if (!rc)
+				spinlocks_initialized = 1;
+		}
+		mutex_unlock(&spinlock_init_lock);
+	}
+	return rc;
+}
+
 static int restart_notifier_cb(struct notifier_block *this,
 				unsigned long code,
 				void *data)
diff --git a/arch/arm/mach-msm/smem_private.h b/arch/arm/mach-msm/smem_private.h
index 89b2b7b..b631e7c 100644
--- a/arch/arm/mach-msm/smem_private.h
+++ b/arch/arm/mach-msm/smem_private.h
@@ -19,7 +19,7 @@
 
 #define SMEM_SPINLOCK_SMEM_ALLOC       "S:3"
 extern remote_spinlock_t remote_spinlock;
-extern int spinlocks_initialized;
+extern int spinlocks_initialized; /* only modify in init_smem_remote_spinlock */
 
 #define SMD_HEAP_SIZE 512
 
@@ -65,4 +65,10 @@
 
 /* used for unit testing spinlocks */
 remote_spinlock_t *smem_get_remote_spinlock(void);
+
+/*
+ * used to ensure the remote spinlock is only inited once since local
+ * spinlock init code appears non-reentrant
+ */
+int init_smem_remote_spinlock(void);
 #endif /* _ARCH_ARM_MACH_MSM_SMEM_PRIVATE_H_ */
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 0e2e2d9..2b14f86 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -2,7 +2,6 @@
 # Makefile for CoreSight drivers.
 #
 obj-$(CONFIG_CORESIGHT) += coresight.o
-obj-$(CONFIG_OF) += of_coresight.o
 obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
 obj-$(CONFIG_CORESIGHT_CSR) += coresight-csr.o
 obj-$(CONFIG_CORESIGHT_TMC) += coresight-tmc.o
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 58fa5c9..2b70d3f 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -717,6 +717,9 @@
 	bool sha1 = false;
 	uint32_t auth_cfg = 0;
 
+	/* clear status */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
 							CRYPTO_CONFIG_REG));
 	/*
@@ -896,6 +899,9 @@
 	uint32_t ivsize = creq->ivsize;
 	int i;
 
+	/* clear status */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
 							CRYPTO_CONFIG_REG));
 	/*
@@ -1213,6 +1219,7 @@
 {
 	struct aead_request *areq;
 	unsigned char mac[SHA256_DIGEST_SIZE];
+	uint32_t status;
 
 	areq = (struct aead_request *) pce_dev->areq;
 	if (areq->src != areq->dst) {
@@ -1227,16 +1234,55 @@
 	/* check MAC */
 	memcpy(mac, (char *)(&pce_dev->ce_sps.result->auth_iv[0]),
 						SHA256_DIGEST_SIZE);
+
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
 
 	if (pce_dev->mode == QCE_MODE_CCM) {
-		uint32_t result_status;
+		int32_t result_status;
+
+		/*
+		 * Don't use result dump status. The operation may not
+		 * be complete.
+		 * Instead, use the status we just read of device.
+		 * In case, we need to use result_status from result
+		 * dump the result_status needs to be byte swapped,
+		 * since we set the device to little endian.
+		 */
+
 		result_status = pce_dev->ce_sps.result->status;
-		result_status &= (1 << CRYPTO_MAC_FAILED);
-		result_status |= (pce_dev->ce_sps.consumer_status |
-					pce_dev->ce_sps.producer_status);
+		pce_dev->ce_sps.result->status = 0;
+
+		if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+			| (1 <<  CRYPTO_HSD_ERR))) {
+
+			pr_err("aead operation error. Status %x\n",
+				status);
+			result_status = -ENXIO;
+		} else if (pce_dev->ce_sps.consumer_status |
+				pce_dev->ce_sps.producer_status)  {
+			pr_err("aead sps operation error. sps status %x %x\n",
+				pce_dev->ce_sps.consumer_status,
+				pce_dev->ce_sps.producer_status);
+			result_status = -ENXIO;
+		} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
+			pr_err("aead operation not done? Status %x, sps status %x %x\n",
+				status,
+				pce_dev->ce_sps.consumer_status,
+				pce_dev->ce_sps.producer_status);
+			result_status = -ENXIO;
+
+		} else if (status & (1 << CRYPTO_MAC_FAILED)) {
+			result_status = -EBADMSG;
+		} else {
+			result_status = 0;
+		}
+
 		pce_dev->qce_cb(areq, mac, NULL, result_status);
+
 	} else {
 		uint32_t ivsize = 0;
 		struct crypto_aead *aead;
@@ -1260,6 +1306,8 @@
 	struct ahash_request *areq;
 	unsigned char digest[SHA256_DIGEST_SIZE];
 	uint32_t bytecount32[2];
+	int32_t result_status = pce_dev->ce_sps.result->status;
+	uint32_t status;
 
 	areq = (struct ahash_request *) pce_dev->areq;
 	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
@@ -1269,10 +1317,39 @@
 	_byte_stream_to_net_words(bytecount32,
 		(unsigned char *)pce_dev->ce_sps.result->auth_byte_count,
 					2 * CRYPTO_REG_SIZE);
+
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
+
+	/*
+	 * Don't use result dump status. The operation may not be complete.
+	 * Instead, use the status we just read of device.
+	 * In case, we need to use result_status from result
+	 * dump the result_status needs to be byte swapped,
+	 * since we set the device to little endian.
+	 */
+
+	if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+			| (1 <<  CRYPTO_HSD_ERR))) {
+
+		pr_err("sha operation error. Status %x\n", status);
+		result_status = -ENXIO;
+	} else if (pce_dev->ce_sps.consumer_status) {
+		pr_err("sha sps operation error. sps status %x\n",
+			pce_dev->ce_sps.consumer_status);
+		result_status = -ENXIO;
+	} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
+		pr_err("sha operation not done? Status %x, sps status %x\n",
+			status, pce_dev->ce_sps.consumer_status);
+		result_status = -ENXIO;
+	} else {
+		result_status = 0;
+	}
 	pce_dev->qce_cb(areq, digest, (char *)bytecount32,
-				pce_dev->ce_sps.consumer_status);
+				result_status);
 	return 0;
 };
 
@@ -1280,6 +1357,8 @@
 {
 	struct ablkcipher_request *areq;
 	unsigned char iv[NUM_OF_CRYPTO_CNTR_IV_REG * CRYPTO_REG_SIZE];
+	uint32_t status;
+	int32_t result_status;
 
 	areq = (struct ablkcipher_request *) pce_dev->areq;
 
@@ -1290,13 +1369,46 @@
 	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 		(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 						DMA_TO_DEVICE);
+
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
 
+	/*
+	 * Don't use result dump status. The operation may not be complete.
+	 * Instead, use the status we just read of device.
+	 * In case, we need to use result_status from result
+	 * dump the result_status needs to be byte swapped,
+	 * since we set the device to little endian.
+	 */
+	if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+			| (1 <<  CRYPTO_HSD_ERR))) {
+		pr_err("ablk_cipher operation error. Status %x\n",
+				status);
+		result_status = -ENXIO;
+	} else if (pce_dev->ce_sps.consumer_status |
+				pce_dev->ce_sps.producer_status)  {
+		pr_err("ablk_cipher sps operation error. sps status %x %x\n",
+				pce_dev->ce_sps.consumer_status,
+				pce_dev->ce_sps.producer_status);
+		result_status = -ENXIO;
+	} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
+		pr_err("ablk_cipher operation not done? Status %x, sps status %x %x\n",
+			status,
+			pce_dev->ce_sps.consumer_status,
+			pce_dev->ce_sps.producer_status);
+		result_status = -ENXIO;
+
+	} else {
+		result_status = 0;
+	}
+
 	if (pce_dev->mode == QCE_MODE_ECB) {
 		pce_dev->qce_cb(areq, NULL, NULL,
 					pce_dev->ce_sps.consumer_status |
-					pce_dev->ce_sps.producer_status);
+					result_status);
 	} else {
 		if (pce_dev->ce_sps.minor_version == 0) {
 			if (pce_dev->mode == QCE_MODE_CBC) {
@@ -1342,9 +1454,7 @@
 				(char *)(pce_dev->ce_sps.result->encr_cntr_iv),
 				sizeof(iv));
 		}
-		pce_dev->qce_cb(areq, NULL, iv,
-			pce_dev->ce_sps.consumer_status |
-			pce_dev->ce_sps.producer_status);
+		pce_dev->qce_cb(areq, NULL, iv, result_status);
 	}
 	return 0;
 };
@@ -1993,6 +2103,9 @@
 	break;
 	}
 
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0, NULL);
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
@@ -2037,13 +2150,9 @@
 	if (mode == QCE_MODE_XTS) {
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG,
 						0, &pcl_info->auth_seg_size);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-						0, &pcl_info->auth_seg_size);
 	} else {
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG,
 						0, &pcl_info->auth_seg_size);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-						0, &pcl_info->auth_seg_size);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_START_REG,
 						0, &pcl_info->auth_seg_size);
 	}
@@ -2130,6 +2239,9 @@
 	break;
 	}
 
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0, NULL);
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
@@ -2156,13 +2268,7 @@
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CNTR1_IV1_REG, 0,
 								NULL);
 	}
-	/* Add dummy to  align size to burst-size multiple */
-	if (!mode_cbc) {
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG,
-						0, &pcl_info->auth_seg_size);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-						0, &pcl_info->auth_seg_size);
-	}
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_le, NULL);
 
@@ -2206,10 +2312,13 @@
 
 		auth_cfg = pdev->reg.auth_cfg_sha1;
 		iv_reg = 5;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-							0, NULL);
 
 	break;
 	case QCE_HASH_SHA256:
@@ -2218,13 +2327,16 @@
 
 		auth_cfg = pdev->reg.auth_cfg_sha256;
 		iv_reg = 8;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-								0, NULL);
 	break;
 	case QCE_HASH_SHA1_HMAC:
 		cmdlistptr->auth_sha1_hmac.cmdlist = (uint32_t)ce_vaddr;
@@ -2233,10 +2345,13 @@
 		auth_cfg = pdev->reg.auth_cfg_hmac_sha1;
 		key_reg = 16;
 		iv_reg = 5;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-							0, NULL);
 	break;
 	case QCE_AEAD_SHA1_HMAC:
 		cmdlistptr->aead_sha1_hmac.cmdlist = (uint32_t)ce_vaddr;
@@ -2245,13 +2360,16 @@
 		auth_cfg = pdev->reg.auth_cfg_aead_sha1_hmac;
 		key_reg = 16;
 		iv_reg = 5;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-							0, NULL);
 	break;
 	case QCE_HASH_SHA256_HMAC:
 		cmdlistptr->auth_sha256_hmac.cmdlist = (uint32_t)ce_vaddr;
@@ -2261,13 +2379,15 @@
 		key_reg = 16;
 		iv_reg = 8;
 
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0,
+					NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-								0, NULL);
 	break;
 	case QCE_HASH_AES_CMAC:
 		if (key_128 == true) {
@@ -2285,13 +2405,16 @@
 			auth_cfg = pdev->reg.auth_cfg_cmac_256;
 			key_reg = 8;
 		}
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0,
+					NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-								0, NULL);
 	break;
 	default:
 		pr_err("Unknown algorithms %d received, exiting now\n", alg);
@@ -2395,10 +2518,13 @@
 
 		key_reg = 8;
 	}
+
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0, NULL);
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
-	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG, 0, NULL);
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_CFG_REG, 0, NULL);
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_START_REG, 0,
 									NULL);
diff --git a/drivers/crypto/msm/qcryptohw_50.h b/drivers/crypto/msm/qcryptohw_50.h
index 1be2702..e93e25c 100644
--- a/drivers/crypto/msm/qcryptohw_50.h
+++ b/drivers/crypto/msm/qcryptohw_50.h
@@ -297,6 +297,7 @@
 #define CRYPTO_DOUT_SIZE_AVAIL_MASK		(0x1F << CRYPTO_DOUT_SIZE_AVAIL)
 #define CRYPTO_DIN_SIZE_AVAIL			21 /* bit 21-25 */
 #define CRYPTO_DIN_SIZE_AVAIL_MASK		(0x1F << CRYPTO_DIN_SIZE_AVAIL)
+#define CRYPTO_HSD_ERR				20
 #define CRYPTO_ACCESS_VIOL			19
 #define CRYPTO_PIPE_ACTIVE_ERR			18
 #define CRYPTO_CFG_CHNG_ERR			17
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index e071650..52340cc 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1454,6 +1454,8 @@
 	}
 	if (ret == 0)
 		device->active_cnt++;
+	trace_kgsl_active_count(device,
+		(unsigned long) __builtin_return_address(0));
 	return ret;
 }
 EXPORT_SYMBOL(kgsl_active_count_get);
@@ -1482,6 +1484,8 @@
 	}
 
 	device->active_cnt++;
+	trace_kgsl_active_count(device,
+		(unsigned long) __builtin_return_address(0));
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_active_count_get_light);
@@ -1504,6 +1508,8 @@
 	kgsl_pwrscale_idle(device);
 	if (device->active_cnt > 1) {
 		device->active_cnt--;
+		trace_kgsl_active_count(device,
+			(unsigned long) __builtin_return_address(0));
 		return;
 	}
 
@@ -1520,6 +1526,8 @@
 	}
 	device->active_cnt--;
 
+	trace_kgsl_active_count(device,
+		(unsigned long) __builtin_return_address(0));
 	if (device->active_cnt == 0)
 		complete(&device->suspend_gate);
 }
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 5f7ee3c..08677ef 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -739,6 +739,30 @@
 			__entry->id, __entry->ts, __entry->age)
 );
 
+TRACE_EVENT(kgsl_active_count,
+
+	TP_PROTO(struct kgsl_device *device, unsigned long ip),
+
+	TP_ARGS(device, ip),
+
+	TP_STRUCT__entry(
+		__string(device_name, device->name)
+		__field(unsigned int, count)
+		__field(unsigned long, ip)
+	),
+
+	TP_fast_assign(
+		__assign_str(device_name, device->name);
+		__entry->count = device->active_cnt;
+		__entry->ip = ip;
+	),
+
+	TP_printk(
+		"d_name=%s active_cnt=%x func=%pf",
+		__get_str(device_name), __entry->count, (void *) __entry->ip
+	)
+);
+
 #endif /* _KGSL_TRACE_H */
 
 /* This part must be outside protection */
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index b3b3b5e..4306b1d 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -83,6 +83,14 @@
 #define QPNP_VADC_M1_LOW_THR_MSB					0x6a
 #define QPNP_VADC_M1_HIGH_THR_LSB				0x6b
 #define QPNP_VADC_M1_HIGH_THR_MSB				0x6c
+#define QPNP_VADC_ACCESS					0xd0
+#define QPNP_VADC_ACCESS_DATA					0xa5
+#define QPNP_VADC_PERH_RESET_CTL3				0xda
+#define QPNP_FOLLOW_OTST2_RB					BIT(3)
+#define QPNP_FOLLOW_WARM_RB					BIT(2)
+#define QPNP_FOLLOW_SHUTDOWN1_RB				BIT(1)
+#define QPNP_FOLLOW_SHUTDOWN2_RB				BIT(0)
+
 #define QPNP_INT_TEST_VAL					0xE1
 
 #define QPNP_VADC_DATA0						0x60
@@ -150,6 +158,40 @@
 	return 0;
 }
 
+static int32_t qpnp_vadc_warm_rst_configure(void)
+{
+	int rc = 0;
+	u8 data = 0;
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("VADC write access failed\n");
+		return rc;
+	}
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_PERH_RESET_CTL3, &data);
+	if (rc < 0) {
+		pr_err("VADC perh reset ctl3 read failed\n");
+		return rc;
+	}
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("VADC write access failed\n");
+		return rc;
+	}
+
+	data |= QPNP_FOLLOW_WARM_RB;
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_PERH_RESET_CTL3, data);
+	if (rc < 0) {
+		pr_err("VADC perh reset ctl3 write failed\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static int32_t qpnp_vadc_enable(bool state)
 {
 	int rc = 0;
@@ -1126,6 +1168,12 @@
 	}
 	vadc->id = fab_id;
 
+	rc = qpnp_vadc_warm_rst_configure();
+	if (rc < 0) {
+		pr_err("Setting perp reset on warm reset failed %d\n", rc);
+		return rc;
+	}
+
 	vadc->vadc_initialized = true;
 	vadc->vadc_iadc_sync_lock = false;
 
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index fcade49..2c2b339 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -75,7 +75,8 @@
 	DMX_FIFO_ERROR, /* Receiver FIFO overrun */
 	DMX_MISSED_ERROR, /* Receiver missed packet */
 	DMX_OK_DECODER_BUF, /* Received OK, new ES data in decoder buffer */
-	DMX_OK_IDX /* Received OK, new index event */
+	DMX_OK_IDX, /* Received OK, new index event */
+	DMX_OK_SCRAMBLING_STATUS, /* Received OK, new scrambling status */
 } ;
 
 
@@ -135,6 +136,7 @@
 		} marker;
 
 		struct dmx_index_event_info idx_event;
+		struct dmx_scrambling_status_event_info scrambling_bits;
 	};
 };
 
@@ -250,6 +252,7 @@
 	int (*ts_insertion_terminate)(struct dmx_ts_feed *feed);
 	int (*ts_insertion_insert_buffer)(struct dmx_ts_feed *feed,
 			char *data, size_t size);
+	int (*get_scrambling_bits)(struct dmx_ts_feed *feed, u8 *value);
 };
 
 /*--------------------------------------------------------------------------*/
@@ -300,6 +303,7 @@
 				struct dmx_secure_mode *sec_mode);
 	int (*oob_command) (struct dmx_section_feed *feed,
 				struct dmx_oob_command *cmd);
+	int (*get_scrambling_bits)(struct dmx_section_feed *feed, u8 *value);
 };
 
 /*--------------------------------------------------------------------------*/
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 2a750a6..6734da8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1796,6 +1796,35 @@
 	return 0;
 }
 
+static int dvb_dmxdev_get_scrambling_bits(struct dmxdev_filter *filter,
+	struct dmx_scrambling_bits *scrambling_bits)
+{
+	struct dmxdev_feed *feed;
+
+	if (!scrambling_bits ||
+		(filter->state != DMXDEV_STATE_GO))
+		return -EINVAL;
+
+	if (filter->type == DMXDEV_TYPE_SEC) {
+		if (filter->feed.sec.feed->get_scrambling_bits)
+			return filter->feed.sec.feed->get_scrambling_bits(
+						filter->feed.sec.feed,
+						&scrambling_bits->value);
+		return -EINVAL;
+	}
+
+	list_for_each_entry(feed, &filter->feed.ts, next) {
+		if (feed->pid == scrambling_bits->pid) {
+			if (feed->ts->get_scrambling_bits)
+				return feed->ts->get_scrambling_bits(feed->ts,
+						&scrambling_bits->value);
+			return -EINVAL;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void dvb_dmxdev_ts_insertion_work(struct work_struct *worker)
 {
 	struct ts_insertion_buffer *ts_buffer =
@@ -2519,6 +2548,13 @@
 			dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
 			spin_unlock(&dmxdevfilter->dev->lock);
 			wake_up_all(&dmxdevfilter->buffer.queue);
+		} else if (dmx_data_ready->status == DMX_OK_SCRAMBLING_STATUS) {
+			event.type = DMX_EVENT_SCRAMBLING_STATUS_CHANGE;
+			event.params.scrambling_status =
+				dmx_data_ready->scrambling_bits;
+			dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
+			spin_unlock(&dmxdevfilter->dev->lock);
+			wake_up_all(&dmxdevfilter->buffer.queue);
 		} else {
 			spin_unlock(&dmxdevfilter->dev->lock);
 		}
@@ -2635,6 +2671,16 @@
 		return 0;
 	}
 
+	if (dmx_data_ready->status == DMX_OK_SCRAMBLING_STATUS) {
+		event.type = DMX_EVENT_SCRAMBLING_STATUS_CHANGE;
+		event.params.scrambling_status =
+			dmx_data_ready->scrambling_bits;
+		dvb_dmxdev_add_event(events, &event);
+		spin_unlock(&dmxdevfilter->dev->lock);
+		wake_up_all(&buffer->queue);
+		return 0;
+	}
+
 	if (dmx_data_ready->status == DMX_OK_DECODER_BUF) {
 		event.type = DMX_EVENT_NEW_ES_DATA;
 		event.params.es_data.buf_handle = dmx_data_ready->buf.handle;
@@ -3938,6 +3984,15 @@
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 
+	case DMX_GET_SCRAMBLING_BITS:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_get_scrambling_bits(dmxdevfilter, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
 	default:
 		ret = -EINVAL;
 		break;
@@ -4193,6 +4248,7 @@
 	struct dmxdev_filter *filter;
 	int active_count = 0;
 	struct dmx_buffer_status buffer_status;
+	struct dmx_scrambling_bits scrambling_bits;
 	const char *pes_feeds[] = {"DEC", "PES", "DVR", "REC"};
 
 	if (!dmxdev)
@@ -4209,23 +4265,32 @@
 				seq_printf(s, "type: SEC, ");
 				seq_printf(s, "PID %04d ",
 						filter->params.sec.pid);
+				scrambling_bits.pid = filter->params.sec.pid;
 			} else {
 				seq_printf(s, "type: %s, ",
 					pes_feeds[filter->params.pes.output]);
 				seq_printf(s, "PID: %04d ",
 						filter->params.pes.pid);
+				scrambling_bits.pid = filter->params.pes.pid;
 			}
 
+			dvb_dmxdev_get_scrambling_bits(filter,
+				&scrambling_bits);
+
 			if (0 == dvb_dmxdev_get_buffer_status(
 						filter, &buffer_status)) {
 				seq_printf(s, "size: %08d, ",
 					buffer_status.size);
 				seq_printf(s, "fullness: %08d, ",
 					buffer_status.fullness);
-				seq_printf(s, "error: %d\n",
+				seq_printf(s, "error: %d, ",
 					buffer_status.error);
+				seq_printf(s, "scramble: %d\n",
+					scrambling_bits.value);
+
 			} else {
-				seq_printf(s, "\n");
+				seq_printf(s, "scramble: %d\n",
+					scrambling_bits.value);
 			}
 		}
 	}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 9844c64..8caa9dd 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -164,6 +164,11 @@
 	return ((buf[1] & 0x1f) << 8) + buf[2];
 }
 
+static inline u16 ts_scrambling_ctrl(const u8 *buf)
+{
+	return (buf[3] >> 6) & 0x3;
+}
+
 static inline u8 payload(const u8 *tsp)
 {
 	if (!(tsp[3] & 0x10))	// no payload?
@@ -1287,6 +1292,32 @@
 static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
 			const u8 *buf, const u8 timestamp[TIMESTAMP_LEN])
 {
+	u16 pid = ts_pid(buf);
+	u8 scrambling_bits = ts_scrambling_ctrl(buf);
+	struct dmx_data_ready dmx_data_ready;
+
+	/*
+	 * Notify on scrambling status change only when we move
+	 * from clear (0) to non-clear and vise-versa
+	 */
+	if ((scrambling_bits && !feed->scrambling_bits) ||
+		(!scrambling_bits && feed->scrambling_bits)) {
+		dmx_data_ready.status = DMX_OK_SCRAMBLING_STATUS;
+		dmx_data_ready.data_length = 0;
+		dmx_data_ready.scrambling_bits.pid = pid;
+		dmx_data_ready.scrambling_bits.old_value =
+			feed->scrambling_bits;
+		dmx_data_ready.scrambling_bits.new_value = scrambling_bits;
+
+		if (feed->type == DMX_TYPE_SEC)
+			feed->data_ready_cb.sec(&feed->filter->filter,
+					&dmx_data_ready);
+		else
+			feed->data_ready_cb.ts(&feed->feed.ts, &dmx_data_ready);
+	}
+
+	feed->scrambling_bits = scrambling_bits;
+
 	switch (feed->type) {
 	case DMX_TYPE_TS:
 		if (!feed->feed.ts.is_filtering)
@@ -2047,6 +2078,7 @@
 	}
 
 	feed->first_cc = 1;
+	feed->scrambling_bits = 0;
 
 	if ((feed->ts_type & TS_PACKET) &&
 		!(feed->ts_type & TS_PAYLOAD_ONLY)) {
@@ -2302,6 +2334,25 @@
 	return ret;
 }
 
+static int dvbdmx_ts_get_scrambling_bits(struct dmx_ts_feed *ts_feed,
+			u8 *value)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+	struct dvb_demux *demux = feed->demux;
+
+	spin_lock(&demux->lock);
+
+	if (!ts_feed->is_filtering) {
+		spin_unlock(&demux->lock);
+		return -EINVAL;
+	}
+
+	*value = feed->scrambling_bits;
+	spin_unlock(&demux->lock);
+
+	return 0;
+}
+
 static int dvbdmx_ts_insertion_insert_buffer(struct dmx_ts_feed *ts_feed,
 			char *data, size_t size)
 {
@@ -2391,6 +2442,7 @@
 	(*ts_feed)->notify_data_read = NULL;
 	(*ts_feed)->set_secure_mode = dmx_ts_set_secure_mode;
 	(*ts_feed)->oob_command = dvbdmx_ts_feed_oob_cmd;
+	(*ts_feed)->get_scrambling_bits = dvbdmx_ts_get_scrambling_bits;
 	(*ts_feed)->ts_insertion_init = NULL;
 	(*ts_feed)->ts_insertion_terminate = NULL;
 	(*ts_feed)->ts_insertion_insert_buffer =
@@ -2557,6 +2609,7 @@
 	dvbdmxfeed->feed.sec.secbufp = 0;
 	dvbdmxfeed->feed.sec.seclen = 0;
 	dvbdmxfeed->first_cc = 1;
+	dvbdmxfeed->scrambling_bits = 0;
 
 	if (!dvbdmx->start_feed) {
 		mutex_unlock(&dvbdmx->mutex);
@@ -2723,6 +2776,25 @@
 	return ret;
 }
 
+static int dvbdmx_section_get_scrambling_bits(
+	struct dmx_section_feed *section_feed, u8 *value)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)section_feed;
+	struct dvb_demux *demux = feed->demux;
+
+	spin_lock(&demux->lock);
+
+	if (!section_feed->is_filtering) {
+		spin_unlock(&demux->lock);
+		return -EINVAL;
+	}
+
+	*value = feed->scrambling_bits;
+	spin_unlock(&demux->lock);
+
+	return 0;
+}
+
 static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
 					struct dmx_section_feed **feed,
 					dmx_section_cb callback)
@@ -2763,6 +2835,7 @@
 	(*feed)->notify_data_read = NULL;
 	(*feed)->set_secure_mode = dmx_section_set_secure_mode;
 	(*feed)->oob_command = dvbdmx_section_feed_oob_cmd;
+	(*feed)->get_scrambling_bits = dvbdmx_section_get_scrambling_bits;
 
 	mutex_unlock(&dvbdmx->mutex);
 	return 0;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index 879aad2..9fb1a12 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -187,6 +187,8 @@
 	int first_cc;
 	int pusi_seen;		/* prevents feeding of garbage from previous section */
 
+	u8 scrambling_bits;
+
 	struct dvb_demux_rec_info *rec_info;
 	u64 prev_tsp_num;
 	u64 prev_stc;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index f3e2f5e..6de6e74 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -38,6 +38,8 @@
 #define VFE_PING_FLAG 0xFFFFFFFF
 #define VFE_PONG_FLAG 0x0
 
+#define VFE_MAX_CFG_TIMEOUT 3000
+
 struct vfe_device;
 struct msm_vfe_axi_stream;
 struct msm_vfe_stats_stream;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 797c7e9..e3d036f6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -845,7 +845,7 @@
 	spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
 	rc = wait_for_completion_interruptible_timeout(
 		&vfe_dev->stream_config_complete,
-		msecs_to_jiffies(500));
+		msecs_to_jiffies(VFE_MAX_CFG_TIMEOUT));
 	if (rc == 0) {
 		pr_err("%s: wait timeout\n", __func__);
 		rc = -1;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index ce71235..d857a14 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -343,7 +343,7 @@
 	atomic_set(&vfe_dev->stats_data.stats_update, 2);
 	rc = wait_for_completion_interruptible_timeout(
 		&vfe_dev->stats_config_complete,
-		msecs_to_jiffies(500));
+		msecs_to_jiffies(VFE_MAX_CFG_TIMEOUT));
 	if (rc == 0) {
 		pr_err("%s: wait timeout\n", __func__);
 		rc = -1;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index fa28d6a..f139b21 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -540,6 +540,8 @@
 	unsigned long flags;
 	struct qseecom_client_listener_data_irsp send_data_rsp;
 	struct qseecom_registered_listener_list *ptr_svc = NULL;
+	sigset_t new_sigset;
+	sigset_t old_sigset;
 
 	while (resp->result == QSEOS_RESULT_INCOMPLETE) {
 		lstnr = resp->data;
@@ -564,17 +566,24 @@
 		}
 		pr_debug("waking up rcv_req_wq and "
 				"waiting for send_resp_wq\n");
-		if (wait_event_freezable(qseecom.send_resp_wq,
-				__qseecom_listener_has_sent_rsp(data))) {
-			pr_warning("Interrupted: exiting send_cmd loop\n");
-			ret = -ERESTARTSYS;
-		}
 
-		if ((data->abort) || (ret == -ERESTARTSYS)) {
+		/* initialize the new signal mask with all signals*/
+		sigfillset(&new_sigset);
+		/* block all signals */
+		sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset);
+
+		do {
+			if (!wait_event_freezable(qseecom.send_resp_wq,
+				__qseecom_listener_has_sent_rsp(data)))
+				break;
+		} while (1);
+
+		/* restore signal mask */
+		sigprocmask(SIG_SETMASK, &old_sigset, NULL);
+		if (data->abort) {
 			pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
 				data->client.app_id, lstnr, ret);
-			if (data->abort)
-				rc = -ENODEV;
+			rc = -ENODEV;
 			send_data_rsp.status  = QSEOS_RESULT_FAILURE;
 		} else {
 			send_data_rsp.status  = QSEOS_RESULT_SUCCESS;
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index fe151b5..acd42ae3 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -107,4 +107,10 @@
 	help
 	  OpenFirmware SLIMBUS accessors
 
+config OF_CORESIGHT
+	def_bool y
+	depends on CORESIGHT
+	help
+	  OpenFirmware CoreSight accessors
+
 endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index c3a31c8..61a99f2 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -15,3 +15,4 @@
 obj-$(CONFIG_OF_SPMI)	+= of_spmi.o
 obj-$(CONFIG_OF_MTD)	+= of_mtd.o
 obj-$(CONFIG_OF_SLIMBUS)	+= of_slimbus.o
+obj-$(CONFIG_OF_CORESIGHT) += of_coresight.o
diff --git a/drivers/coresight/of_coresight.c b/drivers/of/of_coresight.c
similarity index 100%
rename from drivers/coresight/of_coresight.c
rename to drivers/of/of_coresight.c
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 64e8d7a..fc85dba 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -129,15 +129,40 @@
 	[HSIC_BAM]  = hsic_cons_release_resource,
 };
 
-static enum ipa_rm_event cur_prod_state[MAX_BAMS];
-static enum ipa_rm_event cur_cons_state[MAX_BAMS];
-static int sched_lpm;
-static int lpm_wait_handshake;
-static struct completion prod_avail[MAX_BAMS];
-static struct completion cons_avail[MAX_BAMS];
-static struct completion cons_released[MAX_BAMS];
-static struct completion prod_released[MAX_BAMS];
+struct usb_bam_ipa_handshake_info {
+	enum ipa_rm_event cur_prod_state[MAX_BAMS];
+	enum ipa_rm_event cur_cons_state[MAX_BAMS];
 
+	int lpm_wait_handshake;
+	int connect_complete;
+	bool lpm_wait_pipes;
+	int bus_suspend;
+	bool in_lpm;
+
+	int (*wake_cb)(void *);
+	void *wake_param;
+	void (*start)(void *, enum usb_bam_pipe_dir);
+	void (*stop)(void *, enum usb_bam_pipe_dir);
+	void *start_stop_param;
+
+	u32 src_idx;
+	u32 dst_idx;
+	bool cons_stopped;
+	bool prod_stopped;
+
+	struct completion prod_avail[MAX_BAMS];
+	struct completion cons_avail[MAX_BAMS];
+	struct completion cons_released[MAX_BAMS];
+	struct completion prod_released[MAX_BAMS];
+
+	struct mutex suspend_resume_mutex;
+	struct work_struct resume_work;
+	struct work_struct suspend_work;
+	struct work_struct finish_suspend_work;
+};
+
+static spinlock_t usb_bam_ipa_handshake_info_lock;
+static struct usb_bam_ipa_handshake_info info;
 static spinlock_t usb_bam_peer_handshake_info_lock;
 static struct usb_bam_peer_handshake_info peer_handshake_info;
 static spinlock_t usb_bam_lock; /* Protect ctx and usb_bam_connections */
@@ -457,6 +482,7 @@
 		pr_err("%s: ipa_connect failed\n", __func__);
 		return ret;
 	}
+	pipe_connect->ipa_clnt_hdl = clnt_hdl;
 
 	*pipe = sps_alloc_endpoint();
 	if (*pipe == NULL) {
@@ -579,6 +605,31 @@
 	return 0;
 }
 
+static void usb_bam_resume_core(enum usb_bam cur_bam)
+{
+	struct usb_phy *trans = usb_get_transceiver();
+
+	if (cur_bam != HSUSB_BAM)
+		return;
+	BUG_ON(trans == NULL);
+	pr_debug("%s: resume core", __func__);
+	pm_runtime_resume(trans->dev);
+}
+
+static void usb_bam_start_lpm(bool disconnect)
+{
+	struct usb_phy *trans = usb_get_transceiver();
+	BUG_ON(trans == NULL);
+		pr_debug("%s: Going to LPM\n", __func__);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.lpm_wait_handshake = false;
+		info.lpm_wait_pipes = 0;
+	if (disconnect)
+		pm_runtime_put_noidle(trans->dev);
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	pm_runtime_suspend(trans->dev);
+}
+
 int usb_bam_connect(u8 idx, u32 *bam_pipe_idx)
 {
 	int ret;
@@ -608,26 +659,136 @@
 	}
 
 	spin_lock(&usb_bam_lock);
-
 	/* Check if BAM requires RESET before connect and reset of first pipe */
 	if ((pdata->reset_on_connect[pipe_connect->bam_type] == true) &&
 	    (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0))
 		sps_device_reset(ctx.h_bam[pipe_connect->bam_type]);
+	spin_unlock(&usb_bam_lock);
 
 	ret = connect_pipe(idx, bam_pipe_idx);
 	if (ret) {
 		pr_err("%s: pipe connection[%d] failure\n", __func__, idx);
-		spin_unlock(&usb_bam_lock);
 		return ret;
 	}
 
 	pipe_connect->enabled = 1;
+	spin_lock(&usb_bam_lock);
 	ctx.pipes_enabled_per_bam[pipe_connect->bam_type] += 1;
-
 	spin_unlock(&usb_bam_lock);
+
 	return 0;
 }
 
+static int ipa_suspend_pipes(void)
+{
+	struct usb_bam_pipe_connect *dst_pipe_connect, *src_pipe_connect;
+	int ret1, ret2;
+
+	dst_pipe_connect = &usb_bam_connections[info.dst_idx];
+	src_pipe_connect = &usb_bam_connections[info.src_idx];
+
+	if (dst_pipe_connect->ipa_clnt_hdl == -1 ||
+		src_pipe_connect->ipa_clnt_hdl == -1) {
+		pr_err("%s: One of handles is -1, not connected?", __func__);
+	}
+
+	ret1 = ipa_suspend(dst_pipe_connect->ipa_clnt_hdl);
+	if (ret1)
+		pr_err("%s: ipa_suspend on dst failed with %d", __func__, ret1);
+	ret2 = ipa_suspend(src_pipe_connect->ipa_clnt_hdl);
+	if (ret2)
+		pr_err("%s: ipa_suspend on src failed with %d", __func__, ret2);
+
+	return ret1 | ret2;
+}
+
+static int ipa_resume_pipes(void)
+{
+	struct usb_bam_pipe_connect *dst_pipe_connect, *src_pipe_connect;
+	int ret1, ret2;
+
+	src_pipe_connect = &usb_bam_connections[info.src_idx];
+	dst_pipe_connect = &usb_bam_connections[info.dst_idx];
+
+	if (dst_pipe_connect->ipa_clnt_hdl == -1 ||
+		src_pipe_connect->ipa_clnt_hdl == -1) {
+		pr_err("%s: One of handles is -1, not connected?", __func__);
+	}
+
+	ret1 = ipa_resume(dst_pipe_connect->ipa_clnt_hdl);
+	if (ret1)
+		pr_err("%s: ipa_resume on dst failed with %d", __func__, ret1);
+	ret2 = ipa_resume(src_pipe_connect->ipa_clnt_hdl);
+	if (ret2)
+		pr_err("%s: ipa_resume on src failed with %d", __func__, ret2);
+
+	return ret1 | ret2;
+}
+
+static void usb_bam_finish_suspend(void)
+{
+	int ret;
+	u32 cons_empty;
+	struct sps_pipe *cons_pipe = ctx.usb_bam_sps.sps_pipes[info.dst_idx];
+	struct usb_bam_pipe_connect *pipe_connect = &
+			usb_bam_connections[info.dst_idx];
+	enum usb_bam cur_bam = pipe_connect->bam_type;
+
+	if (cur_bam != HSUSB_BAM) {
+		pr_err("%s: Wrong type of BAM=%s\n", __func__,
+			bam_enable_strings[cur_bam]);
+		return;
+	}
+
+	mutex_lock(&info.suspend_resume_mutex);
+
+	/* If resume was called don't finish this work */
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (!info.bus_suspend) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_err("%s: Bus suspend in progress\n", __func__);
+		goto no_lpm;
+	}
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	ret = sps_is_pipe_empty(cons_pipe, &cons_empty);
+	if (ret) {
+		pr_err("%s: sps_is_pipe_empty failed with %d\n", __func__, ret);
+		goto no_lpm;
+	}
+
+	/* Stop CONS transfers and go to lpm if no more data in the pipe */
+	if (cons_empty) {
+		if (info.stop && !info.cons_stopped)
+			info.stop(info.start_stop_param,
+					PEER_PERIPHERAL_TO_USB);
+		pr_err("%s: Starting LPM on Bus Suspend\n", __func__);
+		info.cons_stopped = 1;
+		if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED) {
+			ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
+				ipa_rm_resource_cons[cur_bam]);
+		}
+		ipa_suspend_pipes();
+		mutex_unlock(&info.suspend_resume_mutex);
+		usb_bam_start_lpm(0);
+		return;
+	}
+
+no_lpm:
+
+	/* Finish the handshake. Resume Sequence will start automatically
+	   by the data in the pipes */
+	if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
+				ipa_rm_resource_cons[cur_bam]);
+	mutex_unlock(&info.suspend_resume_mutex);
+}
+
+void usb_bam_finish_suspend_(struct work_struct *w)
+{
+	usb_bam_finish_suspend();
+}
+
 static void usb_prod_notify_cb(void *user_data, enum ipa_rm_event event,
 	unsigned long data)
 {
@@ -637,14 +798,14 @@
 	case IPA_RM_RESOURCE_GRANTED:
 		pr_debug("%s: %s_PROD resource granted\n",
 			__func__, bam_enable_strings[*cur_bam]);
-		cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_GRANTED;
-		complete_all(&prod_avail[*cur_bam]);
+		info.cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_GRANTED;
+		complete_all(&info.prod_avail[*cur_bam]);
 		break;
 	case IPA_RM_RESOURCE_RELEASED:
 		pr_debug("%s: %s_PROD resource released\n",
 			__func__, bam_enable_strings[*cur_bam]);
-		cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_RELEASED;
-		complete_all(&prod_released[*cur_bam]);
+		info.cur_prod_state[*cur_bam] = IPA_RM_RESOURCE_RELEASED;
+		complete_all(&info.prod_released[*cur_bam]);
 		break;
 	default:
 		break;
@@ -657,12 +818,33 @@
 	pr_debug("%s: Request %s_CONS resource\n",
 			__func__, bam_enable_strings[cur_bam]);
 
-	cur_cons_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
-	complete_all(&cons_avail[cur_bam]);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.cur_cons_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
+	complete_all(&info.cons_avail[cur_bam]);
 
-	if (ctx.pipes_enabled_per_bam[cur_bam])
+	spin_lock(&usb_bam_lock);
+	if (ctx.pipes_enabled_per_bam[cur_bam] && info.connect_complete &&
+				!info.bus_suspend && !info.prod_stopped) {
+		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_debug("%s: ACK on cons_request", __func__);
 		return 0;
+	}
 
+	/* A2 wakeup from LPM */
+	if (cur_bam == HSUSB_BAM && ctx.pipes_enabled_per_bam[cur_bam] &&
+		info.connect_complete && info.bus_suspend) {
+		info.bus_suspend = 0;
+		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		if (info.wake_cb)
+			info.wake_cb(info.wake_param);
+	} else {
+		spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	}
+
+	pr_debug("%s: EINPROGRESS on cons_request", __func__);
 	return -EINPROGRESS;
 }
 
@@ -681,12 +863,23 @@
 	pr_debug("%s: Release %s_CONS resource\n",
 			__func__, bam_enable_strings[cur_bam]);
 
-	cur_cons_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
-	complete_all(&cons_released[cur_bam]);
+	info.cur_cons_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
+	complete_all(&info.cons_released[cur_bam]);
 
-	if (!ctx.pipes_enabled_per_bam[cur_bam])
+	spin_lock(&usb_bam_lock);
+	if (!ctx.pipes_enabled_per_bam[cur_bam]) {
+		spin_unlock(&usb_bam_lock);
+		pr_debug("%s: ACK on cons_release", __func__);
 		return 0;
+	}
+	spin_unlock(&usb_bam_lock);
 
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (cur_bam == HSUSB_BAM && info.bus_suspend)
+		queue_work(ctx.usb_bam_wq, &info.finish_suspend_work);
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	pr_debug("%s: EINPROGRESS cons_release", __func__);
 	return -EINPROGRESS;
 }
 
@@ -747,24 +940,24 @@
 
 	pr_debug("%s Request %s_PROD_RES\n", __func__,
 		bam_enable_strings[cur_bam]);
-	if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
+	if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
 		pr_debug("%s: CONS already granted for some reason\n",
 			__func__);
-	if (cur_prod_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
+	if (info.cur_prod_state[cur_bam] == IPA_RM_RESOURCE_GRANTED)
 		pr_debug("%s: PROD already granted for some reason\n",
 			__func__);
 
-	init_completion(&prod_avail[cur_bam]);
-	init_completion(&cons_avail[cur_bam]);
+	init_completion(&info.prod_avail[cur_bam]);
+	init_completion(&info.cons_avail[cur_bam]);
 
 	ret = ipa_rm_request_resource(ipa_rm_resource_prod[cur_bam]);
 	if (!ret) {
-		cur_prod_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
-		complete_all(&prod_avail[cur_bam]);
+		info.cur_prod_state[cur_bam] = IPA_RM_RESOURCE_GRANTED;
+		complete_all(&info.prod_avail[cur_bam]);
 		pr_debug("%s: PROD_GRANTED without wait\n", __func__);
 	} else if (ret == -EINPROGRESS) {
 		pr_debug("%s: Waiting for PROD_GRANTED\n", __func__);
-		if (!wait_for_completion_timeout(&prod_avail[cur_bam],
+		if (!wait_for_completion_timeout(&info.prod_avail[cur_bam],
 			USB_BAM_TIMEOUT))
 			pr_err("%s: Timeout wainting for PROD_GRANTED\n",
 				__func__);
@@ -772,6 +965,261 @@
 		pr_err("%s: ipa_rm_request_resource ret =%d\n", __func__, ret);
 }
 
+void wait_for_cons_granted(enum usb_bam cur_bam)
+{
+	pr_debug("%s: Waiting for CONS\n", __func__);
+	if (info.cur_cons_state[cur_bam] != IPA_RM_RESOURCE_GRANTED) {
+		if (!wait_for_completion_timeout(&info.cons_avail[cur_bam],
+						USB_BAM_TIMEOUT*6))
+			pr_err("%s: Timeout wainting for CONS_REQUEST\n",
+			__func__);
+		pr_err("%s: Finished waiting for CONS\n", __func__);
+	}
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.connect_complete = 1;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	pr_debug("%s: CONS is granted\n", __func__);
+
+	if (info.cur_cons_state[HSUSB_BAM] == IPA_RM_RESOURCE_GRANTED) {
+		pr_debug("%s: Notify CONS_GRANTED\n", __func__);
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
+				 ipa_rm_resource_cons[HSUSB_BAM]);
+	}
+}
+
+void usb_bam_wait_for_cons_granted(
+	struct usb_bam_connect_ipa_params *ipa_params)
+{
+	struct usb_bam_pipe_connect *pipe_connect;
+	enum usb_bam cur_bam;
+	u8 src_idx;
+
+	src_idx = ipa_params->src_idx;
+	pipe_connect = &usb_bam_connections[src_idx];
+	cur_bam = pipe_connect->bam_type;
+
+	wait_for_cons_granted(cur_bam);
+}
+
+static void wait_for_prod_release(enum usb_bam cur_bam)
+{
+	int ret;
+
+	if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		pr_debug("%s consumer already released\n", __func__);
+	 if (info.cur_prod_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		pr_debug("%s producer already released\n", __func__);
+
+	init_completion(&info.prod_released[cur_bam]);
+	init_completion(&info.cons_released[cur_bam]);
+	pr_debug("%s: Releasing %s_PROD\n", __func__,
+				bam_enable_strings[cur_bam]);
+	ret = ipa_rm_release_resource(ipa_rm_resource_prod[cur_bam]);
+	if (!ret) {
+		pr_debug("%s: Released without waiting\n", __func__);
+		info.cur_prod_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
+		complete_all(&info.prod_released[cur_bam]);
+	} else if (ret == -EINPROGRESS) {
+		pr_debug("%s: Waiting for PROD_RELEASED\n", __func__);
+		if (!wait_for_completion_timeout(&info.prod_released[cur_bam],
+						USB_BAM_TIMEOUT))
+			pr_err("%s: Timeout waiting for PROD_RELEASED\n",
+			__func__);
+	} else
+		pr_err("%s: ipa_rm_request_resource ret =%d", __func__, ret);
+}
+
+static int check_pipes_empty(u8 src_idx, u8 dst_idx)
+{
+	struct sps_pipe *prod_pipe, *cons_pipe;
+	u32 prod_empty, cons_empty;
+
+	/* If we have any remaints in the pipes we don't go to sleep */
+	prod_pipe = ctx.usb_bam_sps.sps_pipes[src_idx];
+	cons_pipe = ctx.usb_bam_sps.sps_pipes[dst_idx];
+	if (sps_is_pipe_empty(prod_pipe, &prod_empty) ||
+			sps_is_pipe_empty(cons_pipe, &cons_empty)) {
+		pr_err("%s: sps_is_pipe_empty failed with\n", __func__);
+		return 0;
+	}
+	if (!prod_empty || !cons_empty) {
+		pr_err("%s: pipes not empty prod=%d cond=%d", __func__,
+			prod_empty, cons_empty);
+		return 0;
+	}
+
+	return 1;
+}
+
+void usb_bam_suspend(struct usb_bam_connect_ipa_params *ipa_params)
+{
+	struct usb_bam_pipe_connect *pipe_connect;
+	enum usb_bam cur_bam;
+	u8 src_idx, dst_idx;
+
+	if (!ipa_params) {
+		pr_err("%s: Invalid ipa params\n", __func__);
+		return;
+	}
+
+	src_idx = ipa_params->src_idx;
+	dst_idx = ipa_params->dst_idx;
+
+	if (src_idx >= ctx.max_connections || dst_idx >= ctx.max_connections) {
+		pr_err("%s: Invalid connection index src=%d dst=%d\n",
+			__func__, src_idx, dst_idx);
+	}
+
+	pipe_connect = &usb_bam_connections[src_idx];
+	cur_bam = pipe_connect->bam_type;
+	if (cur_bam != HSUSB_BAM)
+		return;
+
+	info.src_idx = src_idx;
+	info.dst_idx = dst_idx;
+
+	pr_err("%s: Starting suspend sequence(BAM=%s)\n", __func__,
+			bam_enable_strings[cur_bam]);
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.bus_suspend = 1;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	/* Stop PROD transfers */
+	if (info.stop) {
+		spin_lock(&usb_bam_ipa_handshake_info_lock);
+		info.stop(info.start_stop_param, USB_TO_PEER_PERIPHERAL);
+		info.prod_stopped = true;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	}
+
+	/* Don't go to LPM if data in the pipes */
+	if (!check_pipes_empty(src_idx, dst_idx)) {
+		pr_err("%s: pipes not empty, won't start suspend", __func__);
+		return;
+	}
+
+	queue_work(ctx.usb_bam_wq, &info.suspend_work);
+}
+
+static void usb_bam_start_suspend(struct work_struct *w)
+{
+	pr_debug("%s: enter", __func__);
+	mutex_lock(&info.suspend_resume_mutex);
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (!info.bus_suspend) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_err("%s: Resume started, not suspending", __func__);
+		return;
+	}
+
+	/* Stop PROD transfers in case they were started */
+	if (info.stop && !info.prod_stopped) {
+		info.stop(info.start_stop_param, USB_TO_PEER_PERIPHERAL);
+		info.prod_stopped = true;
+	}
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	/* Don't start LPM seq if data in the pipes */
+	if (!check_pipes_empty(info.src_idx, info.dst_idx)) {
+		mutex_unlock(&info.suspend_resume_mutex);
+		return;
+	}
+
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.lpm_wait_handshake = true;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	wait_for_prod_release(HSUSB_BAM);
+
+	mutex_unlock(&info.suspend_resume_mutex);
+	if (info.cur_cons_state[HSUSB_BAM] == IPA_RM_RESOURCE_RELEASED)
+		usb_bam_finish_suspend();
+	else
+		pr_debug("Consumer not released yet\n");
+}
+
+static void usb_bam_finish_resume(struct work_struct *w)
+{
+	struct usb_phy *trans = usb_get_transceiver();
+
+	BUG_ON(trans == NULL);
+	pr_debug("%s: enter", __func__);
+	mutex_lock(&info.suspend_resume_mutex);
+	/* Suspend happened in the meantime */
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (info.bus_suspend) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_err("%s: Bus suspended, not resuming", __func__);
+		mutex_unlock(&info.suspend_resume_mutex);
+		return;
+	}
+	info.lpm_wait_handshake = true;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	wait_for_prod_granted(HSUSB_BAM);
+	wait_for_cons_granted(HSUSB_BAM);
+	if (info.cons_stopped) {
+		ipa_resume_pipes();
+		if (info.start) {
+			pr_debug("%s: Enqueue CONS transfer", __func__);
+			info.start(info.start_stop_param,
+				PEER_PERIPHERAL_TO_USB);
+			info.cons_stopped = 0;
+		}
+	}
+
+	if (info.start) {
+		spin_lock(&usb_bam_ipa_handshake_info_lock);
+		info.start(info.start_stop_param, USB_TO_PEER_PERIPHERAL);
+		info.prod_stopped = false;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	}
+	if (info.cur_cons_state[HSUSB_BAM] == IPA_RM_RESOURCE_GRANTED) {
+		pr_debug("%s: Notify CONS_GRANTED\n", __func__);
+		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
+				 ipa_rm_resource_cons[HSUSB_BAM]);
+	}
+	mutex_unlock(&info.suspend_resume_mutex);
+	pr_debug("%s: done", __func__);
+}
+
+void usb_bam_resume(struct usb_bam_connect_ipa_params *ipa_params)
+{
+	enum usb_bam cur_bam;
+	u8 src_idx, dst_idx;
+	struct usb_bam_pipe_connect *pipe_connect;
+
+	pr_debug("%s: Resuming\n", __func__);
+
+	if (!ipa_params) {
+		pr_err("%s: Invalid ipa params\n", __func__);
+		return;
+	}
+
+	src_idx = ipa_params->src_idx;
+	dst_idx = ipa_params->dst_idx;
+
+	if (src_idx >= ctx.max_connections || dst_idx >= ctx.max_connections) {
+		pr_err("%s: Invalid connection index src=%d dst=%d\n",
+			__func__, src_idx, dst_idx);
+		return;
+	}
+
+	pipe_connect = &usb_bam_connections[src_idx];
+	cur_bam = pipe_connect->bam_type;
+	if (cur_bam != HSUSB_BAM)
+		return;
+
+	info.in_lpm = false;
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.bus_suspend = 0;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+	queue_work(ctx.usb_bam_wq, &info.resume_work);
+}
+
 int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
 	u8 idx;
@@ -800,27 +1248,38 @@
 	pipe_connect = &usb_bam_connections[idx];
 	cur_bam = pipe_connect->bam_type;
 
-	if (cur_bam == HSUSB_BAM) {
-		spin_lock(&usb_bam_lock);
-		sched_lpm = 0;
-		lpm_wait_handshake = 1;
-		spin_unlock(&usb_bam_lock);
-	}
-
 	if (pipe_connect->enabled) {
-		pr_debug("%s: connection %d was already established\n",
+		pr_err("%s: connection %d was already established\n",
 			__func__, idx);
 		return 0;
 	}
 
+	pr_debug("%s: enter", __func__);
+	mutex_lock(&info.suspend_resume_mutex);
+
 	spin_lock(&usb_bam_lock);
+	if (ctx.pipes_enabled_per_bam[cur_bam] == 0) {
+		spin_unlock(&usb_bam_lock);
+		if (cur_bam == HSUSB_BAM) {
+			spin_lock(&usb_bam_ipa_handshake_info_lock);
+			info.lpm_wait_handshake = 1;
+			info.connect_complete = 0;
+			info.lpm_wait_pipes = 1;
+			info.bus_suspend = 0;
+			info.cons_stopped = 0;
+			info.prod_stopped = 0;
+			spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		}
+		usb_bam_resume_core(cur_bam);
+	} else
+		spin_unlock(&usb_bam_lock);
 
 	 /* Check if BAM requires RESET before connect and reset first pipe */
+	 spin_lock(&usb_bam_lock);
 	 if ((pdata->reset_on_connect[cur_bam] == true) &&
 		 (ctx.pipes_enabled_per_bam[cur_bam] == 0))
 			sps_device_reset(ctx.h_bam[cur_bam]);
-
-	spin_unlock(&usb_bam_lock);
+		spin_unlock(&usb_bam_lock);
 
 	if (ipa_params->dir == USB_TO_PEER_PERIPHERAL) {
 		pr_debug("%s: Starting connect sequence\n", __func__);
@@ -830,23 +1289,19 @@
 	ret = connect_pipe_ipa(idx, ipa_params);
 	if (ret) {
 		pr_err("%s: pipe connection failure\n", __func__);
+		mutex_unlock(&info.suspend_resume_mutex);
 		return ret;
 	}
 
 	spin_lock(&usb_bam_lock);
-
 	pipe_connect->enabled = 1;
 	ctx.pipes_enabled_per_bam[cur_bam] += 1;
-
-	if (ipa_params->dir == PEER_PERIPHERAL_TO_USB &&
-		cur_cons_state[cur_bam] == IPA_RM_RESOURCE_GRANTED) {
-		pr_debug("%s: Notify CONS_GRANTED\n", __func__);
-		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
-					 ipa_rm_resource_cons[cur_bam]);
-		pr_debug("%s: Ended connect sequence\n", __func__);
-	}
-
 	spin_unlock(&usb_bam_lock);
+	if (ipa_params->dir == PEER_PERIPHERAL_TO_USB && cur_bam == HSUSB_BAM)
+		wait_for_cons_granted(cur_bam);
+
+	mutex_unlock(&info.suspend_resume_mutex);
+	pr_debug("%s: done", __func__);
 
 	return 0;
 }
@@ -904,6 +1359,14 @@
 			usb_bam_set_inactivity_timer(pipe_connect->bam_type);
 		spin_unlock(&usb_bam_lock);
 
+		/* A2 wakeup not from LPM (CONS was up) */
+		wait_for_prod_granted(pipe_connect->bam_type);
+		if (info.start) {
+			pr_debug("%s: Enqueue PROD transfer", __func__);
+			info.start(info.start_stop_param,
+					USB_TO_PEER_PERIPHERAL);
+		}
+
 		break;
 
 	case USB_BAM_EVENT_INACTIVITY:
@@ -1111,9 +1574,22 @@
 int usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
 	void *param)
 {
+	info.wake_cb = callback;
+	info.wake_param = param;
 	return __usb_bam_register_wake_cb(idx, callback, param, true);
 }
 
+int usb_bam_register_start_stop_cbs(
+	void (*start)(void *, enum usb_bam_pipe_dir),
+	void (*stop)(void *, enum usb_bam_pipe_dir),
+	void *param)
+{
+	info.start = start;
+	info.stop = stop;
+	info.start_stop_param = param;
+	return 0;
+}
+
 int usb_bam_register_peer_reset_cb(int (*callback)(void *), void *param)
 {
 	u32 ret = 0;
@@ -1156,78 +1632,29 @@
 		return 0;
 	}
 
-	spin_lock(&usb_bam_lock);
-
 	ret = disconnect_pipe(idx);
 	if (ret) {
 		pr_err("%s: src pipe disconnection failure\n", __func__);
-		spin_unlock(&usb_bam_lock);
 		return ret;
 	}
 
 	pipe_connect->enabled = 0;
-
+	spin_lock(&usb_bam_lock);
 	if (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0)
 		pr_err("%s: wrong pipes enabled counter for bam_type=%d\n",
 			__func__, pipe_connect->bam_type);
 	else
 		ctx.pipes_enabled_per_bam[pipe_connect->bam_type] -= 1;
-
 	spin_unlock(&usb_bam_lock);
 
 	return 0;
 }
 
-static void usb_bam_start_lpm(void)
-{
-	struct usb_phy *trans = usb_get_transceiver();
-	BUG_ON(trans == NULL);
-	spin_lock(&usb_bam_lock);
-	lpm_wait_handshake = 0;
-	if (sched_lpm) {
-		pr_debug("%s: Going to LPM\n", __func__);
-		spin_unlock(&usb_bam_lock);
-		pm_runtime_resume(trans->dev);
-		pm_runtime_put_noidle(trans->dev);
-		pm_runtime_suspend(trans->dev);
-		return;
-	}
-	spin_unlock(&usb_bam_lock);
-}
-
-static void wait_for_prod_release(enum usb_bam cur_bam)
-{
-	int ret;
-
-	if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
-		pr_debug("%s consumer already released\n", __func__);
-	 if (cur_prod_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
-		pr_debug("%s producer already released\n", __func__);
-
-	init_completion(&prod_released[cur_bam]);
-	init_completion(&cons_released[cur_bam]);
-	pr_debug("%s: Releasing %s_PROD\n", __func__,
-				bam_enable_strings[cur_bam]);
-	ret = ipa_rm_release_resource(ipa_rm_resource_prod[cur_bam]);
-	if (!ret) {
-		pr_debug("%s: Released without waiting\n", __func__);
-		cur_prod_state[cur_bam] = IPA_RM_RESOURCE_RELEASED;
-		complete_all(&prod_released[cur_bam]);
-	} else if (ret == -EINPROGRESS) {
-		pr_debug("%s: Waiting for PROD_RELEASED\n", __func__);
-		if (!wait_for_completion_timeout(&prod_released[cur_bam],
-						USB_BAM_TIMEOUT))
-			pr_err("%s: Timeout waiting for PROD_RELEASED\n",
-			__func__);
-	} else
-		pr_err("%s: ipa_rm_request_resource ret =%d", __func__, ret);
-}
-
 static void wait_for_cons_release(enum usb_bam cur_bam)
 {
 	 pr_debug("%s: Waiting for CONS release\n", __func__);
-	 if (cur_prod_state[cur_bam] != IPA_RM_RESOURCE_RELEASED) {
-		if (!wait_for_completion_timeout(&cons_released[cur_bam],
+	 if (info.cur_cons_state[cur_bam] != IPA_RM_RESOURCE_RELEASED) {
+		if (!wait_for_completion_timeout(&info.cons_released[cur_bam],
 						  USB_BAM_TIMEOUT))
 			pr_err("%s: Timeout wainting for CONS_RELEASE\n",
 				__func__);
@@ -1244,13 +1671,17 @@
 	struct sps_connect *sps_connection;
 	enum usb_bam cur_bam;
 
-
 	if (!ipa_params->prod_clnt_hdl && !ipa_params->cons_clnt_hdl) {
 		pr_err("%s: Both of the handles is missing\n", __func__);
 		return -EINVAL;
 	}
 
 	pr_debug("%s: Starting disconnect sequence\n", __func__);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	info.connect_complete = 0;
+	spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
+	mutex_lock(&info.suspend_resume_mutex);
 	/* Delay USB core to go into lpm before we finish our handshake */
 	if (ipa_params->prod_clnt_hdl) {
 		idx = ipa_params->dst_idx;
@@ -1258,12 +1689,15 @@
 
 		/* Do the release handshake with the A2 via RM */
 		cur_bam = pipe_connect->bam_type;
+		info.lpm_wait_pipes = 1;
 		wait_for_prod_release(cur_bam);
 		/* close USB -> IPA pipe */
+		usb_bam_resume_core(cur_bam);
 		ret = ipa_disconnect(ipa_params->prod_clnt_hdl);
 		if (ret) {
 			pr_err("%s: dst pipe disconnection failure\n",
 				__func__);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
 		sps_connection = &ctx.usb_bam_sps.sps_connections[idx];
@@ -1274,6 +1708,7 @@
 		if (ret) {
 			pr_err("%s: failure to disconnect pipe %d\n",
 				__func__, idx);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
 	}
@@ -1288,6 +1723,7 @@
 		if (ret) {
 			pr_err("%s: src pipe disconnection failure\n",
 				__func__);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
 
@@ -1299,17 +1735,24 @@
 		if (ret) {
 			pr_err("%s: failure to disconnect pipe %d\n",
 				__func__, idx);
+			mutex_unlock(&info.suspend_resume_mutex);
 			return ret;
 		}
-		pr_debug("%s: Notify CONS release\n", __func__);
 
-		if (cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED)
+		pipe_connect->ipa_clnt_hdl = -1;
+
+		if (info.cur_cons_state[cur_bam] == IPA_RM_RESOURCE_RELEASED) {
+			pr_debug("%s Notify CONS _RELEASED\n", __func__);
 			ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
 				ipa_rm_resource_cons[cur_bam]);
+		}
 		pr_debug("%s Ended disconnect sequence\n", __func__);
-		usb_bam_start_lpm();
+		mutex_unlock(&info.suspend_resume_mutex);
+		usb_bam_start_lpm(1);
+		return 0;
 	}
 
+	mutex_unlock(&info.suspend_resume_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(usb_bam_disconnect_ipa);
@@ -1810,18 +2253,23 @@
 		ctx.pipes_enabled_per_bam[i] = 0;
 		ctx.inactivity_timer_ms[i] = 0;
 		ctx.is_bam_inactivity[i] = false;
-		init_completion(&prod_avail[i]);
-		complete(&prod_avail[i]);
-		init_completion(&cons_avail[i]);
-		complete(&cons_avail[i]);
-		init_completion(&cons_released[i]);
-		complete(&cons_released[i]);
-		init_completion(&prod_released[i]);
-		complete(&prod_released[i]);
-		cur_prod_state[i] = IPA_RM_RESOURCE_RELEASED;
-		cur_cons_state[i] = IPA_RM_RESOURCE_RELEASED;
+		init_completion(&info.prod_avail[i]);
+		complete(&info.prod_avail[i]);
+		init_completion(&info.cons_avail[i]);
+		complete(&info.cons_avail[i]);
+		init_completion(&info.cons_released[i]);
+		complete(&info.cons_released[i]);
+		init_completion(&info.prod_released[i]);
+		complete(&info.prod_released[i]);
+		info.cur_prod_state[i] = IPA_RM_RESOURCE_RELEASED;
+		info.cur_cons_state[i] = IPA_RM_RESOURCE_RELEASED;
 	}
 
+	INIT_WORK(&info.resume_work, usb_bam_finish_resume);
+	INIT_WORK(&info.suspend_work, usb_bam_start_suspend);
+	INIT_WORK(&info.finish_suspend_work, usb_bam_finish_suspend_);
+	mutex_init(&info.suspend_resume_mutex);
+
 	spin_lock_init(&usb_bam_peer_handshake_info_lock);
 	INIT_WORK(&peer_handshake_info.reset_event.event_w, usb_bam_sm_work);
 
@@ -1837,8 +2285,8 @@
 		destroy_workqueue(ctx.usb_bam_wq);
 		return ret;
 	}
+	spin_lock_init(&usb_bam_ipa_handshake_info_lock);
 	usb_bam_ipa_create_resources();
-
 	spin_lock_init(&usb_bam_lock);
 
 	return ret;
@@ -1911,14 +2359,14 @@
 
 bool msm_bam_lpm_ok(void)
 {
-	spin_lock(&usb_bam_lock);
-	if (lpm_wait_handshake) {
-		sched_lpm = 1;
-		spin_unlock(&usb_bam_lock);
+	spin_lock(&usb_bam_ipa_handshake_info_lock);
+	if (info.lpm_wait_handshake || info.lpm_wait_pipes) {
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Scheduling LPM for later\n", __func__);
 		return 0;
 	} else {
-		spin_unlock(&usb_bam_lock);
+		info.in_lpm = 1;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Going to LPM now\n", __func__);
 		return 1;
 	}
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index c05f683..b71f903 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -539,9 +539,12 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
-	if (!port->port_usb)
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
 		return;
+	}
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
@@ -552,14 +555,69 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
-	if (!port->port_usb)
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
 		return;
+	}
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
 }
 
+static void gbam_stop_endless_rx(struct gbam_port *port)
+{
+	struct bam_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
+		return;
+	}
+	pr_debug("%s: dequeue\n", __func__);
+
+	status = usb_ep_dequeue(port->port_usb->out, d->rx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+
+}
+static void gbam_stop_endless_tx(struct gbam_port *port)
+{
+	struct bam_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb) {
+		pr_err("%s: port->port_usb is NULL", __func__);
+		return;
+	}
+
+	pr_debug("%s: dequeue\n", __func__);
+	status = usb_ep_dequeue(port->port_usb->in, d->tx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+}
+
+static void gbam_start(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct gbam_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		gbam_start_endless_rx(port);
+	else
+		gbam_start_endless_tx(port);
+}
+
+static void gbam_stop(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct gbam_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		gbam_stop_endless_rx(port);
+	else
+		gbam_stop_endless_tx(port);
+}
+
 static void gbam_start_io(struct gbam_port *port)
 {
 	unsigned long		flags;
@@ -1409,6 +1467,10 @@
 	pr_debug("%s: suspended port %d\n", __func__, port_num);
 
 	usb_bam_register_wake_cb(d->dst_connection_idx, gbam_wake_cb, port);
+	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+		usb_bam_register_start_stop_cbs(gbam_start, gbam_stop, port);
+		usb_bam_suspend(&d->ipa_params);
+	}
 }
 
 void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans)
@@ -1426,4 +1488,6 @@
 	pr_debug("%s: resumed port %d\n", __func__, port_num);
 
 	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
+	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA)
+		usb_bam_resume(&d->ipa_params);
 }
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 2abe2ef..081a09c 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -92,6 +92,7 @@
 	if (!port->port_usb)
 		return;
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("error enqueuing transfer, %d\n", status);
@@ -105,11 +106,40 @@
 	if (!port->port_usb)
 		return;
 
+	pr_debug("%s: enqueue\n", __func__);
 	status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("error enqueuing transfer, %d\n", status);
 }
 
+static void bam_data_stop_endless_rx(struct bam_data_port *port)
+{
+	struct bam_data_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb)
+		return;
+
+	pr_debug("%s: dequeue\n", __func__);
+	status = usb_ep_dequeue(port->port_usb->out, d->rx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+
+}
+static void bam_data_stop_endless_tx(struct bam_data_port *port)
+{
+	struct bam_data_ch_info *d = &port->data_ch;
+	int status;
+
+	if (!port->port_usb)
+		return;
+
+	pr_debug("%s: dequeue\n", __func__);
+	status = usb_ep_dequeue(port->port_usb->in, d->tx_req);
+	if (status)
+		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
+}
+
 static int bam_data_peer_reset_cb(void *param)
 {
 	struct bam_data_port	*port = (struct bam_data_port *)param;
@@ -529,9 +559,28 @@
 	return usb_gadget_wakeup(d_port->cdev->gadget);
 }
 
+static void bam_data_start(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct bam_data_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		bam_data_start_endless_rx(port);
+	else
+		bam_data_start_endless_tx(port);
+}
+
+static void bam_data_stop(void *param, enum usb_bam_pipe_dir dir)
+{
+	struct bam_data_port *port = param;
+
+	if (dir == USB_TO_PEER_PERIPHERAL)
+		bam_data_stop_endless_rx(port);
+	else
+		bam_data_stop_endless_tx(port);
+}
+
 void bam_data_suspend(u8 port_num)
 {
-
 	struct bam_data_port	*port;
 	struct bam_data_ch_info *d;
 
@@ -540,6 +589,11 @@
 
 	pr_debug("%s: suspended port %d\n", __func__, port_num);
 	usb_bam_register_wake_cb(d->dst_connection_idx, bam_data_wake_cb, port);
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+		usb_bam_register_start_stop_cbs(bam_data_start, bam_data_stop,
+									port);
+		usb_bam_suspend(&d->ipa_params);
+	}
 }
 
 void bam_data_resume(u8 port_num)
@@ -553,5 +607,6 @@
 
 	pr_debug("%s: resumed port %d\n", __func__, port_num);
 	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA)
+		usb_bam_resume(&d->ipa_params);
 }
-
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index d4d7ee9..833bab2 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -870,7 +870,7 @@
 		return 0;
 
 	if (motg->pdata->delay_lpm_hndshk_on_disconnect && !msm_bam_lpm_ok())
-		return 0;
+		return -EBUSY;
 
 	disable_irq(motg->irq);
 	host_bus_suspend = !test_bit(MHL, &motg->inputs) && phy->otg->host &&
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index f726e79..1f0efd3 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -287,7 +287,7 @@
 	timeout_count = 100;
 	keys_state = (link0_status >> 28) & 0x7;
 	while ((keys_state != HDCP_KEYS_STATE_VALID) &&
-		timeout_count--) {
+		--timeout_count) {
 		link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
 		keys_state = (link0_status >> 28) & 0x7;
 		DEV_DBG("%s: %s: Keys not ready(%d). s=%d\n, l0=%0x08x",
@@ -320,7 +320,7 @@
 				link0_status);
 			msleep(20);
 		}
-	} while (!an_ready && timeout_count--);
+	} while (!an_ready && --timeout_count);
 
 	if (!timeout_count) {
 		rc = -ETIMEDOUT;
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index aa1eba5..ce9e5b9 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -195,7 +195,7 @@
 	/* write pointer offset in bytes */
 	unsigned int write_offset;
 
-	/* non-zero if data error occured */
+	/* non-zero if data error occurred */
 	int error;
 };
 
@@ -237,7 +237,10 @@
 	 * (dmx_sct_filter_params) and no sections were
 	 * received for the given time.
 	 */
-	DMX_EVENT_SECTION_TIMEOUT = 0x00000400
+	DMX_EVENT_SECTION_TIMEOUT = 0x00000400,
+
+	/* Scrambling bits change between clear and scrambled */
+	DMX_EVENT_SCRAMBLING_STATUS_CHANGE = 0x00000800
 };
 
 enum dmx_oob_cmd {
@@ -256,7 +259,7 @@
 /* Discontinuity indicator was set */
 #define DMX_FILTER_DISCONTINUITY_INDICATOR	0x02
 
-/* PES legnth in PES header is not correct */
+/* PES length in PES header is not correct */
 #define DMX_FILTER_PES_LENGTH_ERROR		0x04
 
 
@@ -412,7 +415,7 @@
 	/*
 	 * The PID the index entry belongs to.
 	 * In case of recording filter, multiple PIDs may exist in the same
-	 * filter through DMX_ADD_PID ioctl and each can be indexed seperatly.
+	 * filter through DMX_ADD_PID ioctl and each can be indexed separately.
 	 */
 	__u16 pid;
 
@@ -423,7 +426,7 @@
 	__u64 match_tsp_num;
 
 	/*
-	 * The TS packet number in the recorded data preceeding
+	 * The TS packet number in the recorded data preceding
 	 * match_tsp_num and has PUSI set.
 	 */
 	__u64 last_pusi_tsp_num;
@@ -432,6 +435,23 @@
 	__u64 stc;
 };
 
+/* Scrambling information associated with DMX_EVENT_SCRAMBLING_STATUS_CHANGE */
+struct dmx_scrambling_status_event_info {
+	/*
+	 * The PID which its scrambling bit status changed.
+	 * In case of recording filter, multiple PIDs may exist in the same
+	 * filter through DMX_ADD_PID ioctl, each may have
+	 * different scrambling bits status.
+	 */
+	__u16 pid;
+
+	/* old value of scrambling bits */
+	__u8 old_value;
+
+	/* new value of scrambling bits */
+	__u8 new_value;
+};
+
 /*
  * Filter's event returned through DMX_GET_EVENT.
  * poll with POLLPRI would block until events are available.
@@ -447,6 +467,7 @@
 		struct dmx_es_data_event_info es_data;
 		struct dmx_marker_event_info marker;
 		struct dmx_index_event_info index;
+		struct dmx_scrambling_status_event_info scrambling_status;
 	} params;
 };
 
@@ -754,6 +775,19 @@
 	__u32 identifier;
 };
 
+struct dmx_scrambling_bits {
+	/*
+	 * The PID to return its scrambling bit value.
+	 * In case of recording filter, multiple PIDs may exist in the same
+	 * filter through DMX_ADD_PID ioctl, each may have different
+	 * scrambling bits status.
+	 */
+	__u16 pid;
+
+	/* Current value of scrambling bits: 0, 1, 2 or 3 */
+	__u8 value;
+};
+
 #define DMX_START                _IO('o', 41)
 #define DMX_STOP                 _IO('o', 42)
 #define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
@@ -784,5 +818,6 @@
 #define DMX_SET_INDEXING_PARAMS _IOW('o', 69, struct dmx_indexing_params)
 #define DMX_SET_TS_INSERTION _IOW('o', 70, struct dmx_set_ts_insertion)
 #define DMX_ABORT_TS_INSERTION _IOW('o', 71, struct dmx_abort_ts_insertion)
+#define DMX_GET_SCRAMBLING_BITS _IOWR('o', 72, struct dmx_scrambling_bits)
 
 #endif /*_DVBDMX_H_*/
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index f551e75..6d7d178 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -3069,4 +3069,32 @@
 	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U =	1<<3,
 };
 
+/**
+ * enum nl80211_connect_failed_reason - connection request failed reasons
+ * @NL80211_CONN_FAIL_MAX_CLIENTS: Maximum number of clients that can be
+ *  handled by the AP is reached.
+ * @NL80211_CONN_FAIL_BLOCKED_CLIENT: Connection request is rejected due to ACL.
+ */
+enum nl80211_connect_failed_reason {
+	NL80211_CONN_FAIL_MAX_CLIENTS,
+	NL80211_CONN_FAIL_BLOCKED_CLIENT,
+};
+
+/**
+ * enum nl80211_acl_policy - access control policy
+ *
+ * Access control policy is applied on a MAC list set by
+ * %NL80211_CMD_START_AP and %NL80211_CMD_SET_MAC_ACL, to
+ * be used with %NL80211_ATTR_ACL_POLICY.
+ *
+ * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
+ *   listed in ACL, i.e. allow all the stations which are not listed
+ *  in ACL to authenticate.
+ * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow the stations which are listed
+ *    in ACL, i.e. deny all the stations which are not listed in ACL.
+ */
+enum nl80211_acl_policy {
+	NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED,
+	NL80211_ACL_POLICY_DENY_UNLESS_LISTED,
+};
 #endif /* __LINUX_NL80211_H */
diff --git a/include/linux/of_coresight.h b/include/linux/of_coresight.h
index 0943dda..eb20e80 100644
--- a/include/linux/of_coresight.h
+++ b/include/linux/of_coresight.h
@@ -13,7 +13,7 @@
 #ifndef __LINUX_OF_CORESIGHT_H
 #define __LINUX_OF_CORESIGHT_H
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_OF_CORESIGHT
 extern struct coresight_platform_data *of_get_coresight_platform_data(
 				struct device *dev, struct device_node *node);
 extern struct coresight_cti_data *of_get_coresight_cti_data(
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 67889bf..952bcb1 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2726,6 +2726,8 @@
 
 #endif /* CONFIG_SMP */
 
+extern struct atomic_notifier_head migration_notifier_head;
+
 extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
 extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
 
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index dc29eb9..fb2b57a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -416,6 +416,26 @@
 	size_t probe_resp_len;
 };
 
+struct mac_address {
+	u8 addr[ETH_ALEN];
+};
+
+/**
+ * struct cfg80211_acl_data - Access control list data
+ *
+ * @acl_policy: ACL policy to be applied on the station's
+ *	entry specified by mac_addr
+ * @n_acl_entries: Number of MAC address entries passed
+ * @mac_addrs: List of MAC addresses of stations to be used for ACL
+ */
+struct cfg80211_acl_data {
+	enum nl80211_acl_policy acl_policy;
+	int n_acl_entries;
+
+	/* Keep it last */
+	struct mac_address mac_addrs[];
+};
+
 /**
  * struct cfg80211_ap_settings - AP configuration
  *
@@ -432,6 +452,8 @@
  * @privacy: the BSS uses privacy
  * @auth_type: Authentication type (algorithm)
  * @inactivity_timeout: time in seconds to determine station's inactivity.
+ * @acl: ACL configuration used by the drivers which has support for
+ *	MAC address based access control
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_beacon_data beacon;
@@ -444,6 +466,7 @@
 	bool privacy;
 	enum nl80211_auth_type auth_type;
 	int inactivity_timeout;
+	const struct cfg80211_acl_data *acl;
 };
 
 /**
@@ -1559,6 +1582,13 @@
  *	later passes to cfg80211_probe_status().
  *
  * @set_noack_map: Set the NoAck Map for the TIDs.
+ * @set_mac_acl: Sets MAC address control list in AP and P2P GO mode.
+ *	Parameters include ACL policy, an array of MAC address of stations
+ *	and the number of MAC addresses. If there is already a list in driver
+ *	this new list replaces the existing one. Driver has to clear its ACL
+ *	when number of MAC addresses entries is passed as 0. Drivers which
+ *	advertise the support for MAC based ACL have to implement this callback.
+ *
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1757,6 +1787,9 @@
 	struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy);
 	int	(*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
 				 struct cfg80211_update_ft_ies_params *ftie);
+
+	int (*set_mac_acl)(struct wiphy *wiphy, struct net_device *dev,
+			   const struct cfg80211_acl_data *params);
 };
 
 /*
@@ -1924,10 +1957,6 @@
 	bool beacon_int_infra_match;
 };
 
-struct mac_address {
-	u8 addr[ETH_ALEN];
-};
-
 struct ieee80211_txrx_stypes {
 	u16 tx, rx;
 };
@@ -2068,6 +2097,9 @@
  * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
  * @ht_capa_mod_mask:  Specify what ht_cap values can be over-ridden.
  *	If null, then none can be over-ridden.
+ *
+ * @max_acl_mac_addrs: Maximum number of MAC addresses that the device
+ *	supports for ACL.
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -2089,6 +2121,8 @@
 	/* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
 	u16 interface_modes;
 
+	u16 max_acl_mac_addrs;
+
 	u32 flags, features;
 
 	u32 ap_sme_capa;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 862e172..1a07d2e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -87,6 +87,8 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/sched.h>
 
+ATOMIC_NOTIFIER_HEAD(migration_notifier_head);
+
 void start_bandwidth_timer(struct hrtimer *period_timer, ktime_t period)
 {
 	unsigned long delta;
@@ -1589,15 +1591,17 @@
 try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
 {
 	unsigned long flags;
-	int cpu, success = 0;
+	int cpu, src_cpu, success = 0;
 
 	smp_wmb();
 	raw_spin_lock_irqsave(&p->pi_lock, flags);
+	src_cpu = task_cpu(p);
+	cpu = src_cpu;
+
 	if (!(p->state & state))
 		goto out;
 
 	success = 1; /* we're going to change ->state */
-	cpu = task_cpu(p);
 
 	if (p->on_rq && ttwu_remote(p, wake_flags))
 		goto stat;
@@ -1634,7 +1638,7 @@
 		p->sched_class->task_waking(p);
 
 	cpu = select_task_rq(p, SD_BALANCE_WAKE, wake_flags);
-	if (task_cpu(p) != cpu) {
+	if (src_cpu != cpu) {
 		wake_flags |= WF_MIGRATED;
 		set_task_cpu(p, cpu);
 	}
@@ -1646,6 +1650,9 @@
 out:
 	raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 
+	if (src_cpu != cpu && task_notify_on_migrate(p))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   cpu, (void *)src_cpu);
 	return success;
 }
 
@@ -5068,6 +5075,7 @@
 static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
 	struct rq *rq_dest, *rq_src;
+	bool moved = false;
 	int ret = 0;
 
 	if (unlikely(!cpu_active(dest_cpu)))
@@ -5094,12 +5102,16 @@
 		set_task_cpu(p, dest_cpu);
 		enqueue_task(rq_dest, p, 0);
 		check_preempt_curr(rq_dest, p, 0);
+		moved = true;
 	}
 done:
 	ret = 1;
 fail:
 	double_rq_unlock(rq_src, rq_dest);
 	raw_spin_unlock(&p->pi_lock);
+	if (moved && task_notify_on_migrate(p))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   dest_cpu, (void *)src_cpu);
 	return ret;
 }
 
@@ -7731,6 +7743,24 @@
 	sched_move_task(task);
 }
 
+static u64 cpu_notify_on_migrate_read_u64(struct cgroup *cgrp,
+					  struct cftype *cft)
+{
+	struct task_group *tg = cgroup_tg(cgrp);
+
+	return tg->notify_on_migrate;
+}
+
+static int cpu_notify_on_migrate_write_u64(struct cgroup *cgrp,
+					   struct cftype *cft, u64 notify)
+{
+	struct task_group *tg = cgroup_tg(cgrp);
+
+	tg->notify_on_migrate = (notify > 0);
+
+	return 0;
+}
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
 static int cpu_shares_write_u64(struct cgroup *cgrp, struct cftype *cftype,
 				u64 shareval)
@@ -8002,6 +8032,11 @@
 #endif /* CONFIG_RT_GROUP_SCHED */
 
 static struct cftype cpu_files[] = {
+	{
+		.name = "notify_on_migrate",
+		.read_u64 = cpu_notify_on_migrate_read_u64,
+		.write_u64 = cpu_notify_on_migrate_write_u64,
+	},
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	{
 		.name = "shares",
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index a1bd252..103730d 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3101,6 +3101,8 @@
 	unsigned int		loop_max;
 };
 
+static DEFINE_PER_CPU(bool, dbs_boost_needed);
+
 /*
  * move_task - move a task from one runqueue to another runqueue.
  * Both runqueues must be locked.
@@ -3111,6 +3113,8 @@
 	set_task_cpu(p, env->dst_cpu);
 	activate_task(env->dst_rq, p, 0);
 	check_preempt_curr(env->dst_rq, p, 0);
+	if (task_notify_on_migrate(p))
+		per_cpu(dbs_boost_needed, env->dst_cpu) = true;
 }
 
 /*
@@ -4541,9 +4545,15 @@
 			 */
 			sd->nr_balance_failed = sd->cache_nice_tries+1;
 		}
-	} else
+	} else {
 		sd->nr_balance_failed = 0;
-
+		if (per_cpu(dbs_boost_needed, this_cpu)) {
+			per_cpu(dbs_boost_needed, this_cpu) = false;
+			atomic_notifier_call_chain(&migration_notifier_head,
+						   this_cpu,
+						   (void *)cpu_of(busiest));
+		}
+	}
 	if (likely(!active_balance)) {
 		/* We were unbalanced, so reset the balancing interval */
 		sd->balance_interval = sd->min_interval;
@@ -4698,6 +4708,12 @@
 out_unlock:
 	busiest_rq->active_balance = 0;
 	raw_spin_unlock_irq(&busiest_rq->lock);
+	if (per_cpu(dbs_boost_needed, target_cpu)) {
+		per_cpu(dbs_boost_needed, target_cpu) = false;
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   target_cpu,
+					   (void *)cpu_of(busiest_rq));
+	}
 	return 0;
 }
 
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 8f32475..f8317df 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1604,6 +1604,7 @@
 	struct task_struct *next_task;
 	struct rq *lowest_rq;
 	int ret = 0;
+	bool moved = false;
 
 	if (!rq->rt.overloaded)
 		return 0;
@@ -1673,6 +1674,7 @@
 
 	deactivate_task(rq, next_task, 0);
 	set_task_cpu(next_task, lowest_rq->cpu);
+	moved = true;
 	activate_task(lowest_rq, next_task, 0);
 	ret = 1;
 
@@ -1683,6 +1685,11 @@
 out:
 	put_task_struct(next_task);
 
+	if (moved && task_notify_on_migrate(next_task))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   cpu_of(lowest_rq),
+					   (void *)cpu_of(rq));
+
 	return ret;
 }
 
@@ -1696,8 +1703,10 @@
 static int pull_rt_task(struct rq *this_rq)
 {
 	int this_cpu = this_rq->cpu, ret = 0, cpu;
-	struct task_struct *p;
+	struct task_struct *p = NULL;
 	struct rq *src_rq;
+	bool moved = false;
+	int src_cpu = 0;
 
 	if (likely(!rt_overloaded(this_rq)))
 		return 0;
@@ -1758,6 +1767,10 @@
 			deactivate_task(src_rq, p, 0);
 			set_task_cpu(p, this_cpu);
 			activate_task(this_rq, p, 0);
+
+			moved = true;
+			src_cpu = cpu_of(src_rq);
+
 			/*
 			 * We continue with the search, just in
 			 * case there's an even higher prio task
@@ -1769,6 +1782,11 @@
 		double_unlock_balance(this_rq, src_rq);
 	}
 
+	if (moved && task_notify_on_migrate(p))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   this_cpu,
+					   (void *)src_cpu);
+
 	return ret;
 }
 
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 451bd4f..5370bcb 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -104,6 +104,8 @@
 struct task_group {
 	struct cgroup_subsys_state css;
 
+	bool notify_on_migrate;
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	/* schedulable entities of this group on each cpu */
 	struct sched_entity **se;
@@ -554,6 +556,11 @@
 	return autogroup_task_group(p, tg);
 }
 
+static inline bool task_notify_on_migrate(struct task_struct *p)
+{
+	return task_group(p)->notify_on_migrate;
+}
+
 /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
 static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
 {
@@ -579,7 +586,10 @@
 {
 	return NULL;
 }
-
+static inline bool task_notify_on_migrate(struct task_struct *p)
+{
+	return false;
+}
 #endif /* CONFIG_CGROUP_SCHED */
 
 static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index ccdfed8..674c1fa 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -505,6 +505,11 @@
 			   ETH_ALEN)))
 		return -EINVAL;
 
+	if (WARN_ON(wiphy->max_acl_mac_addrs &&
+		    (!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME) ||
+		     !rdev->ops->set_mac_acl)))
+		return -EINVAL;
+
 	if (wiphy->addresses)
 		memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e1fa62e..6ed6d3e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -210,6 +210,8 @@
 	[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
 	[NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
 	[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
+	[NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
+	[NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
 	[NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
 	[NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
 	[NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
@@ -1066,6 +1068,11 @@
 			sizeof(*dev->wiphy.ht_capa_mod_mask),
 			dev->wiphy.ht_capa_mod_mask);
 
+	if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
+	    dev->wiphy.max_acl_mac_addrs)
+		NLA_PUT_U32(msg, NL80211_ATTR_MAC_ACL_MAX,
+			    dev->wiphy.max_acl_mac_addrs);
+
 	return genlmsg_end(msg, hdr);
 
  nla_put_failure:
@@ -2105,6 +2112,97 @@
 	return err;
 }
 
+/* This function returns an error or the number of nested attributes */
+static int validate_acl_mac_addrs(struct nlattr *nl_attr)
+{
+	struct nlattr *attr;
+	int n_entries = 0, tmp;
+
+	nla_for_each_nested(attr, nl_attr, tmp) {
+		if (nla_len(attr) != ETH_ALEN)
+			return -EINVAL;
+
+		n_entries++;
+	}
+
+	return n_entries;
+}
+
+/*
+ * This function parses ACL information and allocates memory for ACL data.
+ * On successful return, the calling function is responsible to free the
+ * ACL buffer returned by this function.
+ */
+static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
+						struct genl_info *info)
+{
+	enum nl80211_acl_policy acl_policy;
+	struct nlattr *attr;
+	struct cfg80211_acl_data *acl;
+	int i = 0, n_entries, tmp;
+
+	if (!wiphy->max_acl_mac_addrs)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	if (!info->attrs[NL80211_ATTR_ACL_POLICY])
+		return ERR_PTR(-EINVAL);
+
+	acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
+	if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
+	    acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
+		return ERR_PTR(-EINVAL);
+
+	if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
+		return ERR_PTR(-EINVAL);
+
+	n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
+	if (n_entries < 0)
+		return ERR_PTR(n_entries);
+
+	if (n_entries > wiphy->max_acl_mac_addrs)
+		return ERR_PTR(-ENOTSUPP);
+
+	acl = kzalloc(sizeof(*acl) + (sizeof(struct mac_address) * n_entries),
+		      GFP_KERNEL);
+	if (!acl)
+		return ERR_PTR(-ENOMEM);
+
+	nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
+		memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
+		i++;
+	}
+
+	acl->n_acl_entries = n_entries;
+	acl->acl_policy = acl_policy;
+
+	return acl;
+}
+
+static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct cfg80211_acl_data *acl;
+	int err;
+
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
+
+	if (!dev->ieee80211_ptr->beacon_interval)
+		return -EINVAL;
+
+	acl = parse_acl_data(&rdev->wiphy, info);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+
+	err = rdev->ops->set_mac_acl(&rdev->wiphy, dev, acl);
+
+	kfree(acl);
+
+	return err;
+}
+
 static int nl80211_parse_beacon(struct genl_info *info,
 				struct cfg80211_beacon_data *bcn)
 {
@@ -2251,9 +2349,18 @@
 			info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
 	}
 
+	if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
+		params.acl = parse_acl_data(&rdev->wiphy, info);
+		if (IS_ERR(params.acl))
+			return PTR_ERR(params.acl);
+	}
+
 	err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
 	if (!err)
 		wdev->beacon_interval = params.beacon_interval;
+
+	kfree(params.acl);
+
 	return err;
 }
 
@@ -7063,6 +7170,14 @@
 				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
+		.cmd = NL80211_CMD_SET_MAC_ACL,
+		.doit = nl80211_set_mac_acl,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
+	},
+	{
 		.cmd = NL80211_CMD_UPDATE_FT_IES,
 		.doit = nl80211_update_ft_ies,
 		.policy = nl80211_policy,
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 29703b9..bda43a5 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -2703,7 +2703,7 @@
 	}
 
 	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x01);
-	msleep(250);
+	msleep(20);
 	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
 	pr_debug("%s: leave\n", __func__);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index c2fd2d7..ac26d0c 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -3363,6 +3363,7 @@
 	u32 lbuf_addr_lsw;
 	u32 liomode;
 	u32 io_compressed;
+	int dir = 0;
 
 	if (!ac || ac->apr == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
@@ -3380,15 +3381,21 @@
 	read.seq_id = param->uid;
 	liomode = (NT_MODE | ASYNC_IO_MODE);
 	io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
-	if (ac->io_mode == liomode)
+	if (ac->io_mode == liomode) {
 		lbuf_addr_lsw = (read.buf_addr_lsw - 32);
-	else if (ac->io_mode == io_compressed)
+		/*legacy wma driver case*/
+		dir = IN;
+	} else if (ac->io_mode == io_compressed) {
 		lbuf_addr_lsw = (read.buf_addr_lsw - 64);
-	else
+		dir = OUT;
+	} else {
 		lbuf_addr_lsw = read.buf_addr_lsw;
+		dir = OUT;
+	}
 
-	list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
-		buf_node = list_entry(ptr, struct asm_buffer_node, list);
+	list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
+		buf_node = list_entry(ptr, struct asm_buffer_node,
+			list);
 			if (buf_node->buf_addr_lsw == lbuf_addr_lsw) {
 				read.mem_map_handle = buf_node->mmap_hdl;
 				break;