slim: msm: Revert runtime-PM for Slimbus MSM controller

Using runtime-PM for slimbus MSM controller may cause some race
conditions (e.g. suspend callback is not guaranteed to be complete
when client calls pm_runtime_get_sync). Rely on system-wide suspend
resume callbacks till the race conditions are sorted out.

Change-Id: Ie41aa9fd64c437fc7e2f5699439ca78dedb74cde
Signed-off-by: Sagar Dharia <sdharia@codeaurora.org>
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 4a2ad3f..1e4302b 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -21,7 +21,6 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/clk.h>
-#include <linux/pm_runtime.h>
 #include <mach/sps.h>
 
 /* Per spec.max 40 bytes per received message */
@@ -45,7 +44,6 @@
 #define MSM_SLIM_PERF_SUMM_THRESHOLD	0x8000
 #define MSM_SLIM_NCHANS			32
 #define MSM_SLIM_NPORTS			24
-#define MSM_SLIM_AUTOSUSPEND		MSEC_PER_SEC
 
 /*
  * Need enough descriptors to receive present messages from slaves
@@ -82,7 +80,6 @@
 #define QC_DEVID_SAT1	0x3
 #define QC_DEVID_SAT2	0x4
 #define QC_DEVID_PGD	0x5
-#define QC_MSM_DEVS	5
 
 /* Component registers */
 enum comp_reg {
@@ -187,12 +184,6 @@
 	REF_CLK_GEAR	= 15,
 };
 
-enum msm_ctrl_state {
-	MSM_CTRL_AWAKE,
-	MSM_CTRL_SLEEPING,
-	MSM_CTRL_ASLEEP,
-};
-
 struct msm_slim_sps_bam {
 	u32			hdl;
 	void __iomem		*base;
@@ -235,12 +226,10 @@
 	struct mutex		tx_lock;
 	u8			pgdla;
 	bool			use_rx_msgqs;
+	int			suspended;
 	int			pipe_b;
 	struct completion	reconf;
 	bool			reconf_busy;
-	bool			chan_active;
-	enum msm_ctrl_state	state;
-	int			numdevs;
 };
 
 struct msm_slim_sat {
@@ -461,11 +450,6 @@
 		 * before exiting ISR
 		 */
 		mb();
-		if (dev->ctrl.sched.usedslots == 0 &&
-			dev->state != MSM_CTRL_SLEEPING) {
-			dev->chan_active = false;
-			pm_runtime_put(dev->dev);
-		}
 		complete(&dev->reconf);
 	}
 	pstat = readl_relaxed(dev->base + PGD_PORT_INT_ST_EEn + (16 * dev->ee));
@@ -665,37 +649,17 @@
 	u8 *puc;
 	int timeout;
 	u8 la = txn->la;
-	/*
-	 * Voting for runtime PM: Slimbus has 2 possible use cases:
-	 * 1. messaging
-	 * 2. Data channels
-	 * Messaging case goes through messaging slots and data channels
-	 * use their own slots
-	 * This "get" votes for messaging bandwidth
-	 */
-	if (txn->mc < SLIM_MSG_MC_BEGIN_RECONFIGURATION ||
-		txn->mc > SLIM_MSG_MC_RECONFIGURE_NOW ||
-		dev->state != MSM_CTRL_SLEEPING)
-		pm_runtime_get_sync(dev->dev);
 	mutex_lock(&dev->tx_lock);
-	if (dev->state == MSM_CTRL_ASLEEP) {
-		dev_err(dev->dev, "runtime or system PM suspended state");
-		mutex_unlock(&dev->tx_lock);
-		pm_runtime_put(dev->dev);
-		return -EBUSY;
-	}
 	if (txn->mt == SLIM_MSG_MT_CORE &&
-		txn->mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION) {
-		if (dev->reconf_busy) {
+		txn->mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
+		dev->reconf_busy) {
 			wait_for_completion(&dev->reconf);
 			dev->reconf_busy = false;
-		}
-		/* This "get" votes for data channels */
-		if (dev->ctrl.sched.usedslots != 0 &&
-			!dev->chan_active) {
-			dev->chan_active = true;
-			pm_runtime_get(dev->dev);
-		}
+	}
+	if (dev->suspended) {
+		dev_err(dev->dev, "No transaction in suspended state");
+		mutex_unlock(&dev->tx_lock);
+		return -EBUSY;
 	}
 	txn->rl--;
 	pbuf = msm_get_msg_buf(ctrl, txn->rl);
