Merge "defconfig: enable NETFILTER_XT_MATCH_QUOTA2_LOG for data metering"
diff --git a/arch/arm64/configs/vendor/bengal-perf_defconfig b/arch/arm64/configs/vendor/bengal-perf_defconfig
index 395dc68..dea94f3 100644
--- a/arch/arm64/configs/vendor/bengal-perf_defconfig
+++ b/arch/arm64/configs/vendor/bengal-perf_defconfig
@@ -422,6 +422,7 @@
 CONFIG_RPMSG_CHAR=y
 CONFIG_RPMSG_QCOM_GLINK_RPM=y
 CONFIG_RPMSG_QCOM_GLINK_SMEM=y
+CONFIG_MSM_RPM_SMD=y
 CONFIG_QCOM_COMMAND_DB=y
 CONFIG_QCOM_CPUSS_DUMP=y
 CONFIG_QCOM_RUN_QUEUE_STATS=y
diff --git a/arch/arm64/configs/vendor/bengal_defconfig b/arch/arm64/configs/vendor/bengal_defconfig
index fa34788..6cd50a0 100644
--- a/arch/arm64/configs/vendor/bengal_defconfig
+++ b/arch/arm64/configs/vendor/bengal_defconfig
@@ -441,6 +441,7 @@
 CONFIG_RPMSG_CHAR=y
 CONFIG_RPMSG_QCOM_GLINK_RPM=y
 CONFIG_RPMSG_QCOM_GLINK_SMEM=y
+CONFIG_MSM_RPM_SMD=y
 CONFIG_QCOM_COMMAND_DB=y
 CONFIG_QCOM_CPUSS_DUMP=y
 CONFIG_QCOM_RUN_QUEUE_STATS=y
@@ -473,6 +474,7 @@
 CONFIG_PANIC_ON_GLADIATOR_ERROR=y
 CONFIG_QCOM_WATCHDOG_V2=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QCOM_BUS_SCALING=y
 CONFIG_QCOM_GLINK=y
 CONFIG_QCOM_GLINK_PKT=y
 CONFIG_QCOM_SMP2P_SLEEPSTATE=y
diff --git a/arch/arm64/configs/vendor/lito_defconfig b/arch/arm64/configs/vendor/lito_defconfig
index 9e07f4f5..e722335 100644
--- a/arch/arm64/configs/vendor/lito_defconfig
+++ b/arch/arm64/configs/vendor/lito_defconfig
@@ -670,6 +670,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS=y
+CONFIG_DEBUG_MODULE_LOAD_INFO=y
 CONFIG_DEBUG_INFO=y
 CONFIG_PAGE_OWNER=y
 CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c
index 16ac408..35a084b 100644
--- a/drivers/bus/mhi/core/mhi_init.c
+++ b/drivers/bus/mhi/core/mhi_init.c
@@ -1613,7 +1613,6 @@ static int mhi_driver_probe(struct device *dev)
 	struct mhi_event *mhi_event;
 	struct mhi_chan *ul_chan = mhi_dev->ul_chan;
 	struct mhi_chan *dl_chan = mhi_dev->dl_chan;
-	bool auto_start = false;
 	int ret;
 
 	/* bring device out of lpm */
@@ -1632,7 +1631,11 @@ static int mhi_driver_probe(struct device *dev)
 
 		ul_chan->xfer_cb = mhi_drv->ul_xfer_cb;
 		mhi_dev->status_cb = mhi_drv->status_cb;
-		auto_start = ul_chan->auto_start;
+		if (ul_chan->auto_start) {
+			ret = mhi_prepare_channel(mhi_cntrl, ul_chan);
+			if (ret)
+				goto exit_probe;
+		}
 	}
 
 	if (dl_chan) {
@@ -1656,15 +1659,22 @@ static int mhi_driver_probe(struct device *dev)
 
 		/* ul & dl uses same status cb */
 		mhi_dev->status_cb = mhi_drv->status_cb;
-		auto_start = (auto_start || dl_chan->auto_start);
 	}
 
 	ret = mhi_drv->probe(mhi_dev, mhi_dev->id);
+	if (ret)
+		goto exit_probe;
 
-	if (!ret && auto_start)
-		mhi_prepare_for_transfer(mhi_dev);
+	if (dl_chan && dl_chan->auto_start)
+		mhi_prepare_channel(mhi_cntrl, dl_chan);
+
+	mhi_device_put(mhi_dev, MHI_VOTE_DEVICE);
+
+	return ret;
 
 exit_probe:
+	mhi_unprepare_from_transfer(mhi_dev);
+
 	mhi_device_put(mhi_dev, MHI_VOTE_DEVICE);
 
 	return ret;
diff --git a/drivers/bus/mhi/core/mhi_internal.h b/drivers/bus/mhi/core/mhi_internal.h
index 69129b6..bb2379e 100644
--- a/drivers/bus/mhi/core/mhi_internal.h
+++ b/drivers/bus/mhi/core/mhi_internal.h
@@ -878,6 +878,8 @@ void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl);
 int mhi_dtr_init(void);
 void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
 		      struct image_info *img_info);
+int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
+			struct mhi_chan *mhi_chan);
 
 /* isr handlers */
 irqreturn_t mhi_msi_handlr(int irq_number, void *dev);
diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c
index 8e1e2fd..cd77709 100644
--- a/drivers/bus/mhi/core/mhi_main.c
+++ b/drivers/bus/mhi/core/mhi_main.c
@@ -1569,7 +1569,8 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev)
 		state = mhi_get_mhi_state(mhi_cntrl);
 		ee = mhi_cntrl->ee;
 		mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl);
-		MHI_LOG("device ee:%s dev_state:%s\n",
+		MHI_LOG("local ee: %s device ee:%s dev_state:%s\n",
+			TO_MHI_EXEC_STR(ee),
 			TO_MHI_EXEC_STR(mhi_cntrl->ee),
 			TO_MHI_STATE_STR(state));
 	}
@@ -1582,7 +1583,7 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev)
 	write_unlock_irq(&mhi_cntrl->pm_lock);
 
 	/* if device in rddm don't bother processing sys error */
