Merge "msm: cam: reqmgr: Add list empty check for task list" into msm-4.9
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index 6f35bf7..68824d7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -209,6 +209,30 @@
 	status = "ok";
 };
 
+&labibb {
+	status = "ok";
+	qcom,qpnp-labibb-mode = "lcd";
+};
+
+&dsi_dual_nt35597_truly_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-panel-mode-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 52 0>;
+	qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	qcom,dsi-display-active;
+};
+
+&pmi8998_wled {
+	status = "okay";
+	qcom,led-strings-list = [01 02];
+};
+
 &qupv3_se8_spi {
 	status = "ok";
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index faa0b5e..4391189 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -78,6 +78,30 @@
 	};
 };
 
+&labibb {
+	status = "ok";
+	qcom,qpnp-labibb-mode = "lcd";
+};
+
+&dsi_dual_nt35597_truly_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-panel-mode-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 52 0>;
+	qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	qcom,dsi-display-active;
+};
+
+&pmi8998_wled {
+	status = "okay";
+	qcom,led-strings-list = [01 02];
+};
+
 &ufsphy_mem {
 	compatible = "qcom,ufs-phy-qmp-v3";
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
index 2ff9b2f..e56073c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
@@ -23,6 +23,7 @@
 #include "dsi-panel-sharp-1080p-cmd.dtsi"
 #include "dsi-panel-sharp-dualmipi-1080p-120hz.dtsi"
 #include "dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi"
+#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
 
 &soc {
 	dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -198,15 +199,15 @@
 
 		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
 		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
-		clocks = <&clock_dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
-		       <&clock_dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
 		clock-names = "src_byte_clk", "src_pixel_clk";
 
 		pinctrl-names = "panel_active", "panel_suspend";
 		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
 		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
-		qcom,platform-te-gpio = <&tlmm 10 0>;
 		qcom,platform-reset-gpio = <&tlmm 6 0>;
+		qcom,panel-mode-gpio = <&tlmm 52 0>;
 
 		qcom,dsi-panel = <&dsi_dual_nt35597_truly_video>;
 		vddio-supply = <&pm8998_l14>;
@@ -291,7 +292,7 @@
 };
 
 &mdss_mdp {
-	connectors = <&sde_wb>;
+	connectors = <&sde_wb &dsi_dual_nt35597_truly_video_display>;
 };
 
 &dsi_dual_nt35597_truly_video {
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 9a2ab8c..fa6bae8 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -442,6 +442,7 @@
 CONFIG_QCOM_LAZY_MAPPING=y
 CONFIG_IOMMU_DEBUG=y
 CONFIG_IOMMU_TESTS=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_QCOM_LLCC=y
 CONFIG_QCOM_SDM845_LLCC=y
 CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 31f8703..a71aa64 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -459,6 +459,7 @@
 CONFIG_IOMMU_DEBUG=y
 CONFIG_IOMMU_TESTS=y
 CONFIG_QCOM_CPUSS_DUMP=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_QCOM_LLCC=y
 CONFIG_QCOM_SDM845_LLCC=y
 CONFIG_MSM_BOOT_STATS=y
diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c
index 4824546..678dd10 100644
--- a/drivers/clk/qcom/gcc-sdm845.c
+++ b/drivers/clk/qcom/gcc-sdm845.c
@@ -3295,6 +3295,8 @@
 	[GCC_USB3PHY_PHY_SEC_BCR] = { 0x50010 },
 	[GCC_USB3_DP_PHY_SEC_BCR] = { 0x50014 },
 	[GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
+	[GCC_PCIE_0_PHY_BCR] = { 0x6c01c },
+	[GCC_PCIE_1_PHY_BCR] = { 0x8e01c },
 };
 
 static const struct regmap_config gcc_sdm845_regmap_config = {
diff --git a/drivers/devfreq/bimc-bwmon.c b/drivers/devfreq/bimc-bwmon.c
index 56036ea..d70104d 100644
--- a/drivers/devfreq/bimc-bwmon.c
+++ b/drivers/devfreq/bimc-bwmon.c
@@ -54,6 +54,11 @@
 #define MON2_ZONE_CNT(m)	((m)->base + 0x2D8)
 #define MON2_ZONE_MAX(m, zone)	((m)->base + 0x2E0 + 0x4 * zone)
 
+enum bwmon_type {
+	BWMON_1,
+	BWMON_2,
+};
+
 struct bwmon_spec {
 	bool wrap_on_thres;
 	bool overflow;
@@ -76,7 +81,6 @@
 };
 
 #define to_bwmon(ptr)		container_of(ptr, struct bwmon, hw)
-#define has_hw_sampling(m)		(m->spec->hw_sampling)
 
 #define ENABLE_MASK BIT(0)
 #define THROTTLE_MASK 0x1F
@@ -86,20 +90,29 @@
 #define INT_STATUS_MASK_HWS	0xF0
 
 static DEFINE_SPINLOCK(glb_lock);
-static void mon_enable(struct bwmon *m)
+
+static __always_inline void mon_enable(struct bwmon *m, enum bwmon_type type)
 {
-	if (has_hw_sampling(m))
-		writel_relaxed((ENABLE_MASK | m->throttle_adj), MON2_EN(m));
-	else
-		writel_relaxed((ENABLE_MASK | m->throttle_adj), MON_EN(m));
+	switch (type) {
+	case BWMON_1:
+		writel_relaxed(ENABLE_MASK | m->throttle_adj, MON_EN(m));
+		break;
+	case BWMON_2:
+		writel_relaxed(ENABLE_MASK | m->throttle_adj, MON2_EN(m));
+		break;
+	}
 }
 
-static void mon_disable(struct bwmon *m)
+static __always_inline void mon_disable(struct bwmon *m, enum bwmon_type type)
 {
-	if (has_hw_sampling(m))
-		writel_relaxed(m->throttle_adj, MON2_EN(m));
-	else
+	switch (type) {
+	case BWMON_1:
 		writel_relaxed(m->throttle_adj, MON_EN(m));
+		break;
+	case BWMON_2:
+		writel_relaxed(m->throttle_adj, MON2_EN(m));
+		break;
+	}
 	/*
 	 * mon_disable() and mon_irq_clear(),
 	 * If latter goes first and count happen to trigger irq, we would
@@ -110,24 +123,25 @@
 
 #define MON_CLEAR_BIT	0x1
 #define MON_CLEAR_ALL_BIT	0x2
-static void mon_clear(struct bwmon *m, bool clear_all)
+static __always_inline
+void mon_clear(struct bwmon *m, bool clear_all, enum bwmon_type type)
 {
-	if (!has_hw_sampling(m)) {
+	switch (type) {
+	case BWMON_1:
 		writel_relaxed(MON_CLEAR_BIT, MON_CLEAR(m));
-		goto out;
+		break;
+	case BWMON_2:
+		if (clear_all)
+			writel_relaxed(MON_CLEAR_ALL_BIT, MON2_CLEAR(m));
+		else
+			writel_relaxed(MON_CLEAR_BIT, MON2_CLEAR(m));
+		break;
 	}
-
-	if (clear_all)
-		writel_relaxed(MON_CLEAR_ALL_BIT, MON2_CLEAR(m));
-	else
-		writel_relaxed(MON_CLEAR_BIT, MON2_CLEAR(m));
-
 	/*
 	 * The counter clear and IRQ clear bits are not in the same 4KB
 	 * region. So, we need to make sure the counter clear is completed
 	 * before we try to clear the IRQ or do any other counter operations.
 	 */
-out:
 	mb();
 }
 
@@ -148,72 +162,141 @@
 	}
 }
 
-static void mon_irq_enable(struct bwmon *m)
+static void mon_glb_irq_enable(struct bwmon *m)
 {
 	u32 val;
 
-	spin_lock(&glb_lock);
 	val = readl_relaxed(GLB_INT_EN(m));
 	val |= 1 << m->mport;
 	writel_relaxed(val, GLB_INT_EN(m));
-
-	val = readl_relaxed(MON_INT_EN(m));
-	val |= has_hw_sampling(m) ? INT_STATUS_MASK_HWS : INT_ENABLE_V1;
-	writel_relaxed(val, MON_INT_EN(m));
-	spin_unlock(&glb_lock);
-	/*
-	 * make Sure irq enable complete for local and global
-	 * to avoid race with other monitor calls
-	 */
-	mb();
 }
 
-static void mon_irq_disable(struct bwmon *m)
+static __always_inline
+void mon_irq_enable(struct bwmon *m, enum bwmon_type type)
 {
 	u32 val;
 
 	spin_lock(&glb_lock);
-	val = readl_relaxed(GLB_INT_EN(m));
-	val &= ~(1 << m->mport);
-	writel_relaxed(val, GLB_INT_EN(m));
-
-	val = readl_relaxed(MON_INT_EN(m));
-	val &= has_hw_sampling(m) ? ~INT_STATUS_MASK_HWS : ~INT_ENABLE_V1;
-	writel_relaxed(val, MON_INT_EN(m));
+	switch (type) {
+	case BWMON_1:
+		mon_glb_irq_enable(m);
+		val = readl_relaxed(MON_INT_EN(m));
+		val |= INT_ENABLE_V1;
+		writel_relaxed(val, MON_INT_EN(m));
+		break;
+	case BWMON_2:
+		mon_glb_irq_enable(m);
+		val = readl_relaxed(MON_INT_EN(m));
+		val |= INT_STATUS_MASK_HWS;
+		writel_relaxed(val, MON_INT_EN(m));
+		break;
+	}
 	spin_unlock(&glb_lock);
 	/*
-	 * make Sure irq disable complete for local and global
+	 * make sure irq enable complete for local and global
 	 * to avoid race with other monitor calls
 	 */
 	mb();
 }
 
-static unsigned int mon_irq_status(struct bwmon *m)
+static void mon_glb_irq_disable(struct bwmon *m)
+{
+	u32 val;
+
+	val = readl_relaxed(GLB_INT_EN(m));
+	val &= ~(1 << m->mport);
+	writel_relaxed(val, GLB_INT_EN(m));
+}
+
+static __always_inline
+void mon_irq_disable(struct bwmon *m, enum bwmon_type type)
+{
+	u32 val;
+
+	spin_lock(&glb_lock);
+
+	switch (type) {
+	case BWMON_1:
+		mon_glb_irq_disable(m);
+		val = readl_relaxed(MON_INT_EN(m));
+		val &= ~INT_ENABLE_V1;
+		writel_relaxed(val, MON_INT_EN(m));
+		break;
+	case BWMON_2:
+		mon_glb_irq_disable(m);
+		val = readl_relaxed(MON_INT_EN(m));
+		val &= ~INT_STATUS_MASK_HWS;
+		writel_relaxed(val, MON_INT_EN(m));
+		break;
+	}
+	spin_unlock(&glb_lock);
+	/*
+	 * make sure irq disable complete for local and global
+	 * to avoid race with other monitor calls
+	 */
+	mb();
+}
+
+static __always_inline
+unsigned int mon_irq_status(struct bwmon *m, enum bwmon_type type)
 {
 	u32 mval;
 
-	mval = readl_relaxed(MON_INT_STATUS(m));
-
-	dev_dbg(m->dev, "IRQ status p:%x, g:%x\n", mval,
-			readl_relaxed(GLB_INT_STATUS(m)));
-
-	mval &= has_hw_sampling(m) ? INT_STATUS_MASK_HWS : INT_STATUS_MASK;
+	switch (type) {
+	case BWMON_1:
+		mval = readl_relaxed(MON_INT_STATUS(m));
+		dev_dbg(m->dev, "IRQ status p:%x, g:%x\n", mval,
+				readl_relaxed(GLB_INT_STATUS(m)));
+		mval &= INT_STATUS_MASK;
+		break;
+	case BWMON_2:
+		mval = readl_relaxed(MON_INT_STATUS(m));
+		dev_dbg(m->dev, "IRQ status p:%x, g:%x\n", mval,
+				readl_relaxed(GLB_INT_STATUS(m)));
+		mval &= INT_STATUS_MASK_HWS;
+		break;
+	}
 
 	return mval;
 }
 
-static void mon_irq_clear(struct bwmon *m)
+
+static void mon_glb_irq_clear(struct bwmon *m)
 {
-	u32 intclr;
-
-	intclr = has_hw_sampling(m) ? INT_STATUS_MASK_HWS : INT_STATUS_MASK;
-
-	writel_relaxed(intclr, MON_INT_CLR(m));
+	/*
+	 * Synchronize the local interrupt clear in mon_irq_clear()
+	 * with the global interrupt clear here. Otherwise, the CPU
+	 * may reorder the two writes and clear the global interrupt
+	 * before the local interrupt, causing the global interrupt
+	 * to be retriggered by the local interrupt still being high.
+	 */
 	mb();
 	writel_relaxed(1 << m->mport, GLB_INT_CLR(m));
+	/*
+	 * Similarly, because the global registers are in a different
+	 * region than the local registers, we need to ensure any register
+	 * writes to enable the monitor after this call are ordered with the
+	 * clearing here so that local writes don't happen before the
+	 * interrupt is cleared.
+	 */
 	mb();
 }
 
+static __always_inline
+void mon_irq_clear(struct bwmon *m, enum bwmon_type type)
+{
+	switch (type) {
+	case BWMON_1:
+		writel_relaxed(INT_STATUS_MASK, MON_INT_CLR(m));
+		mon_glb_irq_clear(m);
+		break;
+	case BWMON_2:
+		writel_relaxed(INT_STATUS_MASK_HWS, MON_INT_CLR(m));
+		mon_glb_irq_clear(m);
+		break;
+	}
+}
+
 static int mon_set_throttle_adj(struct bw_hwmon *hw, uint adj)
 {
 	struct bwmon *m = to_bwmon(hw);
@@ -331,12 +414,12 @@
 
 #define THRES_HIT(status)	(status & BIT(0))
 #define OVERFLOW(status)	(status & BIT(1))
-static unsigned long mon_get_count(struct bwmon *m)
+static unsigned long mon_get_count1(struct bwmon *m)
 {
 	unsigned long count, status;
 
 	count = readl_relaxed(MON_CNT(m));
-	status = mon_irq_status(m);
+	status = mon_irq_status(m, BWMON_1);
 
 	dev_dbg(m->dev, "Counter: %08lx\n", count);
 
@@ -385,6 +468,23 @@
 	return count;
 }
 
+static __always_inline
+unsigned long mon_get_count(struct bwmon *m, enum bwmon_type type)
+{
+	unsigned long count;
+
+	switch (type) {
+	case BWMON_1:
+		count = mon_get_count1(m);
+		break;
+	case BWMON_2:
+		count = mon_get_zone_stats(m);
+		break;
+	}
+
+	return count;
+}
+
 /* ********** CPUBW specific code  ********** */
 
 /* Returns MBps of read/writes for the sampling window. */
@@ -398,30 +498,41 @@
 	return mbps;
 }
 
-static unsigned long get_bytes_and_clear(struct bw_hwmon *hw)
+static __always_inline
+unsigned long __get_bytes_and_clear(struct bw_hwmon *hw, enum bwmon_type type)
 {
 	struct bwmon *m = to_bwmon(hw);
 	unsigned long count;
 
-	mon_disable(m);
-	count = has_hw_sampling(m) ? mon_get_zone_stats(m) : mon_get_count(m);
-	mon_clear(m, false);
-	mon_irq_clear(m);
-	mon_enable(m);
+	mon_disable(m, type);
+	count = mon_get_count(m, type);
+	mon_clear(m, false, type);
+	mon_irq_clear(m, type);
+	mon_enable(m, type);
 
 	return count;
 }
 
+static unsigned long get_bytes_and_clear(struct bw_hwmon *hw)
+{
+	return __get_bytes_and_clear(hw, BWMON_1);
+}
+
+static unsigned long get_bytes_and_clear2(struct bw_hwmon *hw)
+{
+	return __get_bytes_and_clear(hw, BWMON_2);
+}
+
 static unsigned long set_thres(struct bw_hwmon *hw, unsigned long bytes)
 {
 	unsigned long count;
 	u32 limit;
 	struct bwmon *m = to_bwmon(hw);
 
-	mon_disable(m);
-	count = mon_get_count(m);
-	mon_clear(m, false);
-	mon_irq_clear(m);
+	mon_disable(m, BWMON_1);
+	count = mon_get_count1(m);
+	mon_clear(m, false, BWMON_1);
+	mon_irq_clear(m, BWMON_1);
 
 	if (likely(!m->spec->wrap_on_thres))
 		limit = bytes;
@@ -429,7 +540,7 @@
 		limit = max(bytes, 500000UL);
 
 	mon_set_limit(m, limit);
-	mon_enable(m);
+	mon_enable(m, BWMON_1);
 
 	return count;
 }
@@ -438,21 +549,22 @@
 {
 	struct bwmon *m = to_bwmon(hw);
 
-	mon_disable(m);
-	mon_clear(m, false);
-	mon_irq_clear(m);
+	mon_disable(m, BWMON_2);
+	mon_clear(m, false, BWMON_2);
+	mon_irq_clear(m, BWMON_2);
 
 	mon_set_zones(m, sample_ms);
-	mon_enable(m);
+	mon_enable(m, BWMON_2);
 
 	return 0;
 }
 
-static irqreturn_t bwmon_intr_handler(int irq, void *dev)
+static irqreturn_t
+__bwmon_intr_handler(int irq, void *dev, enum bwmon_type type)
 {
 	struct bwmon *m = dev;
 
-	m->intr_status = mon_irq_status(m);
+	m->intr_status = mon_irq_status(m, type);
 	if (!m->intr_status)
 		return IRQ_NONE;
 
@@ -462,6 +574,16 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t bwmon_intr_handler(int irq, void *dev)
+{
+	return __bwmon_intr_handler(irq, dev, BWMON_1);
+}
+
+static irqreturn_t bwmon_intr_handler2(int irq, void *dev)
+{
+	return __bwmon_intr_handler(irq, dev, BWMON_2);
+}
+
 static irqreturn_t bwmon_intr_thread(int irq, void *dev)
 {
 	struct bwmon *m = dev;
@@ -470,85 +592,151 @@
 	return IRQ_HANDLED;
 }
 
-static int start_bw_hwmon(struct bw_hwmon *hw, unsigned long mbps)
+static __always_inline int
+__start_bw_hwmon(struct bw_hwmon *hw, unsigned long mbps, enum bwmon_type type)
 {
 	struct bwmon *m = to_bwmon(hw);
-	u32 limit;
-	u32 zone_actions = calc_zone_actions();
+	u32 limit, zone_actions;
 	int ret;
+	irq_handler_t handler;
 
-	ret = request_threaded_irq(m->irq, bwmon_intr_handler,
-				  bwmon_intr_thread,
+	switch (type) {
+	case BWMON_1:
+		handler = bwmon_intr_handler;
+		limit = mbps_to_bytes(mbps, hw->df->profile->polling_ms, 0);
+		break;
+	case BWMON_2:
+		zone_actions = calc_zone_actions();
+		handler = bwmon_intr_handler2;
+		break;
+	}
+
+	ret = request_threaded_irq(m->irq, handler, bwmon_intr_thread,
 				  IRQF_ONESHOT | IRQF_SHARED,
 				  dev_name(m->dev), m);
 	if (ret) {
 		dev_err(m->dev, "Unable to register interrupt handler! (%d)\n",
-				ret);
+			ret);
 		return ret;
 	}
 
-	mon_disable(m);
+	mon_disable(m, type);
 
-	mon_clear(m, true);
-	limit = mbps_to_bytes(mbps, hw->df->profile->polling_ms, 0);
-	if (has_hw_sampling(m)) {
+	mon_clear(m, false, type);
+
+	switch (type) {
+	case BWMON_1:
+		handler = bwmon_intr_handler;
+		mon_set_limit(m, limit);
+		break;
+	case BWMON_2:
 		mon_set_zones(m, hw->df->profile->polling_ms);
 		/* Set the zone actions to increment appropriate counters */
 		writel_relaxed(zone_actions, MON2_ZONE_ACTIONS(m));
-	} else {
-		mon_set_limit(m, limit);
+		break;
 	}
 
-	mon_irq_clear(m);
-	mon_irq_enable(m);
-	mon_enable(m);
+	mon_irq_clear(m, type);
+	mon_irq_enable(m, type);
+	mon_enable(m, type);
 
 	return 0;
 }
 
-static void stop_bw_hwmon(struct bw_hwmon *hw)
+static int start_bw_hwmon(struct bw_hwmon *hw, unsigned long mbps)
+{
+	return __start_bw_hwmon(hw, mbps, BWMON_1);
+}
+
+static int start_bw_hwmon2(struct bw_hwmon *hw, unsigned long mbps)
+{
+	return __start_bw_hwmon(hw, mbps, BWMON_2);
+}
+
+static __always_inline
+void __stop_bw_hwmon(struct bw_hwmon *hw, enum bwmon_type type)
 {
 	struct bwmon *m = to_bwmon(hw);
 
-	mon_irq_disable(m);
+	mon_irq_disable(m, type);
 	free_irq(m->irq, m);
-	mon_disable(m);
-	mon_clear(m, true);
-	mon_irq_clear(m);
+	mon_disable(m, type);
+	mon_clear(m, true, type);
+	mon_irq_clear(m, type);
+}
+
+static void stop_bw_hwmon(struct bw_hwmon *hw)
+{
+	return __stop_bw_hwmon(hw, BWMON_1);
+}
+
+static void stop_bw_hwmon2(struct bw_hwmon *hw)
+{
+	return __stop_bw_hwmon(hw, BWMON_2);
+}
+
+static __always_inline
+int __suspend_bw_hwmon(struct bw_hwmon *hw, enum bwmon_type type)
+{
+	struct bwmon *m = to_bwmon(hw);
+
+	mon_irq_disable(m, type);
+	free_irq(m->irq, m);
+	mon_disable(m, type);
+	mon_irq_clear(m, type);
+
+	return 0;
 }
 
 static int suspend_bw_hwmon(struct bw_hwmon *hw)
 {
-	struct bwmon *m = to_bwmon(hw);
+	return __suspend_bw_hwmon(hw, BWMON_1);
+}
 
-	mon_irq_disable(m);
-	free_irq(m->irq, m);
-	mon_disable(m);
-	mon_irq_clear(m);
+static int suspend_bw_hwmon2(struct bw_hwmon *hw)
+{
+	return __suspend_bw_hwmon(hw, BWMON_2);
+}
+
+static int __resume_bw_hwmon(struct bw_hwmon *hw, enum bwmon_type type)
+{
+	struct bwmon *m = to_bwmon(hw);
+	int ret;
+	irq_handler_t handler;
+
+	switch (type) {
+	case BWMON_1:
+		handler = bwmon_intr_handler;
+		break;
+	case BWMON_2:
+		handler = bwmon_intr_handler2;
+		break;
+	}
+
+	mon_clear(m, false, type);
+	ret = request_threaded_irq(m->irq, handler, bwmon_intr_thread,
+				  IRQF_ONESHOT | IRQF_SHARED,
+				  dev_name(m->dev), m);
+	if (ret) {
+		dev_err(m->dev, "Unable to register interrupt handler! (%d)\n",
+			ret);
+		return ret;
+	}
+
+	mon_irq_enable(m, type);
+	mon_enable(m, type);
 
 	return 0;
 }
 
 static int resume_bw_hwmon(struct bw_hwmon *hw)
 {
-	struct bwmon *m = to_bwmon(hw);
-	int ret;
+	return __resume_bw_hwmon(hw, BWMON_1);
+}
 
-	mon_clear(m, false);
-	ret = request_threaded_irq(m->irq, bwmon_intr_handler,
-				  bwmon_intr_thread,
-				  IRQF_ONESHOT | IRQF_SHARED,
-				  dev_name(m->dev), m);
-	if (ret) {
-		dev_err(m->dev, "Unable to register interrupt handler! (%d)\n",
-				ret);
-		return ret;
-	}
-
-	mon_irq_enable(m);
-	mon_enable(m);
-
-	return 0;
+static int resume_bw_hwmon2(struct bw_hwmon *hw)
+{
+	return __resume_bw_hwmon(hw, BWMON_2);
 }
 
 /*************************************************************************/
@@ -614,16 +802,6 @@
 		return -ENODEV;
 	}
 
-	if (has_hw_sampling(m)) {
-		ret = of_property_read_u32(dev->of_node, "qcom,hw-timer-hz",
-					   &data);
-		if (ret) {
-			dev_err(dev, "HW sampling rate not specified!\n");
-			return ret;
-		}
-		m->hw_timer_hz = data;
-	}
-
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
 	if (!res) {
 		dev_err(dev, "base not found!\n");
@@ -656,15 +834,28 @@
 	if (!m->hw.of_node)
 		return -EINVAL;
 
-	m->hw.start_hwmon = start_bw_hwmon;
-	m->hw.stop_hwmon = stop_bw_hwmon;
-	m->hw.suspend_hwmon = suspend_bw_hwmon;
-	m->hw.resume_hwmon = resume_bw_hwmon;
-	m->hw.get_bytes_and_clear = get_bytes_and_clear;
-	m->hw.set_thres = set_thres;
+	if (m->spec->hw_sampling) {
+		ret = of_property_read_u32(dev->of_node, "qcom,hw-timer-hz",
+					   &m->hw_timer_hz);
+		if (ret) {
+			dev_err(dev, "HW sampling rate not specified!\n");
+			return ret;
+		}
 
-	if (has_hw_sampling(m))
+		m->hw.start_hwmon = start_bw_hwmon2;
+		m->hw.stop_hwmon = stop_bw_hwmon2;
+		m->hw.suspend_hwmon = suspend_bw_hwmon2;
+		m->hw.resume_hwmon = resume_bw_hwmon2;
+		m->hw.get_bytes_and_clear = get_bytes_and_clear2;
 		m->hw.set_hw_events = set_hw_events;
+	} else {
+		m->hw.start_hwmon = start_bw_hwmon;
+		m->hw.stop_hwmon = stop_bw_hwmon;
+		m->hw.suspend_hwmon = suspend_bw_hwmon;
+		m->hw.resume_hwmon = resume_bw_hwmon;
+		m->hw.get_bytes_and_clear = get_bytes_and_clear;
+		m->hw.set_thres = set_thres;
+	}
 
 	if (m->spec->throt_adj) {
 		m->hw.set_throttle_adj = mon_set_throttle_adj;
diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c
index 9a68dbe..3618479 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.c
+++ b/drivers/gpu/drm/msm/sde_power_handle.c
@@ -44,6 +44,7 @@
 static int sde_power_rsc_update(struct sde_power_handle *phandle, bool enable)
 {
 	u32 rsc_state;
+	int ret = 0;
 
 	/* creates the rsc client on the first enable */
 	if (!phandle->rsc_client_init) {
@@ -59,8 +60,11 @@
 
 	rsc_state = enable ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE;
 
-	return sde_rsc_client_state_update(phandle->rsc_client,
+	if (phandle->rsc_client)
+		ret = sde_rsc_client_state_update(phandle->rsc_client,
 			rsc_state, NULL, -1);
+
+	return ret;
 }
 
 struct sde_power_client *sde_power_client_create(
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index c1b812a..d762904 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -388,7 +388,7 @@
 
 static int sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
 	struct sde_rsc_cmd_config *config,
-	struct sde_rsc_client *caller_client, bool wait_req)
+	struct sde_rsc_client *caller_client)
 {
 	struct sde_rsc_client *client;
 	int rc = STATE_UPDATE_NOT_ALLOWED;
@@ -416,8 +416,8 @@
 	if (rsc->hw_ops.state_update)
 		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_CMD_STATE);
 
-	/* wait for vsync */
-	if (!rc && wait_req)
+	/* wait for vsync for vid to cmd state switch */
+	if (!rc && (rsc->current_state == SDE_RSC_VID_STATE))
 		drm_wait_one_vblank(rsc->master_drm,
 						rsc->primary_client->crtc_id);
 end:
@@ -436,13 +436,19 @@
 
 	if (rsc->hw_ops.state_update)
 		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_CLK_STATE);
+
+	/* wait for vsync for cmd to clk state switch */
+	if (!rc && rsc->primary_client &&
+				(rsc->current_state == SDE_RSC_CMD_STATE))
+		drm_wait_one_vblank(rsc->master_drm,
+						rsc->primary_client->crtc_id);
 end:
 	return rc;
 }
 
 static bool sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,
 	struct sde_rsc_cmd_config *config,
-	struct sde_rsc_client *caller_client, bool wait_req)
+	struct sde_rsc_client *caller_client)
 {
 	int rc = 0;
 
@@ -454,8 +460,9 @@
 	if (rsc->hw_ops.state_update)
 		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_VID_STATE);
 
-	/* wait for vsync */
-	if (!rc && rsc->primary_client && wait_req)
+	/* wait for vsync for cmd to vid state switch */
+	if (!rc && rsc->primary_client &&
+			(rsc->current_state == SDE_RSC_CMD_STATE))
 		drm_wait_one_vblank(rsc->master_drm,
 						rsc->primary_client->crtc_id);
 	return rc;
@@ -481,7 +488,6 @@
 {
 	int rc = 0;
 	struct sde_rsc_priv *rsc;
-	bool wait_requested = false;
 
 	if (!caller_client) {
 		pr_err("invalid client for rsc state update\n");
@@ -512,11 +518,7 @@
 		__builtin_return_address(0), rsc->current_state,
 		caller_client->name, state);
 
-	/* only switch state needs vsync wait */
-	wait_requested = (rsc->current_state == SDE_RSC_VID_STATE) ||
-			(rsc->current_state == SDE_RSC_CMD_STATE);
-
-	if (rsc->power_collapse)
+	if (rsc->current_state == SDE_RSC_IDLE_STATE)
 		sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
 
 	switch (state) {
@@ -526,7 +528,7 @@
 		/* video state client might be exiting; try cmd state switch */
 		if (rc == TRY_CMD_MODE_SWITCH) {
 			rc = sde_rsc_switch_to_cmd(rsc, NULL,
-					rsc->primary_client, wait_requested);
+							rsc->primary_client);
 			if (!rc)
 				state = SDE_RSC_CMD_STATE;
 
@@ -539,13 +541,11 @@
 		break;
 
 	case SDE_RSC_CMD_STATE:
-		rc = sde_rsc_switch_to_cmd(rsc, config, caller_client,
-								wait_requested);
+		rc = sde_rsc_switch_to_cmd(rsc, config, caller_client);
 		break;
 
 	case SDE_RSC_VID_STATE:
-		rc = sde_rsc_switch_to_vid(rsc, config, caller_client,
-								wait_requested);
+		rc = sde_rsc_switch_to_vid(rsc, config, caller_client);
 		break;
 
 	case SDE_RSC_CLK_STATE:
@@ -561,7 +561,7 @@
 		rc = 0;
 		goto clk_disable;
 	} else if (rc) {
-		pr_err("state update failed rc:%d\n", rc);
+		pr_debug("state:%d update failed rc:%d\n", state, rc);
 		goto clk_disable;
 	}
 
@@ -569,7 +569,7 @@
 	rsc->current_state = state;
 
 clk_disable:
-	if (rsc->power_collapse)
+	if (rsc->current_state == SDE_RSC_IDLE_STATE)
 		sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
 end:
 	mutex_unlock(&rsc->client_lock);
@@ -615,14 +615,9 @@
 			caller_client->name, ab_vote, ib_vote);
 
 	mutex_lock(&rsc->client_lock);
-	if ((caller_client->current_state == SDE_RSC_IDLE_STATE) ||
-		(rsc->current_state == SDE_RSC_IDLE_STATE)) {
-
-		pr_err("invalid state: client state:%d rsc state:%d\n",
-			caller_client->current_state, rsc->current_state);
-		rc = -EINVAL;
-		goto end;
-	}
+	rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+	if (rc)
+		goto clk_enable_fail;
 
 	if (rsc->hw_ops.is_amc_mode)
 		amc_mode = rsc->hw_ops.is_amc_mode(rsc);
@@ -644,14 +639,19 @@
 		}
 	}
 