@@ -704,10 +668,6 @@
 
 	if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
 		mutex_unlock(&dev->tx_lock);
-		if (txn->mc < SLIM_MSG_MC_BEGIN_RECONFIGURATION ||
-			txn->mc > SLIM_MSG_MC_RECONFIGURE_NOW ||
-			dev->state != MSM_CTRL_SLEEPING)
-			pm_runtime_put(dev->dev);
 		return -EPROTONOSUPPORT;
 	}
 	if (txn->mt == SLIM_MSG_MT_CORE && txn->la == 0xFF &&
@@ -755,15 +715,11 @@
 			 */
 			dev->pipes[*puc].connected = false;
 			mutex_unlock(&dev->tx_lock);
-			if (dev->state != MSM_CTRL_SLEEPING)
-				pm_runtime_put(dev->dev);
 			return 0;
 		}
 		if (dev->err) {
 			dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
 			mutex_unlock(&dev->tx_lock);
-			if (dev->state != MSM_CTRL_SLEEPING)
-				pm_runtime_put(dev->dev);
 			return dev->err;
 		}
 		*(puc) = *(puc) + dev->pipe_b;
@@ -774,37 +730,10 @@
 	dev->wr_comp = &done;
 	msm_send_msg_buf(ctrl, pbuf, txn->rl);
 	timeout = wait_for_completion_timeout(&done, HZ);
-
-	if (dev->state == MSM_CTRL_SLEEPING &&
-			txn->mc == SLIM_MSG_MC_RECONFIGURE_NOW &&
-			txn->mt == SLIM_MSG_MT_CORE && timeout) {
-		timeout = wait_for_completion_timeout(&dev->reconf, HZ);
-		dev->reconf_busy = false;
-		if (timeout) {
-			clk_disable(dev->rclk);
-			disable_irq(dev->irq);
-			dev->state = MSM_CTRL_ASLEEP;
-		}
-	}
-	if (!timeout && dev->state == MSM_CTRL_SLEEPING &&
-			txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
-			txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW &&
-			txn->mt == SLIM_MSG_MT_CORE) {
-		dev->reconf_busy = false;
-		dev->state = MSM_CTRL_AWAKE;
-		dev_err(dev->dev, "clock pause failed");
-		mutex_unlock(&dev->tx_lock);
-		return -ETIMEDOUT;
-	}
-
-	mutex_unlock(&dev->tx_lock);
-	if (!txn->rbuf && dev->state == MSM_CTRL_AWAKE)
-		pm_runtime_put(dev->dev);
-
 	if (!timeout)
 		dev_err(dev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
 					txn->mt);
-
+	mutex_unlock(&dev->tx_lock);
 	return timeout ? dev->err : -ETIMEDOUT;
 }
 
@@ -834,7 +763,6 @@
 static int msm_clk_pause_wakeup(struct slim_controller *ctrl)
 {
 	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
-	enable_irq(dev->irq);
 	clk_enable(dev->rclk);
 	writel_relaxed(1, dev->base + FRM_WAKEUP);
 	/* Make sure framer wakeup write goes through before exiting function */
@@ -849,7 +777,6 @@
 	 * we get the message
 	 */
 	usleep_range(5000, 5000);
-	dev->state = MSM_CTRL_AWAKE;
 	return 0;
 }
 
@@ -994,9 +921,6 @@
 				e_addr[1] == QC_DEVID_PGD &&
 				e_addr[2] != QC_CHIPID_SL)
 				dev->pgdla = laddr;
-			dev->numdevs++;
-			if (!ret && dev->numdevs == QC_MSM_DEVS)
-				pm_runtime_enable(dev->dev);
 
 		} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
 				mc == SLIM_MSG_MC_REPLY_VALUE) {
@@ -1004,7 +928,6 @@
 			dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len - 4);
 			slim_msg_response(&dev->ctrl, &buf[4], tid,
 						len - 4);
