slim: msm: Enable Runtime-PM for slimbus with error handling
Enable Runtime-PM and make sure error handling is done to avoid
unbalanced runtime-PM get/put votes.
Change-Id: Idcb8c2b0715719469b0e4dce68a4d6c9c261eff3
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 984ab71..062b928 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -334,9 +334,18 @@
return false;
}
-static void msm_slim_get_ctrl(struct msm_slim_ctrl *dev)
+static int msm_slim_get_ctrl(struct msm_slim_ctrl *dev)
{
- pm_runtime_get_sync(dev->dev);
+ int ref;
+ int ret = pm_runtime_get_sync(dev->dev);
+ if (ret >= 0) {
+ ref = atomic_read(&dev->dev->power.usage_count);
+ if (ref <= 0) {
+ dev_err(dev->dev, "reference count -ve:%d", ref);
+ ret = -ENODEV;
+ }
+ }
+ return ret;
}
static void msm_slim_put_ctrl(struct msm_slim_ctrl *dev)
{
@@ -472,10 +481,6 @@
* before exiting ISR
*/
mb();
- if (dev->ctrl.sched.usedslots == 0 && dev->chan_active) {
- dev->chan_active = false;
- msm_slim_put_ctrl(dev);
- }
complete(&dev->reconf);
}
pstat = readl_relaxed(dev->base + PGD_PORT_INT_ST_EEn + (16 * dev->ee));
@@ -674,6 +679,7 @@
u32 *pbuf;
u8 *puc;
int timeout;
+ int msgv = -1;
u8 la = txn->la;
u8 mc = (u8)(txn->mc & 0xFF);
/*
@@ -685,12 +691,14 @@
* This "get" votes for messaging bandwidth
*/
if (!(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
- msm_slim_get_ctrl(dev);
+ msgv = msm_slim_get_ctrl(dev);
mutex_lock(&dev->tx_lock);
- if (dev->state == MSM_CTRL_ASLEEP) {
+ if (dev->state == MSM_CTRL_ASLEEP ||
+ ((!(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)) &&
+ dev->state == MSM_CTRL_SLEEPING)) {
dev_err(dev->dev, "runtime or system PM suspended state");
mutex_unlock(&dev->tx_lock);
- if (!(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+ if (msgv >= 0)
msm_slim_put_ctrl(dev);
return -EBUSY;
}
@@ -703,8 +711,9 @@
/* This "get" votes for data channels */
if (dev->ctrl.sched.usedslots != 0 &&
!dev->chan_active) {
- dev->chan_active = true;
- msm_slim_get_ctrl(dev);
+ int chv = msm_slim_get_ctrl(dev);
+ if (chv >= 0)
+ dev->chan_active = true;
}
}
txn->rl--;
@@ -714,7 +723,7 @@
if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
mutex_unlock(&dev->tx_lock);
- if (!(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+ if (msgv >= 0)
msm_slim_put_ctrl(dev);
return -EPROTONOSUPPORT;
}
@@ -761,13 +770,15 @@
*/
dev->pipes[*puc].connected = false;
mutex_unlock(&dev->tx_lock);
- msm_slim_put_ctrl(dev);
+ if (msgv >= 0)
+ msm_slim_put_ctrl(dev);
return 0;
}
if (dev->err) {
dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
mutex_unlock(&dev->tx_lock);
- msm_slim_put_ctrl(dev);
+ if (msgv >= 0)
+ msm_slim_put_ctrl(dev);
return dev->err;
}
*(puc) = *(puc) + dev->pipe_b;
@@ -779,25 +790,36 @@
msm_send_msg_buf(ctrl, pbuf, txn->rl);
timeout = wait_for_completion_timeout(&done, HZ);
- if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW |
- SLIM_MSG_CLK_PAUSE_SEQ_FLG)) && timeout) {
- timeout = wait_for_completion_timeout(&dev->reconf, HZ);
- dev->reconf_busy = false;
- if (timeout) {
- clk_disable(dev->rclk);
- disable_irq(dev->irq);
+ if (mc == SLIM_MSG_MC_RECONFIGURE_NOW) {
+ if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW |
+ SLIM_MSG_CLK_PAUSE_SEQ_FLG)) &&
+ timeout) {
+ timeout = wait_for_completion_timeout(&dev->reconf, HZ);
+ dev->reconf_busy = false;
+ if (timeout) {
+ clk_disable(dev->rclk);
+ disable_irq(dev->irq);
+ }
+ }
+ if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW |
+ SLIM_MSG_CLK_PAUSE_SEQ_FLG)) &&
+ !timeout) {
+ dev->reconf_busy = false;
+ dev_err(dev->dev, "clock pause failed");
+ mutex_unlock(&dev->tx_lock);
+ return -ETIMEDOUT;
+ }
+ if (txn->mt == SLIM_MSG_MT_CORE &&
+ txn->mc == SLIM_MSG_MC_RECONFIGURE_NOW) {
+ if (dev->ctrl.sched.usedslots == 0 &&
+ dev->chan_active) {
+ dev->chan_active = false;
+ msm_slim_put_ctrl(dev);
+ }
}
}
- if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW |
- SLIM_MSG_CLK_PAUSE_SEQ_FLG)) && !timeout) {
- dev->reconf_busy = false;
- dev_err(dev->dev, "clock pause failed");
- mutex_unlock(&dev->tx_lock);
- return -ETIMEDOUT;
- }
-
mutex_unlock(&dev->tx_lock);
- if (!txn->rbuf && !(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+ if (msgv >= 0)
msm_slim_put_ctrl(dev);
if (!timeout)
@@ -993,14 +1015,8 @@
e_addr[2] != QC_CHIPID_SL)
dev->pgdla = laddr;
if (!ret && !pm_runtime_enabled(dev->dev) &&
- laddr == (QC_MSM_DEVS - 1)) {
+ laddr == (QC_MSM_DEVS - 1))
pm_runtime_enable(dev->dev);
- /*
- * Avoid runtime-PM by default, but allow
- * command line activation
- */
- pm_runtime_forbid(dev->dev);
- }
} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
mc == SLIM_MSG_MC_REPLY_VALUE) {
@@ -1008,7 +1024,7 @@
dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len - 4);
slim_msg_response(&dev->ctrl, &buf[4], tid,
len - 4);
- msm_slim_put_ctrl(dev);
+ pm_runtime_mark_last_busy(dev->dev);
} else if (mc == SLIM_MSG_MC_REPORT_INFORMATION) {
u8 l_addr = buf[2];
u16 ele = (u16)buf[4] << 4;
@@ -1041,6 +1057,7 @@
u8 len, mc, mt;
u32 bw_sl;
int ret = 0;
+ int satv = -1;
bool gen_ack = false;
u8 tid;
u8 wbuf[8];
@@ -1062,14 +1079,16 @@
e_addr[i] = buf[7-i];
if (pm_runtime_enabled(dev->dev)) {
- msm_slim_get_ctrl(dev);
- sat->pending_capability = true;
+ satv = msm_slim_get_ctrl(dev);
+ if (satv >= 0)
+ sat->pending_capability = true;
}
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)
- msm_slim_get_ctrl(dev);
+ mc != SLIM_MSG_MC_REPORT_PRESENT) {
+ satv = msm_slim_get_ctrl(dev);
+ }
switch (mc) {
case SLIM_MSG_MC_REPORT_PRESENT:
/* Remove runtime_pm vote once satellite acks */
@@ -1137,8 +1156,9 @@
ret);
}
if (!sat->pending_reconf) {
- msm_slim_get_ctrl(dev);
- sat->pending_reconf = true;
+ int chv = msm_slim_get_ctrl(dev);
+ if (chv >= 0)
+ sat->pending_reconf = true;
}
break;
case SLIM_USR_MC_RECONFIG_NOW:
@@ -1190,7 +1210,7 @@
break;
}
if (!gen_ack) {
- if (mc != SLIM_MSG_MC_REPORT_PRESENT)
+ if (mc != SLIM_MSG_MC_REPORT_PRESENT && satv >= 0)
msm_slim_put_ctrl(dev);
continue;
}
@@ -1207,7 +1227,8 @@
txn.wbuf = wbuf;
txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
msm_xfer_msg(&dev->ctrl, &txn);
- msm_slim_put_ctrl(dev);
+ if (satv >= 0)
+ msm_slim_put_ctrl(dev);
}
}
@@ -1900,10 +1921,12 @@
dev_dbg(device, "pm_runtime: suspending...\n");
dev->state = MSM_CTRL_SLEEPING;
ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
- if (ret)
+ if (ret) {
+ dev_err(device, "clk pause not entered:%d", ret);
dev->state = MSM_CTRL_AWAKE;
- else
+ } else {
dev->state = MSM_CTRL_ASLEEP;
+ }
return ret;
}
@@ -1915,10 +1938,12 @@
dev_dbg(device, "pm_runtime: resuming...\n");
if (dev->state == MSM_CTRL_ASLEEP)
ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
- if (ret)
+ if (ret) {
+ dev_err(device, "clk pause not exited:%d", ret);
dev->state = MSM_CTRL_ASLEEP;
- else
+ } else {
dev->state = MSM_CTRL_AWAKE;
+ }
return ret;
}