+	rpmh_invalidate(rsc->disp_rsc);
 	sde_power_data_bus_set_quota(&rsc->phandle, rsc->pclient,
 		SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT, ab_vote, ib_vote);
+	rpmh_flush(rsc->disp_rsc);
 
 	if (rsc->hw_ops.tcs_use_ok)
 		rsc->hw_ops.tcs_use_ok(rsc);
 
 end:
+	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
+clk_enable_fail:
 	mutex_unlock(&rsc->client_lock);
+
 	return rc;
 }
 EXPORT_SYMBOL(sde_rsc_client_vote);
@@ -668,6 +668,10 @@
 	rsc = s->private;
 
 	mutex_lock(&rsc->client_lock);
+	ret = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+	if (ret)
+		goto end;
+
 	seq_printf(s, "rsc current state:%d\n", rsc->current_state);
 	seq_printf(s, "wraper backoff time(ns):%d\n",
 				rsc->timer_config.static_wakeup_time_ns);
@@ -691,17 +695,15 @@
 		seq_printf(s, "\t client:%s state:%d\n",
 				client->name, client->current_state);
 
-	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
-
 	if (rsc->hw_ops.debug_show) {
 		ret = rsc->hw_ops.debug_show(s, rsc);
 		if (ret)
 			pr_err("sde rsc: hw debug failed ret:%d\n", ret);
 	}