-	if (mhi_cntrl->ee == MHI_EE_RDDM) {
+	if (mhi_cntrl->ee == MHI_EE_RDDM && ee != MHI_EE_DISABLE_TRANSITION) {
 		if (mhi_cntrl->ee != ee) {
 			mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data,
 					     MHI_CB_EE_RDDM);
@@ -1688,8 +1689,8 @@ int mhi_send_cmd(struct mhi_controller *mhi_cntrl,
 	return 0;
 }
 
-static int __mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
-				 struct mhi_chan *mhi_chan)
+int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
+			struct mhi_chan *mhi_chan)
 {
 	int ret = 0;
 
@@ -2076,7 +2077,7 @@ int mhi_prepare_for_transfer(struct mhi_device *mhi_dev)
 		if (!mhi_chan)
 			continue;
 
-		ret = __mhi_prepare_channel(mhi_cntrl, mhi_chan);
+		ret = mhi_prepare_channel(mhi_cntrl, mhi_chan);
 		if (ret) {
 			MHI_ERR("Error moving chan %s,%d to START state\n",
 				mhi_chan->name, mhi_chan->chan);
diff --git a/drivers/bus/mhi/devices/mhi_satellite.c b/drivers/bus/mhi/devices/mhi_satellite.c
index 9fff109..d9de31a 100644
--- a/drivers/bus/mhi/devices/mhi_satellite.c
+++ b/drivers/bus/mhi/devices/mhi_satellite.c
@@ -235,14 +235,15 @@ enum mhi_sat_state {
 	SAT_DISCONNECTED, /* rpmsg link is down */
 	SAT_FATAL_DETECT, /* device is down as fatal error was detected early */
 	SAT_ERROR, /* device is down after error or graceful shutdown */
-	SAT_DISABLED, /* set if rpmsg link goes down after device is down */
+	SAT_DISABLED, /* no further processing: wait for device removal */
 };
 
 #define MHI_SAT_ACTIVE(cntrl) (cntrl->state == SAT_RUNNING)
-#define MHI_SAT_FATAL_DETECT(cntrl) (cntrl->state == SAT_FATAL_DETECT)
+#define MHI_SAT_IN_ERROR_STATE(cntrl) (cntrl->state >= SAT_FATAL_DETECT)
 #define MHI_SAT_ALLOW_CONNECTION(cntrl) (cntrl->state == SAT_READY || \
 					 cntrl->state == SAT_DISCONNECTED)
-#define MHI_SAT_IN_ERROR_STATE(cntrl) (cntrl->state >= SAT_FATAL_DETECT)
+#define MHI_SAT_ALLOW_SYS_ERR(cntrl) (cntrl->state == SAT_RUNNING || \
+					cntrl->state == SAT_FATAL_DETECT)
 
 struct mhi_sat_cntrl {
 	struct list_head node;
@@ -940,10 +941,15 @@ static void mhi_sat_dev_status_cb(struct mhi_device *mhi_dev,
 
 	MHI_SAT_LOG("Device fatal error detected\n");
 	spin_lock_irqsave(&sat_cntrl->state_lock, flags);
-	if (MHI_SAT_ACTIVE(sat_cntrl))
+	if (MHI_SAT_ACTIVE(sat_cntrl)) {
 		sat_cntrl->error_cookie = async_schedule(mhi_sat_error_worker,
 							 sat_cntrl);
-	sat_cntrl->state = SAT_FATAL_DETECT;
+		sat_cntrl->state = SAT_FATAL_DETECT;
+	} else {
+		/* rpmsg link down or HELLO not sent or an error occurred */
+		sat_cntrl->state = SAT_DISABLED;
+	}
+
 	spin_unlock_irqrestore(&sat_cntrl->state_lock, flags);
 }
 
@@ -968,7 +974,7 @@ static void mhi_sat_dev_remove(struct mhi_device *mhi_dev)
 
 	/* send sys_err if first device is removed */
 	spin_lock_irq(&sat_cntrl->state_lock);
-	if (MHI_SAT_ACTIVE(sat_cntrl) || MHI_SAT_FATAL_DETECT(sat_cntrl))
+	if (MHI_SAT_ALLOW_SYS_ERR(sat_cntrl))
 		send_sys_err = true;
 	sat_cntrl->state = SAT_ERROR;
 	spin_unlock_irq(&sat_cntrl->state_lock);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index c13f049..c1a3b89 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -263,6 +263,7 @@ struct smq_invoke_ctx {
 	struct fastrpc_buf *lbuf;
 	size_t used;
 	struct fastrpc_file *fl;
+	uint32_t handle;
 	uint32_t sc;
 	struct overlap *overs;
 	struct overlap **overps;
@@ -365,6 +366,8 @@ struct fastrpc_apps {
 	bool legacy_remote_heap;
 	/* Unique job id for each message */
 	uint64_t jobid[NUM_CHANNELS];
+	struct wakeup_source *wake_source;
+	unsigned int wake_count;
 };
 
 struct fastrpc_mmap {
@@ -446,6 +449,8 @@ struct fastrpc_file {
 	/* Identifies the device (MINOR_NUM_DEV / MINOR_NUM_SECURE_DEV) */
 	int dev_minor;
 	char *debug_buf;
+	/* Flag to enable PM wake/relax voting for every remote invoke */
+	int wake_enable;
 };
 
 static struct fastrpc_apps gfa;
@@ -1319,6 +1324,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
 			goto bail;
 	}
 	ctx->crc = (uint32_t *)invokefd->crc;
+	ctx->handle = invoke->handle;
 	ctx->sc = invoke->sc;
 	if (bufs) {
 		VERIFY(err, 0 == context_build_overlap(ctx));
@@ -2025,7 +2031,36 @@ static void fastrpc_init(struct fastrpc_apps *me)
 	me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL;
 }
 
-static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl);
+static inline void fastrpc_pm_awake(int fl_wake_enable, int *wake_enable)
+{
+	struct fastrpc_apps *me = &gfa;
+
+	if (!fl_wake_enable)
+		return;
+
+	spin_lock(&me->hlock);
+	if (!me->wake_count)
+		__pm_stay_awake(me->wake_source);
+	me->wake_count++;
+	spin_unlock(&me->hlock);
+	*wake_enable = 1;
+}
+
+static inline void fastrpc_pm_relax(int *wake_enable)
+{
+	struct fastrpc_apps *me = &gfa;
+
+	if (!(*wake_enable))
+		return;
+
+	spin_lock(&me->hlock);
+	if (me->wake_count)
+		me->wake_count--;
+	if (!me->wake_count)
+		__pm_relax(me->wake_source);
+	spin_unlock(&me->hlock);
+	*wake_enable = 0;
+}
 
 static inline int fastrpc_wait_for_response(struct smq_invoke_ctx *ctx,
 						uint32_t kernel)
@@ -2083,8 +2118,8 @@ static void fastrpc_wait_for_completion(struct smq_invoke_ctx *ctx,
 			if (!err) {
 				ctx->isWorkDone = true;
 			} else if (!ctx->isWorkDone) {
-				pr_info("poll timeout ctxid 0x%llx sc 0x%x\n",
-					 ctx->ctxid, ctx->sc);
+				pr_info("adsprpc: %s: %s: poll timeout for handle 0x%x, sc 0x%x\n",
+				__func__, current->comm, ctx->handle, ctx->sc);
 				interrupted = fastrpc_wait_for_response(ctx,
 									kernel);
 				*pInterrupted = interrupted;
@@ -2102,8 +2137,9 @@ static void fastrpc_wait_for_completion(struct smq_invoke_ctx *ctx,
 			break;
 
 		default:
-			pr_err("adsprpc: unsupported response flags 0x%x\n",
-				 ctx->rspFlags);
+			*pInterrupted = -EBADR;
+			pr_err("Error: adsprpc: %s: unsupported response flags 0x%x for handle 0x%x, sc 0x%x\n",
+			current->comm, ctx->rspFlags, ctx->handle, ctx->sc);
 			return;
 		} /* end of switch */
 	} /* end of while loop */
@@ -2135,10 +2171,11 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
 	struct fastrpc_ioctl_invoke *invoke = &inv->inv;
 	int cid = fl->cid;
 	int interrupted = 0;
-	int err = 0;
+	int err = 0, wake_enable = 0;
 	struct timespec invoket = {0};
 	int64_t *perf_counter = NULL;
 
+	fastrpc_pm_awake(fl->wake_enable, &wake_enable);
 	if (fl->profile) {
 		perf_counter = getperfcounter(fl, PERF_COUNT);
 		getnstimeofday(&invoket);
@@ -2158,7 +2195,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
 
 	VERIFY(err, fl->cid >= 0 && fl->cid < NUM_CHANNELS && fl->sctx != NULL);
 	if (err) {
-		pr_err("adsprpc: ERROR: %s: user application %s domain is not set\n",
+		pr_err("adsprpc: ERROR: %s: kernel session not initialized yet for %s\n",
 			__func__, current->comm);
 		err = -EBADR;
 		goto bail;
@@ -2204,15 +2241,17 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
 	if (err)
 		goto bail;
  wait:
+	fastrpc_pm_relax(&wake_enable);
 	fastrpc_wait_for_completion(ctx, &interrupted, kernel);
+	fastrpc_pm_awake(fl->wake_enable, &wake_enable);
 	VERIFY(err, 0 == (err = interrupted));
 	if (err)
 		goto bail;
 
-	VERIFY(err, ctx->isWorkDone);
-	if (err) {
-		pr_err("adsprpc: ctx work done failed, sc 0x%x handle 0x%x\n",
-				ctx->sc, invoke->handle);
+	if (!ctx->isWorkDone) {
+		err = -EPROTO;
+		pr_err("Error: adsprpc: %s: %s: WorkDone state is invalid for handle 0x%x, sc 0x%x\n",
+			__func__, current->comm, invoke->handle, ctx->sc);
 		goto bail;
 	}
 
@@ -2240,6 +2279,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
 	if (fl->profile && !interrupted)
 		fastrpc_update_invoke_count(invoke->handle, perf_counter,
 						&invoket);
+	fastrpc_pm_relax(&wake_enable);
 	return err;
 }
 
@@ -3204,9 +3244,12 @@ static int fastrpc_session_alloc_locked(struct fastrpc_channel_ctx *chan,
 				break;
 			}
 		}
-		VERIFY(err, idx < chan->sesscount);
-		if (err)
+		if (idx >= chan->sesscount) {
+			err = -EUSERS;
+			pr_err("adsprpc: ERROR %d: %s: max concurrent sessions limit (%d) already reached on %s\n",
+				err, __func__, chan->sesscount, chan->subsys);
 			goto bail;
+		}
 		chan->session[idx].smmu.faults = 0;
 	} else {
 		VERIFY(err, me->dev != NULL);
@@ -3710,7 +3753,7 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
 
 	VERIFY(err, fl && fl->sctx && fl->cid >= 0 && fl->cid < NUM_CHANNELS);
 	if (err) {
-		pr_err("adsprpc: ERROR: %s: user application %s domain is not set\n",
+		pr_err("adsprpc: ERROR: %s: kernel session not initialized yet for %s\n",
 			__func__, current->comm);
 		err = -EBADR;
 		return err;
@@ -3852,8 +3895,8 @@ static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
 		fl->cid = cid;
 		fl->ssrcount = fl->apps->channel[cid].ssrcount;
 		mutex_lock(&fl->apps->channel[cid].smd_mutex);
-		VERIFY(err, 0 == (err = fastrpc_session_alloc_locked(
-				&fl->apps->channel[cid], 0, &fl->sctx)));
+		err = fastrpc_session_alloc_locked(&fl->apps->channel[cid],
+				0, &fl->sctx);
 		mutex_unlock(&fl->apps->channel[cid].smd_mutex);
 		if (err)
 			goto bail;
@@ -3899,8 +3942,11 @@ static int fastrpc_internal_control(struct fastrpc_file *fl,
 	case FASTRPC_CONTROL_KALLOC:
 		cp->kalloc.kalloc_support = 1;
 		break;
+	case FASTRPC_CONTROL_WAKELOCK:
+		fl->wake_enable = cp->wp.enable;
+		break;
 	default:
-		err = -ENOTTY;
+		err = -EBADRQC;
 		break;
 	}
 bail:
@@ -4014,6 +4060,7 @@ static int fastrpc_control(struct fastrpc_ioctl_control *cp,
 bail:
 	return err;
 }
+
 static int fastrpc_get_dsp_info(struct fastrpc_ioctl_dsp_capabilities *dsp_cap,
 				void *param, struct fastrpc_file *fl)
 {
@@ -4789,11 +4836,19 @@ static int __init fastrpc_device_init(void)
 
 	err = register_rpmsg_driver(&fastrpc_rpmsg_client);
 	if (err) {
-		pr_err("adsprpc: register_rpmsg_driver: failed with err %d\n",
-			err);
+		pr_err("adsprpc: %s: register_rpmsg_driver failed with err %d\n",
+			__func__, err);
 		goto device_create_bail;
 	}
 	me->rpmsg_register = 1;
+
+	me->wake_source = wakeup_source_register("adsprpc");
+	VERIFY(err, !IS_ERR_OR_NULL(me->wake_source));
+	if (err) {
+		pr_err("adsprpc: Error: %s: wakeup_source_register failed with err %d\n",
+					__func__, PTR_ERR(me->wake_source));
+		goto device_create_bail;
+	}
 	return 0;
 device_create_bail:
 	for (i = 0; i < NUM_CHANNELS; i++) {
@@ -4844,6 +4899,8 @@ static void __exit fastrpc_device_exit(void)
 	unregister_chrdev_region(me->dev_no, NUM_CHANNELS);
 	if (me->rpmsg_register == 1)
 		unregister_rpmsg_driver(&fastrpc_rpmsg_client);
+	if (me->wake_source)
+		wakeup_source_unregister(me->wake_source);
 	debugfs_remove_recursive(debugfs_root);
 }
 
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 571f585..c1e5af9 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -234,23 +234,32 @@ struct fastrpc_ioctl_perf {			/* kernel performance data */
 	uintptr_t keys;
 };
 
-#define FASTRPC_CONTROL_LATENCY	(1)
+enum fastrpc_control_type {
+	FASTRPC_CONTROL_LATENCY		=	1,
+	FASTRPC_CONTROL_SMMU		=	2,
+	FASTRPC_CONTROL_KALLOC		=	3,
+	FASTRPC_CONTROL_WAKELOCK	=	4,
+};
+
 struct fastrpc_ctrl_latency {
 	uint32_t enable;	/* latency control enable */
 	uint32_t latency;	/* latency request in us */
 };
 
-#define FASTRPC_CONTROL_KALLOC	(3)
 struct fastrpc_ctrl_kalloc {
 	uint32_t kalloc_support;  /* Remote memory allocation from kernel */
 };
 
-/* FASTRPC_CONTROL value 2 is reserved in user space */
+struct fastrpc_ctrl_wakelock {
+	uint32_t enable;	/* wakelock control enable */
+};
+
 struct fastrpc_ioctl_control {
 	uint32_t req;
 	union {
 		struct fastrpc_ctrl_latency lp;
 		struct fastrpc_ctrl_kalloc kalloc;
+		struct fastrpc_ctrl_wakelock wp;
 	};
 };
 
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 950d04c..9cfe1c1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1044,6 +1044,7 @@ static void diag_init_apps_feature(void)
 
 	SET_APPS_FEATURE(driver, F_DIAG_EVENT_REPORT);
 	SET_APPS_FEATURE(driver, F_DIAG_HW_ACCELERATION);
+	SET_APPS_FEATURE(driver, F_DIAG_MULTI_SIM_MASK);
 }
 
 void diag_send_error_rsp(unsigned char *buf, int len,
diff --git a/drivers/clk/qcom/camcc-lito.c b/drivers/clk/qcom/camcc-lito.c
index 20c3295..e7900c8 100644
--- a/drivers/clk/qcom/camcc-lito.c
+++ b/drivers/clk/qcom/camcc-lito.c
@@ -324,7 +324,7 @@ static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = {
 	},
 };
 
-static const struct alpha_pll_config cam_cc_pll2_config = {
+static struct alpha_pll_config cam_cc_pll2_config = {
 	.l = 0x32,
 	.cal_l = 0x32,
 	.alpha = 0x0,
@@ -2319,6 +2319,7 @@ static const struct qcom_cc_desc cam_cc_lito_desc = {
 
 static const struct of_device_id cam_cc_lito_match_table[] = {
 	{ .compatible = "qcom,lito-camcc" },
+	{ .compatible = "qcom,lito-camcc-v2" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, cam_cc_lito_match_table);
@@ -2361,6 +2362,10 @@ static int cam_cc_lito_probe(struct platform_device *pdev)
 
 	clk_lucid_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config);
 	clk_lucid_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config);
+
+	if (of_device_is_compatible(pdev->dev.of_node, "qcom,lito-camcc-v2"))
+		cam_cc_pll2_config.test_ctl_val = 0x00000000;
+
 	clk_zonda_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config);
 	clk_lucid_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config);
 	clk_lucid_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config);
diff --git a/drivers/clk/qcom/clk-voter.c b/drivers/clk/qcom/clk-voter.c
index 1ffc5e5..b8f585f 100644
--- a/drivers/clk/qcom/clk-voter.c
+++ b/drivers/clk/qcom/clk-voter.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2019, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/clk.h>
@@ -126,6 +126,16 @@ static unsigned long voter_clk_recalc_rate(struct clk_hw *hw,
 	return v->rate;
 }
 
+int voter_clk_handoff(struct clk_hw *hw)
+{
+	struct clk_voter *v = to_clk_voter(hw);
+
+	v->enabled = true;
+
+	return 0;
+}
+EXPORT_SYMBOL(voter_clk_handoff);
+
 const struct clk_ops clk_ops_voter = {
 	.prepare = voter_clk_prepare,
 	.unprepare = voter_clk_unprepare,
diff --git a/drivers/clk/qcom/clk-voter.h b/drivers/clk/qcom/clk-voter.h
index b9a36f6..57333bb 100644
--- a/drivers/clk/qcom/clk-voter.h
+++ b/drivers/clk/qcom/clk-voter.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2019, The Linux Foundation. All rights reserved.
  */
 
 #ifndef __QCOM_CLK_VOTER_H__
@@ -27,6 +27,7 @@ extern const struct clk_ops clk_ops_voter;
 		.hw.init = &(struct clk_init_data){			   \
 			.ops = &clk_ops_voter,				   \
 			.name = #clk_name,				   \
+			.flags = CLK_ENABLE_HAND_OFF,			   \
 			.parent_names = (const char *[]){ #_parent_name }, \
 			.num_parents = 1,				   \
 		},							   \
@@ -38,4 +39,6 @@ extern const struct clk_ops clk_ops_voter;
 #define DEFINE_CLK_BRANCH_VOTER(clk_name, _parent_name) \
 	 __DEFINE_CLK_VOTER(clk_name, _parent_name, 1000, 1)
 
+int voter_clk_handoff(struct clk_hw *hw);
+
 #endif
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index a9bcfbb..d00c6f5 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -3227,12 +3227,17 @@ static void _aead_aes_fb_stage1_ahash_complete(
 		unsigned char *tmp;
 
 		tmp = kmalloc(ctx->authsize, GFP_KERNEL);
+		if (!tmp) {
+			err = -ENOMEM;
+			goto ret;
+		}
 		scatterwalk_map_and_copy(tmp, rctx->fb_aes_src,
 			req->cryptlen - ctx->authsize, ctx->authsize, 0);
 		if (memcmp(rctx->fb_ahash_digest, tmp, ctx->authsize) != 0)
 			err = -EBADMSG;
 		kfree(tmp);
 	}
+ret:
 	if (err)
 		_qcrypto_aead_aes_192_fb_a_cb(rctx, err);
 	else {
@@ -3359,6 +3364,10 @@ static int _qcrypto_aead_aes_192_fallback(struct aead_request *req,
 			unsigned char *tmp;
 
 			tmp = kmalloc(ctx->authsize, GFP_KERNEL);
+			if (!tmp) {
+				rc = -ENOMEM;
+				goto ret;
+			}
 			/* compare icv */
 			scatterwalk_map_and_copy(tmp,
 				src, req->cryptlen - ctx->authsize,
diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c
index 7495487..b6c699f 100644
--- a/drivers/gpu/msm/adreno_a6xx_gmu.c
+++ b/drivers/gpu/msm/adreno_a6xx_gmu.c
@@ -346,7 +346,7 @@ static int a6xx_gmu_start(struct kgsl_device *device)
 	u32 mask = 0x000001FF;
 
 	/* Check for 0xBABEFACE on legacy targets */
-	if (gmu->ver.core <= 0x20010003) {
+	if (gmu->ver.core <= 0x20010004) {
 		val = 0xBABEFACE;
 		mask = 0xFFFFFFFF;
 	}
@@ -1156,31 +1156,11 @@ static int a6xx_gmu_load_firmware(struct kgsl_device *device)
 
 #define A6XX_VBIF_XIN_HALT_CTRL1_ACKS   (BIT(0) | BIT(1) | BIT(2) | BIT(3))
 
-static void a6xx_isense_disable(struct kgsl_device *device)
-{
-	unsigned int val;
-	const struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-
-	if (!ADRENO_FEATURE(adreno_dev, ADRENO_LM) ||
-		!test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag))
-		return;
-
-	gmu_core_regread(device, A6XX_GPU_CS_ENABLE_REG, &val);
-	if (val) {
-		gmu_core_regwrite(device, A6XX_GPU_CS_ENABLE_REG, 0);
-		gmu_core_regwrite(device, A6XX_GMU_ISENSE_CTRL, 0);
-	}
-}
-
 static int a6xx_gmu_suspend(struct kgsl_device *device)
 {
 	int ret = 0;
 	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
 
-	/* do it only if LM feature is enabled */
-	/* Disable ISENSE if it's on */
-	a6xx_isense_disable(device);
-
 	/* If SPTP_RAC is on, turn off SPTP_RAC HS */
 	a6xx_gmu_sptprac_disable(ADRENO_DEVICE(device));
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index fe0a4b5..41047a0 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -3624,12 +3624,16 @@ long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv,
 	unsigned int cmd, void *data)
 {
 	struct kgsl_process_private *process = dev_priv->process_priv;
+	struct kgsl_device *device = dev_priv->device;
 	struct kgsl_sparse_phys_alloc *param = data;
 	struct kgsl_mem_entry *entry;
 	uint64_t flags;
 	int ret;
 	int id;
 
+	if (!(device->flags & KGSL_FLAG_SPARSE))
+		return -ENOTSUPP;
+
 	ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
 	if (ret)
 		return ret;
@@ -3713,9 +3717,13 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv,
 	unsigned int cmd, void *data)
 {
 	struct kgsl_process_private *process = dev_priv->process_priv;
+	struct kgsl_device *device = dev_priv->device;
 	struct kgsl_sparse_phys_free *param = data;
 	struct kgsl_mem_entry *entry;
 
+	if (!(device->flags & KGSL_FLAG_SPARSE))
+		return -ENOTSUPP;
+
 	entry = kgsl_sharedmem_find_id_flags(process, param->id,
 			KGSL_MEMFLAGS_SPARSE_PHYS);
 	if (entry == NULL)
@@ -3745,10 +3753,14 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
 	unsigned int cmd, void *data)
 {
 	struct kgsl_process_private *private = dev_priv->process_priv;
+	struct kgsl_device *device = dev_priv->device;
 	struct kgsl_sparse_virt_alloc *param = data;
 	struct kgsl_mem_entry *entry;
 	int ret;
 
+	if (!(device->flags & KGSL_FLAG_SPARSE))
+		return -ENOTSUPP;
+
 	ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
 	if (ret)
 		return ret;
@@ -3789,9 +3801,13 @@ long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv,
 	unsigned int cmd, void *data)
 {
 	struct kgsl_process_private *process = dev_priv->process_priv;
+	struct kgsl_device *device = dev_priv->device;
 	struct kgsl_sparse_virt_free *param = data;
 	struct kgsl_mem_entry *entry = NULL;
 
+	if (!(device->flags & KGSL_FLAG_SPARSE))
+		return -ENOTSUPP;
+
 	entry = kgsl_sharedmem_find_id_flags(process, param->id,
 			KGSL_MEMFLAGS_SPARSE_VIRT);
 	if (entry == NULL)
@@ -4138,6 +4154,7 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
 		unsigned int cmd, void *data)
 {
 	struct kgsl_process_private *private = dev_priv->process_priv;
+	struct kgsl_device *device = dev_priv->device;
 	struct kgsl_sparse_bind *param = data;
 	struct kgsl_sparse_binding_object obj;
 	struct kgsl_mem_entry *virt_entry;
@@ -4146,6 +4163,9 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
 	int ret = 0;
 	int i = 0;
 
+	if (!(device->flags & KGSL_FLAG_SPARSE))
+		return -ENOTSUPP;
+
 	ptr = (void __user *) (uintptr_t) param->list;
 
 	if (param->size > sizeof(struct kgsl_sparse_binding_object) ||
@@ -4201,6 +4221,9 @@ long kgsl_ioctl_gpu_sparse_command(struct kgsl_device_private *dev_priv,
 	long result;
 	unsigned int i = 0;
 
+	if (!(device->flags & KGSL_FLAG_SPARSE))
+		return -ENOTSUPP;
+
 	/* Make sure sparse and syncpoint count isn't too big */
 	if (param->numsparse > KGSL_MAX_SPARSE ||
 		param->numsyncs > KGSL_MAX_SYNCPOINTS)
@@ -5011,6 +5034,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
 	if (status)
 		return status;
 
+	/* Disable the sparse ioctl invocation as they are not used */
+	device->flags &= ~KGSL_FLAG_SPARSE;
+
 	kgsl_device_debugfs_init(device);
 
 	status = kgsl_pwrctrl_init(device);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index e1979cd..8813993 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -50,6 +50,7 @@ enum kgsl_event_results {
 };
 
 #define KGSL_FLAG_WAKE_ON_TOUCH BIT(0)
+#define KGSL_FLAG_SPARSE        BIT(1)
 
 /*
  * "list" of event types for ftrace symbolic magic
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index d449e60..3ab671d 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -115,6 +115,7 @@ struct geni_i2c_dev {
 	struct msm_gpi_dma_async_tx_cb_param rx_cb;
 	enum i2c_se_mode se_mode;
 	bool cmd_done;
+	bool is_shared;
 };
 
 struct geni_i2c_err_log {
@@ -420,15 +421,6 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 	struct geni_i2c_dev *gi2c = i2c_get_adapdata(adap);
 	int i, ret = 0, timeout = 0;
 
-	ret = pinctrl_select_state(gi2c->i2c_rsc.geni_pinctrl,
-				gi2c->i2c_rsc.geni_gpio_active);
-	if (ret) {
-		GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
-			"%s: Error %d pinctrl_select_state active\n",
-			__func__, ret);
-		return ret;
-	}
-
 	if (!gi2c->tx_c) {
 		gi2c->tx_c = dma_request_slave_channel(gi2c->dev, "tx");
 		if (!gi2c->tx_c) {
@@ -647,8 +639,6 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 geni_i2c_gsi_xfer_out:
 	if (!ret && gi2c->err)
 		ret = gi2c->err;
-	pinctrl_select_state(gi2c->i2c_rsc.geni_pinctrl,
-				gi2c->i2c_rsc.geni_gpio_sleep);
 	return ret;
 }
 
@@ -907,6 +897,11 @@ static int geni_i2c_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	if (of_property_read_bool(pdev->dev.of_node, "qcom,shared")) {
+		gi2c->is_shared = true;
+		dev_info(&pdev->dev, "Multi-EE usecase\n");
+	}
+
 	if (of_property_read_u32(pdev->dev.of_node, "qcom,clk-freq-out",
 				&gi2c->i2c_rsc.clk_freq_out)) {
 		dev_info(&pdev->dev,
@@ -984,12 +979,14 @@ static int geni_i2c_runtime_suspend(struct device *dev)
 {
 	struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
 
-	if (gi2c->se_mode == FIFO_SE_DMA) {
+	if (gi2c->se_mode == FIFO_SE_DMA)
 		disable_irq(gi2c->irq);
-		se_geni_resources_off(&gi2c->i2c_rsc);
-	} else {
-		/* GPIO is set to sleep state already. So just clocks off */
+
+	if (gi2c->is_shared) {
+		/* Do not unconfigure GPIOs if shared se */
 		se_geni_clks_off(&gi2c->i2c_rsc);
+	} else {
+		se_geni_resources_off(&gi2c->i2c_rsc);
 	}
 	return 0;
 }
@@ -1006,10 +1003,7 @@ static int geni_i2c_runtime_resume(struct device *dev)
 		gi2c->ipcl = ipc_log_context_create(2, ipc_name, 0);
 	}
 
-	if (gi2c->se_mode != GSI_ONLY)
-		ret = se_geni_resources_on(&gi2c->i2c_rsc);
-	else
-		ret = se_geni_clks_on(&gi2c->i2c_rsc);
+	ret = se_geni_resources_on(&gi2c->i2c_rsc);
 
 	if (ret)
 		return ret;
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 5299eea..11f7366 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -856,6 +856,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called zylonite-wm97xx.
 
+config SECURE_TOUCH_SYNAPTICS_DSX
+	bool "Secure Touch"
+	depends on TOUCHSCREEN_SYNAPTICS_DSX_I2C
+	help
+	  Say Y here to enable Secure Touch in supported driver.
+
+	  If unsure, say N.
+
+	  To compile the supported driver with Secure Touch enabled,
+	  choose M here.
+
 config TOUCHSCREEN_USB_COMPOSITE
 	tristate "USB Touchscreen Driver"
 	depends on USB_ARCH_HAS_HCD
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
index e4ff2ea..4e2dc13 100755
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
@@ -45,6 +45,16 @@
 #ifdef KERNEL_ABOVE_2_6_38
 #include <linux/input/mt.h>
 #endif
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+#include <linux/errno.h>
+#include <soc/qcom/scm.h>
+enum subsystem {
+	TZ = 1,
+	APSS = 3
+};
+
+#define TZ_BLSP_MODIFY_OWNERSHIP_ID 3
+#endif
 
 #include <linux/completion.h>
 
@@ -182,17 +192,18 @@ static ssize_t synaptics_rmi4_synad_pid_store(struct device *dev,
 static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj,
 		struct kobj_attribute *attr, char *buf);
 
-struct synaptics_rmi4_f01_device_status {
-	union {
-		struct {
-			unsigned char status_code:4;
-			unsigned char reserved:2;
-			unsigned char flash_prog:1;
-			unsigned char unconfigured:1;
-		} __packed;
-		unsigned char data[1];
-	};
-};
+static irqreturn_t synaptics_rmi4_irq(int irq, void *data);
+
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+static ssize_t synaptics_rmi4_secure_touch_enable_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_secure_touch_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t synaptics_rmi4_secure_touch_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+#endif
 
 struct synaptics_rmi4_f11_query_0_5 {
 	union {
@@ -705,6 +716,14 @@ static struct device_attribute attrs[] = {
 	__ATTR(wake_gesture, 0664,
 			synaptics_rmi4_wake_gesture_show,
 			synaptics_rmi4_wake_gesture_store),
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+	__ATTR(secure_touch_enable, 0664,
+			synaptics_rmi4_secure_touch_enable_show,
+			synaptics_rmi4_secure_touch_enable_store),
+	__ATTR(secure_touch, 0444,
+			synaptics_rmi4_secure_touch_show,
+			NULL),
+#endif
 #ifdef USE_DATA_SERVER
 	__ATTR(synad_pid, 0220,
 			synaptics_rmi4_show_error,
@@ -720,6 +739,224 @@ static struct kobj_attribute virtual_key_map_attr = {
 	.show = synaptics_rmi4_virtual_key_map_show,
 };
 
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+static int synaptics_rmi4_i2c_change_pipe_owner(
+		struct synaptics_rmi4_data *rmi4_data, enum subsystem subsystem)
+{
+	struct scm_desc desc;
+	struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+	int ret = 0;
+
+	desc.arginfo = SCM_ARGS(2);
+	desc.args[0] = i2c->adapter->nr;
+	desc.args[1] = subsystem;
+
+	ret = scm_call2(SCM_SIP_FNID(SCM_SVC_TZ, TZ_BLSP_MODIFY_OWNERSHIP_ID),
+			&desc);
+	if (ret) {
+		dev_err(rmi4_data->pdev->dev.parent, "%s: failed\n",
+				__func__);
+		return ret;
+	}
+
+	return desc.ret[0];
+}
+
+static void synaptics_rmi4_secure_touch_init(struct synaptics_rmi4_data *data)
+{
+	data->st_initialized = false;
+	init_completion(&data->st_powerdown);
+	init_completion(&data->st_irq_processed);
+
+	/* Get clocks */
+	data->core_clk = devm_clk_get(data->pdev->dev.parent, "core_clk");
+	if (IS_ERR(data->core_clk)) {
+		dev_dbg(data->pdev->dev.parent,
+				"%s: error on clk_get(core_clk): %ld\n",
+				__func__, PTR_ERR(data->core_clk));
+		data->core_clk = NULL;
+	}
+
+	data->iface_clk = devm_clk_get(data->pdev->dev.parent, "iface_clk");
+	if (IS_ERR(data->iface_clk)) {
+		dev_dbg(data->pdev->dev.parent,
+				"%s: error on clk_get(iface_clk): %ld\n",
+				__func__, PTR_ERR(data->iface_clk));
+		data->iface_clk = NULL;
+	}
+	data->st_initialized = true;
+}
+
+static void synaptics_rmi4_secure_touch_notify(
+		struct synaptics_rmi4_data *rmi4_data)
+{
+	sysfs_notify(&rmi4_data->input_dev->dev.kobj, NULL, "secure_touch");
+}
+
+static irqreturn_t synaptics_rmi4_filter_interrupt(
+		struct synaptics_rmi4_data *rmi4_data)
+{
+	if (atomic_read(&rmi4_data->st_enabled)) {
+		if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, 0, 1) == 0) {
+			reinit_completion(&rmi4_data->st_irq_processed);
+			synaptics_rmi4_secure_touch_notify(rmi4_data);
+			wait_for_completion_interruptible(
+					&rmi4_data->st_irq_processed);
+		}
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+/*
+ * 'blocking' variable will have value 'true' when we want to prevent the driver
+ * from accessing the xPU/SMMU protected HW resources while the session is
+ * active.
+ */
+static void synaptics_rmi4_secure_touch_stop(
+		struct synaptics_rmi4_data *rmi4_data, bool blocking)
+{
+	if (atomic_read(&rmi4_data->st_enabled)) {
+		atomic_set(&rmi4_data->st_pending_irqs, -1);
+		synaptics_rmi4_secure_touch_notify(rmi4_data);
+		if (blocking)
+			wait_for_completion_interruptible(
+					&rmi4_data->st_powerdown);
+	}
+}
+
+#else
+static void synaptics_rmi4_secure_touch_init(
+		struct synaptics_rmi4_data *rmi4_data)
+{
+}
+
+static irqreturn_t synaptics_rmi4_filter_interrupt(
+		struct synaptics_rmi4_data *rmi4_data)
+{
+	return IRQ_NONE;
+}
+
+static void synaptics_rmi4_secure_touch_stop(
+		struct synaptics_rmi4_data *rmi4_data, bool blocking)
+{
+}
+#endif
+
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+static ssize_t synaptics_rmi4_secure_touch_enable_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d",
+			atomic_read(&rmi4_data->st_enabled));
+}
+
+/*
+ * Accept only "0" and "1" valid values.
+ * "0" will reset the st_enabled flag, then wake up the reading process and
+ * the interrupt handler.
+ * The bus driver is notified via pm_runtime that it is not required to stay
+ * awake anymore.
+ * It will also make sure the queue of events is emptied in the controller,
+ * in case a touch happened in between the secure touch being disabled and
+ * the local ISR being ungated.
+ * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
+ * The bus driver is requested via pm_runtime to stay awake.
+ */
+static ssize_t synaptics_rmi4_secure_touch_enable_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+	unsigned long value;
+	int err = 0;
+
+	if (count > 2)
+		return -EINVAL;
+
+	if (!rmi4_data->st_initialized)
+		return -EIO;
+
+	err = kstrtoul(buf, 10, &value);
+	if (err)
+		return err;
+
+	err = count;
+
+	switch (value) {
+	case 0:
+		if (atomic_read(&rmi4_data->st_enabled) == 0)
+			break;
+		synaptics_rmi4_i2c_change_pipe_owner(rmi4_data, APSS);
+		synaptics_rmi4_bus_put(rmi4_data);
+		atomic_set(&rmi4_data->st_enabled, 0);
+		synaptics_rmi4_secure_touch_notify(rmi4_data);
+		complete(&rmi4_data->st_irq_processed);
+		synaptics_rmi4_irq(rmi4_data->irq, rmi4_data);
+		complete(&rmi4_data->st_powerdown);
+
+		break;
+	case 1:
+		if (atomic_read(&rmi4_data->st_enabled)) {
+			err = -EBUSY;
+			break;
+		}
+		synchronize_irq(rmi4_data->irq);
+
+		if (synaptics_rmi4_bus_get(rmi4_data) < 0) {
+			dev_err(rmi4_data->pdev->dev.parent,
+					"synaptics_rmi4_bus_get failed\n");
+			err = -EIO;
+			break;
+		}
+		synaptics_rmi4_i2c_change_pipe_owner(rmi4_data, TZ);
+		reinit_completion(&rmi4_data->st_powerdown);
+		reinit_completion(&rmi4_data->st_irq_processed);
+		atomic_set(&rmi4_data->st_enabled, 1);
+		atomic_set(&rmi4_data->st_pending_irqs,  0);
+		break;
+	default:
+		dev_err(rmi4_data->pdev->dev.parent,
+				"unsupported value: %lu\n", value);
+		err = -EINVAL;
+		break;
+	}
+	return err;
+}
+
+/*
+ * This function returns whether there are pending interrupts, or
+ * other error conditions that need to be signaled to the userspace library,
+ * according tot he following logic:
+ * - st_enabled is 0 if secure touch is not enabled, returning -EBADF
+ * - st_pending_irqs is -1 to signal that secure touch is in being stopped,
+ *   returning -EINVAL
+ * - st_pending_irqs is 1 to signal that there is a pending irq, returning
+ *   the value "1" to the sysfs read operation
+ * - st_pending_irqs is 0 (only remaining case left) if the pending interrupt
+ *   has been processed, so the interrupt handler can be allowed to continue.
+ */
+static ssize_t synaptics_rmi4_secure_touch_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+	int val = 0;
+
+	if (atomic_read(&rmi4_data->st_enabled) == 0)
+		return -EBADF;
+	if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, -1, 0) == -1)
+		return -EINVAL;
+	if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, 1, 0) == 1)
+		val = 1;
+	else
+		complete(&rmi4_data->st_irq_processed);
+
+	return scnprintf(buf, PAGE_SIZE, "%u", val);
+}
+#endif
+
 static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
@@ -1673,10 +1910,9 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
 		bool report)
 {
 	int retval;
-	unsigned char data[MAX_INTR_REGISTERS + 1];
-	unsigned char *intr = &data[1];
+	unsigned char *data = NULL;
+	unsigned char *intr;
 	bool was_in_bl_mode;
-	struct synaptics_rmi4_f01_device_status status;
 	struct synaptics_rmi4_fn *fhandler;
 	struct synaptics_rmi4_exp_fhandler *exp_fhandler;
 	struct synaptics_rmi4_device_info *rmi;
@@ -1687,6 +1923,14 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
 	 * Get interrupt status information from F01 Data1 register to
 	 * determine the source(s) that are flagging the interrupt.
 	 */
+	data = kcalloc((MAX_INTR_REGISTERS + 1), sizeof(char), GFP_KERNEL);
+	if (!data) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
+	intr = &data[1];
+
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			rmi4_data->f01_data_base_addr,
 			data,
@@ -1695,31 +1939,31 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read interrupt status\n",
 				__func__);
-		return retval;
+		goto exit;
 	}
 
-	status.data[0] = data[0];
-	if (status.status_code == STATUS_CRC_IN_PROGRESS) {
+	rmi4_data->status.data[0] = data[0];
+	if (rmi4_data->status.status_code == STATUS_CRC_IN_PROGRESS) {
 		retval = synaptics_rmi4_check_status(rmi4_data,
 				&was_in_bl_mode);
 		if (retval < 0) {
 			dev_err(rmi4_data->pdev->dev.parent,
 					"%s: Failed to check status\n",
 					__func__);
-			return retval;
+			goto exit;
 		}
 		retval = synaptics_rmi4_reg_read(rmi4_data,
 				rmi4_data->f01_data_base_addr,
-				status.data,
-				sizeof(status.data));
+				rmi4_data->status.data,
+				sizeof(rmi4_data->status.data));
 		if (retval < 0) {
 			dev_err(rmi4_data->pdev->dev.parent,
 					"%s: Failed to read device status\n",
 					__func__);
-			return retval;
+			goto exit;
 		}
 	}
-	if (status.unconfigured && !status.flash_prog) {
+	if (rmi4_data->status.unconfigured && !rmi4_data->status.flash_prog) {
 		pr_notice("%s: spontaneous reset detected\n", __func__);
 		retval = synaptics_rmi4_reinit_device(rmi4_data);
 		if (retval < 0) {
@@ -1730,7 +1974,7 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
 	}
 
 	if (!report)
-		return retval;
+		goto exit;
 
 	/*
 	 * Traverse the function handler list and service the source(s)
@@ -1758,7 +2002,8 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
 		}
 	}
 	mutex_unlock(&exp_data.mutex);
-
+exit:
+	kfree(data);
 	return retval;
 }
 
@@ -1768,6 +2013,9 @@ static irqreturn_t synaptics_rmi4_irq(int irq, void *data)
 	const struct synaptics_dsx_board_data *bdata =
 			rmi4_data->hw_if->board_data;
 
+	if (synaptics_rmi4_filter_interrupt(data) == IRQ_HANDLED)
+		return IRQ_HANDLED;
+
 	if (gpio_get_value(bdata->irq_gpio) != bdata->irq_on_state)
 		goto exit;
 
@@ -1816,12 +2064,18 @@ static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
 		bool enable, bool attn_only)
 {
 	int retval = 0;
-	unsigned char data[MAX_INTR_REGISTERS];
+	unsigned char *data = NULL;
 	const struct synaptics_dsx_board_data *bdata =
 			rmi4_data->hw_if->board_data;
 
 	mutex_lock(&(rmi4_data->rmi4_irq_enable_mutex));
 
+	data = kcalloc(MAX_INTR_REGISTERS, sizeof(char), GFP_KERNEL);
+	if (!data) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	if (attn_only) {
 		retval = synaptics_rmi4_int_enable(rmi4_data, enable);
 		goto exit;
@@ -1875,8 +2129,8 @@ static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
 	}
 
 exit:
+	kfree(data);
 	mutex_unlock(&(rmi4_data->rmi4_irq_enable_mutex));
-
 	return retval;
 }
 
@@ -2280,8 +2534,8 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
 	unsigned char subpacket;
 	unsigned char ctrl_23_size;
 	unsigned char size_of_2d_data;
-	unsigned char size_of_query5;
-	unsigned char size_of_query8;
+	unsigned char *size_of_query5 = NULL;
+	unsigned char *size_of_query8 = NULL;
 	unsigned char ctrl_8_offset;
 	unsigned char ctrl_20_offset;
 	unsigned char ctrl_23_offset;
@@ -2311,6 +2565,18 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
 	extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
 	size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data);
 
+	size_of_query5 = kcalloc(1, sizeof(char), GFP_KERNEL);
+	if (!size_of_query5) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
+	size_of_query8 = kcalloc(1, sizeof(char), GFP_KERNEL);
+	if (!size_of_query8) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	query_5 = kzalloc(sizeof(*query_5), GFP_KERNEL);
 	if (!query_5) {
 		dev_err(rmi4_data->pdev->dev.parent,
@@ -2367,19 +2633,19 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
 
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			fhandler->full_addr.query_base + 4,
-			&size_of_query5,
-			sizeof(size_of_query5));
+			size_of_query5,
+			sizeof(*size_of_query5));
 	if (retval < 0)
 		goto exit;
 
-	if (size_of_query5 > sizeof(query_5->data))
-		size_of_query5 = sizeof(query_5->data);
+	if (*size_of_query5 > sizeof(query_5->data))
+		*size_of_query5 = sizeof(query_5->data);
 	memset(query_5->data, 0x00, sizeof(query_5->data));
 
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			fhandler->full_addr.query_base + 5,
 			query_5->data,
-			size_of_query5);
+			*size_of_query5);
 	if (retval < 0)
 		goto exit;
 
@@ -2494,26 +2760,26 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
 
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			fhandler->full_addr.query_base + 7,
-			&size_of_query8,
-			sizeof(size_of_query8));
+			size_of_query8,
+			sizeof(*size_of_query8));
 	if (retval < 0)
 		goto exit;
 
-	if (size_of_query8 > sizeof(query_8->data))
-		size_of_query8 = sizeof(query_8->data);
+	if (*size_of_query8 > sizeof(query_8->data))
+		*size_of_query8 = sizeof(query_8->data);
 	memset(query_8->data, 0x00, sizeof(query_8->data));
 
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			fhandler->full_addr.query_base + 8,
 			query_8->data,
-			size_of_query8);
+			*size_of_query8);
 	if (retval < 0)
 		goto exit;
 
 	/* Determine the presence of the Data0 register */
 	extra_data->data1_offset = query_8->data0_is_present;
 
-	if ((size_of_query8 >= 3) && (query_8->data15_is_present)) {
+	if ((*size_of_query8 >= 3) && (query_8->data15_is_present)) {
 		extra_data->data15_offset = query_8->data0_is_present +
 				query_8->data1_is_present +
 				query_8->data2_is_present +
@@ -2535,7 +2801,7 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
 	}
 
 #ifdef REPORT_2D_PRESSURE
-	if ((size_of_query8 >= 5) && (query_8->data29_is_present)) {
+	if ((*size_of_query8 >= 5) && (query_8->data29_is_present)) {
 		extra_data->data29_offset = query_8->data0_is_present +
 				query_8->data1_is_present +
 				query_8->data2_is_present +
@@ -2683,6 +2949,8 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
 	}
 
 exit:
+	kfree(size_of_query5);
+	kfree(size_of_query8);
 	kfree(query_5);
 	kfree(query_8);
 	kfree(ctrl_8);
@@ -2908,16 +3176,15 @@ static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
 {
 	int retval;
 	int timeout = CHECK_STATUS_TIMEOUT_MS;
-	struct synaptics_rmi4_f01_device_status status;
 
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			rmi4_data->f01_data_base_addr,
-			status.data,
-			sizeof(status.data));
+			rmi4_data->status.data,
+			sizeof(rmi4_data->status.data));
 	if (retval < 0)
 		return retval;
 
-	while (status.status_code == STATUS_CRC_IN_PROGRESS) {
+	while (rmi4_data->status.status_code == STATUS_CRC_IN_PROGRESS) {
 		if (timeout > 0)
 			msleep(20);
 		else
@@ -2925,8 +3192,8 @@ static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
 
 		retval = synaptics_rmi4_reg_read(rmi4_data,
 				rmi4_data->f01_data_base_addr,
-				status.data,
-				sizeof(status.data));
+				rmi4_data->status.data,
+				sizeof(rmi4_data->status.data));
 		if (retval < 0)
 			return retval;
 
@@ -2936,11 +3203,11 @@ static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
 	if (timeout != CHECK_STATUS_TIMEOUT_MS)
 		*was_in_bl_mode = true;
 
-	if (status.flash_prog == 1) {
+	if (rmi4_data->status.flash_prog == 1) {
 		rmi4_data->flash_prog_mode = true;
 		pr_notice("%s: In flash prog mode, status = 0x%02x\n",
 				__func__,
-				status.status_code);
+				rmi4_data->status.status_code);
 	} else {
 		rmi4_data->flash_prog_mode = false;
 	}
@@ -2951,32 +3218,39 @@ static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
 static int synaptics_rmi4_set_configured(struct synaptics_rmi4_data *rmi4_data)
 {
 	int retval;
-	unsigned char device_ctrl;
+	unsigned char *device_ctrl = NULL;
+
+	device_ctrl = kcalloc(1, sizeof(char), GFP_KERNEL);
+	if (!device_ctrl) {
+		retval = -ENOMEM;
+		goto exit;
+	}
 
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			rmi4_data->f01_ctrl_base_addr,
-			&device_ctrl,
-			sizeof(device_ctrl));
+			device_ctrl,
+			sizeof(*device_ctrl));
 	if (retval < 0) {
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to set configured\n",
 				__func__);
-		return retval;
+		goto exit;
 	}
 
-	rmi4_data->no_sleep_setting = device_ctrl & NO_SLEEP_ON;
-	device_ctrl |= CONFIGURED;
+	rmi4_data->no_sleep_setting = *device_ctrl & NO_SLEEP_ON;
+	*device_ctrl |= CONFIGURED;
 
 	retval = synaptics_rmi4_reg_write(rmi4_data,
 			rmi4_data->f01_ctrl_base_addr,
-			&device_ctrl,
-			sizeof(device_ctrl));
+			device_ctrl,
+			sizeof(*device_ctrl));
 	if (retval < 0) {
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to set configured\n",
 				__func__);
 	}
-
+exit:
+	kfree(device_ctrl);
 	return retval;
 }
 
@@ -3013,7 +3287,6 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
 	bool f01found;
 	bool f35found;
 	bool was_in_bl_mode;
-	struct synaptics_rmi4_fn_desc rmi_fd;
 	struct synaptics_rmi4_fn *fhandler;
 	struct synaptics_rmi4_device_info *rmi;
 
@@ -3034,8 +3307,8 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
 
 			retval = synaptics_rmi4_reg_read(rmi4_data,
 					pdt_entry_addr,
-					(unsigned char *)&rmi_fd,
-					sizeof(rmi_fd));
+					(unsigned char *)&rmi4_data->rmi_fd,
+					sizeof(rmi4_data->rmi_fd));
 			if (retval < 0)
 				return retval;
 
@@ -3043,7 +3316,7 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
 
 			fhandler = NULL;
 
-			if (rmi_fd.fn_number == 0) {
+			if (rmi4_data->rmi_fd.fn_number == 0) {
 				dev_dbg(rmi4_data->pdev->dev.parent,
 						"%s: Reached end of PDT\n",
 						__func__);
@@ -3052,28 +3325,30 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
 
 			dev_dbg(rmi4_data->pdev->dev.parent,
 					"%s: F%02x found (page %d)\n",
-					__func__, rmi_fd.fn_number,
+					__func__, rmi4_data->rmi_fd.fn_number,
 					page_number);
 
-			switch (rmi_fd.fn_number) {
+			switch (rmi4_data->rmi_fd.fn_number) {
 			case SYNAPTICS_RMI4_F01:
-				if (rmi_fd.intr_src_count == 0)
+				if (rmi4_data->rmi_fd.intr_src_count == 0)
 					break;
 
 				f01found = true;
 
 				retval = synaptics_rmi4_alloc_fh(&fhandler,
-						&rmi_fd, page_number);
+						&rmi4_data->rmi_fd,
+						page_number);
 				if (retval < 0) {
 					dev_err(rmi4_data->pdev->dev.parent,
-							"%s: Failed to alloc for F%d\n",
-							__func__,
-							rmi_fd.fn_number);
+						"%s: Failed to alloc for F%d\n",
+						__func__,
+						rmi4_data->rmi_fd.fn_number);
 					return retval;
 				}
 
 				retval = synaptics_rmi4_f01_init(rmi4_data,
-						fhandler, &rmi_fd, intr_count);
+						fhandler, &rmi4_data->rmi_fd,
+						intr_count);
 				if (retval < 0)
 					return retval;
 
@@ -3097,59 +3372,65 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
 
 				break;
 			case SYNAPTICS_RMI4_F11:
-				if (rmi_fd.intr_src_count == 0)
+				if (rmi4_data->rmi_fd.intr_src_count == 0)
 					break;
 
 				retval = synaptics_rmi4_alloc_fh(&fhandler,
-						&rmi_fd, page_number);
+						&rmi4_data->rmi_fd,
+						page_number);
 				if (retval < 0) {
 					dev_err(rmi4_data->pdev->dev.parent,
-							"%s: Failed to alloc for F%d\n",
-							__func__,
-							rmi_fd.fn_number);
+						"%s: Failed to alloc for F%d\n",
+						__func__,
+						rmi4_data->rmi_fd.fn_number);
 					return retval;
 				}
 
 				retval = synaptics_rmi4_f11_init(rmi4_data,
-						fhandler, &rmi_fd, intr_count);
+						fhandler, &rmi4_data->rmi_fd,
+						intr_count);
 				if (retval < 0)
 					return retval;
 				break;
 			case SYNAPTICS_RMI4_F12:
-				if (rmi_fd.intr_src_count == 0)
+				if (rmi4_data->rmi_fd.intr_src_count == 0)
 					break;
 
 				retval = synaptics_rmi4_alloc_fh(&fhandler,
-						&rmi_fd, page_number);
+						&rmi4_data->rmi_fd,
+						page_number);
 				if (retval < 0) {
 					dev_err(rmi4_data->pdev->dev.parent,
-							"%s: Failed to alloc for F%d\n",
-							__func__,
-							rmi_fd.fn_number);
+						"%s: Failed to alloc for F%d\n",
+						__func__,
+						rmi4_data->rmi_fd.fn_number);
 					return retval;
 				}
 
 				retval = synaptics_rmi4_f12_init(rmi4_data,
-						fhandler, &rmi_fd, intr_count);
+						fhandler, &rmi4_data->rmi_fd,
+						intr_count);
 				if (retval < 0)
 					return retval;
 				break;
 			case SYNAPTICS_RMI4_F1A:
-				if (rmi_fd.intr_src_count == 0)
+				if (rmi4_data->rmi_fd.intr_src_count == 0)
 					break;
 
 				retval = synaptics_rmi4_alloc_fh(&fhandler,
-						&rmi_fd, page_number);
+						&rmi4_data->rmi_fd,
+						page_number);
 				if (retval < 0) {
 					dev_err(rmi4_data->pdev->dev.parent,
-							"%s: Failed to alloc for F%d\n",
-							__func__,
-							rmi_fd.fn_number);
+						"%s: Failed to alloc for F%d\n",
+						__func__,
+						rmi4_data->rmi_fd.fn_number);
 					return retval;
 				}
 
 				retval = synaptics_rmi4_f1a_init(rmi4_data,
-						fhandler, &rmi_fd, intr_count);
+						fhandler, &rmi4_data->rmi_fd,
+						intr_count);
 				if (retval < 0) {
 #ifdef IGNORE_FN_INIT_FAILURE
 					kfree(fhandler);
@@ -3161,25 +3442,27 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
 				break;
 #ifdef USE_DATA_SERVER
 			case SYNAPTICS_RMI4_F21:
-				if (rmi_fd.intr_src_count == 0)
+				if (rmi4_data->rmi_fd.intr_src_count == 0)
 					break;
 
 				retval = synaptics_rmi4_alloc_fh(&fhandler,
-						&rmi_fd, page_number);
+						&rmi4_data->rmi_fd,
+						page_number);
 				if (retval < 0) {
 					dev_err(rmi4_data->pdev->dev.parent,
-							"%s: Failed to alloc for F%d\n",
-							__func__,
-							rmi_fd.fn_number);
+						"%s: Failed to alloc for F%d\n",
+						__func__,
+						rmi4_data->rmi_fd.fn_number);
 					return retval;
 				}
 
-				fhandler->fn_number = rmi_fd.fn_number;
+				fhandler->fn_number =
+					rmi4_data->rmi_fd.fn_number;
 				fhandler->num_of_data_sources =
-						rmi_fd.intr_src_count;
+					rmi4_data->rmi_fd.intr_src_count;
 
-				synaptics_rmi4_set_intr_mask(fhandler, &rmi_fd,
-						intr_count);
+				synaptics_rmi4_set_intr_mask(fhandler,
+						&rmi4_data->rmi_fd, intr_count);
 				break;
 #endif
 			case SYNAPTICS_RMI4_F35:
@@ -3188,16 +3471,16 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
 #ifdef F51_DISCRETE_FORCE
 			case SYNAPTICS_RMI4_F51:
 				rmi4_data->f51_query_base_addr =
-						rmi_fd.query_base_addr |
-						(page_number << 8);
+					rmi4_data->rmi_fd.query_base_addr |
+					(page_number << 8);
 				break;
 #endif
 			}
 
 			/* Accumulate the interrupt count */
-			intr_count += rmi_fd.intr_src_count;
+			intr_count += rmi4_data->rmi_fd.intr_src_count;
 
-			if (fhandler && rmi_fd.intr_src_count) {
+			if (fhandler && rmi4_data->rmi_fd.intr_src_count) {
 				list_add_tail(&fhandler->link,
 						&rmi->support_fn_list);
 			}
@@ -4114,39 +4397,47 @@ static int synaptics_rmi4_sleep_enable(struct synaptics_rmi4_data *rmi4_data,
 		bool enable)
 {
 	int retval;
-	unsigned char device_ctrl;
+	unsigned char *device_ctrl = NULL;
 	unsigned char no_sleep_setting = rmi4_data->no_sleep_setting;
 
+	device_ctrl = kcalloc(1, sizeof(char), GFP_KERNEL);
+	if (!device_ctrl) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			rmi4_data->f01_ctrl_base_addr,
-			&device_ctrl,
-			sizeof(device_ctrl));
+			device_ctrl,
+			sizeof(*device_ctrl));
 	if (retval < 0) {
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read device control\n",
 				__func__);
-		return retval;
+		goto exit;
 	}
 
-	device_ctrl = device_ctrl & ~MASK_3BIT;
+	*device_ctrl = *device_ctrl & ~MASK_3BIT;
 	if (enable)
-		device_ctrl = device_ctrl | SENSOR_SLEEP;
+		*device_ctrl = *device_ctrl | SENSOR_SLEEP;
 	else
-		device_ctrl = device_ctrl | no_sleep_setting | NORMAL_OPERATION;
+		*device_ctrl = *device_ctrl | no_sleep_setting |
+			NORMAL_OPERATION;
 
 	retval = synaptics_rmi4_reg_write(rmi4_data,
 			rmi4_data->f01_ctrl_base_addr,
-			&device_ctrl,
-			sizeof(device_ctrl));
+			device_ctrl,
+			sizeof(*device_ctrl));
 	if (retval < 0) {
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to write device control\n",
 				__func__);
-		return retval;
+		goto exit;
 	}
 
 	rmi4_data->sensor_sleep = enable;
-
+exit:
+	kfree(device_ctrl);
 	return retval;
 }
 
@@ -4291,6 +4582,11 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
 			goto err_drm_reg;
 		}
 	}
