Merge "slim_ngd: Use DSP before-shutdown notification for DSP SSR"
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index bca0af0..fd2d0e3 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -163,27 +163,51 @@
case QMI_SERVER_ARRIVE:
schedule_work(&qmi->ssr_up);
break;
- case QMI_SERVER_EXIT:
- dev->state = MSM_CTRL_DOWN;
- /* make sure autosuspend is not called until ADSP comes up*/
- pm_runtime_get_noresume(dev->dev);
- /* Reset ctrl_up completion */
- init_completion(&dev->ctrl_up);
- schedule_work(&qmi->ssr_down);
- break;
default:
break;
}
return 0;
}
+static int dsp_ssr_notify_cb(struct notifier_block *n, unsigned long code,
+ void *_cmd)
+{
+ struct msm_slim_ss *dsp = container_of(n, struct msm_slim_ss, nb);
+ struct msm_slim_ctrl *dev = container_of(dsp, struct msm_slim_ctrl,
+ dsp);
+
+ switch (code) {
+ case SUBSYS_BEFORE_SHUTDOWN:
+ SLIM_INFO(dev, "SLIM DSP SSR notify cb:%lu\n", code);
+ /* wait for current transaction */
+ mutex_lock(&dev->tx_lock);
+ /* make sure autosuspend is not called until ADSP comes up*/
+ pm_runtime_get_noresume(dev->dev);
+ dev->state = MSM_CTRL_DOWN;
+ /* Reset ctrl_up completion */
+ init_completion(&dev->ctrl_up);
+ /* disconnect BAM pipes */
+ if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
+ dev->use_rx_msgqs = MSM_MSGQ_DOWN;
+ if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
+ dev->use_tx_msgqs = MSM_MSGQ_DOWN;
+ msm_slim_sps_exit(dev, false);
+ schedule_work(&dev->qmi.ssr_down);
+ mutex_unlock(&dev->tx_lock);
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
static int mdm_ssr_notify_cb(struct notifier_block *n, unsigned long code,
void *_cmd)
{
void __iomem *ngd;
- struct msm_slim_mdm *mdm = container_of(n, struct msm_slim_mdm, nb);
- struct msm_slim_ctrl *dev = container_of(mdm, struct msm_slim_ctrl,
- mdm);
+ struct msm_slim_ss *ext_mdm = container_of(n, struct msm_slim_ss, nb);
+ struct msm_slim_ctrl *dev = container_of(ext_mdm, struct msm_slim_ctrl,
+ ext_mdm);
struct slim_controller *ctrl = &dev->ctrl;
u32 laddr;
struct slim_device *sbdev;
@@ -198,11 +222,11 @@
* handover later
*/
msm_slim_qmi_check_framer_request(dev);
- dev->mdm.state = MSM_CTRL_DOWN;
+ dev->ext_mdm.state = MSM_CTRL_DOWN;
msm_slim_put_ctrl(dev);
break;
case SUBSYS_AFTER_POWERUP:
- if (dev->mdm.state != MSM_CTRL_DOWN)
+ if (dev->ext_mdm.state != MSM_CTRL_DOWN)
return NOTIFY_DONE;
SLIM_INFO(dev,
"SLIM %lu external_modem SSR notify cb\n", code);
@@ -213,10 +237,12 @@
ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
laddr = readl_relaxed(ngd + NGD_STATUS);
if (!(laddr & NGD_LADDR)) {
+ mutex_lock(&dev->tx_lock);
/* runtime-pm state should be consistent with HW */
pm_runtime_disable(dev->dev);
pm_runtime_set_suspended(dev->dev);
dev->state = MSM_CTRL_DOWN;
+ mutex_unlock(&dev->tx_lock);
SLIM_INFO(dev,
"SLIM MDM SSR (active framer on MDM) dev-down\n");
list_for_each_entry(sbdev, &ctrl->devs, dev_list)
@@ -225,7 +251,7 @@
pm_runtime_set_active(dev->dev);
pm_runtime_enable(dev->dev);
}
- dev->mdm.state = MSM_CTRL_AWAKE;
+ dev->ext_mdm.state = MSM_CTRL_AWAKE;
msm_slim_put_ctrl(dev);
break;
default:
@@ -286,6 +312,7 @@
bool report_sat = false;
bool sync_wr = true;
+ mutex_lock(&dev->tx_lock);
if (txn->mc == SLIM_USR_MC_REPORT_SATELLITE &&
txn->mt == SLIM_MSG_MT_SRC_REFERRED_USER)
report_sat = true;
@@ -298,6 +325,7 @@
* If the state was DOWN, SSR UP notification will take
* care of putting the device in active state.
*/
+ mutex_unlock(&dev->tx_lock);
ret = ngd_slim_runtime_resume(dev->dev);
if (ret) {
@@ -307,17 +335,24 @@
}
}
- else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
+ 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;
}
+
/* If txn is tried when controller is down, wait for ADSP to boot */
if (!report_sat) {
- if (dev->state == MSM_CTRL_DOWN) {
+ enum msm_ctrl_state cur_state = dev->state;
+
+ mutex_unlock(&dev->tx_lock);
+ if (cur_state == MSM_CTRL_DOWN) {
u8 mc = (u8)txn->mc;
int timeout;
SLIM_INFO(dev, "ADSP slimbus not up yet\n");
@@ -359,27 +394,29 @@
return -EREMOTEIO;
timeout = wait_for_completion_timeout(&dev->ctrl_up,
HZ);
- if (!timeout && dev->state == MSM_CTRL_DOWN)
+ if (!timeout)
return -ETIMEDOUT;
}
ret = msm_slim_get_ctrl(dev);
+ mutex_lock(&dev->tx_lock);
/*
* Runtime-pm's callbacks are not called until runtime-pm's
* error status is cleared
* Setting runtime status to suspended clears the error
* It also makes HW status cosistent with what SW has it here
*/
- if (pm_runtime_enabled(dev->dev) && ret < 0) {
+ if ((pm_runtime_enabled(dev->dev) && ret < 0) ||
+ dev->state == MSM_CTRL_DOWN) {
SLIM_ERR(dev, "slim ctrl vote failed ret:%d, state:%d",
ret, dev->state);
pm_runtime_set_suspended(dev->dev);
+ mutex_unlock(&dev->tx_lock);
msm_slim_put_ctrl(dev);
return -EREMOTEIO;
} else {
dev->state = MSM_CTRL_AWAKE;
}
}
- mutex_lock(&dev->tx_lock);
if (txn->mt == SLIM_MSG_MT_CORE &&
(txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
@@ -413,12 +450,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;
}
@@ -538,9 +575,11 @@
* transactions don't timeout due to unavailable
* descriptors
*/
- msm_slim_disconnect_endp(dev, &dev->tx_msgq,
- &dev->use_tx_msgqs);
- msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
+ if (dev->state != MSM_CTRL_DOWN) {
+ msm_slim_disconnect_endp(dev, &dev->tx_msgq,
+ &dev->use_tx_msgqs);
+ msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
+ }
} else {
ret = dev->err;
}
@@ -1227,12 +1266,6 @@
struct slim_device *sbdev;
ngd_slim_enable(dev, false);
- /* disconnect BAM pipes */
- if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
- dev->use_rx_msgqs = MSM_MSGQ_DOWN;
- if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
- dev->use_tx_msgqs = MSM_MSGQ_DOWN;
- msm_slim_sps_exit(dev, false);
/* device up should be called again after SSR */
list_for_each_entry(sbdev, &ctrl->devs, dev_list)
slim_report_absent(sbdev);
@@ -1442,14 +1475,21 @@
pm_runtime_set_suspended(dev->dev);
pm_runtime_enable(dev->dev);
+ dev->dsp.nb.notifier_call = dsp_ssr_notify_cb;
+ dev->dsp.ssr = subsys_notif_register_notifier("adsp",
+ &dev->dsp.nb);
+ if (IS_ERR_OR_NULL(dev->dsp.ssr))
+ dev_err(dev->dev,
+ "subsys_notif_register_notifier failed %p",
+ dev->dsp.ssr);
if (slim_mdm) {
- dev->mdm.nb.notifier_call = mdm_ssr_notify_cb;
- dev->mdm.ssr = subsys_notif_register_notifier(ext_modem_id,
- &dev->mdm.nb);
- if (IS_ERR_OR_NULL(dev->mdm.ssr))
+ dev->ext_mdm.nb.notifier_call = mdm_ssr_notify_cb;
+ dev->ext_mdm.ssr = subsys_notif_register_notifier(ext_modem_id,
+ &dev->ext_mdm.nb);
+ if (IS_ERR_OR_NULL(dev->ext_mdm.ssr))
dev_err(dev->dev,
"subsys_notif_register_notifier failed %p",
- dev->mdm.ssr);
+ dev->ext_mdm.ssr);
}
INIT_WORK(&dev->qmi.ssr_down, ngd_adsp_down);
@@ -1507,8 +1547,12 @@
SLIMBUS_QMI_SVC_V1,
SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
pm_runtime_disable(&pdev->dev);
- if (!IS_ERR_OR_NULL(dev->mdm.ssr))
- subsys_notif_unregister_notifier(dev->mdm.ssr, &dev->mdm.nb);
+ if (!IS_ERR_OR_NULL(dev->dsp.ssr))
+ subsys_notif_unregister_notifier(dev->dsp.ssr,
+ &dev->dsp.nb);
+ if (!IS_ERR_OR_NULL(dev->ext_mdm.ssr))
+ subsys_notif_unregister_notifier(dev->ext_mdm.ssr,
+ &dev->ext_mdm.nb);
free_irq(dev->irq, dev);
slim_del_controller(&dev->ctrl);
kthread_stop(dev->rx_msgq_thread);
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index 11741b8..c3f371c 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -951,10 +951,16 @@
void msm_slim_sps_exit(struct msm_slim_ctrl *dev, bool dereg)
{
+ int i;
+
if (dev->use_rx_msgqs >= MSM_MSGQ_ENABLED)
msm_slim_remove_ep(dev, &dev->rx_msgq, &dev->use_rx_msgqs);
if (dev->use_tx_msgqs >= MSM_MSGQ_ENABLED)
msm_slim_remove_ep(dev, &dev->tx_msgq, &dev->use_tx_msgqs);
+ for (i = dev->port_b; i < MSM_SLIM_NPORTS; i++) {
+ if (dev->pipes[i - dev->port_b].connected)
+ msm_slim_disconn_pipe_port(dev, i - dev->port_b);
+ }
if (dereg) {
int i;
for (i = dev->port_b; i < MSM_SLIM_NPORTS; i++) {
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 5f12f24..99297a9 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -214,7 +214,7 @@
struct work_struct ssr_up;
};
-struct msm_slim_mdm {
+struct msm_slim_ss {
struct notifier_block nb;
void *ssr;
enum msm_ctrl_state state;
@@ -269,7 +269,8 @@
u32 ver;
struct msm_slim_qmi qmi;
struct msm_slim_pdata pdata;
- struct msm_slim_mdm mdm;
+ struct msm_slim_ss ext_mdm;
+ struct msm_slim_ss dsp;
int default_ipc_log_mask;
int ipc_log_mask;
bool sysfs_created;