-
 	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
-	mutex_unlock(&rsc->client_lock);
 
+end:
+	mutex_unlock(&rsc->client_lock);
 	return 0;
 }
 
@@ -722,20 +724,23 @@
 {
 	struct sde_rsc_priv *rsc = file->private_data;
 	char buffer[MAX_BUFFER_SIZE];
-	int blen = 0;
+	int blen = 0, rc;
 
 	if (*ppos || !rsc || !rsc->hw_ops.mode_ctrl)
 		return 0;
 
 	mutex_lock(&rsc->client_lock);
-	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+	rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+	if (rc)
+		goto end;
 
 	blen = rsc->hw_ops.mode_ctrl(rsc, MODE_READ, buffer,
 							MAX_BUFFER_SIZE, 0);
 
 	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
-	mutex_unlock(&rsc->client_lock);
 
+end:
+	mutex_unlock(&rsc->client_lock);
 	if (blen < 0)
 		return 0;
 
@@ -752,6 +757,7 @@
 	struct sde_rsc_priv *rsc = file->private_data;
 	char *input, *mode;
 	u32 mode0_state = 0, mode1_state = 0, mode2_state = 0;
+	int rc;
 
 	if (!rsc || !rsc->hw_ops.mode_ctrl)
 		return 0;
@@ -767,7 +773,9 @@
 	input[count - 1] = '\0';
 
 	mutex_lock(&rsc->client_lock);
-	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+	rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+	if (rc)
+		goto clk_enable_fail;
 
 	mode = strnstr(input, "mode0=", strlen("mode0="));
 	if (mode) {
@@ -794,9 +802,10 @@
 
 end:
 	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
+clk_enable_fail:
 	mutex_unlock(&rsc->client_lock);
 
-	pr_err("req: mode0:%d mode1:%d mode2:%d\n", mode0_state, mode1_state,
+	pr_info("req: mode0:%d mode1:%d mode2:%d\n", mode0_state, mode1_state,
 								mode2_state);
 	kfree(input);
 	return count;
@@ -814,20 +823,23 @@
 {
 	struct sde_rsc_priv *rsc = file->private_data;
 	char buffer[MAX_BUFFER_SIZE];
-	int blen = 0;
+	int blen = 0, rc;
 
 	if (*ppos || !rsc || !rsc->hw_ops.hw_vsync)
 		return 0;
 
 	mutex_lock(&rsc->client_lock);
-	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+	rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+	if (rc)
+		goto end;
 
 	blen = rsc->hw_ops.hw_vsync(rsc, VSYNC_READ, buffer,
 						MAX_BUFFER_SIZE, 0);
 
 	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
-	mutex_unlock(&rsc->client_lock);
 
+end:
+	mutex_unlock(&rsc->client_lock);
 	if (blen < 0)
 		return 0;
 
@@ -844,6 +856,7 @@
 	struct sde_rsc_priv *rsc = file->private_data;
 	char *input, *vsync_mode;
 	u32 vsync_state = 0;
+	int rc;
 
 	if (!rsc || !rsc->hw_ops.hw_vsync)
 		return 0;
@@ -865,7 +878,9 @@
 	}
 
 	mutex_lock(&rsc->client_lock);
-	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+	rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+	if (rc)
+		goto end;
 
 	if (vsync_state)
 		rsc->hw_ops.hw_vsync(rsc, VSYNC_ENABLE, NULL,
@@ -874,8 +889,9 @@
 		rsc->hw_ops.hw_vsync(rsc, VSYNC_DISABLE, NULL, 0, 0);
 
 	sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
-	mutex_unlock(&rsc->client_lock);
 
+end:
+	mutex_unlock(&rsc->client_lock);
 	kfree(input);
 	return count;
 }
@@ -930,6 +946,8 @@
 		msm_dss_iounmap(&rsc->wrapper_io);
 	if (rsc->drv_io.base)
 		msm_dss_iounmap(&rsc->drv_io);
+	if (rsc->disp_rsc)
+		rpmh_release(rsc->disp_rsc);
 	if (rsc->pclient)
 		sde_power_client_destroy(&rsc->phandle, rsc->pclient);
 
@@ -1038,6 +1056,17 @@
 		goto sde_rsc_fail;
 	}
 
+	rsc->disp_rsc = rpmh_get_byname(pdev, "disp_rsc");
+	if (IS_ERR_OR_NULL(rsc->disp_rsc)) {
+		ret = PTR_ERR(rsc->disp_rsc);
+		rsc->disp_rsc = NULL;
+		pr_err("sde rsc:get display rsc failed ret:%d\n", ret);
+		goto sde_rsc_fail;
+	}
+	rpmh_invalidate(rsc->disp_rsc);
+	/* call flush to disable the disp rsc interrupt */
+	rpmh_flush(rsc->disp_rsc);
+
 	ret = msm_dss_ioremap_byname(pdev, &rsc->wrapper_io, "wrapper");
 	if (ret) {
 		pr_err("sde rsc: wrapper io data mapping failed ret=%d\n", ret);
@@ -1084,7 +1113,6 @@
 	snprintf(name, MAX_RSC_CLIENT_NAME_LEN, "%s%d", "sde_rsc", counter);
 	_sde_rsc_init_debugfs(rsc, name);
 	counter++;
-	rsc->power_collapse = true;
 
 	ret = component_add(&pdev->dev, &sde_rsc_comp_ops);
 	if (ret)
diff --git a/drivers/gpu/drm/msm/sde_rsc_hw.c b/drivers/gpu/drm/msm/sde_rsc_hw.c
index de579c1..b63fbc6 100644
--- a/drivers/gpu/drm/msm/sde_rsc_hw.c
+++ b/drivers/gpu/drm/msm/sde_rsc_hw.c
@@ -36,6 +36,7 @@
 #define SDE_RSCC_AMC_TCS_MODE_IRQ_STATUS_DRV0		0x1c00
 
 #define SDE_RSCC_SOFT_WAKEUP_TIME_LO_DRV0		0xc04
+#define SDE_RSCC_SOFT_WAKEUP_TIME_HI_DRV0		0xc08
 #define SDE_RSCC_MAX_IDLE_DURATION_DRV0			0xc0c
 #define SDE_RSC_SOLVER_TIME_SLOT_TABLE_0_DRV0		0x1000
 #define SDE_RSC_SOLVER_TIME_SLOT_TABLE_1_DRV0		0x1004
@@ -224,7 +225,9 @@
 	pr_debug("rsc solver init\n");
 
 	dss_reg_w(&rsc->drv_io, SDE_RSCC_SOFT_WAKEUP_TIME_LO_DRV0,
-					0x7FFFFFFF, rsc->debug_mode);
+					0xFFFFFFFF, rsc->debug_mode);
+	dss_reg_w(&rsc->drv_io, SDE_RSCC_SOFT_WAKEUP_TIME_HI_DRV0,
+					0xFFFFFFFF, rsc->debug_mode);
 	dss_reg_w(&rsc->drv_io, SDE_RSCC_MAX_IDLE_DURATION_DRV0,
 					0xEFFFFFFF, rsc->debug_mode);
 
@@ -308,6 +311,15 @@
 
 	rsc_event_trigger(rsc, SDE_RSC_EVENT_PRE_CORE_PC);
 
+	/* update qtimers to high during clk & video mode state */
+	if ((rsc->current_state == SDE_RSC_VID_STATE) ||
+			(rsc->current_state == SDE_RSC_CLK_STATE)) {
+		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F0_QTMR_V1_CNTP_CVAL_HI,
+						0xffffffff, rsc->debug_mode);
+		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F0_QTMR_V1_CNTP_CVAL_LO,
+						0xffffffff, rsc->debug_mode);
+	}
+
 	wrapper_status = dss_reg_r(&rsc->wrapper_io, SDE_RSCC_WRAPPER_CTRL,
 				rsc->debug_mode);
 	wrapper_status |= BIT(3);