+
+	/* Initialize secure touch */
+	synaptics_rmi4_secure_touch_init(rmi4_data);
+	synaptics_rmi4_secure_touch_stop(rmi4_data, true);
+
 	rmi4_data->rmi4_probe_wq = create_singlethread_workqueue(
 						"Synaptics_rmi4_probe_wq");
 	if (!rmi4_data->rmi4_probe_wq) {
@@ -4641,6 +4937,7 @@ static int synaptics_rmi4_dsi_panel_notifier_cb(struct notifier_block *self,
 
 	if (evdata && evdata->data && rmi4_data) {
 		if (event == DRM_PANEL_EARLY_EVENT_BLANK) {
+			synaptics_rmi4_secure_touch_stop(rmi4_data, false);
 			transition = *(int *)evdata->data;
 			if (transition == DRM_PANEL_BLANK_POWERDOWN) {
 				if (rmi4_data->initialized)
@@ -4679,6 +4976,13 @@ static int synaptics_rmi4_early_suspend(struct early_suspend *h)
 
 	if (rmi4_data->stay_awake)
 		return retval;
+	/*
+	 * During early suspend/late resume, the driver doesn't access xPU/SMMU
+	 * protected HW resources. So, there is no compelling need to block,
+	 * but notifying the userspace that a power event has occurred is
+	 * enough. Hence 'blocking' variable can be set to false.
+	 */
+	synaptics_rmi4_secure_touch_stop(rmi4_data, false);
 
 	if (rmi4_data->enable_wakeup_gesture) {
 		if (rmi4_data->no_sleep_setting) {
@@ -4743,6 +5047,8 @@ static int synaptics_rmi4_late_resume(struct early_suspend *h)
 	if (rmi4_data->stay_awake)
 		return retval;
 
+	synaptics_rmi4_secure_touch_stop(rmi4_data, false);
+
 	if (rmi4_data->enable_wakeup_gesture) {
 		disable_irq_wake(rmi4_data->irq);
 		goto exit;
@@ -4791,6 +5097,8 @@ static int synaptics_rmi4_suspend(struct device *dev)
 	if (rmi4_data->stay_awake)
 		return 0;
 
+	synaptics_rmi4_secure_touch_stop(rmi4_data, true);
+
 	if (rmi4_data->enable_wakeup_gesture) {
 		if (rmi4_data->no_sleep_setting) {
 			synaptics_rmi4_reg_read(rmi4_data,
@@ -4862,6 +5170,7 @@ static int synaptics_rmi4_resume(struct device *dev)
 			rmi4_data->hw_if->board_data;
 	if (rmi4_data->stay_awake)
 		return 0;
+	synaptics_rmi4_secure_touch_stop(rmi4_data, true);
 
 	if (rmi4_data->enable_wakeup_gesture) {
 		disable_irq_wake(rmi4_data->irq);
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h
index 8f175e3..0a778b0 100755
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.h
@@ -51,6 +51,13 @@
 
 #include <drm/drm_panel.h>
 
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+#include <linux/completion.h>
+#include <linux/atomic.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#endif
+
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38))
 #define KERNEL_ABOVE_2_6_38
 #endif
@@ -282,6 +289,17 @@ struct synaptics_rmi4_device_info {
 	struct list_head support_fn_list;
 };
 
+struct synaptics_rmi4_f01_device_status {
+	union {
+		struct {
+			unsigned char status_code:4;
+			unsigned char reserved:2;
+			unsigned char flash_prog:1;
+			unsigned char unconfigured:1;
+		} __packed;
+		unsigned char data[1];
+	};
+};
 /*
  * struct synaptics_rmi4_data - RMI4 device instance data
  * @pdev: pointer to platform device
@@ -356,6 +374,8 @@ struct synaptics_rmi4_data {
 	const struct synaptics_dsx_hw_interface *hw_if;
 	struct synaptics_rmi4_device_info rmi4_mod_info;
 	struct synaptics_rmi4_input_settings input_settings;
+	struct synaptics_rmi4_fn_desc rmi_fd;
+	struct synaptics_rmi4_f01_device_status status;
 	struct kobject *board_prop_dir;
 	struct regulator *pwr_reg;
 	struct regulator *bus_reg;
@@ -431,6 +451,15 @@ struct synaptics_rmi4_data {
 			bool enable);
 	void (*report_touch)(struct synaptics_rmi4_data *rmi4_data,
 			struct synaptics_rmi4_fn *fhandler);
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+	atomic_t st_enabled;
+	atomic_t st_pending_irqs;
+	struct completion st_powerdown;
+	struct completion st_irq_processed;
+	bool st_initialized;
+	struct clk *core_clk;
+	struct clk *iface_clk;
+#endif
 };
 
 struct synaptics_dsx_bus_access {
@@ -439,6 +468,8 @@ struct synaptics_dsx_bus_access {
 		unsigned char *data, unsigned int length);
 	int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr,
 		unsigned char *data, unsigned int length);
+	int (*get)(struct synaptics_rmi4_data *rmi4_data);
+	void (*put)(struct synaptics_rmi4_data *rmi4_data);
 };
 
 struct synaptics_dsx_hw_interface {
@@ -489,6 +520,16 @@ static inline int synaptics_rmi4_reg_write(
 	return rmi4_data->hw_if->bus_access->write(rmi4_data, addr, data, len);
 }
 
+static inline int synaptics_rmi4_bus_get(struct synaptics_rmi4_data *rmi4_data)
+{
+	return rmi4_data->hw_if->bus_access->get(rmi4_data);
+}
+
+static inline void synaptics_rmi4_bus_put(struct synaptics_rmi4_data *rmi4_data)
+{
+	rmi4_data->hw_if->bus_access->put(rmi4_data);
+}
+
 static inline ssize_t synaptics_rmi4_show_error(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
index 2372368..6e78ebb 100755
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
@@ -1388,30 +1388,42 @@ static int fwu_parse_image_info(void)
 
 static int fwu_read_flash_status(void)
 {
-	int retval;
-	unsigned char status;
-	unsigned char command;
+	int retval = 0;
+	unsigned char *status = NULL;
+	unsigned char *command = NULL;
 	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
 
+	status = kcalloc(1, sizeof(char), GFP_KERNEL);
+	if (!status) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
+	command = kcalloc(1, sizeof(char), GFP_KERNEL);
+	if (!command) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			fwu->f34_fd.data_base_addr + fwu->off.flash_status,
-			&status,
-			sizeof(status));
+			status,
+			sizeof(*status));
 	if (retval < 0) {
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read flash status\n",
 				__func__);
-		return retval;
+		goto exit;
 	}
 
-	fwu->in_bl_mode = status >> 7;
+	fwu->in_bl_mode = *status >> 7;
 
 	if (fwu->bl_version == BL_V5)
-		fwu->flash_status = (status >> 4) & MASK_3BIT;
+		fwu->flash_status = (*status >> 4) & MASK_3BIT;
 	else if (fwu->bl_version == BL_V6)
-		fwu->flash_status = status & MASK_3BIT;
+		fwu->flash_status = *status & MASK_3BIT;
 	else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
-		fwu->flash_status = status & MASK_5BIT;
+		fwu->flash_status = *status & MASK_5BIT;
 
 	if (fwu->write_bootloader)
 		fwu->flash_status = 0x00;
@@ -1429,26 +1441,28 @@ static int fwu_read_flash_status(void)
 
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			fwu->f34_fd.data_base_addr + fwu->off.flash_cmd,
-			&command,
-			sizeof(command));
+			command,
+			sizeof(*command));
 	if (retval < 0) {
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read flash command\n",
 				__func__);
-		return retval;
+		goto exit;
 	}
 
 	if (fwu->bl_version == BL_V5)
-		fwu->command = command & MASK_4BIT;
+		fwu->command = *command & MASK_4BIT;
 	else if (fwu->bl_version == BL_V6)
-		fwu->command = command & MASK_6BIT;
+		fwu->command = *command & MASK_6BIT;
 	else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
-		fwu->command = command;
+		fwu->command = *command;
 
 	if (fwu->write_bootloader)
 		fwu->command = 0x00;
-
-	return 0;
+exit:
+	kfree(status);
+	kfree(command);
+	return retval;
 }
 
 static int fwu_wait_for_idle(int timeout_ms, bool poll)
@@ -2062,10 +2076,22 @@ static int fwu_read_f34_v5v6_queries(void)
 	unsigned char count;
 	unsigned char base;
 	unsigned char offset;
-	unsigned char buf[10];
-	struct f34_v5v6_flash_properties_2 properties_2;
+	unsigned char *buf = NULL;
+	struct f34_v5v6_flash_properties_2 *properties_2 = NULL;
 	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
 
+	buf = kcalloc(10, sizeof(char), GFP_KERNEL);
+	if (!buf) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
+	properties_2 = kzalloc(sizeof(*properties_2), GFP_KERNEL);
+	if (!properties_2) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	base = fwu->f34_fd.query_base_addr;
 
 	retval = synaptics_rmi4_reg_read(rmi4_data,
@@ -2076,7 +2102,7 @@ static int fwu_read_f34_v5v6_queries(void)
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read bootloader ID\n",
 				__func__);
-		return retval;
+		goto exit;
 	}
 
 	if (fwu->bl_version == BL_V5) {
@@ -2103,7 +2129,7 @@ static int fwu_read_f34_v5v6_queries(void)
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read block size info\n",
 				__func__);
-		return retval;
+		goto exit;
 	}
 
 	batohs(&fwu->block_size, &(buf[0]));
@@ -2124,7 +2150,7 @@ static int fwu_read_f34_v5v6_queries(void)
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read flash properties\n",
 				__func__);
-		return retval;
+		goto exit;
 	}
 
 	count = 4;
@@ -2146,7 +2172,7 @@ static int fwu_read_f34_v5v6_queries(void)
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read block count info\n",
 				__func__);
-		return retval;
+		goto exit;
 	}
 
 	batohs(&fwu->blkcount.ui_firmware, &(buf[0]));
@@ -2178,17 +2204,17 @@ static int fwu_read_f34_v5v6_queries(void)
 	if (fwu->flash_properties.has_query4) {
 		retval = synaptics_rmi4_reg_read(rmi4_data,
 				base + fwu->off.properties_2,
-				properties_2.data,
-				sizeof(properties_2.data));
+				properties_2->data,
+				sizeof(properties_2->data));
 		if (retval < 0) {
 			dev_err(rmi4_data->pdev->dev.parent,
 					"%s: Failed to read flash properties 2\n",
 					__func__);
-			return retval;
+			goto exit;
 		}
 		offset = fwu->off.properties_2 + 1;
 		count = 0;
-		if (properties_2.has_guest_code) {
+		if (properties_2->has_guest_code) {
 			retval = synaptics_rmi4_reg_read(rmi4_data,
 					base + offset + count,
 					buf,
@@ -2197,7 +2223,7 @@ static int fwu_read_f34_v5v6_queries(void)
 				dev_err(rmi4_data->pdev->dev.parent,
 						"%s: Failed to read guest code block count\n",
 						__func__);
-				return retval;
+				goto exit;
 			}
 
 			batohs(&fwu->blkcount.guest_code, &(buf[0]));
@@ -2205,7 +2231,7 @@ static int fwu_read_f34_v5v6_queries(void)
 			fwu->has_guest_code = true;
 		}
 #ifdef SYNA_TDDI
-		if (properties_2.has_force_config) {
+		if (properties_2->has_force_config) {
 			retval = synaptics_rmi4_reg_read(rmi4_data,
 					base + offset + count,
 					buf,
@@ -2214,13 +2240,13 @@ static int fwu_read_f34_v5v6_queries(void)
 				dev_err(rmi4_data->pdev->dev.parent,
 					"%s: Failed to read tddi force block count\n",
 					__func__);
-				return retval;
+				goto exit;
 			}
 			batohs(&fwu->blkcount.tddi_force_config, &(buf[0]));
 			count++;
 			fwu->has_force_config = true;
 		}
-		if (properties_2.has_lockdown_data) {
+		if (properties_2->has_lockdown_data) {
 			retval = synaptics_rmi4_reg_read(rmi4_data,
 					base + offset + count,
 					buf,
@@ -2229,13 +2255,13 @@ static int fwu_read_f34_v5v6_queries(void)
 				dev_err(rmi4_data->pdev->dev.parent,
 					"%s: Failed to read tddi lockdown block count\n",
 					__func__);
-				return retval;
+				goto exit;
 			}
 			batohs(&fwu->blkcount.tddi_lockdown_data, &(buf[0]));
 			count++;
 			fwu->has_lockdown_data = true;
 		}
-		if (properties_2.has_lcm_data) {
+		if (properties_2->has_lcm_data) {
 			retval = synaptics_rmi4_reg_read(rmi4_data,
 					base + offset + count,
 					buf,
@@ -2244,13 +2270,13 @@ static int fwu_read_f34_v5v6_queries(void)
 				dev_err(rmi4_data->pdev->dev.parent,
 					"%s: Failed to read tddi lcm block count\n",
 					__func__);
-				return retval;
+				goto exit;
 			}
 			batohs(&fwu->blkcount.tddi_lcm_data, &(buf[0]));
 			count++;
 			fwu->has_lcm_data = true;
 		}
-		if (properties_2.has_oem_data) {
+		if (properties_2->has_oem_data) {
 			retval = synaptics_rmi4_reg_read(rmi4_data,
 					base + offset + count,
 					buf,
@@ -2259,7 +2285,7 @@ static int fwu_read_f34_v5v6_queries(void)
 				dev_err(rmi4_data->pdev->dev.parent,
 					"%s: Failed to read tddi oem block count\n",
 					__func__);
-				return retval;
+				goto exit;
 			}
 			batohs(&fwu->blkcount.tddi_oem_data, &(buf[0]));
 			fwu->has_oem_data = true;
@@ -2268,8 +2294,10 @@ static int fwu_read_f34_v5v6_queries(void)
 	}
 
 	fwu->has_utility_param = false;
-
-	return 0;
+exit:
+	kfree(properties_2);
+	kfree(buf);
+	return retval;
 }
 
 static int fwu_read_f34_queries(void)
@@ -2790,7 +2818,6 @@ static int fwu_scan_pdt(void)
 	bool f01found = false;
 	bool f34found = false;
 	bool f35found = false;
-	struct synaptics_rmi4_fn_desc rmi_fd;
 	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
 
 	fwu->in_ub_mode = false;
@@ -2798,38 +2825,38 @@ static int fwu_scan_pdt(void)
 	for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
 		retval = synaptics_rmi4_reg_read(rmi4_data,
 				addr,
-				(unsigned char *)&rmi_fd,
-				sizeof(rmi_fd));
+				(unsigned char *)&rmi4_data->rmi_fd,
+				sizeof(rmi4_data->rmi_fd));
 		if (retval < 0)
 			return retval;
 
-		if (rmi_fd.fn_number) {
+		if (rmi4_data->rmi_fd.fn_number) {
 			dev_dbg(rmi4_data->pdev->dev.parent,
 					"%s: Found F%02x\n",
-					__func__, rmi_fd.fn_number);
-			switch (rmi_fd.fn_number) {
+					__func__, rmi4_data->rmi_fd.fn_number);
+			switch (rmi4_data->rmi_fd.fn_number) {
 			case SYNAPTICS_RMI4_F01:
 				f01found = true;
 
 				rmi4_data->f01_query_base_addr =
-						rmi_fd.query_base_addr;
+					rmi4_data->rmi_fd.query_base_addr;
 				rmi4_data->f01_ctrl_base_addr =
-						rmi_fd.ctrl_base_addr;
+					rmi4_data->rmi_fd.ctrl_base_addr;
 				rmi4_data->f01_data_base_addr =
-						rmi_fd.data_base_addr;
+					rmi4_data->rmi_fd.data_base_addr;
 				rmi4_data->f01_cmd_base_addr =
-						rmi_fd.cmd_base_addr;
+					rmi4_data->rmi_fd.cmd_base_addr;
 				break;
 			case SYNAPTICS_RMI4_F34:
 				f34found = true;
 				fwu->f34_fd.query_base_addr =
-						rmi_fd.query_base_addr;
+					rmi4_data->rmi_fd.query_base_addr;
 				fwu->f34_fd.ctrl_base_addr =
-						rmi_fd.ctrl_base_addr;
+					rmi4_data->rmi_fd.ctrl_base_addr;
 				fwu->f34_fd.data_base_addr =
-						rmi_fd.data_base_addr;
+					rmi4_data->rmi_fd.data_base_addr;
 
-				switch (rmi_fd.fn_version) {
+				switch (rmi4_data->rmi_fd.fn_version) {
 				case F34_V0:
 					fwu->bl_version = BL_V5;
 					break;
@@ -2847,7 +2874,7 @@ static int fwu_scan_pdt(void)
 				}
 
 				fwu->intr_mask = 0;
-				intr_src = rmi_fd.intr_src_count;
+				intr_src = rmi4_data->rmi_fd.intr_src_count;
 				intr_off = intr_count % 8;
 				for (ii = intr_off;
 						ii < (intr_src + intr_off);
@@ -2858,20 +2885,20 @@ static int fwu_scan_pdt(void)
 			case SYNAPTICS_RMI4_F35:
 				f35found = true;
 				fwu->f35_fd.query_base_addr =
-						rmi_fd.query_base_addr;
+					rmi4_data->rmi_fd.query_base_addr;
 				fwu->f35_fd.ctrl_base_addr =
-						rmi_fd.ctrl_base_addr;
+					rmi4_data->rmi_fd.ctrl_base_addr;
 				fwu->f35_fd.data_base_addr =
-						rmi_fd.data_base_addr;
+					rmi4_data->rmi_fd.data_base_addr;
 				fwu->f35_fd.cmd_base_addr =
-						rmi_fd.cmd_base_addr;
+					rmi4_data->rmi_fd.cmd_base_addr;
 				break;
 			}
 		} else {
 			break;
 		}
 
-		intr_count += rmi_fd.intr_src_count;
+		intr_count += rmi4_data->rmi_fd.intr_src_count;
 	}
 
 	if (!f01found || !f34found) {
@@ -5568,7 +5595,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
 {
 	int retval;
 	unsigned char attr_count;
-	struct pdt_properties pdt_props;
+	struct pdt_properties *pdt_props = NULL;
 
 	if (fwu) {
 		dev_dbg(rmi4_data->pdev->dev.parent,
@@ -5577,6 +5604,12 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
 		return 0;
 	}
 
+	pdt_props = kzalloc(sizeof(*pdt_props), GFP_KERNEL);
+	if (!pdt_props) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	fwu = kzalloc(sizeof(*fwu), GFP_KERNEL);
 	if (!fwu) {
 		dev_err(rmi4_data->pdev->dev.parent,
@@ -5599,13 +5632,13 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
 
 	retval = synaptics_rmi4_reg_read(rmi4_data,
 			PDT_PROPS,
-			pdt_props.data,
-			sizeof(pdt_props.data));
+			pdt_props->data,
+			sizeof(pdt_props->data));
 	if (retval < 0) {
 		dev_dbg(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read PDT properties, assuming 0x00\n",
 				__func__);
-	} else if (pdt_props.has_bsr) {
+	} else if (pdt_props->has_bsr) {
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Reflash for LTS not currently supported\n",
 				__func__);
@@ -5697,6 +5730,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
 	fwu = NULL;
 
 exit:
+	kfree(pdt_props);
 	return retval;
 }
 
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
index 00ea777..9b75990 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
@@ -273,11 +273,17 @@ static int synaptics_rmi4_i2c_set_page(struct synaptics_rmi4_data *rmi4_data,
 {
 	int retval = 0;
 	unsigned char retry;
-	unsigned char buf[PAGE_SELECT_LEN];
+	unsigned char *buf = NULL;
 	unsigned char page;
 	struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
 	struct i2c_msg msg[2];
 
+	buf = kcalloc(PAGE_SELECT_LEN, sizeof(char), GFP_KERNEL);
+	if (!buf) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	msg[0].addr = hw_if.board_data->i2c_addr;
 	msg[0].flags = 0;
 	msg[0].len = PAGE_SELECT_LEN;
@@ -308,6 +314,8 @@ static int synaptics_rmi4_i2c_set_page(struct synaptics_rmi4_data *rmi4_data,
 		retval = PAGE_SELECT_LEN;
 	}
 
+exit:
+	kfree(buf);
 	return retval;
 }
 
@@ -316,7 +324,7 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
 {
 	int retval = 0;
 	unsigned char retry;
-	unsigned char buf;
+	unsigned char *buf = NULL;
 	unsigned char index = 0;
 	unsigned char xfer_msgs;
 	unsigned char remaining_msgs;
@@ -329,6 +337,12 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
 
 	mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
 
+	buf = kcalloc(1, sizeof(char), GFP_KERNEL);
+	if (!buf) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr);
 	if (retval != PAGE_SELECT_LEN) {
 		retval = -EIO;
@@ -338,13 +352,13 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
 	msg[0].addr = hw_if.board_data->i2c_addr;
 	msg[0].flags = 0;
 	msg[0].len = 1;
-	msg[0].buf = &buf;
+	msg[0].buf = buf;
 	msg[rd_msgs].addr = hw_if.board_data->i2c_addr;
 	msg[rd_msgs].flags = I2C_M_RD;
 	msg[rd_msgs].len = (unsigned short)remaining_length;
 	msg[rd_msgs].buf = &data[data_offset];
 
-	buf = addr & MASK_8BIT;
+	buf[0] = addr & MASK_8BIT;
 
 	remaining_msgs = rd_msgs + 1;
 
@@ -383,8 +397,8 @@ static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
 	retval = length;
 
 exit:
+	kfree(buf);
 	mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
-
 	return retval;
 }
 
@@ -504,10 +518,73 @@ static int check_default_tp(struct device_node *dt, const char *prop)
 	return ret;
 }
 
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+static int synaptics_rmi4_clk_prepare_enable(
+		struct synaptics_rmi4_data *rmi4_data)
+{
+	int ret;
+
+	ret = clk_prepare_enable(rmi4_data->iface_clk);
+	if (ret) {
+		dev_err(rmi4_data->pdev->dev.parent,
+				"error on clk_prepare_enable(iface_clk):%d\n",
+				ret);
+		return ret;
+	}
+	ret = clk_prepare_enable(rmi4_data->core_clk);
+	if (ret) {
+		clk_disable_unprepare(rmi4_data->iface_clk);
+		dev_err(rmi4_data->pdev->dev.parent,
+				"error clk_prepare_enable(core_clk):%d\n", ret);
+	}
+	return ret;
+}
+
+static void synaptics_rmi4_clk_disable_unprepare(
+		struct synaptics_rmi4_data *rmi4_data)
+{
+	clk_disable_unprepare(rmi4_data->core_clk);
+	clk_disable_unprepare(rmi4_data->iface_clk);
+}
+
+static int synaptics_rmi4_i2c_get(struct synaptics_rmi4_data *rmi4_data)
+{
+	int retval;
+	struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+
+	mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+	retval = pm_runtime_get_sync(i2c->adapter->dev.parent);
+	if (retval >= 0 && rmi4_data->core_clk != NULL &&
+			rmi4_data->iface_clk != NULL) {
+		retval = synaptics_rmi4_clk_prepare_enable(rmi4_data);
+		if (retval)
+			pm_runtime_put_sync(i2c->adapter->dev.parent);
+	}
+	mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+
+	return retval;
+}
+
+static void synaptics_rmi4_i2c_put(struct synaptics_rmi4_data *rmi4_data)
+{
+	struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
+
+	mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+	if (rmi4_data->core_clk != NULL && rmi4_data->iface_clk != NULL)
+		synaptics_rmi4_clk_disable_unprepare(rmi4_data);
+	pm_runtime_put_sync(i2c->adapter->dev.parent);
+	mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex);
+}
+#endif
+
 static struct synaptics_dsx_bus_access bus_access = {
 	.type = BUS_I2C,
 	.read = synaptics_rmi4_i2c_read,
 	.write = synaptics_rmi4_i2c_write,
+#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX)
+	.get = synaptics_rmi4_i2c_get,
+	.put = synaptics_rmi4_i2c_put,
+#endif
 };
 
 static void synaptics_rmi4_i2c_dev_release(struct device *dev)
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_test_reporting.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_test_reporting.c
index c17b692..3a0be3c 100755
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_test_reporting.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_test_reporting.c
@@ -4673,25 +4673,31 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
 	unsigned char ii;
 	unsigned char rx_electrodes;
 	unsigned char tx_electrodes;
-	struct f55_control_43 ctrl_43;
+	struct f55_control_43 *ctrl_43 = NULL;
+
+	ctrl_43 = kzalloc(sizeof(*ctrl_43), GFP_KERNEL);
+	if (!ctrl_43) {
+		retval = -ENOMEM;
+		goto exit;
+	}
 
 	retval = test_f55_set_queries();
 	if (retval < 0) {
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read F55 query registers\n",
 				__func__);
-		return;
+		goto exit;
 	}
 
 	if (!f55->query.has_sensor_assignment)
-		return;
+		goto exit;
 
 	retval = test_f55_set_controls();
 	if (retval < 0) {
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to set up F55 control registers\n",
 				__func__);
-		return;
+		goto exit;
 	}
 
 	tx_electrodes = f55->query.num_of_tx_electrodes;
@@ -4708,7 +4714,7 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read F55 tx assignment\n",
 				__func__);
-		return;
+		goto exit;
 	}
 
 	retval = synaptics_rmi4_reg_read(rmi4_data,
@@ -4719,7 +4725,7 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
 		dev_err(rmi4_data->pdev->dev.parent,
 				"%s: Failed to read F55 rx assignment\n",
 				__func__);
-		return;
+		goto exit;
 	}
 
 	f54->tx_assigned = 0;
@@ -4742,17 +4748,17 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
 	if (f55->extended_amp) {
 		retval = synaptics_rmi4_reg_read(rmi4_data,
 				f55->control_base_addr + f55->afe_mux_offset,
-				ctrl_43.data,
-				sizeof(ctrl_43.data));
+				ctrl_43->data,
+				sizeof(ctrl_43->data));
 		if (retval < 0) {
 			dev_err(rmi4_data->pdev->dev.parent,
 					"%s: Failed to read F55 AFE mux sizes\n",
 					__func__);
-			return;
+			goto exit;
 		}
 
-		f54->tx_assigned = ctrl_43.afe_l_mux_size +
-				ctrl_43.afe_r_mux_size;
+		f54->tx_assigned = ctrl_43->afe_l_mux_size +
+				ctrl_43->afe_r_mux_size;
 	}
 
 	/* force mapping */
@@ -4768,7 +4774,7 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
 			dev_err(rmi4_data->pdev->dev.parent,
 					"%s: Failed to read F55 force tx assignment\n",
 					__func__);
-			return;
+			goto exit;
 		}
 
 		retval = synaptics_rmi4_reg_read(rmi4_data,
@@ -4779,7 +4785,7 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
 			dev_err(rmi4_data->pdev->dev.parent,
 					"%s: Failed to read F55 force rx assignment\n",
 					__func__);
-			return;
+			goto exit;
 		}
 
 		for (ii = 0; ii < tx_electrodes; ii++) {
@@ -4792,6 +4798,10 @@ static void test_f55_init(struct synaptics_rmi4_data *rmi4_data)
 				f54->rx_assigned++;
 		}
 	}
+
+exit:
+	kfree(ctrl_43);
+	return;
 }
 
 static void test_f55_set_regs(struct synaptics_rmi4_data *rmi4_data,
@@ -4981,7 +4991,6 @@ static int test_scan_pdt(void)
 	unsigned short addr;
 	bool f54found = false;
 	bool f55found = false;
-	struct synaptics_rmi4_fn_desc rmi_fd;
 	struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data;
 
 	for (page = 0; page < PAGES_TO_SERVICE; page++) {
@@ -4990,30 +4999,31 @@ static int test_scan_pdt(void)
 
 			retval = synaptics_rmi4_reg_read(rmi4_data,
 					addr,
-					(unsigned char *)&rmi_fd,
-					sizeof(rmi_fd));
+					(unsigned char *)&rmi4_data->rmi_fd,
+					sizeof(rmi4_data->rmi_fd));
 			if (retval < 0)
 				return retval;
 
 			addr &= ~(MASK_8BIT << 8);
 
-			if (!rmi_fd.fn_number)
+			if (!rmi4_data->rmi_fd.fn_number)
 				break;
 
-			switch (rmi_fd.fn_number) {
+			switch (rmi4_data->rmi_fd.fn_number) {
 			case SYNAPTICS_RMI4_F54:
 				test_f54_set_regs(rmi4_data,
-						&rmi_fd, intr_count, page);
+						&rmi4_data->rmi_fd, intr_count,
+						page);
 				f54found = true;
 				break;
 			case SYNAPTICS_RMI4_F55:
 				test_f55_set_regs(rmi4_data,
-						&rmi_fd, page);
+						&rmi4_data->rmi_fd, page);
 				f55found = true;
 				break;
 			case SYNAPTICS_RMI4_F21:
 				test_f21_set_regs(rmi4_data,
-						&rmi_fd, page);
+						&rmi4_data->rmi_fd, page);
 				break;
 			default:
 				break;
@@ -5022,7 +5032,7 @@ static int test_scan_pdt(void)
 			if (f54found && f55found)
 				goto pdt_done;
 
-			intr_count += rmi_fd.intr_src_count;
+			intr_count += rmi4_data->rmi_fd.intr_src_count;
 		}
 	}
 
diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c
index 3c7a511..b94402a 100644
--- a/drivers/mmc/host/cqhci.c
+++ b/drivers/mmc/host/cqhci.c
@@ -102,6 +102,10 @@ static void cqhci_set_irqs(struct cqhci_host *cq_host, u32 set)
 static void cqhci_dumpregs(struct cqhci_host *cq_host)
 {
 	struct mmc_host *mmc = cq_host->mmc;
+	int offset = 0;
+
+	if (cq_host->offset_changed)
+		offset = CQE_V5_VENDOR_CFG;
 
 	mmc_log_string(mmc,
 	"CQHCI_CTL=0x%08x CQHCI_IS=0x%08x CQHCI_ISTE=0x%08x CQHCI_ISGE=0x%08x CQHCI_TDBR=0x%08x CQHCI_TCN=0x%08x CQHCI_DQS=0x%08x CQHCI_DPT=0x%08x CQHCI_TERRI=0x%08x CQHCI_CRI=0x%08x CQHCI_CRA=0x%08x CQHCI_CRDCT=0x%08x\n",
@@ -147,6 +151,8 @@ static void cqhci_dumpregs(struct cqhci_host *cq_host)
 	CQHCI_DUMP("Resp idx:  0x%08x | Resp arg: 0x%08x\n",
 		   cqhci_readl(cq_host, CQHCI_CRI),
 		   cqhci_readl(cq_host, CQHCI_CRA));
+	CQHCI_DUMP("Vendor cfg 0x%08x\n",
+		   cqhci_readl(cq_host, CQHCI_VENDOR_CFG + offset));
 
 	if (cq_host->ops->dumpregs)
 		cq_host->ops->dumpregs(mmc);
@@ -279,6 +285,12 @@ static void __cqhci_enable(struct cqhci_host *cq_host)
 		cq_host->caps |= CQHCI_CAP_CRYPTO_SUPPORT |
 				CQHCI_TASK_DESC_SZ_128;
 		cqcfg |= CQHCI_ICE_ENABLE;
+		/*
+		 * For SDHC v5.0 onwards, ICE 3.0 specific registers are added
+		 * in CQ register space, due to which few CQ registers are
+		 * shifted. Set offset_changed boolean to use updated address.
+		 */
+		 cq_host->offset_changed = true;
 	}
 
 	cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
@@ -698,8 +710,12 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
 	cq_host->qcnt += 1;
 
+	/* Ensure the task descriptor list is flushed before ringing doorbell */
+	wmb();
 	mmc_log_string(mmc, "tag: %d\n", tag);
 	cqhci_writel(cq_host, 1 << tag, CQHCI_TDBR);
+	/* Commit the doorbell write immediately */
+	wmb();
 	if (!(cqhci_readl(cq_host, CQHCI_TDBR) & (1 << tag)))
 		pr_debug("%s: cqhci: doorbell not set for tag %d\n",
 			 mmc_hostname(mmc), tag);
@@ -809,8 +825,10 @@ static void cqhci_finish_mrq(struct mmc_host *mmc, unsigned int tag)
 	struct cqhci_slot *slot = &cq_host->slot[tag];
 	struct mmc_request *mrq = slot->mrq;
 	struct mmc_data *data;
-	int err = 0;
+	int err = 0, offset = 0;
 
+	if (cq_host->offset_changed)
+		offset = CQE_V5_VENDOR_CFG;
 	if (!mrq) {
 		WARN_ONCE(1, "%s: cqhci: spurious TCN for tag %d\n",
 			  mmc_hostname(mmc), tag);
@@ -840,6 +858,11 @@ static void cqhci_finish_mrq(struct mmc_host *mmc, unsigned int tag)
 			data->bytes_xfered = 0;
 		else
 			data->bytes_xfered = data->blksz * data->blocks;
+	} else {
+		cqhci_writel(cq_host, cqhci_readl(cq_host,
+				CQHCI_VENDOR_CFG + offset) |
+				CMDQ_SEND_STATUS_TRIGGER,
+				CQHCI_VENDOR_CFG + offset);
 	}
 
 	if (!(cq_host->caps & CQHCI_CAP_CRYPTO_SUPPORT) &&
diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
index e87e9bc..da4324b 100644
--- a/drivers/mmc/host/cqhci.h
+++ b/drivers/mmc/host/cqhci.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -116,6 +117,14 @@
 /* command response argument */
 #define CQHCI_CRA			0x5C
 
+/*
+ * Add new macro for updated CQ vendor specific
+ * register address for SDHC v5.0 onwards.
+ */
+#define CQE_V5_VENDOR_CFG	0x900
+#define CQHCI_VENDOR_CFG   0x100
+#define CMDQ_SEND_STATUS_TRIGGER (1 << 31)
+
 #define CQHCI_INT_ALL			0xF
 #define CQHCI_IC_DEFAULT_ICCTH		31
 #define CQHCI_IC_DEFAULT_ICTOVAL	1
@@ -183,6 +192,7 @@ struct cqhci_host {
 	bool activated;
 	bool waiting_for_idle;
 	bool recovery_halt;
+	bool offset_changed;
 
 	size_t desc_size;
 	size_t data_size;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index ee219c7..f25c9cd 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2400,6 +2400,7 @@ static int sdhci_msm_cqe_add_host(struct sdhci_host *host,
 
 	msm_host->mmc->caps2 |= MMC_CAP2_CQE;
 	cq_host->ops = &sdhci_msm_cqhci_ops;
+	msm_host->cq_host = cq_host;
 
 	dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
 	if (dma64)
@@ -3950,6 +3951,46 @@ static void sdhci_msm_cache_debug_data(struct sdhci_host *host)
 		sizeof(struct sdhci_host));
 }
 
+#define MAX_TEST_BUS 60
+#define DRV_NAME "cqhci-host"
+static void sdhci_msm_cqe_dump_debug_ram(struct sdhci_host *host)
+{
+	int i = 0;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	const struct sdhci_msm_offset *msm_host_offset =
+					msm_host->offset;
+	struct cqhci_host *cq_host;
+	u32 version;
+	u16 minor;
+	int offset;
+
+	if (msm_host->cq_host)
+		cq_host = msm_host->cq_host;
+	else
+		return;
+
+	version = sdhci_msm_readl_relaxed(host,
+		msm_host_offset->CORE_MCI_VERSION);
+	minor = version & CORE_VERSION_TARGET_MASK;
+	/* registers offset changed starting from 4.2.0 */
+	offset = minor >= SDHCI_MSM_VER_420 ? 0 : 0x48;
+
+	if (cq_host->offset_changed)
+		offset += CQE_V5_VENDOR_CFG;
+	pr_err("---- Debug RAM dump ----\n");
+	pr_err(DRV_NAME ": Debug RAM wrap-around: 0x%08x | Debug RAM overlap: 0x%08x\n",
+	       cqhci_readl(cq_host, CQ_CMD_DBG_RAM_WA + offset),
+	       cqhci_readl(cq_host, CQ_CMD_DBG_RAM_OL + offset));
+
+	while (i < 16) {
+		pr_err(DRV_NAME ": Debug RAM dump [%d]: 0x%08x\n", i,
+		       cqhci_readl(cq_host, CQ_CMD_DBG_RAM + offset + (4 * i)));
+		i++;
+	}
+	pr_err("-------------------------\n");
+}
+
 void sdhci_msm_dump_vendor_regs(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -3964,6 +4005,8 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host)
 
 	sdhci_msm_cache_debug_data(host);
 	pr_info("----------- VENDOR REGISTER DUMP -----------\n");
+	if (msm_host->cq_host)
+		sdhci_msm_cqe_dump_debug_ram(host);
 
 	mmc_log_string(host->mmc, "Data cnt: 0x%08x | Fifo cnt: 0x%08x\n",
 		sdhci_msm_readl_relaxed(host,
diff --git a/drivers/mmc/host/sdhci-msm.h b/drivers/mmc/host/sdhci-msm.h
index 58f5632a..051dfa8 100644
--- a/drivers/mmc/host/sdhci-msm.h
+++ b/drivers/mmc/host/sdhci-msm.h
@@ -225,6 +225,7 @@ struct sdhci_msm_host {
 	atomic_t clks_on; /* Set if clocks are enabled */
 	struct sdhci_msm_pltfm_data *pdata;
 	struct mmc_host  *mmc;
+	struct cqhci_host *cq_host;
 	struct sdhci_msm_debug_data cached_data;
 	struct sdhci_pltfm_data sdhci_msm_pdata;
 	u32 curr_pwr_state;
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_descriptor.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_descriptor.c
index 40238e6..e39a151 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_descriptor.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_descriptor.c
@@ -34,8 +34,9 @@ rmnet_get_frag_descriptor(struct rmnet_port *port)
 {
 	struct rmnet_frag_descriptor_pool *pool = port->frag_desc_pool;
 	struct rmnet_frag_descriptor *frag_desc;
+	unsigned long flags;
 
-	spin_lock(&port->desc_pool_lock);
+	spin_lock_irqsave(&port->desc_pool_lock, flags);
 	if (!list_empty(&pool->free_list)) {
 		frag_desc = list_first_entry(&pool->free_list,
 					     struct rmnet_frag_descriptor,
@@ -52,7 +53,7 @@ rmnet_get_frag_descriptor(struct rmnet_port *port)
 	}
 
 out:
-	spin_unlock(&port->desc_pool_lock);
+	spin_unlock_irqrestore(&port->desc_pool_lock, flags);
 	return frag_desc;
 }
 EXPORT_SYMBOL(rmnet_get_frag_descriptor);
@@ -62,6 +63,7 @@ void rmnet_recycle_frag_descriptor(struct rmnet_frag_descriptor *frag_desc,
 {
 	struct rmnet_frag_descriptor_pool *pool = port->frag_desc_pool;
 	struct page *page = skb_frag_page(&frag_desc->frag);
+	unsigned long flags;
 
 	list_del(&frag_desc->list);
 	if (page)
@@ -70,9 +72,9 @@ void rmnet_recycle_frag_descriptor(struct rmnet_frag_descriptor *frag_desc,
 	memset(frag_desc, 0, sizeof(*frag_desc));
 	INIT_LIST_HEAD(&frag_desc->list);
 	INIT_LIST_HEAD(&frag_desc->sub_frags);
-	spin_lock(&port->desc_pool_lock);
+	spin_lock_irqsave(&port->desc_pool_lock, flags);
 	list_add_tail(&frag_desc->list, &pool->free_list);
-	spin_unlock(&port->desc_pool_lock);
+	spin_unlock_irqrestore(&port->desc_pool_lock, flags);
 }
 EXPORT_SYMBOL(rmnet_recycle_frag_descriptor);
 
@@ -670,6 +672,12 @@ static void __rmnet_frag_segment_data(struct rmnet_frag_descriptor *coal_desc,
 		new_frag->tcp_seq_set = 1;
 		new_frag->tcp_seq = htonl(ntohl(th->seq) +
 					  coal_desc->data_offset);
+	} else if (coal_desc->trans_proto == IPPROTO_UDP) {
+		struct udphdr *uh;
+
+		uh = (struct udphdr *)(hdr_start + coal_desc->ip_len);
+		if (coal_desc->ip_proto == 4 && !uh->check)
+			csum_valid = true;
 	}
 
 	if (coal_desc->ip_proto == 4) {
@@ -734,6 +742,7 @@ rmnet_frag_segment_coal_data(struct rmnet_frag_descriptor *coal_desc,
 	u8 pkt, total_pkt = 0;
 	u8 nlo;
 	bool gro = coal_desc->dev->features & NETIF_F_GRO_HW;
+	bool zero_csum = false;
 
 	/* Pull off the headers we no longer need */
 	if (!rmnet_frag_pull(coal_desc, port, sizeof(struct rmnet_map_header)))
@@ -794,7 +803,12 @@ rmnet_frag_segment_coal_data(struct rmnet_frag_descriptor *coal_desc,
 		th = (struct tcphdr *)((u8 *)iph + coal_desc->ip_len);
 		coal_desc->trans_len = th->doff * 4;
 	} else if (coal_desc->trans_proto == IPPROTO_UDP) {
-		coal_desc->trans_len = sizeof(struct udphdr);
+		struct udphdr *uh;
+
+		uh = (struct udphdr *)((u8 *)iph + coal_desc->ip_len);
+		coal_desc->trans_len = sizeof(*uh);
+		if (coal_desc->ip_proto == 4 && !uh->check)
+			zero_csum = true;
 	} else {
 		priv->stats.coal.coal_trans_invalid++;
 		return;
@@ -802,7 +816,7 @@ rmnet_frag_segment_coal_data(struct rmnet_frag_descriptor *coal_desc,
 
 	coal_desc->hdrs_valid = 1;
 
-	if (rmnet_map_v5_csum_buggy(coal_hdr)) {
+	if (rmnet_map_v5_csum_buggy(coal_hdr) && !zero_csum) {
 		/* Mark the checksum as valid if it checks out */
 		if (rmnet_frag_validate_csum(coal_desc))
 			coal_desc->csum_valid = true;
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
index 84a42c9..da5e47c 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
@@ -716,6 +716,7 @@ __rmnet_map_segment_coal_skb(struct sk_buff *coal_skb,
 	struct rmnet_priv *priv = netdev_priv(coal_skb->dev);
 	__sum16 *check = NULL;
 	u32 alloc_len;
+	bool zero_csum = false;
 
 	/* We can avoid copying the data if the SKB we got from the lower-level
 	 * drivers was nonlinear.
@@ -747,6 +748,8 @@ __rmnet_map_segment_coal_skb(struct sk_buff *coal_skb,
 
 		uh->len = htons(skbn->len);
 		check = &uh->check;
+		if (coal_meta->ip_proto == 4 && !uh->check)
+			zero_csum = true;
 	}
 
 	/* Push IP header and update necessary fields */
@@ -767,7 +770,7 @@ __rmnet_map_segment_coal_skb(struct sk_buff *coal_skb,
 	}
 
 	/* Handle checksum status */
-	if (likely(csum_valid)) {
+	if (likely(csum_valid) || zero_csum) {
 		/* Set the partial checksum information */
 		rmnet_map_partial_csum(skbn, coal_meta);
 	} else if (check) {
@@ -865,6 +868,7 @@ static void rmnet_map_segment_coal_skb(struct sk_buff *coal_skb,
 	u8 pkt, total_pkt = 0;
 	u8 nlo;
 	bool gro = coal_skb->dev->features & NETIF_F_GRO_HW;
+	bool zero_csum = false;
 
 	memset(&coal_meta, 0, sizeof(coal_meta));
 
@@ -926,12 +930,15 @@ static void rmnet_map_segment_coal_skb(struct sk_buff *coal_skb,
 		uh = (struct udphdr *)((u8 *)iph + coal_meta.ip_len);
 		coal_meta.trans_len = sizeof(*uh);
 		coal_meta.trans_header = uh;
+		/* Check for v4 zero checksum */
+		if (coal_meta.ip_proto == 4 && !uh->check)
+			zero_csum = true;
 	} else {
 		priv->stats.coal.coal_trans_invalid++;
 		return;
 	}
 
-	if (rmnet_map_v5_csum_buggy(coal_hdr)) {
+	if (rmnet_map_v5_csum_buggy(coal_hdr) && !zero_csum) {
 		rmnet_map_move_headers(coal_skb);
 		/* Mark as valid if it checks out */
 		if (rmnet_map_validate_csum(coal_skb, &coal_meta))
diff --git a/drivers/net/wireless/cnss2/bus.c b/drivers/net/wireless/cnss2/bus.c
index 5601883..5aa68e3 100644
--- a/drivers/net/wireless/cnss2/bus.c
+++ b/drivers/net/wireless/cnss2/bus.c
@@ -186,6 +186,36 @@ int cnss_bus_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv)
 	}
 }
 
+int cnss_bus_qmi_send_get(struct cnss_plat_data *plat_priv)
+{
+	if (!plat_priv)
+		return -ENODEV;
+
+	switch (plat_priv->bus_type) {
+	case CNSS_BUS_PCI:
+		return cnss_pci_qmi_send_get(plat_priv->bus_priv);
+	default:
+		cnss_pr_err("Unsupported bus type: %d\n",
+			    plat_priv->bus_type);
+		return -EINVAL;
+	}
+}
+
+int cnss_bus_qmi_send_put(struct cnss_plat_data *plat_priv)
+{
+	if (!plat_priv)
+		return -ENODEV;
+
+	switch (plat_priv->bus_type) {
+	case CNSS_BUS_PCI:
+		return cnss_pci_qmi_send_put(plat_priv->bus_priv);
+	default:
+		cnss_pr_err("Unsupported bus type: %d\n",
+			    plat_priv->bus_type);
+		return -EINVAL;
+	}
+}
+
 void cnss_bus_fw_boot_timeout_hdlr(struct timer_list *t)
 {
 	struct cnss_plat_data *plat_priv =
diff --git a/drivers/net/wireless/cnss2/bus.h b/drivers/net/wireless/cnss2/bus.h
index 8ec4887..5248eb5 100644
--- a/drivers/net/wireless/cnss2/bus.h
+++ b/drivers/net/wireless/cnss2/bus.h
@@ -30,6 +30,8 @@ int cnss_bus_alloc_qdss_mem(struct cnss_plat_data *plat_priv);
 void cnss_bus_free_qdss_mem(struct cnss_plat_data *plat_priv);
 u32 cnss_bus_get_wake_irq(struct cnss_plat_data *plat_priv);
 int cnss_bus_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv);
+int cnss_bus_qmi_send_get(struct cnss_plat_data *plat_priv);
+int cnss_bus_qmi_send_put(struct cnss_plat_data *plat_priv);
 void cnss_bus_fw_boot_timeout_hdlr(struct timer_list *t);
 void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv,
 				bool in_panic);
diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c
index a1e0dc5..bb55c31 100644
--- a/drivers/net/wireless/cnss2/debug.c
+++ b/drivers/net/wireless/cnss2/debug.c
@@ -477,6 +477,10 @@ static ssize_t cnss_runtime_pm_debug_write(struct file *fp,
 		cnss_pci_pm_runtime_put_noidle(pci_priv);
 	} else if (sysfs_streq(cmd, "mark_last_busy")) {
 		cnss_pci_pm_runtime_mark_last_busy(pci_priv);
+	} else if (sysfs_streq(cmd, "resume_bus")) {
+		cnss_pci_resume_bus(pci_priv);
+	} else if (sysfs_streq(cmd, "suspend_bus")) {
+		cnss_pci_suspend_bus(pci_priv);
 	} else {
 		cnss_pr_err("Runtime PM debugfs command is invalid\n");
 		ret = -EINVAL;
@@ -500,6 +504,8 @@ static int cnss_runtime_pm_debug_show(struct seq_file *s, void *data)
 	seq_puts(s, "put_noidle: do runtime PM put noidle\n");
 	seq_puts(s, "put_autosuspend: do runtime PM put autosuspend\n");
 	seq_puts(s, "mark_last_busy: do runtime PM mark last busy\n");
+	seq_puts(s, "resume_bus: do bus resume only\n");
+	seq_puts(s, "suspend_bus: do bus suspend only\n");
 
 	return 0;
 }
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index f64d31d..5beeaa3 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -1210,13 +1210,23 @@ EXPORT_SYMBOL(cnss_force_collect_rddm);
 
 int cnss_qmi_send_get(struct device *dev)
 {
-	return 0;
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
+
+	if (!test_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state))
+		return 0;
+
+	return cnss_bus_qmi_send_get(plat_priv);
 }
 EXPORT_SYMBOL(cnss_qmi_send_get);
 
 int cnss_qmi_send_put(struct device *dev)
 {
-	return 0;
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
+
+	if (!test_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state))
+		return 0;
+
+	return cnss_bus_qmi_send_put(plat_priv);
 }
 EXPORT_SYMBOL(cnss_qmi_send_put);
 
@@ -1224,7 +1234,25 @@ int cnss_qmi_send(struct device *dev, int type, void *cmd,
 		  int cmd_len, void *cb_ctx,
 		  int (*cb)(void *ctx, void *event, int event_len))
 {
-	return -EINVAL;
+	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
+	int ret;
+
+	if (!plat_priv)
+		return -ENODEV;
+
+	if (!test_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state))
+		return -EINVAL;
+
+	plat_priv->get_info_cb = cb;
+	plat_priv->get_info_cb_ctx = cb_ctx;
+
+	ret = cnss_wlfw_get_info_send_sync(plat_priv, type, cmd, cmd_len);
+	if (ret) {
+		plat_priv->get_info_cb = NULL;
+		plat_priv->get_info_cb_ctx = NULL;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(cnss_qmi_send);
 
diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h
index 8009799..9e9068a 100644
--- a/drivers/net/wireless/cnss2/main.h
+++ b/drivers/net/wireless/cnss2/main.h
@@ -353,6 +353,8 @@ struct cnss_plat_data {
 	struct qmi_handle ims_qmi;
 	struct qmi_txn txn;
 	u64 dynamic_feature;
+	void *get_info_cb_ctx;
+	int (*get_info_cb)(void *ctx, void *event, int event_len);
 };
 
 #ifdef CONFIG_ARCH_QCOM
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index dcecd94..3b7e5c70 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -1223,6 +1223,9 @@ int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv)
 		}
 	}
 
+	plat_priv->get_info_cb_ctx = NULL;
+	plat_priv->get_info_cb = NULL;
+
 	return 0;
 }
 
@@ -2015,7 +2018,7 @@ static int cnss_pci_resume_driver(struct cnss_pci_data *pci_priv)
 	return ret;
 }
 
-static int cnss_pci_suspend_bus(struct cnss_pci_data *pci_priv)
+int cnss_pci_suspend_bus(struct cnss_pci_data *pci_priv)
 {
 	struct pci_dev *pci_dev = pci_priv->pci_dev;
 	int ret = 0;
@@ -2060,7 +2063,7 @@ static int cnss_pci_suspend_bus(struct cnss_pci_data *pci_priv)
 	return ret;
 }
 
-static int cnss_pci_resume_bus(struct cnss_pci_data *pci_priv)
+int cnss_pci_resume_bus(struct cnss_pci_data *pci_priv)
 {
 	struct pci_dev *pci_dev = pci_priv->pci_dev;
 	int ret = 0;
@@ -2486,11 +2489,16 @@ int cnss_auto_suspend(struct device *dev)
 	if (!plat_priv)
 		return -ENODEV;
 
+	mutex_lock(&pci_priv->bus_lock);
 	ret = cnss_pci_suspend_bus(pci_priv);
-	if (ret)
+	if (ret) {
+		mutex_unlock(&pci_priv->bus_lock);
 		return ret;
+	}
 
 	cnss_pci_set_auto_suspended(pci_priv, 1);
+	mutex_unlock(&pci_priv->bus_lock);
+
 	cnss_pci_set_monitor_wake_intr(pci_priv, true);
 
 	bus_bw_info = &plat_priv->bus_bw_info;
@@ -2516,11 +2524,15 @@ int cnss_auto_resume(struct device *dev)
 	if (!plat_priv)
 		return -ENODEV;
 
+	mutex_lock(&pci_priv->bus_lock);
 	ret = cnss_pci_resume_bus(pci_priv);
-	if (ret)
+	if (ret) {
+		mutex_unlock(&pci_priv->bus_lock);
 		return ret;
+	}
 
 	cnss_pci_set_auto_suspended(pci_priv, 0);
+	mutex_unlock(&pci_priv->bus_lock);
 
 	bus_bw_info = &plat_priv->bus_bw_info;
 	msm_bus_scale_client_update_request(bus_bw_info->bus_client,
@@ -2613,6 +2625,46 @@ int cnss_pci_force_wake_release(struct device *dev)
 }
 EXPORT_SYMBOL(cnss_pci_force_wake_release);
 
+int cnss_pci_qmi_send_get(struct cnss_pci_data *pci_priv)
+{
+	int ret = 0;
+
+	if (!pci_priv)
+		return -ENODEV;
+
+	mutex_lock(&pci_priv->bus_lock);
+	if (!cnss_pci_get_auto_suspended(pci_priv))
+		goto out;
+
+	cnss_pr_vdbg("Starting to handle get info prepare\n");
+
+	ret = cnss_pci_resume_bus(pci_priv);
+
+out:
+	mutex_unlock(&pci_priv->bus_lock);
+	return ret;
+}
+
+int cnss_pci_qmi_send_put(struct cnss_pci_data *pci_priv)
+{
+	int ret = 0;
+
+	if (!pci_priv)
+		return -ENODEV;
+
+	mutex_lock(&pci_priv->bus_lock);
+	if (!cnss_pci_get_auto_suspended(pci_priv))
+		goto out;
+
+	cnss_pr_vdbg("Starting to handle get info done\n");
+
+	ret = cnss_pci_suspend_bus(pci_priv);
+
+out:
+	mutex_unlock(&pci_priv->bus_lock);
+	return ret;
+}
+
 int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv)
 {
 	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
@@ -3716,6 +3768,7 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
 	plat_priv->bus_priv = pci_priv;
 	snprintf(plat_priv->firmware_name, sizeof(plat_priv->firmware_name),
 		 DEFAULT_FW_FILE_NAME);
+	mutex_init(&pci_priv->bus_lock);
 
 	ret = cnss_register_subsys(plat_priv);
 	if (ret)
diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h
index 8dcb14a6..e7da860 100644
--- a/drivers/net/wireless/cnss2/pci.h
+++ b/drivers/net/wireless/cnss2/pci.h
@@ -92,6 +92,7 @@ struct cnss_pci_data {
 	struct timer_list dev_rddm_timer;
 	struct delayed_work time_sync_work;
 	u8 disable_pc;
+	struct mutex bus_lock; /* mutex for suspend and resume bus */
 	struct cnss_pci_debug_reg *debug_reg;
 	struct cnss_misc_reg *wcss_reg;
 	u32 wcss_reg_size;
@@ -173,6 +174,8 @@ void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic);
 void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv);
 u32 cnss_pci_get_wake_msi(struct cnss_pci_data *pci_priv);
 int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv);
+int cnss_pci_qmi_send_get(struct cnss_pci_data *pci_priv);
+int cnss_pci_qmi_send_put(struct cnss_pci_data *pci_priv);
 void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv);
 int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv);
 int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv);
@@ -196,5 +199,7 @@ void cnss_pci_pm_runtime_mark_last_busy(struct cnss_pci_data *pci_priv);
 int cnss_pci_update_status(struct cnss_pci_data *pci_priv,
 			   enum cnss_driver_status status);
 int cnss_pcie_is_device_down(struct cnss_pci_data *pci_priv);
+int cnss_pci_suspend_bus(struct cnss_pci_data *pci_priv);
+int cnss_pci_resume_bus(struct cnss_pci_data *pci_priv);
 
 #endif /* _CNSS_PCI_H */
diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c
index 02178b3..2ffb1be 100644
--- a/drivers/net/wireless/cnss2/qmi.c
+++ b/drivers/net/wireless/cnss2/qmi.c
@@ -92,6 +92,8 @@ static int cnss_wlfw_ind_register_send_sync(struct cnss_plat_data *plat_priv)
 	req->qdss_trace_save_enable = 1;
 	req->qdss_trace_free_enable_valid = 1;
 	req->qdss_trace_free_enable = 1;
+	req->respond_get_info_enable_valid = 1;
+	req->respond_get_info_enable = 1;
 
 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
 			   wlfw_ind_register_resp_msg_v01_ei, resp);
@@ -1458,6 +1460,77 @@ int cnss_wlfw_dynamic_feature_mask_send_sync(struct cnss_plat_data *plat_priv)
 	return ret;
 }
 
+int cnss_wlfw_get_info_send_sync(struct cnss_plat_data *plat_priv, int type,
+				 void *cmd, int cmd_len)
+{
+	struct wlfw_get_info_req_msg_v01 *req;
+	struct wlfw_get_info_resp_msg_v01 *resp;
+	struct qmi_txn txn;
+	int ret = 0;
+
+	cnss_pr_vdbg("Sending get info message, type: %d, cmd length: %d, state: 0x%lx\n",
+		     type, cmd_len, plat_priv->driver_state);
+
+	if (cmd_len > QMI_WLFW_MAX_DATA_SIZE_V01)
+		return -EINVAL;
+
+	req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		kfree(req);
+		return -ENOMEM;
+	}
+
+	req->type = type;
+	req->data_len = cmd_len;
+	memcpy(req->data, cmd, req->data_len);
+
+	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
+			   wlfw_get_info_resp_msg_v01_ei, resp);
+	if (ret < 0) {
+		cnss_pr_err("Failed to initialize txn for get info request, err: %d\n",
+			    ret);
+		goto out;
+	}
+
+	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
+			       QMI_WLFW_GET_INFO_REQ_V01,
+			       WLFW_GET_INFO_REQ_MSG_V01_MAX_MSG_LEN,
+			       wlfw_get_info_req_msg_v01_ei, req);
+	if (ret < 0) {
+		qmi_txn_cancel(&txn);
+		cnss_pr_err("Failed to send get info request, err: %d\n",
+			    ret);
+		goto out;
+	}
+
+	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
+	if (ret < 0) {
+		cnss_pr_err("Failed to wait for response of get info request, err: %d\n",
+			    ret);
+		goto out;
+	}
+
+	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
+		cnss_pr_err("Get info request failed, result: %d, err: %d\n",
+			    resp->resp.result, resp->resp.error);
+		ret = -resp->resp.result;
+		goto out;
+	}
+
+	kfree(req);
+	kfree(resp);
+	return 0;
+
+out:
+	kfree(req);
+	kfree(resp);
+	return ret;
+}
+
 unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv)
 {
 	cnss_pr_dbg("QMI timeout is %u ms\n", QMI_WLFW_TIMEOUT_MS);
@@ -1717,6 +1790,31 @@ static void cnss_wlfw_qdss_trace_free_ind_cb(struct qmi_handle *qmi_wlfw,
 			       0, NULL);
 }
 
+static void cnss_wlfw_respond_get_info_ind_cb(struct qmi_handle *qmi_wlfw,
+					      struct sockaddr_qrtr *sq,
+					      struct qmi_txn *txn,
+					      const void *data)
+{
+	struct cnss_plat_data *plat_priv =
+		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
+	const struct wlfw_respond_get_info_ind_msg_v01 *ind_msg = data;
+
+	cnss_pr_vdbg("Received QMI WLFW respond get info indication\n");
+
+	if (!txn) {
+		cnss_pr_err("Spurious indication\n");
+		return;
+	}
+
+	cnss_pr_vdbg("Extract message with event length: %d, type: %d, is last: %d, seq no: %d\n",
+		     ind_msg->data_len, ind_msg->type,
+		     ind_msg->is_last, ind_msg->seq_no);
+
+	if (plat_priv->get_info_cb_ctx && plat_priv->get_info_cb)
+		plat_priv->get_info_cb(plat_priv->get_info_cb_ctx,
+				       (void *)ind_msg->data,
+				       ind_msg->data_len);
+}
 static struct qmi_msg_handler qmi_wlfw_msg_handlers[] = {
 	{
 		.type = QMI_INDICATION,
@@ -1785,6 +1883,14 @@ static struct qmi_msg_handler qmi_wlfw_msg_handlers[] = {
 		sizeof(struct wlfw_qdss_trace_free_ind_msg_v01),
 		.fn = cnss_wlfw_qdss_trace_free_ind_cb
 	},
+	{
+		.type = QMI_INDICATION,
+		.msg_id = QMI_WLFW_RESPOND_GET_INFO_IND_V01,
+		.ei = wlfw_respond_get_info_ind_msg_v01_ei,
+		.decoded_size =
+		sizeof(struct wlfw_respond_get_info_ind_msg_v01),
+		.fn = cnss_wlfw_respond_get_info_ind_cb
+	},
 	{}
 };
 
diff --git a/drivers/net/wireless/cnss2/qmi.h b/drivers/net/wireless/cnss2/qmi.h
index a064660..fc2a2c6 100644
--- a/drivers/net/wireless/cnss2/qmi.h
+++ b/drivers/net/wireless/cnss2/qmi.h
@@ -59,6 +59,8 @@ int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
 int cnss_wlfw_antenna_switch_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_antenna_grant_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_dynamic_feature_mask_send_sync(struct cnss_plat_data *plat_priv);
+int cnss_wlfw_get_info_send_sync(struct cnss_plat_data *plat_priv, int type,
+				 void *cmd, int cmd_len);
 int cnss_register_coex_service(struct cnss_plat_data *plat_priv);
 void cnss_unregister_coex_service(struct cnss_plat_data *plat_priv);
 int coex_antenna_switch_to_wlan_send_sync_msg(struct cnss_plat_data *plat_priv);
diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
index 03a418e..682a20b 100644
--- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
+++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
@@ -704,6 +704,24 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = {
 					   qdss_trace_free_enable),
 	},
 	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x1F,
+		.offset         = offsetof(struct wlfw_ind_register_req_msg_v01,
+					   respond_get_info_enable_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x1F,
+		.offset         = offsetof(struct wlfw_ind_register_req_msg_v01,
+					   respond_get_info_enable),
+	},
+	{
 		.data_type      = QMI_EOTI,
 		.array_type       = NO_ARRAY,
 		.tlv_type       = QMI_COMMON_TLV_TYPE,
@@ -3608,3 +3626,143 @@ struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[] = {
 	},
 };
 
+struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wlfw_get_info_req_msg_v01,
+					   type),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u16),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct wlfw_get_info_req_msg_v01,
+					   data_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = QMI_WLFW_MAX_DATA_SIZE_V01,
+		.elem_size      = sizeof(u8),
+		.array_type       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct wlfw_get_info_req_msg_v01,
+					   data),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct wlfw_get_info_resp_msg_v01,
+					   resp),
+		.ei_array      = qmi_response_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info wlfw_respond_get_info_ind_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u16),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct
+					   wlfw_respond_get_info_ind_msg_v01,
+					   data_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = QMI_WLFW_MAX_DATA_SIZE_V01,
+		.elem_size      = sizeof(u8),
+		.array_type       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct
+					   wlfw_respond_get_info_ind_msg_v01,
+					   data),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(struct
+					   wlfw_respond_get_info_ind_msg_v01,
+					   type_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(struct
+					   wlfw_respond_get_info_ind_msg_v01,
+					   type),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x11,
+		.offset         = offsetof(struct
+					   wlfw_respond_get_info_ind_msg_v01,
+					   is_last_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x11,
+		.offset         = offsetof(struct
+					   wlfw_respond_get_info_ind_msg_v01,
+					   is_last),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x12,
+		.offset         = offsetof(struct
+					   wlfw_respond_get_info_ind_msg_v01,
+					   seq_no_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x12,
+		.offset         = offsetof(struct
+					   wlfw_respond_get_info_ind_msg_v01,
+					   seq_no),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
index dacdfdb..0e18d80 100644
--- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
+++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
@@ -13,6 +13,7 @@
 #define QMI_WLFW_BDF_DOWNLOAD_REQ_V01 0x0025
 #define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037
 #define QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01 0x0044
+#define QMI_WLFW_GET_INFO_REQ_V01 0x004A
 #define QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01 0x002A
 #define QMI_WLFW_CAL_DONE_IND_V01 0x003E
 #define QMI_WLFW_WFC_CALL_STATUS_RESP_V01 0x0049
@@ -23,6 +24,7 @@
 #define QMI_WLFW_FW_INIT_DONE_IND_V01 0x0038
 #define QMI_WLFW_ANTENNA_GRANT_RESP_V01 0x0048
 #define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026
+#define QMI_WLFW_RESPOND_GET_INFO_IND_V01 0x004B
 #define QMI_WLFW_M3_INFO_RESP_V01 0x003C
 #define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029
 #define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027
@@ -49,6 +51,7 @@
 #define QMI_WLFW_ATHDIAG_WRITE_REQ_V01 0x0031
 #define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022
 #define QMI_WLFW_RESPOND_MEM_REQ_V01 0x0036
+#define QMI_WLFW_GET_INFO_RESP_V01 0x004A
 #define QMI_WLFW_QDSS_TRACE_MODE_RESP_V01 0x0045
 #define QMI_WLFW_PIN_CONNECT_RESULT_IND_V01 0x002C
 #define QMI_WLFW_FW_READY_IND_V01 0x0021
@@ -272,9 +275,11 @@ struct wlfw_ind_register_req_msg_v01 {
 	u8 qdss_trace_save_enable;
 	u8 qdss_trace_free_enable_valid;
 	u8 qdss_trace_free_enable;
+	u8 respond_get_info_enable_valid;
+	u8 respond_get_info_enable;
 };
 
-#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 66
+#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 70
 extern struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[];
 
 struct wlfw_ind_register_resp_msg_v01 {
@@ -949,4 +954,34 @@ struct wlfw_wfc_call_status_resp_msg_v01 {
 #define WLFW_WFC_CALL_STATUS_RESP_MSG_V01_MAX_MSG_LEN 7
 extern struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[];
 
+struct wlfw_get_info_req_msg_v01 {
+	u8 type;
+	u32 data_len;
+	u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
+};
+
+#define WLFW_GET_INFO_REQ_MSG_V01_MAX_MSG_LEN 6153
+extern struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[];
+
+struct wlfw_get_info_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+};
+
+#define WLFW_GET_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[];
+
+struct wlfw_respond_get_info_ind_msg_v01 {
+	u32 data_len;
+	u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
+	u8 type_valid;
+	u8 type;
+	u8 is_last_valid;
+	u8 is_last;
+	u8 seq_no_valid;
+	u32 seq_no;
+};
+
+#define WLFW_RESPOND_GET_INFO_IND_MSG_V01_MAX_MSG_LEN 6164
+extern struct qmi_elem_info wlfw_respond_get_info_ind_msg_v01_ei[];
+
 #endif
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index f06ca58..cd0e278 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -908,6 +908,9 @@ static int pci_pm_resume(struct device *dev)
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	int error = 0;
 
+	if (pci_dev->no_d3hot)
+		goto skip_pci_pm_restore;
+
 	/*
 	 * This is necessary for the suspend error path in which resume is
 	 * called without restoring the standard config registers of the device.
@@ -915,6 +918,7 @@ static int pci_pm_resume(struct device *dev)
 	if (pci_dev->state_saved)
 		pci_restore_standard_config(pci_dev);
 
+skip_pci_pm_restore:
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_resume(dev);
 
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index d578a72..cc6bf43 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -2423,6 +2423,11 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl,
 	ctx->stats.dp.last_timestamp = jiffies_to_msecs(jiffies);
 	atomic_inc(&gsi_ctx->num_chan);
 
+	if (props->prot == GSI_CHAN_PROT_GCI) {
+		gsi_ctx->coal_info.ch_id = props->ch_id;
+		gsi_ctx->coal_info.evchid = props->evt_ring_hdl;
+	}
+
 	return GSI_STATUS_SUCCESS;
 }
 EXPORT_SYMBOL(gsi_alloc_channel);
@@ -3155,6 +3160,10 @@ int gsi_dealloc_channel(unsigned long chan_hdl)
 		atomic_dec(&ctx->evtr->chan_ref_cnt);
 	atomic_dec(&gsi_ctx->num_chan);
 
+	if (ctx->props.prot == GSI_CHAN_PROT_GCI) {
+		gsi_ctx->coal_info.ch_id = GSI_CHAN_MAX;
+		gsi_ctx->coal_info.evchid = GSI_EVT_RING_MAX;
+	}
 	return GSI_STATUS_SUCCESS;
 }
 EXPORT_SYMBOL(gsi_dealloc_channel);
@@ -3707,7 +3716,7 @@ EXPORT_SYMBOL(gsi_poll_n_channel);
 
 int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
 {
-	struct gsi_chan_ctx *ctx;
+	struct gsi_chan_ctx *ctx, *coal_ctx;
 	enum gsi_chan_mode curr;
 	unsigned long flags;
 	enum gsi_chan_mode chan_mode;
@@ -3753,8 +3762,14 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
 		gsi_writel(1 << ctx->evtr->id, gsi_ctx->base +
 			GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_OFFS(gsi_ctx->per.ee));
 		atomic_set(&ctx->poll_mode, mode);
-		if ((ctx->props.prot == GSI_CHAN_PROT_GCI) && ctx->evtr->chan)
+		if ((ctx->props.prot == GSI_CHAN_PROT_GCI) && ctx->evtr->chan) {
 			atomic_set(&ctx->evtr->chan->poll_mode, mode);
+		} else if (gsi_ctx->coal_info.evchid == ctx->evtr->id) {
+			coal_ctx = &gsi_ctx->chan[gsi_ctx->coal_info.ch_id];
+			if (coal_ctx != NULL)
+				atomic_set(&coal_ctx->poll_mode, mode);
+		}
+
 		GSIDBG("set gsi_ctx evtr_id %d to %d mode\n",
 			ctx->evtr->id, mode);
 		ctx->stats.callback_to_poll++;
@@ -3763,8 +3778,13 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode)
 	if (curr == GSI_CHAN_MODE_POLL &&
 			mode == GSI_CHAN_MODE_CALLBACK) {
 		atomic_set(&ctx->poll_mode, mode);
-		if ((ctx->props.prot == GSI_CHAN_PROT_GCI) && ctx->evtr->chan)
+		if ((ctx->props.prot == GSI_CHAN_PROT_GCI) && ctx->evtr->chan) {
 			atomic_set(&ctx->evtr->chan->poll_mode, mode);
+		} else if (gsi_ctx->coal_info.evchid == ctx->evtr->id) {
+			coal_ctx = &gsi_ctx->chan[gsi_ctx->coal_info.ch_id];
+			if (coal_ctx != NULL)
+				atomic_set(&coal_ctx->poll_mode, mode);
+		}
 		__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, ~0);
 		GSIDBG("set gsi_ctx evtr_id %d to %d mode\n",
 			ctx->evtr->id, mode);
diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h
index 45dec44..3b6c648 100644
--- a/drivers/platform/msm/gsi/gsi.h
+++ b/drivers/platform/msm/gsi/gsi.h
@@ -200,6 +200,11 @@ struct gsi_generic_ee_cmd_debug_stats {
 	unsigned long halt_channel;
 };
 
+struct gsi_coal_chan_info {
+	uint8_t ch_id;
+	uint8_t evchid;
+};
+
 struct gsi_ctx {
 	void __iomem *base;
 	struct device *dev;
@@ -223,6 +228,7 @@ struct gsi_ctx {
 	struct completion gen_ee_cmd_compl;
 	void *ipc_logbuf;
 	void *ipc_logbuf_low;
+	struct gsi_coal_chan_info coal_info;
 	/*
 	 * The following used only on emulation systems.
 	 */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 927b040..79bc2f9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -34,6 +34,7 @@
 #include <asm/cacheflush.h>
 #include <linux/soc/qcom/smem_state.h>
 #include <linux/of_irq.h>
+#include <linux/ctype.h>
 
 #ifdef CONFIG_ARM64
 
@@ -5968,6 +5969,7 @@ static ssize_t ipa3_write(struct file *file, const char __user *buf,
 	unsigned long missing;
 
 	char dbg_buff[32] = { 0 };
+	int i = 0;
 
 	if (count >= sizeof(dbg_buff))
 		return -EFAULT;
@@ -5988,6 +5990,17 @@ static ssize_t ipa3_write(struct file *file, const char __user *buf,
 	if (ipa3_is_ready())
 		return count;
 
+	/*Ignore empty ipa_config file*/
+	for (i = 0 ; i < count ; ++i) {
+		if (!isspace(dbg_buff[i]))
+			break;
+	}
+
+	if (i == count) {
+		IPADBG("Empty ipa_config file\n");
+		return count;
+	}
+
 	/* Check MHI configuration on MDM devices */
 	if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_MDM) {
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index d17ff30..fb8b055 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -2423,7 +2423,7 @@ static const struct ipa_ep_configuration ipa3_ep_mapping
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
 			{ 16, 10, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } },
-	[IPA_4_5][IPA_CLIENT_USB_DPL_CONS]        = {
+	[IPA_4_5_MHI][IPA_CLIENT_USB_DPL_CONS]        = {
 			true, IPA_v4_5_MHI_GROUP_DDR,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 11c520f..cfc7751 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -3104,7 +3104,8 @@ static int rmnet_ipa3_set_data_quota_wifi(struct wan_ioctl_set_data_quota *data)
 	IPAWANERR("iface name %s, quota %lu\n",
 		  data->interface_name, (unsigned long) data->quota_mbytes);
 
-	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) {
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5 &&
+		ipa3_ctx->ipa_hw_type != IPA_HW_v4_7) {
 		IPADBG("use ipa-uc for quota\n");
 		rc = ipa3_uc_quota_monitor(data->set_quota);
 	} else {
@@ -3835,6 +3836,7 @@ int rmnet_ipa3_query_tethering_stats_all(
 	} else if (upstream_type == IPA_UPSTEAM_WLAN) {
 		IPAWANDBG_LOW(" query wifi-backhaul stats\n");
 		if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5 ||
+			ipa3_ctx->ipa_hw_type == IPA_HW_v4_7 ||
 			!ipa3_ctx->hw_stats.enabled) {
 			IPAWANDBG("hw version %d,hw_stats.enabled %d\n",
 				ipa3_ctx->ipa_hw_type,
diff --git a/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c b/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c
index caae2ba..c4d53df 100644
--- a/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c
+++ b/drivers/platform/msm/ipa/test/ipa_test_hw_stats.c
@@ -736,7 +736,8 @@ static int ipa_test_hw_stats_set_uc_event_ring(void *priv)
 	/* set uc event ring */
 	IPA_UT_INFO("========set uc event ring ========\n");
 
-	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) {
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5 &&
+		ipa3_ctx->ipa_hw_type != IPA_HW_v4_7) {
 		if (ipa3_ctx->uc_ctx.uc_loaded &&
 			!ipa3_ctx->uc_ctx.uc_event_ring_valid) {
 			if (ipa3_uc_setup_event_ring()) {
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 9a00920..47197f0 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -1436,7 +1436,7 @@ static int smb5_dc_get_prop(struct power_supply *psy,
 		rc = smblib_get_prop_dc_voltage_max(chg, val);
 		break;
 	case POWER_SUPPLY_PROP_REAL_TYPE:
-		val->intval = POWER_SUPPLY_TYPE_WIPOWER;
+		val->intval = POWER_SUPPLY_TYPE_WIRELESS;
 		break;
 	case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
 		rc = smblib_get_prop_voltage_wls_output(chg, val);
@@ -2785,6 +2785,7 @@ static int smb5_determine_initial_status(struct smb5 *chip)
 		smblib_suspend_on_debug_battery(chg);
 
 	usb_plugin_irq_handler(0, &irq_data);
+	dc_plugin_irq_handler(0, &irq_data);
 	typec_attach_detach_irq_handler(0, &irq_data);
 	typec_state_change_irq_handler(0, &irq_data);
 	usb_source_change_irq_handler(0, &irq_data);
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index 2890df6..cadb594 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -832,10 +832,10 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg,
 	if (vbus_allowance != CONTINUOUS)
 		return 0;
 
+	aicl_threshold = min_allowed_uv / 1000 - CONT_AICL_HEADROOM_MV;
 	if (chg->adapter_cc_mode)
-		aicl_threshold = AICL_THRESHOLD_MV_IN_CC;
-	else
-		aicl_threshold = min_allowed_uv / 1000 - CONT_AICL_HEADROOM_MV;
+		aicl_threshold = min(aicl_threshold, AICL_THRESHOLD_MV_IN_CC);
+
 	rc = smblib_set_charge_param(chg, &chg->param.aicl_cont_threshold,
 							aicl_threshold);
 	if (rc < 0) {
@@ -3584,6 +3584,7 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
 		return -EINVAL;
 	}
 
+	chg->power_role = val->intval;
 	return rc;
 }
 
@@ -4172,15 +4173,86 @@ int smblib_set_prop_usb_voltage_max_limit(struct smb_charger *chg,
 	return 0;
 }
 
+void smblib_typec_irq_config(struct smb_charger *chg, bool en)
+{
+	if (en == chg->typec_irq_en)
+		return;
+
+	if (en) {
+		enable_irq(
+			chg->irq_info[TYPEC_ATTACH_DETACH_IRQ].irq);
+		enable_irq(
+			chg->irq_info[TYPEC_CC_STATE_CHANGE_IRQ].irq);
+		enable_irq(
+			chg->irq_info[TYPEC_OR_RID_DETECTION_CHANGE_IRQ].irq);
+	} else {
+		disable_irq_nosync(
+			chg->irq_info[TYPEC_ATTACH_DETACH_IRQ].irq);
+		disable_irq_nosync(
+			chg->irq_info[TYPEC_CC_STATE_CHANGE_IRQ].irq);
+		disable_irq_nosync(
+			chg->irq_info[TYPEC_OR_RID_DETECTION_CHANGE_IRQ].irq);
+	}
+
+	chg->typec_irq_en = en;
+}
+
+#define PR_LOCK_TIMEOUT_MS	1000
 int smblib_set_prop_typec_power_role(struct smb_charger *chg,
 				     const union power_supply_propval *val)
 {
 	int rc = 0;
 	u8 power_role;
+	enum power_supply_typec_mode typec_mode;
+	bool snk_attached = false, src_attached = false, is_pr_lock = false;
 
 	if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
 		return 0;
 
+	smblib_dbg(chg, PR_MISC, "power role change: %d --> %d!",
+			chg->power_role, val->intval);
+
+	if (chg->power_role == val->intval) {
+		smblib_dbg(chg, PR_MISC, "power role already in %d, ignore!",
+				chg->power_role);
+		return 0;
+	}
+
+	typec_mode = smblib_get_prop_typec_mode(chg);
+	if (typec_mode >= POWER_SUPPLY_TYPEC_SINK &&
+			typec_mode <= POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER)
+		snk_attached = true;
+	else if (typec_mode >= POWER_SUPPLY_TYPEC_SOURCE_DEFAULT &&
+			typec_mode <= POWER_SUPPLY_TYPEC_SOURCE_HIGH)
+		src_attached = true;
+
+	/*
+	 * If current power role is in DRP, and type-c is already in the
+	 * mode (source or sink) that's being requested, it means this is
+	 * a power role locking request from USBPD driver. Disable type-c
+	 * related interrupts for locking power role to avoid the redundant
+	 * notifications.
+	 */
+	if ((chg->power_role == POWER_SUPPLY_TYPEC_PR_DUAL) &&
+		((src_attached && val->intval == POWER_SUPPLY_TYPEC_PR_SINK) ||
+		(snk_attached && val->intval == POWER_SUPPLY_TYPEC_PR_SOURCE)))
+		is_pr_lock = true;
+
+	smblib_dbg(chg, PR_MISC, "snk_attached = %d, src_attached = %d, is_pr_lock = %d\n",
+			snk_attached, src_attached, is_pr_lock);
+	cancel_delayed_work_sync(&chg->pr_lock_clear_work);
+	if (!chg->pr_lock_in_progress && is_pr_lock) {
+		smblib_dbg(chg, PR_MISC, "disable type-c interrupts for power role locking\n");
+		smblib_typec_irq_config(chg, false);
+		schedule_delayed_work(&chg->pr_lock_clear_work,
+					msecs_to_jiffies(PR_LOCK_TIMEOUT_MS));
+	} else if (chg->pr_lock_in_progress && !is_pr_lock) {
+		smblib_dbg(chg, PR_MISC, "restore type-c interrupts after exit power role locking\n");
+		smblib_typec_irq_config(chg, true);
+	}
+
+	chg->pr_lock_in_progress = is_pr_lock;
+
 	switch (val->intval) {
 	case POWER_SUPPLY_TYPEC_PR_NONE:
 		power_role = TYPEC_DISABLE_CMD_BIT;
@@ -4208,6 +4280,7 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
 		return rc;
 	}
 
+	chg->power_role = val->intval;
 	return rc;
 }
 
@@ -5532,8 +5605,10 @@ static void typec_src_insertion(struct smb_charger *chg)
 	int rc = 0;
 	u8 stat;
 
-	if (chg->pr_swap_in_progress)
+	if (chg->pr_swap_in_progress) {
+		vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0);
 		return;
+	}
 
 	rc = smblib_read(chg, LEGACY_CABLE_STATUS_REG, &stat);
 	if (rc < 0) {
@@ -6190,7 +6265,8 @@ irqreturn_t dc_plugin_irq_handler(int irq, void *data)
 		chg->last_wls_vout = 0;
 	}
 
-	power_supply_changed(chg->dc_psy);
+	if (chg->dc_psy)
+		power_supply_changed(chg->dc_psy);
 
 	smblib_dbg(chg, (PR_WLS | PR_INTERRUPT), "dcin_present= %d, usbin_present= %d, cp_reason = %d\n",
 			dcin_present, vbus_present, chg->cp_reason);
@@ -6467,13 +6543,19 @@ int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg,
 		if (rc < 0) {
 			smblib_err(chg, "Couldn't read TYPE_C_CCOUT_CONTROL_REG rc=%d\n",
 				rc);
+			return rc;
 		}
 
 		/* enable DRP */
 		rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
 				 TYPEC_POWER_ROLE_CMD_MASK, 0);
-		if (rc < 0)
+		if (rc < 0) {
 			smblib_err(chg, "Couldn't enable DRP rc=%d\n", rc);
+			return rc;
+		}
+		chg->power_role = POWER_SUPPLY_TYPEC_PR_DUAL;
+		smblib_dbg(chg, PR_MISC, "restore power role: %d\n",
+				chg->power_role);
 	}
 
 	return 0;
@@ -6482,6 +6564,18 @@ int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg,
 /***************
  * Work Queues *
  ***************/
+static void smblib_pr_lock_clear_work(struct work_struct *work)
+{
+	struct smb_charger *chg = container_of(work, struct smb_charger,
+						pr_lock_clear_work.work);
+
+	if (chg->pr_lock_in_progress) {
+		smblib_dbg(chg, PR_MISC, "restore type-c interrupts\n");
+		smblib_typec_irq_config(chg, true);
+		chg->pr_lock_in_progress = false;
+	}
+}
+
 static void smblib_pr_swap_detach_work(struct work_struct *work)
 {
 	struct smb_charger *chg = container_of(work, struct smb_charger,
@@ -7258,6 +7352,8 @@ int smblib_init(struct smb_charger *chg)
 	INIT_DELAYED_WORK(&chg->usbov_dbc_work, smblib_usbov_dbc_work);
 	INIT_DELAYED_WORK(&chg->pr_swap_detach_work,
 					smblib_pr_swap_detach_work);
+	INIT_DELAYED_WORK(&chg->pr_lock_clear_work,
+					smblib_pr_lock_clear_work);
 
 	if (chg->wa_flags & CHG_TERMINATION_WA) {
 		INIT_WORK(&chg->chg_termination_work,
@@ -7301,6 +7397,7 @@ int smblib_init(struct smb_charger *chg)
 	chg->sec_chg_selected = POWER_SUPPLY_CHARGER_SEC_NONE;
 	chg->cp_reason = POWER_SUPPLY_CP_NONE;
 	chg->thermal_status = TEMP_BELOW_RANGE;
+	chg->typec_irq_en = true;
 
 	switch (chg->mode) {
 	case PARALLEL_MASTER:
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 32cd1a6..613304d 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -447,6 +447,7 @@ struct smb_charger {
 	struct delayed_work	thermal_regulation_work;
 	struct delayed_work	usbov_dbc_work;
 	struct delayed_work	pr_swap_detach_work;
+	struct delayed_work	pr_lock_clear_work;
 
 	struct alarm		lpd_recheck_timer;
 	struct alarm		moisture_protection_alarm;
@@ -464,10 +465,12 @@ struct smb_charger {
 	int			voltage_max_uv;
 	int			pd_active;
 	bool			pd_hard_reset;
+	bool			pr_lock_in_progress;
 	bool			pr_swap_in_progress;
 	bool			early_usb_attach;
 	bool			ok_to_pd;
 	bool			typec_legacy;
+	bool			typec_irq_en;
 
 	/* cached status */
 	bool			system_suspend_supported;
@@ -502,6 +505,7 @@ struct smb_charger {
 	int			hw_max_icl_ua;
 	int			auto_recharge_soc;
 	enum sink_src_mode	sink_src_mode;
+	enum power_supply_typec_power_role power_role;
 	enum jeita_cfg_stat	jeita_configured;
 	int			charger_temp_max;
 	int			smb_temp_max;
diff --git a/drivers/regulator/qpnp-amoled-regulator.c b/drivers/regulator/qpnp-amoled-regulator.c
index f5f89ee..78da900 100644
--- a/drivers/regulator/qpnp-amoled-regulator.c
+++ b/drivers/regulator/qpnp-amoled-regulator.c
@@ -15,7 +15,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/mutex.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
@@ -74,7 +73,6 @@ struct ab_regulator {
 	/* DT params */
 	bool			swire_control;
 	bool			pd_control;
-	u32			aod_entry_poll_time_ms;
 };
 
 struct ibb_regulator {
@@ -91,9 +89,6 @@ struct qpnp_amoled {
 	struct oledb_regulator	oledb;
 	struct ab_regulator	ab;
 	struct ibb_regulator	ibb;
-	struct mutex		reg_lock;
-	struct work_struct	aod_work;
-	struct workqueue_struct *wq;
 
 	/* DT params */
 	u32			oledb_base;
@@ -226,102 +221,6 @@ static int qpnp_ab_pd_control(struct qpnp_amoled *chip, bool en)
 	return qpnp_amoled_write(chip, AB_LDO_PD_CTL(chip), &val, 1);
 }
 
-#define AB_VREG_OK_POLL_TIME_US		2000
-#define AB_VREG_OK_POLL_HIGH_TRIES	8
-#define AB_VREG_OK_POLL_HIGH_TIME_US	10000
-#define AB_VREG_OK_POLL_AGAIN_TRIES	10
-
-static int qpnp_ab_poll_vreg_ok(struct qpnp_amoled *chip, bool status,
-				u32 poll_time_us)
-{
-	u32 i, poll_us = AB_VREG_OK_POLL_TIME_US, wait_time_us = 0;
-	bool swire_high = false, poll_again = false, monitor = false;
-	int rc;
-	u8 val;
-
-	if (poll_time_us < AB_VREG_OK_POLL_TIME_US)
-		return -EINVAL;
-
-	i = poll_time_us / AB_VREG_OK_POLL_TIME_US;
-loop:
-	while (i--) {
-		/* Write a dummy value before reading AB_STATUS1 */
-		rc = qpnp_amoled_write(chip, AB_STATUS1(chip), &val, 1);
-		if (rc < 0)
-			return rc;
-
-		rc = qpnp_amoled_read(chip, AB_STATUS1(chip), &val, 1);
-		if (rc < 0)
-			return rc;
-
-		wait_time_us += poll_us;
-		if (((val & VREG_OK_BIT) >> VREG_OK_SHIFT) == status) {
-			pr_debug("Waited for %d us\n", wait_time_us);
-
-			/*
-			 * Return if we're polling for VREG_OK low. Else, poll
-			 * for VREG_OK high for at least 80 ms. IF VREG_OK stays
-			 * high, then consider it as a valid SWIRE pulse.
-			 */
-
-			if (status) {
-				swire_high = true;
-				if (!poll_again && !monitor) {
-					pr_debug("SWIRE is high, start monitoring\n");
-					i = AB_VREG_OK_POLL_HIGH_TRIES;
-					poll_us = AB_VREG_OK_POLL_HIGH_TIME_US;
-					wait_time_us = 0;
-					monitor = true;
-				}
-
-				if (poll_again)
-					poll_again = false;
-			} else {
-				return 0;
-			}
-		} else {
-			/*
-			 * If we're here when polling for VREG_OK high, then it
-			 * is possibly because of an intermittent SWIRE pulse.
-			 * Ignore it and poll for valid SWIRE pulse again.
-			 */
-			if (status && swire_high && monitor) {
-				pr_debug("SWIRE is low\n");
-				poll_again = true;
-				swire_high = false;
-				break;
-			}
-
-			if (poll_again)
-				poll_again = false;
-		}
-
-		usleep_range(poll_us, poll_us + 1);
-	}
-
-	/*
-	 * If poll_again is set, then VREG_OK should be polled for another
-	 * 100 ms for valid SWIRE signal.
-	 */
-
-	if (poll_again) {
-		pr_debug("polling again for SWIRE\n");
-		i = AB_VREG_OK_POLL_AGAIN_TRIES;
-		poll_us = AB_VREG_OK_POLL_HIGH_TIME_US;
-		wait_time_us = 0;
-		goto loop;
-	}
-
-	/* If swire_high is set, then it's a valid SWIRE signal, return 0. */
-	if (swire_high) {
-		pr_debug("SWIRE is high\n");
-		return 0;
-	}
-
-	pr_err("AB_STATUS1: %x poll for VREG_OK %d timed out\n", val, status);
-	return -ETIMEDOUT;
-}
-
 static int qpnp_ibb_pd_control(struct qpnp_amoled *chip, bool en)
 {
 	u8 val = en ? ENABLE_PD_BIT : 0;
@@ -330,70 +229,24 @@ static int qpnp_ibb_pd_control(struct qpnp_amoled *chip, bool en)
 					val);
 }
 
-static int qpnp_ibb_aod_config(struct qpnp_amoled *chip, bool aod)
+static int qpnp_ab_ibb_regulator_set_mode(struct regulator_dev *rdev,
+						unsigned int mode)
 {
+	struct qpnp_amoled *chip  = rdev_get_drvdata(rdev);
 	int rc;
-	u8 ps_ctl, smart_ps_ctl, nlimit_dac;
 
-	pr_debug("aod: %d\n", aod);
-	if (aod) {
-		ps_ctl = 0x82;
-		smart_ps_ctl = 0;
-		nlimit_dac = 0;
-	} else {
-		ps_ctl = 0x02;
-		smart_ps_ctl = 0x80;
-		nlimit_dac = 0x3;
+	if (mode != REGULATOR_MODE_NORMAL && mode != REGULATOR_MODE_STANDBY &&
+		mode != REGULATOR_MODE_IDLE) {
+		pr_err("Unsupported mode %u\n", mode);
+		return -EINVAL;
 	}
 
-	rc = qpnp_amoled_write(chip, IBB_SMART_PS_CTL(chip), &smart_ps_ctl, 1);
-	if (rc < 0)
-		return rc;
-
-	rc = qpnp_amoled_write(chip, IBB_NLIMIT_DAC(chip), &nlimit_dac, 1);
-	if (rc < 0)
-		return rc;
-
-	rc = qpnp_amoled_write(chip, IBB_PS_CTL(chip), &ps_ctl, 1);
-	return rc;
-}
-
-static void qpnp_amoled_aod_work(struct work_struct *work)
-{
-	struct qpnp_amoled *chip = container_of(work, struct qpnp_amoled,
-					aod_work);
-	u8 val = 0;
-	unsigned int mode;
-	u32 poll_time_us = 100000;
-	int rc;
-
-	mutex_lock(&chip->reg_lock);
-	mode = chip->ab.vreg.mode;
-	mutex_unlock(&chip->reg_lock);
+	if (mode == chip->ab.vreg.mode || mode == chip->ibb.vreg.mode)
+		return 0;
 
 	pr_debug("mode: %d\n", mode);
-	if (mode == REGULATOR_MODE_NORMAL) {
-		rc = qpnp_ibb_aod_config(chip, true);
-		if (rc < 0)
-			goto error;
 
-		/* poll for VREG_OK high */
-		rc = qpnp_ab_poll_vreg_ok(chip, true, poll_time_us);
-		if (rc < 0)
-			goto error;
-
-		/*
-		 * As per the hardware recommendation, Wait for ~10 ms after
-		 * polling for VREG_OK before changing the configuration when
-		 * exiting from AOD mode.
-		 */
-
-		usleep_range(10000, 10001);
-
-		rc = qpnp_ibb_aod_config(chip, false);
-		if (rc < 0)
-			goto error;
-
+	if (mode == REGULATOR_MODE_NORMAL || mode == REGULATOR_MODE_STANDBY) {
 		if (chip->ibb.pd_control) {
 			rc = qpnp_ibb_pd_control(chip, true);
 			if (rc < 0)
@@ -406,14 +259,6 @@ static void qpnp_amoled_aod_work(struct work_struct *work)
 				goto error;
 		}
 	} else if (mode == REGULATOR_MODE_IDLE) {
-		if (chip->ab.aod_entry_poll_time_ms > 0)
-			poll_time_us = chip->ab.aod_entry_poll_time_ms * 1000;
-
-		/* poll for VREG_OK low */
-		rc = qpnp_ab_poll_vreg_ok(chip, false, poll_time_us);
-		if (rc < 0)
-			goto error;
-
 		if (chip->ibb.pd_control) {
 			rc = qpnp_ibb_pd_control(chip, false);
 			if (rc < 0)
@@ -425,53 +270,12 @@ static void qpnp_amoled_aod_work(struct work_struct *work)
 			if (rc < 0)
 				goto error;
 		}
-
-		val = 0xF1;
-	} else if (mode == REGULATOR_MODE_STANDBY) {
-		/* Restore the normal configuration without any delay */
-		rc = qpnp_ibb_aod_config(chip, false);
-		if (rc < 0)
-			goto error;
-
-		if (chip->ibb.pd_control) {
-			rc = qpnp_ibb_pd_control(chip, true);
-			if (rc < 0)
-				goto error;
-		}
-
-		if (chip->ab.pd_control) {
-			rc = qpnp_ab_pd_control(chip, true);
-			if (rc < 0)
-				goto error;
-		}
 	}
 
-	rc = qpnp_amoled_write(chip, AB_LDO_SW_DBG_CTL(chip), &val, 1);
+	chip->ab.vreg.mode = chip->ibb.vreg.mode = mode;
 error:
 	if (rc < 0)
 		pr_err("Failed to configure for mode %d\n", mode);
-}
-
-static int qpnp_ab_ibb_regulator_set_mode(struct regulator_dev *rdev,
-						unsigned int mode)
-{
-	struct qpnp_amoled *chip  = rdev_get_drvdata(rdev);
-
-	if (mode != REGULATOR_MODE_NORMAL && mode != REGULATOR_MODE_STANDBY &&
-		mode != REGULATOR_MODE_IDLE) {
-		pr_err("Unsupported mode %u\n", mode);
-		return -EINVAL;
-	}
-
-	pr_debug("mode: %d\n", mode);
-	if (mode == chip->ab.vreg.mode || mode == chip->ibb.vreg.mode)
-		return 0;
-
-	mutex_lock(&chip->reg_lock);
-	chip->ab.vreg.mode = chip->ibb.vreg.mode = mode;
-	mutex_unlock(&chip->reg_lock);
-
-	queue_work(chip->wq, &chip->aod_work);
 	return 0;
 }
 
@@ -720,9 +524,6 @@ static int qpnp_amoled_parse_dt(struct qpnp_amoled *chip)
 							"qcom,swire-control");
 			chip->ab.pd_control = of_property_read_bool(temp,
 							"qcom,aod-pd-control");
-			of_property_read_u32(temp,
-				"qcom,aod-entry-poll-time-ms",
-				&chip->ab.aod_entry_poll_time_ms);
 			break;
 		case IBB_PERIPH_TYPE:
 			chip->ibb_base = base;
@@ -758,19 +559,6 @@ static int qpnp_amoled_regulator_probe(struct platform_device *pdev)
 	if (!chip)
 		return -ENOMEM;
 
-	/*
-	 * We need this workqueue to order the mode transitions that require
-	 * timing considerations. This way, we can ensure whenever the mode
-	 * transition is requested, it can be queued with high priority.
-	 */
-	chip->wq = alloc_ordered_workqueue("qpnp_amoled_wq", WQ_HIGHPRI);
-	if (!chip->wq) {
-		dev_err(chip->dev, "Unable to alloc workqueue\n");
-		return -ENOMEM;
-	}
-
-	mutex_init(&chip->reg_lock);
-	INIT_WORK(&chip->aod_work, qpnp_amoled_aod_work);
 	chip->dev = &pdev->dev;
 
 	chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
@@ -789,23 +577,15 @@ static int qpnp_amoled_regulator_probe(struct platform_device *pdev)
 	}
 
 	rc = qpnp_amoled_hw_init(chip);
-	if (rc < 0) {
+	if (rc < 0)
 		dev_err(chip->dev, "Failed to initialize HW rc=%d\n", rc);
-		goto error;
-	}
 
-	return 0;
 error:
-	destroy_workqueue(chip->wq);
 	return rc;
 }
 
 static int qpnp_amoled_regulator_remove(struct platform_device *pdev)
 {
-	struct qpnp_amoled *chip = dev_get_drvdata(&pdev->dev);
-
-	cancel_work_sync(&chip->aod_work);
-	destroy_workqueue(chip->wq);
 	return 0;
 }
 
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 4da79b9..2da1b15 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -535,6 +535,7 @@ struct ufs_vreg {
 	int max_uV;
 	bool low_voltage_sup;
 	bool low_voltage_active;
+	bool sys_suspend_pwr_off;
 	int min_uA;
 	int max_uA;
 };
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 382e923..bd0415c 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -217,9 +217,24 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name,
 	} else if (!strcmp(name, "vccq")) {
 		vreg->min_uV = UFS_VREG_VCCQ_MIN_UV;
 		vreg->max_uV = UFS_VREG_VCCQ_MAX_UV;
+		/**
+		 * Only if the SoC supports turning off VCCQ or VCCQ2 power
+		 * supply source during power collapse, set a flag to turn off
+		 * the specified power supply to reduce the system power
+		 * consumption during system suspend events. The tradeoffs are:
+		 *   - System resume time will increase due
+		 *     to UFS device full re-initialization time.
+		 *   - UFS device life may be affected due to multiple
+		 *     UFS power on/off events.
+		 * The benefits vs tradeoff should be considered carefully.
+		 */
+		if (of_property_read_bool(np, "vccq-pwr-collapse-sup"))
+			vreg->sys_suspend_pwr_off = true;
 	} else if (!strcmp(name, "vccq2")) {
 		vreg->min_uV = UFS_VREG_VCCQ2_MIN_UV;
 		vreg->max_uV = UFS_VREG_VCCQ2_MAX_UV;
+		if (of_property_read_bool(np, "vccq2-pwr-collapse-sup"))
+			vreg->sys_suspend_pwr_off = true;
 	}
 
 	goto out;
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3bbff74..e4329a45 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -8864,6 +8864,22 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
 			goto out;
 	}
 
+	/**
+	 * UFS3.0 and newer devices use Vcc and Vccq(1.2V)
+	 * while UFS2.1 devices use Vcc and Vccq2(1.8V) power
+	 * supplies. If the system allows turning off the regulators
+	 * during power collapse event, turn off the regulators
+	 * during system suspend events. This will cause the UFS
+	 * device to re-initialize upon system resume events.
+	 */
+	if ((hba->dev_info.w_spec_version >= 0x300 &&
+		hba->vreg_info.vccq->sys_suspend_pwr_off) ||
+		(hba->dev_info.w_spec_version < 0x300 &&
+		hba->vreg_info.vccq2->sys_suspend_pwr_off))
+		hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state(
+				UFS_POWERDOWN_PWR_MODE,
+				UIC_LINK_OFF_STATE);
+
 	/* UFS device is also active now */
 	ufshcd_set_ufs_dev_active(hba);
 	ufshcd_force_reset_auto_bkops(hba);
@@ -10109,7 +10125,20 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
 	 */
 	if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) &&
 	    !hba->dev_info.is_lu_power_on_wp) {
-		ufshcd_setup_vreg(hba, false);
+		ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
+		if (hba->dev_info.w_spec_version >= 0x300 &&
+			hba->vreg_info.vccq->sys_suspend_pwr_off)
+			ufshcd_toggle_vreg(hba->dev,
+				hba->vreg_info.vccq, false);
+		else
+			ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);
+
+		if (hba->dev_info.w_spec_version < 0x300 &&
+			hba->vreg_info.vccq2->sys_suspend_pwr_off)
+			ufshcd_toggle_vreg(hba->dev,
+				hba->vreg_info.vccq2, false);
+		else
+			ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
 	} else if (!ufshcd_is_ufs_dev_active(hba)) {
 		ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
 		if (!ufshcd_is_link_active(hba)) {
@@ -10124,23 +10153,40 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)
 	int ret = 0;
 
 	if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) &&
-	    !hba->dev_info.is_lu_power_on_wp) {
-		ret = ufshcd_setup_vreg(hba, true);
-	} else if (!ufshcd_is_ufs_dev_active(hba)) {
-		if (!ret && !ufshcd_is_link_active(hba)) {
+		!hba->dev_info.is_lu_power_on_wp) {
+		if (hba->dev_info.w_spec_version < 0x300 &&
+			hba->vreg_info.vccq2->sys_suspend_pwr_off)
+			ret = ufshcd_toggle_vreg(hba->dev,
+				hba->vreg_info.vccq2, true);
+		else
+			ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2);
+		if (ret)
+			goto vcc_disable;
+
+		if (hba->dev_info.w_spec_version >= 0x300 &&
+			hba->vreg_info.vccq->sys_suspend_pwr_off)
+			ret = ufshcd_toggle_vreg(hba->dev,
+				hba->vreg_info.vccq, true);
+		else
 			ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq);
-			if (ret)
-				goto vcc_disable;
+		if (ret)
+			goto vccq2_lpm;
+		ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, true);
+	} else if (!ufshcd_is_ufs_dev_active(hba)) {
+		if (!ufshcd_is_link_active(hba)) {
 			ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2);
 			if (ret)
-				goto vccq_lpm;
+				goto vcc_disable;
+			ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq);
+			if (ret)
+				goto vccq2_lpm;
 		}
 		ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, true);
 	}
 	goto out;
 
-vccq_lpm:
-	ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);
+vccq2_lpm:
+	ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
 vcc_disable:
 	ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
 out:
diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c
index 9007fa3..724d597 100644
--- a/drivers/soc/qcom/peripheral-loader.c
+++ b/drivers/soc/qcom/peripheral-loader.c
@@ -379,7 +379,11 @@ static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev)
 					      &ss_valid_seg_cnt,
 					      desc->num_aux_minidump_ids);
 
-	ret = do_minidump(ramdump_dev, ramdump_segs, ss_valid_seg_cnt);
+	if (desc->minidump_as_elf32)
+		ret = do_elf_ramdump(ramdump_dev, ramdump_segs,
+				     ss_valid_seg_cnt);
+	else
+		ret = do_minidump(ramdump_dev, ramdump_segs, ss_valid_seg_cnt);
 	if (ret)
 		pil_err(desc, "%s: Minidump collection failed for subsys %s rc:%d\n",
 			__func__, desc->name, ret);
@@ -1557,6 +1561,9 @@ int pil_desc_init(struct pil_desc *desc)
 	if (!desc->unmap_fw_mem)
 		desc->unmap_fw_mem = unmap_fw_mem;
 
+	desc->minidump_as_elf32 = of_property_read_bool(
+					ofnode, "qcom,minidump-as-elf32");
+
 	return 0;
 err_parse_dt:
 	ida_simple_remove(&pil_ida, priv->id);
diff --git a/drivers/soc/qcom/peripheral-loader.h b/drivers/soc/qcom/peripheral-loader.h
index c265657..62e5d4a 100644
--- a/drivers/soc/qcom/peripheral-loader.h
+++ b/drivers/soc/qcom/peripheral-loader.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2019, The Linux Foundation. All rights reserved.
  */
 #ifndef __MSM_PERIPHERAL_LOADER_H
 #define __MSM_PERIPHERAL_LOADER_H
@@ -62,6 +62,7 @@ struct pil_desc {
 	int minidump_id;
 	int *aux_minidump_ids;
 	int num_aux_minidump_ids;
+	bool minidump_as_elf32;
 };
 
 /**
diff --git a/drivers/soc/qcom/qmi_rmnet.c b/drivers/soc/qcom/qmi_rmnet.c
index 46732bf..5cc51bf 100644
--- a/drivers/soc/qcom/qmi_rmnet.c
+++ b/drivers/soc/qcom/qmi_rmnet.c
@@ -976,6 +976,9 @@ void qmi_rmnet_work_init(void *port)
 	rmnet_ps_wq = alloc_workqueue("rmnet_powersave_work",
 					WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, 1);
 
+	if (!rmnet_ps_wq)
+		return;
+
 	rmnet_work = kzalloc(sizeof(*rmnet_work), GFP_ATOMIC);
 	if (!rmnet_work) {
 		destroy_workqueue(rmnet_ps_wq);
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 4443e277..be34be0 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/atomic.h>
@@ -559,6 +559,10 @@ int rpmh_flush(const struct device *dev)
 		return 0;
 	}
 
+	do {
+		ret = rpmh_rsc_invalidate(ctrlr_to_drv(ctrlr));
+	} while (ret == -EAGAIN);
+
 	/* First flush the cached batch requests */
 	ret = flush_batch(ctrlr);
 	if (ret)
diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c
index 233346b..2ee761a 100644
--- a/drivers/soc/qcom/spcom.c
+++ b/drivers/soc/qcom/spcom.c
@@ -185,6 +185,12 @@ struct spcom_channel {
 	size_t actual_rx_size;	/* actual data size received */
 	void *rpmsg_rx_buf;
 
+	/**
+	 * to track if rx_buf is read in the same session
+	 * in which it is updated
+	 */
+	uint32_t rx_buf_txn_id;
+
 	/* shared buffer lock/unlock support */
 	int dmabuf_fd_table[SPCOM_MAX_ION_BUF_PER_CH];
 	struct dma_buf *dmabuf_handle_table[SPCOM_MAX_ION_BUF_PER_CH];
@@ -341,6 +347,7 @@ static int spcom_init_channel(struct spcom_channel *ch,
 	ch->actual_rx_size = 0;
 	ch->is_busy = false;
 	ch->txn_id = INITIAL_TXN_ID; /* use non-zero nonce for debug */
+	ch->rx_buf_txn_id = ch->txn_id;
 	memset(ch->pid, 0, sizeof(ch->pid));
 	ch->rpmsg_abort = false;
 	ch->rpmsg_rx_buf = NULL;
@@ -394,6 +401,16 @@ static int spcom_rx(struct spcom_channel *ch,
 
 	mutex_lock(&ch->lock);
 
+	if (ch->rx_buf_txn_id != ch->txn_id) {
+		pr_debug("rpmsg_rx_buf is updated in a different session\n");
+		if (ch->rpmsg_rx_buf) {
+			memset(ch->rpmsg_rx_buf, 0, ch->actual_rx_size);
+			kfree((void *)ch->rpmsg_rx_buf);
+			ch->rpmsg_rx_buf = NULL;
+			ch->actual_rx_size = 0;
+		}
+	}
+
 	/* check for already pending data */
 	if (!ch->actual_rx_size) {
 		reinit_completion(&ch->rx_done);
@@ -2161,6 +2178,7 @@ static void spcom_signal_rx_done(struct work_struct *ignored)
 		}
 		ch->rpmsg_rx_buf = rx_item->rpmsg_rx_buf;
 		ch->actual_rx_size = rx_item->rx_buf_size;
+		ch->rx_buf_txn_id = ch->txn_id;
 		complete_all(&ch->rx_done);
 		mutex_unlock(&ch->lock);
 
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index a57cf1d..1c8e898 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -166,6 +166,7 @@ struct msm_geni_serial_port {
 	void *ipc_log_rx;
 	void *ipc_log_pwr;
 	void *ipc_log_misc;
+	void *console_log;
 	unsigned int cur_baud;
 	int ioctl_count;
 	int edge_count;
@@ -777,6 +778,7 @@ static void msm_geni_serial_console_write(struct console *co, const char *s,
 	bool locked = true;
 	unsigned long flags;
 	unsigned int geni_status;
+	int irq_en;
 
 	/* Max 1 port supported as of now */
 	WARN_ON(co->index < 0 || co->index >= GENI_UART_CONS_PORTS);
@@ -806,12 +808,22 @@ static void msm_geni_serial_console_write(struct console *co, const char *s,
 		}
 		writel_relaxed(M_CMD_CANCEL_EN, uport->membase +
 							SE_GENI_M_IRQ_CLEAR);
-	} else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->cur_tx_remaining)
+	} else if ((geni_status & M_GENI_CMD_ACTIVE) &&
+						!port->cur_tx_remaining) {
 		/* It seems we can interrupt existing transfers unless all data
 		 * has been sent, in which case we need to look for done first.
 		 */
 		msm_geni_serial_poll_cancel_tx(uport);
 
+		/* Enable WM interrupt for every new console write op */
+		if (uart_circ_chars_pending(&uport->state->xmit)) {
+			irq_en = geni_read_reg_nolog(uport->membase,
+						SE_GENI_M_IRQ_EN);
+			geni_write_reg_nolog(irq_en | M_TX_FIFO_WATERMARK_EN,
+					uport->membase, SE_GENI_M_IRQ_EN);
+		}
+	}
+
 	__msm_geni_serial_console_write(uport, s, count);
 
 	if (port->cur_tx_remaining)
@@ -1310,6 +1322,7 @@ static int msm_geni_serial_handle_tx(struct uart_port *uport, bool done,
 	unsigned int fifo_width_bytes =
 		(uart_console(uport) ? 1 : (msm_port->tx_fifo_width >> 3));
 	int temp_tail = 0;
+	int irq_en;
 
 	tx_fifo_status = geni_read_reg_nolog(uport->membase,
 					SE_GENI_TX_FIFO_STATUS);
@@ -1340,6 +1353,12 @@ static int msm_geni_serial_handle_tx(struct uart_port *uport, bool done,
 	if (!msm_port->cur_tx_remaining) {
 		msm_geni_serial_setup_tx(uport, pending);
 		msm_port->cur_tx_remaining = pending;
+
+		/* Re-enable WM interrupt when starting new transfer */
+		irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
+		if (!(irq_en & M_TX_FIFO_WATERMARK_EN))
+			geni_write_reg_nolog(irq_en | M_TX_FIFO_WATERMARK_EN,
+					uport->membase, SE_GENI_M_IRQ_EN);
 	}
 
 	bytes_remaining = xmit_size;
@@ -1367,7 +1386,24 @@ static int msm_geni_serial_handle_tx(struct uart_port *uport, bool done,
 		wmb();
 	}
 	xmit->tail = temp_tail;
+
+	/*
+	 * The tx fifo watermark is level triggered and latched. Though we had
+	 * cleared it in qcom_geni_serial_isr it will have already reasserted
+	 * so we must clear it again here after our writes.
+	 */
+	geni_write_reg_nolog(M_TX_FIFO_WATERMARK_EN, uport->membase,
+						SE_GENI_M_IRQ_CLEAR);
+
 exit_handle_tx:
+	if (!msm_port->cur_tx_remaining) {
+		irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
+		/* Clear WM interrupt post each transfer completion */
+		if (irq_en & M_TX_FIFO_WATERMARK_EN)
+			geni_write_reg_nolog(irq_en & ~M_TX_FIFO_WATERMARK_EN,
+					uport->membase, SE_GENI_M_IRQ_EN);
+	}
+
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(uport);
 	return 0;
@@ -1469,8 +1505,11 @@ static irqreturn_t msm_geni_serial_isr(int isr, void *dev)
 	bool drop_rx = false;
 
 	spin_lock_irqsave(&uport->lock, flags);
-	if (uart_console(uport) && uport->suspended)
+	if (uart_console(uport) && uport->suspended) {
+		IPC_LOG_MSG(msm_port->console_log,
+			"%s. Console in suspend state\n", __func__);
 		goto exit_geni_serial_isr;
+	}
 	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
 		dev_err(uport->dev, "%s.Device is suspended.\n", __func__);
 		IPC_LOG_MSG(msm_port->ipc_log_misc,
@@ -1481,6 +1520,10 @@ static irqreturn_t msm_geni_serial_isr(int isr, void *dev)
 						SE_GENI_M_IRQ_STATUS);
 	s_irq_status = geni_read_reg_nolog(uport->membase,
 						SE_GENI_S_IRQ_STATUS);
+	if (uart_console(uport))
+		IPC_LOG_MSG(msm_port->console_log,
+			"%s. sirq 0x%x mirq:0x%x\n", __func__, s_irq_status,
+								m_irq_status);
 	m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
 	dma = geni_read_reg_nolog(uport->membase, SE_GENI_DMA_MODE_EN);
 	dma_tx_status = geni_read_reg_nolog(uport->membase, SE_DMA_TX_IRQ_STAT);
@@ -2318,14 +2361,13 @@ static void console_unregister(struct uart_driver *drv)
 static void msm_geni_serial_debug_init(struct uart_port *uport, bool console)
 {
 	struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+	char name[30];
 
 	msm_port->dbg = debugfs_create_dir(dev_name(uport->dev), NULL);
 	if (IS_ERR_OR_NULL(msm_port->dbg))
 		dev_err(uport->dev, "Failed to create dbg dir\n");
 
 	if (!console) {
-		char name[30];
-
 		memset(name, 0, sizeof(name));
 		if (!msm_port->ipc_log_rx) {
 			scnprintf(name, sizeof(name), "%s%s",
@@ -2362,6 +2404,16 @@ static void msm_geni_serial_debug_init(struct uart_port *uport, bool console)
 			if (!msm_port->ipc_log_misc)
 				dev_info(uport->dev, "Err in Misc IPC Log\n");
 		}
+	} else {
+		memset(name, 0, sizeof(name));
+		if (!msm_port->console_log) {
+			scnprintf(name, sizeof(name), "%s%s",
+					dev_name(uport->dev), "_console");
+			msm_port->console_log = ipc_log_context_create(
+					IPC_LOG_MISC_PAGES, name, 0);
+			if (!msm_port->console_log)
+				dev_info(uport->dev, "Err in Misc IPC Log\n");
+		}
 	}
 }
 
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 3e79dba..8a0f116 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1406,6 +1406,7 @@ static int dwc3_probe(struct platform_device *pdev)
 
 	void __iomem		*regs;
 	int			irq;
+	char			dma_ipc_log_ctx_name[40];
 
 	if (count >= DWC_CTRL_COUNT) {
 		dev_err(dev, "Err dwc instance %d >= %d available\n",
@@ -1545,6 +1546,13 @@ static int dwc3_probe(struct platform_device *pdev)
 	if (!dwc->dwc_ipc_log_ctxt)
 		dev_err(dwc->dev, "Error getting ipc_log_ctxt\n");
 
+	snprintf(dma_ipc_log_ctx_name, sizeof(dma_ipc_log_ctx_name),
+					"%s.ep_events", dev_name(dwc->dev));
+	dwc->dwc_dma_ipc_log_ctxt = ipc_log_context_create(NUM_LOG_PAGES,
+						dma_ipc_log_ctx_name, 0);
+	if (!dwc->dwc_dma_ipc_log_ctxt)
+		dev_err(dwc->dev, "Error getting ipc_log_ctxt for ep_events\n");
+
 	dwc3_instance[count] = dwc;
 	dwc->index = count;
 	count++;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 6f24144..4b039b3 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1318,6 +1318,7 @@ struct dwc3 {
 
 	unsigned int		index;
 	void			*dwc_ipc_log_ctxt;
+	void			*dwc_dma_ipc_log_ctxt;
 	struct dwc3_gadget_events	dbg_gadget_events;
 	int			tx_fifo_size;
 	int			last_fifo_depth;
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index a03602d..f1659b7 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -36,6 +36,18 @@
 #define dbg_setup(ep_num, req) \
 	dwc3_dbg_setup(dwc, ep_num, req)
 
+#define dbg_ep_queue(ep_num, req) \
+	dwc3_dbg_dma_queue(dwc, ep_num, req)
+
+#define dbg_ep_dequeue(ep_num, req) \
+	dwc3_dbg_dma_dequeue(dwc, ep_num, req)
+
+#define dbg_ep_unmap(ep_num, req) \
+	dwc3_dbg_dma_unmap(dwc, ep_num, req)
+
+#define dbg_ep_map(ep_num, req) \
+	dwc3_dbg_dma_map(dwc, ep_num, req)
+
 #define dbg_log_string(fmt, ...) \
 	ipc_log_string(dwc->dwc_ipc_log_ctxt,\
 			"%s: " fmt, __func__, ##__VA_ARGS__)
@@ -660,6 +672,14 @@ void dwc3_dbg_setup(struct dwc3 *dwc, u8 ep_num,
 		const struct usb_ctrlrequest *req);
 void dwc3_dbg_print_reg(struct dwc3 *dwc,
 		const char *name, int reg);
+void dwc3_dbg_dma_queue(struct dwc3 *dwc, u8 ep_num,
+			struct dwc3_request *req);
+void dwc3_dbg_dma_dequeue(struct dwc3 *dwc, u8 ep_num,
+			struct dwc3_request *req);
+void dwc3_dbg_dma_map(struct dwc3 *dwc, u8 ep_num,
+			struct dwc3_request *req);
+void dwc3_dbg_dma_unmap(struct dwc3 *dwc, u8 ep_num,
+			struct dwc3_request *req);
 
 #ifdef CONFIG_DEBUG_FS
 extern void dwc3_debugfs_init(struct dwc3 *);
diff --git a/drivers/usb/dwc3/debug_ipc.c b/drivers/usb/dwc3/debug_ipc.c
index b694246..98f27a5 100644
--- a/drivers/usb/dwc3/debug_ipc.c
+++ b/drivers/usb/dwc3/debug_ipc.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
  */
 
 #include "debug.h"
@@ -136,3 +136,47 @@ void dwc3_dbg_print_reg(struct dwc3 *dwc, const char *name, int reg)
 
 	ipc_log_string(dwc->dwc_ipc_log_ctxt, "%s = 0x%08x", name, reg);
 }
+
+void dwc3_dbg_dma_unmap(struct dwc3 *dwc, u8 ep_num, struct dwc3_request *req)
+{
+	if (ep_num < 2)
+		return;
+
+	ipc_log_string(dwc->dwc_dma_ipc_log_ctxt,
+		"%02X-%-3.3s %-25.25s 0x%pK 0x%lx %u 0x%lx %d", ep_num >> 1,
+		ep_num & 1 ? "IN":"OUT", "UNMAP", &req->request,
+		req->request.dma, req->request.length, req->trb_dma,
+		req->trb->ctrl & DWC3_TRB_CTRL_HWO);
+}
+
+void dwc3_dbg_dma_map(struct dwc3 *dwc, u8 ep_num, struct dwc3_request *req)
+{
+	if (ep_num < 2)
+		return;
+
+	ipc_log_string(dwc->dwc_dma_ipc_log_ctxt,
+		"%02X-%-3.3s %-25.25s 0x%pK 0x%lx %u 0x%lx", ep_num >> 1,
+		ep_num & 1 ? "IN":"OUT", "MAP", &req->request, req->request.dma,
+		req->request.length, req->trb_dma);
+}
+
+void dwc3_dbg_dma_dequeue(struct dwc3 *dwc, u8 ep_num, struct dwc3_request *req)
+{
+	if (ep_num < 2)
+		return;
+
+	ipc_log_string(dwc->dwc_dma_ipc_log_ctxt,
+		"%02X-%-3.3s %-25.25s 0x%pK 0x%lx 0x%lx", ep_num >> 1,
+		ep_num & 1 ? "IN":"OUT", "DEQUEUE", &req->request,
+		req->request.dma, req->trb_dma);
+}
+
+void dwc3_dbg_dma_queue(struct dwc3 *dwc, u8 ep_num, struct dwc3_request *req)
+{
+	if (ep_num < 2)
+		return;
+
+	ipc_log_string(dwc->dwc_dma_ipc_log_ctxt,
+		"%02X-%-3.3s %-25.25s 0x%pK", ep_num >> 1,
+		ep_num & 1 ? "IN":"OUT", "QUEUE", &req->request);
+}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index ddf7a78..6b4dcd9 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -289,9 +289,11 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
 	if (req->request.status == -EINPROGRESS)
 		req->request.status = status;
 
-	if (req->trb)
+	if (req->trb) {
+		dbg_ep_unmap(dep->number, req);
 		usb_gadget_unmap_request_by_dev(dwc->sysdev,
 				&req->request, req->direction);
+	}
 
 	req->trb = NULL;
 	trace_dwc3_gadget_giveback(req);
@@ -1401,6 +1403,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
 		else
 			dwc3_prepare_one_trb_linear(dep, req);
 
+		dbg_ep_map(dep->number, req);
 		if (!dwc3_calc_trbs_left(dep))
 			return;
 	}
@@ -1545,6 +1548,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 
 	list_add_tail(&req->list, &dep->pending_list);
 
+	dbg_ep_queue(dep->number, req);
 	/*
 	 * NOTICE: Isochronous endpoints should NEVER be prestarted. We must
 	 * wait for a XferNotReady event so we will know what's the current
@@ -1704,7 +1708,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
 	}
 
 out1:
-	dbg_event(dep->number, "DEQUEUE", 0);
+	dbg_ep_dequeue(dep->number, req);
 	/* giveback the request */
 
 	dwc3_gadget_giveback(dep, req, -ECONNRESET);
diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c
index 93fc8fd..ce1afb0 100644
--- a/drivers/usb/phy/phy-msm-qusb.c
+++ b/drivers/usb/phy/phy-msm-qusb.c
@@ -99,6 +99,7 @@ struct qusb_phy {
 	void __iomem		*ref_clk_base;
 	void __iomem		*tcsr_clamp_dig_n;
 	void __iomem		*tcsr_conn_box_spare;
+	void __iomem		*eud_enable_reg;
 
 	struct clk		*ref_clk_src;
 	struct clk		*ref_clk;
@@ -404,6 +405,11 @@ static int qusb_phy_init(struct usb_phy *phy)
 
 	dev_dbg(phy->dev, "%s\n", __func__);
 
+	if (qphy->eud_enable_reg && readl_relaxed(qphy->eud_enable_reg)) {
+		dev_err(qphy->phy.dev, "eud is enabled\n");
+		return 0;
+	}
+
 	/*
 	 * ref clock is enabled by default after power on reset. Linux clock
 	 * driver will disable this clock as part of late init if peripheral
@@ -717,6 +723,11 @@ static int qusb_phy_dpdm_regulator_enable(struct regulator_dev *rdev)
 	dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n",
 				__func__, qphy->dpdm_enable);
 
+	if (qphy->eud_enable_reg && readl_relaxed(qphy->eud_enable_reg)) {
+		dev_err(qphy->phy.dev, "eud is enabled\n");
+		return 0;
+	}
+
 	mutex_lock(&qphy->phy_lock);
 	if (!qphy->dpdm_enable) {
 		ret = qusb_phy_enable_power(qphy, true);
@@ -904,6 +915,16 @@ static int qusb_phy_probe(struct platform_device *pdev)
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+							"eud_enable_reg");
+	if (res) {
+		qphy->eud_enable_reg = devm_ioremap_resource(dev, res);
+		if (IS_ERR(qphy->eud_enable_reg)) {
+			dev_err(dev, "err getting eud_enable_reg address\n");
+			return PTR_ERR(qphy->eud_enable_reg);
+		}
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 							"ref_clk_addr");
 	if (res) {
 		qphy->ref_clk_base = devm_ioremap_nocache(dev,
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 3b7988cb..a1877e7 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1745,6 +1745,8 @@ static int f2fs_ioc_getversion(struct file *filp, unsigned long arg)
 static int f2fs_ioc_start_atomic_write(struct file *filp)
 {
 	struct inode *inode = file_inode(filp);
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
 	int ret;
 
 	if (!inode_owner_or_capable(inode))
@@ -1785,6 +1787,12 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
 		goto out;
 	}
 
+	spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
+	if (list_empty(&fi->inmem_ilist))
+		list_add_tail(&fi->inmem_ilist, &sbi->inode_list[ATOMIC_FILE]);
+	spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
+
+	/* add inode in inmem_list first and set atomic_file */
 	set_inode_flag(inode, FI_ATOMIC_FILE);
 	clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
 	up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
@@ -1826,11 +1834,8 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
 			goto err_out;
 
 		ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true);
-		if (!ret) {
-			clear_inode_flag(inode, FI_ATOMIC_FILE);
-			F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
-			stat_dec_atomic_write(inode);
-		}
+		if (!ret)
+			f2fs_drop_inmem_pages(inode);
 	} else {
 		ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 1, false);
 	}
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index ac824f6..d71a143 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -185,8 +185,6 @@ bool f2fs_need_SSR(struct f2fs_sb_info *sbi)
 
 void f2fs_register_inmem_page(struct inode *inode, struct page *page)
 {
-	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-	struct f2fs_inode_info *fi = F2FS_I(inode);
 	struct inmem_pages *new;
 
 	f2fs_trace_pid(page);
@@ -200,15 +198,11 @@ void f2fs_register_inmem_page(struct inode *inode, struct page *page)
 	INIT_LIST_HEAD(&new->list);
 
 	/* increase reference count with clean state */
-	mutex_lock(&fi->inmem_lock);
 	get_page(page);
-	list_add_tail(&new->list, &fi->inmem_pages);
-	spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
-	if (list_empty(&fi->inmem_ilist))
-		list_add_tail(&fi->inmem_ilist, &sbi->inode_list[ATOMIC_FILE]);
-	spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
+	mutex_lock(&F2FS_I(inode)->inmem_lock);
+	list_add_tail(&new->list, &F2FS_I(inode)->inmem_pages);
 	inc_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES);
-	mutex_unlock(&fi->inmem_lock);
+	mutex_unlock(&F2FS_I(inode)->inmem_lock);
 
 	trace_f2fs_register_inmem_page(page, INMEM);
 }
@@ -330,19 +324,17 @@ void f2fs_drop_inmem_pages(struct inode *inode)
 		mutex_lock(&fi->inmem_lock);
 		__revoke_inmem_pages(inode, &fi->inmem_pages,
 						true, false, true);
-
-		if (list_empty(&fi->inmem_pages)) {
-			spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
-			if (!list_empty(&fi->inmem_ilist))
-				list_del_init(&fi->inmem_ilist);
-			spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
-		}
 		mutex_unlock(&fi->inmem_lock);
 	}
 
 	clear_inode_flag(inode, FI_ATOMIC_FILE);
 	fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
 	stat_dec_atomic_write(inode);
+
+	spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
+	if (!list_empty(&fi->inmem_ilist))
+		list_del_init(&fi->inmem_ilist);
+	spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
 }
 
 void f2fs_drop_inmem_page(struct inode *inode, struct page *page)
@@ -471,11 +463,6 @@ int f2fs_commit_inmem_pages(struct inode *inode)
 
 	mutex_lock(&fi->inmem_lock);
 	err = __f2fs_commit_inmem_pages(inode);
-
-	spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
-	if (!list_empty(&fi->inmem_ilist))
-		list_del_init(&fi->inmem_ilist);
-	spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
 	mutex_unlock(&fi->inmem_lock);
 
 	clear_inode_flag(inode, FI_ATOMIC_COMMIT);
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index d0a8920..57cf4b6 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -540,7 +540,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
 			      struct ovl_cattr *attr, bool origin)
 {
 	int err;
-	const struct cred *old_cred;
+	const struct cred *old_cred, *hold_cred = NULL;
 	struct cred *override_cred;
 	struct dentry *parent = dentry->d_parent;
 
@@ -575,7 +575,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
 				goto out_revert_creds;
 			}
 		}
-		put_cred(override_creds(override_cred));
+		hold_cred = override_creds(override_cred);
 		put_cred(override_cred);
 
 		if (!ovl_dentry_is_whiteout(dentry))
@@ -584,7 +584,9 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
 			err = ovl_create_over_whiteout(dentry, inode, attr);
 	}
 out_revert_creds:
-	ovl_revert_creds(old_cred);
+	ovl_revert_creds(old_cred ?: hold_cred);
+	if (old_cred && hold_cred)
+		put_cred(hold_cred);
 	return err;
 }
 
diff --git a/kernel/module.c b/kernel/module.c
index 8644c18..984fdb8 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2187,6 +2187,10 @@ static void free_module(struct module *mod)
 
 	/* Finally, free the core (containing the module structure) */
 	disable_ro_nx(&mod->core_layout);
+#ifdef CONFIG_DEBUG_MODULE_LOAD_INFO
+	pr_info("Unloaded %s: module core layout, start: 0x%pK size: 0x%x\n",
+		mod->name, mod->core_layout.base, mod->core_layout.size);
+#endif
 	module_memfree(mod->core_layout.base);
 }
 
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 6c164cd..f3d53fc 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -155,6 +155,18 @@
 	  actual pointer values, ignoring the kptr_restrict setting.
 	  Not to be enabled on production builds.
 
+config DEBUG_MODULE_LOAD_INFO
+        bool "Use prints for module info under a debug flag"
+	help
+	  If you say Y here the resulting kernel image will include
+	  debug prints which was kept under DEBUG_MODULE_LOAD_INFO.
+	  This will be used by developer to debug loadable modules in
+	  the kernel.
+	  Say Y here only if you plan to debug the kernel.
+	  Not to be enabled on production builds.
+
+	  If unsure, say N.
+
 endmenu # "printk and dmesg options"
 
 menu "Compile-time checks and compiler options"
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 4272af2..23c82c3 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -1256,12 +1256,10 @@ void add_to_oom_reaper(struct task_struct *p)
 
 	task_unlock(p);
 
-	if (strcmp(current->comm, ULMK_MAGIC) && __ratelimit(&reaper_rs)
+	if (!strcmp(current->comm, ULMK_MAGIC) && __ratelimit(&reaper_rs)
 			&& p->signal->oom_score_adj == 0) {
 		show_mem(SHOW_MEM_FILTER_NODES, NULL);
 		show_mem_call_notifiers();
-		if (sysctl_oom_dump_tasks)
-			dump_tasks(NULL, NULL);
 	}
 
 	put_task_struct(p);
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 2cc2ec7..dc2287c 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1162,7 +1162,7 @@ const char * const vmstat_text[] = {
 	"nr_vmscan_immediate_reclaim",
 	"nr_dirtied",
 	"nr_written",
-	"", /* nr_indirectly_reclaimable */
+	"nr_indirectly_reclaimable",
 	"nr_unreclaimable_pages",
 
 	/* enum writeback_stat_item counters */