-			pm_runtime_put(dev->dev);
 		} else if (mc == SLIM_MSG_MC_REPORT_INFORMATION) {
 			u8 l_addr = buf[2];
 			u16 ele = (u16)buf[4] << 4;
@@ -1057,19 +980,11 @@
 			for (i = 0; i < 6; i++)
 				e_addr[i] = buf[7-i];
 
-			pm_runtime_get_sync(dev->dev);
 			slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr);
 			sat->satcl.laddr = laddr;
-		} else if (mt != SLIM_MSG_MT_CORE &&
-				mc != SLIM_MSG_MC_REPORT_PRESENT)
-			pm_runtime_get_sync(dev->dev);
+		}
 		switch (mc) {
 		case SLIM_MSG_MC_REPORT_PRESENT:
-			/* Remove runtime_pm vote once satellite acks */
-			if (mt != SLIM_MSG_MT_CORE) {
-				pm_runtime_put(dev->dev);
-				continue;
-			}
 			/* send a Manager capability msg */
 			if (sat->sent_capability)
 				continue;
@@ -1170,11 +1085,8 @@
 		default:
 			break;
 		}
-		if (!gen_ack) {
-			if (mc != SLIM_MSG_MC_REPORT_PRESENT)
-				pm_runtime_put(dev->dev);
+		if (!gen_ack)
 			continue;
-		}
 		wbuf[0] = tid;
 		if (!ret)
 			wbuf[1] = MSM_SAT_SUCCSS;
@@ -1187,7 +1099,6 @@
 		txn.wbuf = wbuf;
 		txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
 		msm_xfer_msg(&dev->ctrl, &txn);
-		pm_runtime_put(dev->dev);
 	}
 }
 
@@ -1791,9 +1702,6 @@
 	 * function
 	 */
 	mb();
-	pm_runtime_use_autosuspend(&pdev->dev);
-	pm_runtime_set_autosuspend_delay(&pdev->dev, MSM_SLIM_AUTOSUSPEND);
-	pm_runtime_set_active(&pdev->dev);
 	dev_dbg(dev->dev, "MSM SB controller is up!\n");
 	return 0;
 
@@ -1827,13 +1735,12 @@
 	struct resource *slew_mem = dev->slew_mem;
 	struct msm_slim_sat *sat = dev->satd;
 	slim_remove_device(&sat->satcl);
-	pm_runtime_disable(&pdev->dev);
-	pm_runtime_set_suspended(&pdev->dev);
 	kfree(sat->satch);
 	destroy_workqueue(sat->wq);
 	kfree(sat);
 	free_irq(dev->irq, dev);
 	slim_del_controller(&dev->ctrl);
+	clk_disable(dev->rclk);
 	clk_put(dev->rclk);
 	msm_slim_sps_exit(dev);
 	kthread_stop(dev->rx_msgq_thread);