@@ -357,8 +369,6 @@
 	return 0;
 
 end:
-	regulator_set_mode(rsc->fs, REGULATOR_MODE_NORMAL);
-
 	rsc_event_trigger(rsc, SDE_RSC_EVENT_POST_CORE_RESTORE);
 
 	return rc;
@@ -378,8 +388,7 @@
 	if ((state == SDE_RSC_VID_STATE) || (state == SDE_RSC_CLK_STATE)) {
 		reg = dss_reg_r(&rsc->wrapper_io,
 			SDE_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode);
-		reg |= BIT(8);
-		reg &= ~(BIT(1) | BIT(0));
+		reg &= ~(BIT(8) | BIT(0));
 		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
 							reg, rsc->debug_mode);
 	}
@@ -411,7 +420,7 @@
 			rc = 0;
 			break;
 		}
-		usleep_range(1, 2);
+		usleep_range(10, 100);
 	}
 
 	reg = dss_reg_r(&rsc->wrapper_io, SDE_RSCC_SPARE_PWR_EVENT,
@@ -419,14 +428,9 @@
 	reg &= ~BIT(13);
 	dss_reg_w(&rsc->wrapper_io, SDE_RSCC_SPARE_PWR_EVENT,
 							reg, rsc->debug_mode);
-
 	if (rc)
 		pr_err("vdd reg is not enabled yet\n");
 
-	rc = regulator_set_mode(rsc->fs, REGULATOR_MODE_NORMAL);
-	if (rc)
-		pr_err("vdd reg normal mode set failed rc:%d\n", rc);
-
 	rsc_event_trigger(rsc, SDE_RSC_EVENT_POST_CORE_RESTORE);
 
 	return rc;
@@ -454,6 +458,9 @@
 						0x1, rsc->debug_mode);
 		dss_reg_w(&rsc->drv_io, SDE_RSCC_SOLVER_OVERRIDE_CTRL_DRV0,
 							0x0, rsc->debug_mode);
