slim_ngd: Ensure device state consistency with runtime-pm during SSR
During ADSP SSR, client's thread calling runtime-pm resume will
fail since ADSP is unreachable. Make sure such power-up/resume attempt
is blocked until ADSP comes up by using mutex during device-state
transition.
Change-Id: Ie85e52bb2974aaee9654eb8fa1cc60fe37c61b75
Signed-off-by: Sagar Dharia <sdharia@codeaurora.org>
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index fd2d0e3..f3a886b 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -247,7 +247,7 @@
"SLIM MDM SSR (active framer on MDM) dev-down\n");
list_for_each_entry(sbdev, &ctrl->devs, dev_list)
slim_report_absent(sbdev);
- ngd_slim_power_up(dev, true);
+ ngd_slim_runtime_resume(dev->dev);
pm_runtime_set_active(dev->dev);
pm_runtime_enable(dev->dev);
}
@@ -312,12 +312,22 @@
bool report_sat = false;
bool sync_wr = true;
- mutex_lock(&dev->tx_lock);
+ if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
+ return -EPROTONOSUPPORT;
+
+ if (txn->mt == SLIM_MSG_MT_CORE &&
+ (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
+ txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW))
+ return 0;
+
if (txn->mc == SLIM_USR_MC_REPORT_SATELLITE &&
txn->mt == SLIM_MSG_MT_SRC_REFERRED_USER)
report_sat = true;
- if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
- report_sat == false) {
+ else
+ mutex_lock(&dev->tx_lock);
+
+ if (!report_sat && !pm_runtime_enabled(dev->dev) &&
+ dev->state == MSM_CTRL_ASLEEP) {
/*
* Counter-part of system-suspend when runtime-pm is not enabled
* This way, resume can be left empty and device will be put in
@@ -333,28 +343,16 @@
ret, dev->state);
return -EREMOTEIO;
}
- }
-
- else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG) {
- mutex_unlock(&dev->tx_lock);
- return -EPROTONOSUPPORT;
- }
-
- if (txn->mt == SLIM_MSG_MT_CORE &&
- (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
- txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) {
- mutex_unlock(&dev->tx_lock);
- return 0;
+ mutex_lock(&dev->tx_lock);
}
/* If txn is tried when controller is down, wait for ADSP to boot */
if (!report_sat) {
- enum msm_ctrl_state cur_state = dev->state;
- mutex_unlock(&dev->tx_lock);
- if (cur_state == MSM_CTRL_DOWN) {
+ if (dev->state == MSM_CTRL_DOWN) {
u8 mc = (u8)txn->mc;
int timeout;
+ mutex_unlock(&dev->tx_lock);
SLIM_INFO(dev, "ADSP slimbus not up yet\n");
/*
* Messages related to data channel management can't
@@ -396,7 +394,10 @@
HZ);
if (!timeout)
return -ETIMEDOUT;
+ mutex_lock(&dev->tx_lock);
}
+
+ mutex_unlock(&dev->tx_lock);
ret = msm_slim_get_ctrl(dev);
mutex_lock(&dev->tx_lock);
/*
@@ -413,8 +414,6 @@
mutex_unlock(&dev->tx_lock);
msm_slim_put_ctrl(dev);
return -EREMOTEIO;
- } else {
- dev->state = MSM_CTRL_AWAKE;
}
}
@@ -450,12 +449,12 @@
SLIM_DBG(dev, "SLIM PGD LA:0x%x, ret:%d\n",
dev->pgdla, ret);
if (ret) {
- mutex_unlock(&dev->tx_lock);
SLIM_ERR(dev,
"Incorrect SLIM-PGD EAPC:0x%x\n",
dev->pdata.eapc);
return ret;
}
+ mutex_lock(&dev->tx_lock);
}
txn->la = dev->pgdla;
}
@@ -624,9 +623,10 @@
return ret ? ret : dev->err;
}
ngd_xfer_err:
- mutex_unlock(&dev->tx_lock);
- if (!report_sat)
+ if (!report_sat) {
+ mutex_unlock(&dev->tx_lock);
msm_slim_put_ctrl(dev);
+ }
return ret ? ret : dev->err;
}
@@ -935,7 +935,6 @@
enum msm_ctrl_state prev_state = dev->state;
SLIM_INFO(dev,
"SLIM SAT: capability exchange successful\n");
- dev->state = MSM_CTRL_AWAKE;
if (prev_state >= MSM_CTRL_ASLEEP)
complete(&dev->reconf);
else
@@ -1019,8 +1018,10 @@
if (!mdm_restart && cur_state == MSM_CTRL_DOWN) {
int timeout = wait_for_completion_timeout(&dev->qmi.qmi_comp,
HZ);
- if (!timeout)
+ if (!timeout) {
SLIM_ERR(dev, "slimbus QMI init timed out\n");
+ return -EREMOTEIO;
+ }
}
/* No need to vote if contorller is not in low power mode */
@@ -1107,11 +1108,11 @@
SLIM_ERR(dev, "Failed to receive master capability\n");
return -ETIMEDOUT;
}
- if (cur_state == MSM_CTRL_DOWN) {
- complete(&dev->ctrl_up);
- /* Resetting the log level */
- SLIM_RST_LOGLVL(dev);
- }
+ /* mutliple transactions waiting on slimbus to power up? */
+ if (cur_state == MSM_CTRL_DOWN)
+ complete_all(&dev->ctrl_up);
+ /* Resetting the log level */
+ SLIM_RST_LOGLVL(dev);
return 0;
}
@@ -1568,8 +1569,10 @@
{
struct platform_device *pdev = to_platform_device(device);
struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
+ mutex_lock(&dev->tx_lock);
if (dev->state == MSM_CTRL_AWAKE)
dev->state = MSM_CTRL_IDLE;
+ mutex_unlock(&dev->tx_lock);
dev_dbg(device, "pm_runtime: idle...\n");
pm_request_autosuspend(device);
return -EAGAIN;
@@ -1586,6 +1589,7 @@
struct platform_device *pdev = to_platform_device(device);
struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
int ret = 0;
+ mutex_lock(&dev->tx_lock);
if (dev->state >= MSM_CTRL_ASLEEP)
ret = ngd_slim_power_up(dev, false);
if (ret) {
@@ -1597,6 +1601,7 @@
} else {
dev->state = MSM_CTRL_AWAKE;
}
+ mutex_unlock(&dev->tx_lock);
SLIM_INFO(dev, "Slim runtime resume: ret %d\n", ret);
return ret;
}
@@ -1607,6 +1612,7 @@
struct platform_device *pdev = to_platform_device(device);
struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
int ret = 0;
+ mutex_lock(&dev->tx_lock);
ret = ngd_slim_power_down(dev);
if (ret) {
if (ret != -EBUSY)
@@ -1615,6 +1621,7 @@
} else {
dev->state = MSM_CTRL_ASLEEP;
}
+ mutex_unlock(&dev->tx_lock);
SLIM_INFO(dev, "Slim runtime suspend: ret %d\n", ret);
return ret;
}