@@ -1853,78 +1760,79 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM_RUNTIME
-static int msm_slim_runtime_idle(struct device *device)
+#ifdef CONFIG_PM
+static int msm_slim_suspend(struct device *device)
 {
 	struct platform_device *pdev = to_platform_device(device);
 	struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
-	dev_dbg(device, "pm_runtime: idle...\n");
-	pm_runtime_mark_last_busy(dev->dev);
-	pm_request_autosuspend(device);
-	return -EAGAIN;
-}
-#endif
-
-/*
- * If PM_RUNTIME is not defined, these 2 functions become helper
- * functions to be called from system suspend/resume. So they are not
- * inside ifdef CONFIG_PM_RUNTIME
- */
-static int msm_slim_runtime_suspend(struct device *device)
-{
-	struct platform_device *pdev = to_platform_device(device);
-	struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
-	dev_dbg(device, "pm_runtime: suspending...\n");
-	dev->state = MSM_CTRL_SLEEPING;
-	return slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
-}
-
-static int msm_slim_runtime_resume(struct device *device)
-{
-	struct platform_device *pdev = to_platform_device(device);
-	struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
-	dev_dbg(device, "pm_runtime: resuming...\n");
+	int ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
+	/* Make sure clock pause goes through */
 	mutex_lock(&dev->tx_lock);
-	if (dev->state == MSM_CTRL_ASLEEP) {
-		mutex_unlock(&dev->tx_lock);
-		return slim_ctrl_clk_pause(&dev->ctrl, true, 0);
+	if (!ret && dev->reconf_busy) {
+		wait_for_completion(&dev->reconf);
+		dev->reconf_busy = false;
 	}
 	mutex_unlock(&dev->tx_lock);
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int msm_slim_suspend(struct device *dev)
-{
-	int ret = 0;
-	if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
-		dev_dbg(dev, "system suspend");
-		ret = msm_slim_runtime_suspend(dev);
-	}
-	if (ret == -EBUSY) {
+	if (!ret) {
+		clk_disable(dev->rclk);
+		disable_irq(dev->irq);
+		dev->suspended = 1;
+	} else if (ret == -EBUSY) {
 		/*
-		* If the clock pause failed due to active channels, there is
-		* a possibility that some audio stream is active during suspend
-		* We dont want to return suspend failure in that case so that
-		* display and relevant components can still go to suspend.
-		* If there is some other error, then it should be passed-on
-		* to system level suspend
-		*/
+		 * If the clock pause failed due to active channels, there is
+		 * a possibility that some audio stream is active during suspend
+		 * We dont want to return suspend failure in that case so that
+		 * display and relevant components can still go to suspend.
+		 * If there is some other error, then it should be passed-on
+		 * to system level suspend
+		 */
 		ret = 0;
 	}
 	return ret;
 }
 
-static int msm_slim_resume(struct device *dev)
+static int msm_slim_resume(struct device *device)
 {
-	/* If runtime_pm is enabled, this resume shouldn't do anything */
-	if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
-		dev_dbg(dev, "system resume");
-		return msm_slim_runtime_resume(dev);
+	struct platform_device *pdev = to_platform_device(device);
+	struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
+	mutex_lock(&dev->tx_lock);
+	if (dev->suspended) {
+		dev->suspended = 0;
+		mutex_unlock(&dev->tx_lock);
+		enable_irq(dev->irq);
+		return slim_ctrl_clk_pause(&dev->ctrl, true, 0);
 	}
+	mutex_unlock(&dev->tx_lock);
 	return 0;
 }
-#endif /* CONFIG_PM_SLEEP */
+#else
+#define msm_slim_suspend NULL
+#define msm_slim_resume NULL
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_slim_runtime_idle(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: idle...\n");
+	return 0;
+}
+
+static int msm_slim_runtime_suspend(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: suspending...\n");
+	return 0;
+}
+
+static int msm_slim_runtime_resume(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: resuming...\n");
+	return 0;
+}
+#else
+#define msm_slim_runtime_idle NULL
+#define msm_slim_runtime_suspend NULL
+#define msm_slim_runtime_resume NULL
+#endif
 
 static const struct dev_pm_ops msm_slim_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index bb30570..3b79129 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -892,6 +892,10 @@
 	cur = slim_slicecodefromsize(sl);
 	ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4));
 
+	ret = slim_ctrl_clk_pause(ctrl, true, 0);
+	if (ret)
+		return ret;
+
 	if (wbuf)
 		mlen += len;
 	if (rbuf) {
@@ -1123,6 +1127,10 @@
 	u8 chan = (u8)(chanh & 0xFF);
 	struct slim_ich *slc = &ctrl->chans[chan];
 
+	ret = slim_ctrl_clk_pause(ctrl, true, 0);
+	if (ret)
+		return ret;
+
 	mutex_lock(&ctrl->m_ctrl);
 	/* Make sure the channel is not already pending reconf. or active */
 	if (slc->state >= SLIM_CH_PENDING_ACTIVE) {
@@ -1185,8 +1193,11 @@
 int slim_disconnect_ports(struct slim_device *sb, u32 *ph, int nph)
 {
 	struct slim_controller *ctrl = sb->ctrl;
-	int i;
+	int i, ret;
 
+	ret = slim_ctrl_clk_pause(ctrl, true, 0);
+	if (ret)
+		return ret;
 	mutex_lock(&ctrl->m_ctrl);
 
 	for (i = 0; i < nph; i++)
@@ -2378,6 +2389,10 @@
 	u32 segdist;
 	struct slim_pending_ch *pch;
 
+	ret = slim_ctrl_clk_pause(ctrl, true, 0);
+	if (ret)
+		return ret;
+
 	mutex_lock(&ctrl->sched.m_reconf);
 	mutex_lock(&ctrl->m_ctrl);
 	ctrl->sched.pending_msgsl += sb->pending_msgsl - sb->cur_msgsl;