+		dss_reg_w(&rsc->drv_io,
+			SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x7,
+			rsc->debug_mode);
 		reg = dss_reg_r(&rsc->wrapper_io,
 			SDE_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode);
 		reg |= (BIT(0) | BIT(8));
@@ -477,8 +484,9 @@
 		reg &= ~(BIT(1) | BIT(0));
 		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
 							reg, rsc->debug_mode);
-		dss_reg_w(&rsc->drv_io, SDE_RSCC_SOLVER_OVERRIDE_CTRL_DRV0,
-							0x1, rsc->debug_mode);
+		dss_reg_w(&rsc->drv_io,
+			SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x5,
+			rsc->debug_mode);
 		/* make sure that solver mode is override */
 		wmb();
 
@@ -487,6 +495,17 @@
 
 	case SDE_RSC_CLK_STATE:
 		pr_debug("clk state handling\n");
+
+		reg = dss_reg_r(&rsc->wrapper_io,
+			SDE_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode);
+		reg &= ~(BIT(8) | BIT(0));
+		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
+							reg, rsc->debug_mode);
+		dss_reg_w(&rsc->drv_io,
+			SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x5,
+			rsc->debug_mode);
+		/* make sure that solver mode is disabled */
+		wmb();
 		break;
 
 	case SDE_RSC_IDLE_STATE:
diff --git a/drivers/gpu/drm/msm/sde_rsc_priv.h b/drivers/gpu/drm/msm/sde_rsc_priv.h
index 30810fe..b83a866 100644
--- a/drivers/gpu/drm/msm/sde_rsc_priv.h
+++ b/drivers/gpu/drm/msm/sde_rsc_priv.h
@@ -111,6 +111,7 @@
  * @pclient:		module power client of phandle
  * @fs:			"MDSS GDSC" handle
  *
+ * @disp_rsc:		display rsc handle
  * @drv_io:		sde drv io data mapping
  * @wrapper_io:		wrapper io data mapping
  *
@@ -141,6 +142,7 @@
 	struct sde_power_client *pclient;
 	struct regulator *fs;
 
+	struct rpmh_client *disp_rsc;
 	struct dss_io_data drv_io;
 	struct dss_io_data wrapper_io;
 
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index 28d93a9..69b639a 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -678,6 +678,7 @@
 #define A6XX_GMU_DCVS_RETURN			0x1CBFF
 #define A6XX_GMU_CM3_SYSRESET			0x1F800
 #define A6XX_GMU_CM3_BOOT_CONFIG		0x1F801
+#define A6XX_GMU_CM3_FW_BUSY			0x1F81A
 #define A6XX_GMU_CM3_FW_INIT_RESULT		0x1F81C
 #define A6XX_GMU_PWR_COL_INTER_FRAME_CTRL	0x1F8C0
 #define A6XX_GMU_PWR_COL_INTER_FRAME_HYST	0x1F8C1
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index c721065..3c3f99f 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -1303,16 +1303,11 @@
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct gmu_device *gmu = &device->gmu;
 
-	if (timed_poll_check(device, A6XX_GMU_RPMH_POWER_STATE,
-		gmu->idle_level, GMU_START_TIMEOUT, 0xf)) {
-		dev_err(&gmu->pdev->dev,
-			"GMU is not going to powerstate %d\n",
-			gmu->idle_level);
-		return -ETIMEDOUT;
-	}
+	/* TODO: Remove this register write when firmware is updated */
+	kgsl_gmu_regwrite(device, A6XX_GMU_CM3_FW_BUSY, 0);
 
 	if (timed_poll_check(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS,
-		0, GMU_START_TIMEOUT, CXGXCPUBUSYIGNAHB)) {
+			0, GMU_START_TIMEOUT, CXGXCPUBUSYIGNAHB)) {
 		dev_err(&gmu->pdev->dev, "GMU is not idling\n");
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 416085f..0c821cd 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -1369,24 +1369,39 @@
 	return ret;
 }
 
+#define GMU_IDLE_TIMEOUT	10 /* ms */
+
 /* Caller shall ensure GPU is ready for SLUMBER */
 void gmu_stop(struct kgsl_device *device)
 {
 	struct gmu_device *gmu = &device->gmu;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
+	unsigned long t;
+	bool idle = false;
 
 	if (!test_bit(GMU_CLK_ON, &gmu->flags))
 		return;
 
-	if (gpudev->wait_for_gmu_idle &&
-		!gpudev->wait_for_gmu_idle(adreno_dev)) {
-		dev_err(&gmu->pdev->dev, "Failure to stop gmu");
-		return;
+	if (gpudev->hw_isidle) {
+		t = jiffies + msecs_to_jiffies(GMU_IDLE_TIMEOUT);
+		while (!time_after(jiffies, t)) {
+			if (gpudev->hw_isidle(adreno_dev)) {
+				idle = true;
+				break;
+			}
+			cpu_relax();
+		}
 	}
 
 	gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_NOTIFY_SLUMBER, 0, 0);
 
+	if (!idle || (gpudev->wait_for_gmu_idle &&
+			gpudev->wait_for_gmu_idle(adreno_dev))) {
+		dev_err(&gmu->pdev->dev, "Failure to stop GMU");
+		return;
+	}
+
 	/* Pending message in all queues are abandoned */
 	hfi_stop(gmu);
 	clear_bit(GMU_HFI_ON, &gmu->flags);
diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h
index a2ca67c..7055eb7 100644
--- a/drivers/gpu/msm/kgsl_gmu.h
+++ b/drivers/gpu/msm/kgsl_gmu.h
@@ -146,7 +146,7 @@
 	GPU_HW_NAP = 0x4,
 	GPU_HW_MIN_VOLT = 0x5,
 	GPU_HW_MIN_DDR = 0x6,
-	GPU_HW_SLUMBER = 0xF
+	GPU_HW_SLUMBER = 0x7
 };
 
 /**
diff --git a/drivers/mailbox/qti-tcs.c b/drivers/mailbox/qti-tcs.c
index b150bad..dfed3cd 100644
--- a/drivers/mailbox/qti-tcs.c
+++ b/drivers/mailbox/qti-tcs.c
@@ -85,7 +85,6 @@
 #define TCS_HIDDEN_CMD_SHIFT		0x08
 
 #define TCS_TYPE_NR			4
-#define TCS_MBOX_TOUT_MS		2000
 #define MAX_POOL_SIZE			(MAX_TCS_PER_TYPE * TCS_TYPE_NR)
 #define TCS_M_INIT			0xFFFF
 
@@ -97,7 +96,6 @@
 	struct tcs_mbox_msg *msg;
 	u32 m; /* m-th TCS */
 	struct tasklet_struct tasklet;
-	struct delayed_work dwork;
 	int err;
 	int idx;
 	bool in_use;
@@ -141,7 +139,6 @@
 };
 
 static void tcs_notify_tx_done(unsigned long data);
-static void tcs_notify_timeout(struct work_struct *work);
 
 static int tcs_response_pool_init(struct tcs_drv *drv)
 {
@@ -155,7 +152,6 @@
 	for (i = 0; i < MAX_POOL_SIZE; i++) {
 		tasklet_init(&pool->resp[i].tasklet, tcs_notify_tx_done,
 						(unsigned long) &pool->resp[i]);
-		INIT_DELAYED_WORK(&pool->resp[i].dwork, tcs_notify_timeout);
 		pool->resp[i].drv = drv;
 		pool->resp[i].idx = i;
 		pool->resp[i].m = TCS_M_INIT;
@@ -337,11 +333,6 @@
 	tasklet_schedule(&resp->tasklet);
 }
 
-static inline void schedule_tcs_err_response(struct tcs_response *resp)
-{
-	schedule_delayed_work(&resp->dwork, msecs_to_jiffies(TCS_MBOX_TOUT_MS));
-}
-
 /**
  * tcs_irq_handler: TX Done / Recv data handler
  */
@@ -371,8 +362,6 @@
 			continue;
 		}
 
-		cancel_delayed_work(&resp->dwork);
-
 		tcs = get_tcs_from_index(drv, m);
 		if (!tcs) {
 			pr_err("TCS-%d doesn't exist in DRV\n", m);
@@ -448,80 +437,6 @@
 	free_response(resp);
 }
 
-/**
- * tcs_notify_timeout: TX Done for requests that do trigger TCS, but
- * we do not get a response IRQ back.
- */
-static void tcs_notify_timeout(struct work_struct *work)
-{
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct tcs_response *resp = container_of(dwork,
-					struct tcs_response, dwork);
-	struct mbox_chan *chan = resp->chan;
-	struct tcs_mbox_msg *msg = resp->msg;
-	struct tcs_drv *drv = resp->drv;
-	int m = resp->m;
-	u32 irq_status;
-	struct tcs_mbox *tcs = get_tcs_from_index(drv, m);
-	bool pending = false;
-	int sent_count, irq_count;
-	int i;
-
-	/* Read while holding a lock, to get a consistent state snapshot */
-	spin_lock(&tcs->tcs_lock);
-	irq_status = read_tcs_reg(drv->reg_base, TCS_DRV_IRQ_STATUS, 0, 0);
-	sent_count = atomic_read(&drv->tcs_send_count[m]);
-	irq_count = atomic_read(&drv->tcs_irq_count[m]);
-
-	if (!tcs_is_free(drv, m)) {
-		struct tcs_cmd *cmd;
-		u32 addr;
-
-		for (i = 0; i < msg->num_payload; i++) {
-			cmd = &msg->payload[i];
-			addr = read_tcs_reg(drv->reg_base, TCS_DRV_CMD_ADDR,
-						m, i);
-			pending |= (cmd->addr == addr);
-		}
-	}
-	spin_unlock(&tcs->tcs_lock);
-
-	if (pending) {
-		pr_err("TCS-%d waiting for response. (sent=%d recvd=%d ctrlr-sts=0x%x)\n",
-			m, sent_count, irq_count, irq_status & (u32)BIT(m));
-		for (i = 0; i < msg->num_payload; i++)
-			pr_err("Addr: 0x%x Data: 0x%x\n",
-					msg->payload[i].addr,
-					msg->payload[i].data);
-		/*
-		 * In case the RPMH resource fails to respond to the
-		 * completion request, the TCS would be blocked forever
-		 * waiting on the response. There is no way to recover
-		 * from such a case. But WARN() to investigate any false
-		 * positives.
-		 */
-		WARN_ON(irq_status & BIT(m));
-
-		/* Clear the TCS status register so we could try again */
-		write_tcs_reg(drv->reg_base, TCS_DRV_IRQ_CLEAR, 0, 0, BIT(m));
-
-		/* Increment the response count, so it doesn't keep adding up */
-		atomic_inc(&drv->tcs_irq_count[m]);
-
-		/*
-		 * If the request was fire-n-forget then the controller,
-		 * then our controller is OK, but the accelerator may be
-		 * in a bad state.
-		 * Let the upper layers figure out what needs to be done
-		 * in such a case. Return error code and carry on.
-		 */
-		atomic_set(&drv->tcs_in_use[m], 0);
-	}
-
-	mbox_notify_tx_done(chan, msg, -1, -ETIMEDOUT);
-	free_response(resp);
-}
-
 static void __tcs_buffer_write(struct tcs_drv *drv, int d, int m, int n,
 			struct tcs_mbox_msg *msg, bool trigger)
 {
@@ -595,60 +510,45 @@
 	return true;
 }
 
-static void wait_for_req_inflight(struct tcs_drv *drv, struct tcs_mbox *tcs,
+static int check_for_req_inflight(struct tcs_drv *drv, struct tcs_mbox *tcs,
 						struct tcs_mbox_msg *msg)
 {
-	u32 curr_enabled;
+	u32 curr_enabled, addr;
 	int i, j, k;
-	bool is_free;
+	void __iomem *base = drv->reg_base;
+	int m = tcs->tcs_offset;
 
-	do  {
-		is_free = true;
-		for (i = 1; i > tcs->tcs_mask; i = i << 1) {
-			if (!(tcs->tcs_mask & i))
+	for (i = 0; i < tcs->num_tcs; i++, m++) {
+		if (tcs_is_free(drv, m))
+			continue;
+
+		curr_enabled = read_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0);
+		for (j = 0; j < curr_enabled; j++) {
+			if (!(curr_enabled & BIT(j)))
 				continue;
-			if (tcs_is_free(drv, i))
-				continue;
-			curr_enabled = read_tcs_reg(drv->reg_base,
-						TCS_DRV_CMD_ENABLE, i, 0);
-			for (j = 0; j < msg->num_payload; j++) {
-				for (k = 0; k < curr_enabled; k++) {
-					if (!(curr_enabled & BIT(k)))
-						continue;
-					if (tcs->cmd_addr[k] ==
-						msg->payload[j].addr) {
-						is_free = false;
-						goto retry;
-					}
-				}
+			addr = read_tcs_reg(base, TCS_DRV_CMD_ADDR, m, j);
+			for (k = 0; k < msg->num_payload; k++) {
+				if (addr == msg->payload[k].addr)
+					return -EBUSY;
 			}
 		}
-retry:
-		if (!is_free)
-			udelay(1);
-	} while (!is_free);
+	}
+
+	return 0;
 }
 
 static int find_free_tcs(struct tcs_mbox *tcs)
 {
-	int slot, m = 0;
-	u32 irq_status;
+	int slot = -EBUSY;
+	int m = 0;
 
 	/* Loop until we find a free AMC */
-	do {
+	for (m = 0; m < tcs->num_tcs; m++) {
 		if (tcs_is_free(tcs->drv, tcs->tcs_offset + m)) {
 			slot = m * tcs->ncpt;
 			break;
 		}
-		if (++m >= tcs->num_tcs) {
-			m = 0;
-			irq_status = read_tcs_reg(tcs->drv->reg_base,
-						TCS_DRV_IRQ_STATUS, 0, 0);
-			WARN((irq_status & tcs->tcs_mask && in_irq()),
-				"TCS busy. Request should not be made from hard IRQ context.");
-			udelay(10);
-		}
-	} while (1);
+	}
 
 	return slot;
 }
@@ -711,8 +611,9 @@
 	struct tcs_drv *drv = container_of(chan->mbox, struct tcs_drv, mbox);
 	int d = drv->drv_id;
 	struct tcs_mbox *tcs;
-	int i, slot, offset, m, n;
+	int i, slot, offset, m, n, ret;
 	struct tcs_response *resp = NULL;
+	unsigned long flags;
 
 	tcs = get_tcs_for_msg(drv, msg);
 	if (IS_ERR(tcs))
@@ -722,16 +623,24 @@
 		resp = setup_response(drv, msg, chan, TCS_M_INIT, 0);
 
 	/* Identify the sequential slots that we can write to */
-	spin_lock(&tcs->tcs_lock);
+	spin_lock_irqsave(&tcs->tcs_lock, flags);
 	slot = find_slots(tcs, msg);
 	if (slot < 0) {
 		dev_err(dev, "No TCS slot found.\n");
-		spin_unlock(&tcs->tcs_lock);
+		spin_unlock_irqrestore(&tcs->tcs_lock, flags);
 		if (resp)
 			free_response(resp);
 		return slot;
 	}
 
+	if (trigger) {
+		ret = check_for_req_inflight(drv, tcs, msg);
+		if (ret) {
+			spin_unlock_irqrestore(&tcs->tcs_lock, flags);
+			return ret;
+		}
+	}
+
 	/* Mark the slots as in-use, before we unlock */
 	if (tcs->type == SLEEP_TCS || tcs->type == WAKE_TCS)
 		bitmap_set(tcs->slots, slot, msg->num_payload);
@@ -750,17 +659,12 @@
 		/* Mark the TCS as busy */
 		atomic_set(&drv->tcs_in_use[m], 1);
 		atomic_inc(&drv->tcs_send_count[m]);
-		wait_for_req_inflight(drv, tcs, msg);
 	}
 
 	/* Write to the TCS or AMC */
 	__tcs_buffer_write(drv, d, m, n, msg, trigger);
 
-	/* Schedule a timeout response, incase there is no actual response */
-	if (trigger)
-		schedule_tcs_err_response(resp);
-
-	spin_unlock(&tcs->tcs_lock);
+	spin_unlock_irqrestore(&tcs->tcs_lock, flags);
 
 	return 0;
 }
@@ -777,22 +681,21 @@
 	int m, i;
 	int inv_types[] = { WAKE_TCS, SLEEP_TCS };
 	int type = 0;
+	unsigned long flags;
 
 	do {
 		tcs = get_tcs_of_type(drv, inv_types[type]);
 		if (IS_ERR(tcs))
 			return PTR_ERR(tcs);
 
-		spin_lock(&tcs->tcs_lock);
+		spin_lock_irqsave(&tcs->tcs_lock, flags);
 		for (i = 0; i < tcs->num_tcs; i++) {
 			m = i + tcs->tcs_offset;
-			while (!tcs_is_free(drv, m))
-				udelay(1);
 			__tcs_buffer_invalidate(drv->reg_base, m);
 		}
 		/* Mark the TCS as free */
 		bitmap_zero(tcs->slots, MAX_TCS_SLOTS);
-		spin_unlock(&tcs->tcs_lock);
+		spin_unlock_irqrestore(&tcs->tcs_lock, flags);
 	} while (++type < ARRAY_SIZE(inv_types));
 
 	return 0;
@@ -814,6 +717,7 @@
 	struct tcs_mbox_msg *msg = data;
 	const struct device *dev = chan->cl->dev;
 	int ret = -EINVAL;
+	int count = 0;
 
 	if (!msg) {
 		dev_err(dev, "Payload error.\n");
@@ -850,7 +754,14 @@
 		tcs_mbox_invalidate(chan);
 
 	/* Post the message to the TCS and trigger */
-	ret = tcs_mbox_write(chan, msg, true);
+	do {
+		ret = tcs_mbox_write(chan, msg, true);
+		if (ret == -EBUSY) {
+			ret = -EIO;
+			udelay(10);
+		} else
+			break;
+	} while (++count < 10);
 
 tx_fail:
 	if (ret) {
@@ -885,6 +796,7 @@
 	const struct device *dev = chan->cl->dev;
 	struct tcs_drv *drv = container_of(chan->mbox, struct tcs_drv, mbox);
 	struct tcs_mbox *tcs;
+	unsigned long flags;
 
 	tcs = get_tcs_of_type(drv, CONTROL_TCS);
 	if (IS_ERR(tcs))
@@ -895,9 +807,9 @@
 		return -EINVAL;
 	}
 
-	spin_lock(&tcs->tcs_lock);
+	spin_lock_irqsave(&tcs->tcs_lock, flags);
 	__tcs_write_hidden(tcs->drv, drv->drv_id, msg);
-	spin_unlock(&tcs->tcs_lock);
+	spin_unlock_irqrestore(&tcs->tcs_lock, flags);
 
 	return 0;
 }
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
index 683386c..b16e37e 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
@@ -412,6 +412,7 @@
 			goto put_regulator;
 		}
 		disable_irq(soc_info->irq_line->start);
+		soc_info->irq_data = irq_data;
 	}
 
 	/* Get Clock */
@@ -439,7 +440,8 @@
 
 	if (soc_info->irq_line) {
 		disable_irq(soc_info->irq_line->start);
-		free_irq(soc_info->irq_line->start, soc_info);
+		devm_free_irq(&soc_info->pdev->dev,
+			soc_info->irq_line->start, irq_data);
 	}
 
 put_regulator:
@@ -495,7 +497,8 @@
 
 	if (soc_info->irq_line) {
 		disable_irq(soc_info->irq_line->start);
-		free_irq(soc_info->irq_line->start, soc_info);
+		devm_free_irq(&soc_info->pdev->dev,
+			soc_info->irq_line->start, soc_info->irq_data);
 	}
 
 	return 0;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index 0baa9e6..3e8226f 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
@@ -58,6 +58,7 @@
  * @index:                  Instance id for the camera device
  * @irq_name:               Name of the irq associated with the device
  * @irq_line:               Irq resource
+ * @irq_data:               Private data that is passed when IRQ is requested
  * @num_mem_block:          Number of entry in the "reg-names"
  * @mem_block_name:         Array of the reg block name
  * @mem_block_cam_base:     Array of offset of this register space compared
@@ -85,6 +86,7 @@
 
 	const char                     *irq_name;
 	struct resource                *irq_line;
+	void                           *irq_data;
 
 	uint32_t                        num_mem_block;
 	const char                     *mem_block_name[CAM_SOC_MAX_BLOCK];
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index 1c94632..15ecc10 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -2594,8 +2594,13 @@
 static long sde_rotator_compat_ioctl32(struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
+	struct video_device *vdev = video_devdata(file);
+	struct sde_rotator_ctx *ctx =
+			sde_rotator_ctx_from_fh(file->private_data);
 	long ret;
 
+	mutex_lock(vdev->lock);
+
 	switch (cmd) {
 	case VIDIOC_S_SDE_ROTATOR_FENCE:
 	case VIDIOC_G_SDE_ROTATOR_FENCE:
@@ -2604,14 +2609,14 @@
 
 		if (copy_from_user(&fence, (void __user *)arg,
 				sizeof(struct msm_sde_rotator_fence)))
-			return -EFAULT;
+			goto ioctl32_error;
 
 		ret = sde_rotator_private_ioctl(file, file->private_data,
 			0, cmd, (void *)&fence);
 
 		if (copy_to_user((void __user *)arg, &fence,
 				sizeof(struct msm_sde_rotator_fence)))
-			return -EFAULT;
+			goto ioctl32_error;
 
 		break;
 	}
@@ -2622,24 +2627,31 @@
 
 		if (copy_from_user(&comp_ratio, (void __user *)arg,
 				sizeof(struct msm_sde_rotator_comp_ratio)))
-			return -EFAULT;
+			goto ioctl32_error;
 
 		ret = sde_rotator_private_ioctl(file, file->private_data,
 			0, cmd, (void *)&comp_ratio);
 
 		if (copy_to_user((void __user *)arg, &comp_ratio,
 				sizeof(struct msm_sde_rotator_comp_ratio)))
-			return -EFAULT;
+			goto ioctl32_error;
 
 		break;
 	}
 	default:
+		SDEDEV_ERR(ctx->rot_dev->dev, "invalid ioctl32 type:%x\n", cmd);
 		ret = -ENOIOCTLCMD;
 		break;
 
 	}
 
+	mutex_unlock(vdev->lock);
 	return ret;
+
+ioctl32_error:
+	mutex_unlock(vdev->lock);
+	SDEDEV_ERR(ctx->rot_dev->dev, "error handling ioctl32 cmd:%x\n", cmd);
+	return -EFAULT;
 }
 #endif
 
diff --git a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
index 61de231..3c89a73 100644
--- a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
+++ b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
@@ -210,6 +210,7 @@
 #else
 void wcnss_prealloc_check_memory_leak(void) {}
 #endif
+EXPORT_SYMBOL(wcnss_prealloc_check_memory_leak);
 
 int wcnss_pre_alloc_reset(void)
 {
@@ -225,6 +226,7 @@
 
 	return n;
 }
+EXPORT_SYMBOL(wcnss_pre_alloc_reset);
 
 static int __init wcnss_pre_alloc_init(void)
 {
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 0b35caa..b759776 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -48,11 +48,6 @@
 #include <soc/qcom/socinfo.h>
 #include <soc/qcom/ramdump.h>
 
-#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
-#include <net/cnss_prealloc.h>
-#endif
-
-
 #include "wlan_firmware_service_v01.h"
 
 #ifdef CONFIG_ICNSS_DEBUG
@@ -1968,8 +1963,6 @@
 	if (ret < 0) {
 		icnss_pr_err("Driver probe failed: %d, state: 0x%lx\n",
 			     ret, priv->state);
-		wcnss_prealloc_check_memory_leak();
-		wcnss_pre_alloc_reset();
 		goto out;
 	}
 
@@ -2099,8 +2092,6 @@
 	if (ret) {
 		icnss_pr_err("Driver probe failed: %d, state: 0x%lx\n",
 			     ret, penv->state);
-		wcnss_prealloc_check_memory_leak();
-		wcnss_pre_alloc_reset();
 		goto power_off;
 	}
 
@@ -2126,8 +2117,6 @@
 		penv->ops->remove(&penv->pdev->dev);
 
 	clear_bit(ICNSS_DRIVER_PROBED, &penv->state);
-	wcnss_prealloc_check_memory_leak();
-	wcnss_pre_alloc_reset();
 
 	penv->ops = NULL;
 
@@ -2152,8 +2141,6 @@
 	penv->ops->remove(&priv->pdev->dev);
 
 	clear_bit(ICNSS_DRIVER_PROBED, &priv->state);
-	wcnss_prealloc_check_memory_leak();
-	wcnss_pre_alloc_reset();
 
 	icnss_hw_power_off(penv);
 
diff --git a/drivers/soc/qcom/msm-core.c b/drivers/soc/qcom/msm-core.c
index de2a1ce..4ec791c 100644
--- a/drivers/soc/qcom/msm-core.c
+++ b/drivers/soc/qcom/msm-core.c
@@ -35,6 +35,7 @@
 #include <linux/uaccess.h>
 #include <linux/uio_driver.h>
 #include <asm/smp_plat.h>
+#include <asm/cputype.h>
 #include <stdbool.h>
 #define CREATE_TRACE_POINTS
 #include <trace/events/trace_msm_core.h>
@@ -46,7 +47,6 @@
 #define DEFAULT_TEMP 40
 #define DEFAULT_LOW_HYST_TEMP 10
 #define DEFAULT_HIGH_HYST_TEMP 5
-#define CLUSTER_OFFSET_FOR_MPIDR 8
 #define MAX_CORES_PER_CLUSTER 4
 #define MAX_NUM_OF_CLUSTERS 2
 #define NUM_OF_CORNERS 10
@@ -291,12 +291,11 @@
 	int cpu = -1;
 	struct cpu_activity_info *node;
 	struct cpu_static_info *sp, *clear_sp;
-	int cpumask, cluster, mpidr;
+	int cpumask, cluster;
 	bool pdata_valid[NR_CPUS] = {0};
 
 	get_user(cpumask, &argp->cpumask);
 	get_user(cluster, &argp->cluster);
-	mpidr = cluster << 8;
 
 	pr_debug("%s: cpumask %d, cluster: %d\n", __func__, cpumask,
 					cluster);
@@ -304,10 +303,12 @@
 		if (!(cpumask & 0x01))
 			continue;
 
-		mpidr |= i;
 		for_each_possible_cpu(cpu) {
-			if (cpu_logical_map(cpu) == mpidr)
-				break;
+			if ((cpu_topology[cpu].core_id != i) &&
+				(cpu_topology[cpu].cluster_id != cluster))
+				continue;
+
+			break;
 		}
 	}
 
@@ -348,10 +349,9 @@
 	for (i = 0; i < MAX_CORES_PER_CLUSTER; i++, cpumask >>= 1) {
 		if (!(cpumask & 0x01))
 			continue;
-		mpidr = (cluster << CLUSTER_OFFSET_FOR_MPIDR);
-		mpidr |= i;
 		for_each_possible_cpu(cpu) {
-			if (!(cpu_logical_map(cpu) == mpidr))
+			if (((cpu_topology[cpu].core_id != i) ||
+				(cpu_topology[cpu].cluster_id != cluster)))
 				continue;
 
 			node = &activity[cpu];
@@ -395,14 +395,12 @@
 	struct cpu_activity_info *node = NULL;
 	struct sched_params __user *argp = (struct sched_params __user *)arg;
 	int i, cpu = num_possible_cpus();
-	int mpidr, cluster, cpumask;
+	int cluster, cpumask;
 
 	if (!argp)
 		return -EINVAL;
 
 	get_user(cluster, &argp->cluster);
-	mpidr = (cluster << (MAX_CORES_PER_CLUSTER *
-			MAX_NUM_OF_CLUSTERS));
 	get_user(cpumask, &argp->cpumask);
 
 	switch (cmd) {
@@ -414,8 +412,11 @@
 	case EA_VOLT:
 		for (i = 0; cpumask > 0; i++, cpumask >>= 1) {
 			for_each_possible_cpu(cpu) {
-				if (cpu_logical_map(cpu) == (mpidr | i))
-					break;
+				if (((cpu_topology[cpu].core_id != i) ||
+				(cpu_topology[cpu].cluster_id != cluster)))
+					continue;
+
+				break;
 			}
 		}
 		if (cpu >= num_possible_cpus())
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm845.h b/include/dt-bindings/clock/qcom,gcc-sdm845.h
index 6c62503..73a8c0b 100644
--- a/include/dt-bindings/clock/qcom,gcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,gcc-sdm845.h
@@ -214,6 +214,8 @@
 #define GCC_USB3PHY_PHY_SEC_BCR					22
 #define GCC_USB3_DP_PHY_SEC_BCR					23
 #define GCC_USB_PHY_CFG_AHB2PHY_BCR				24
+#define GCC_PCIE_0_PHY_BCR					25
+#define GCC_PCIE_1_PHY_BCR					26
 
 /* Dummy clocks for rate measurement */
 #define MEASURE_ONLY_SNOC_CLK					0