Merge "slim: ngd: Handle Process Domain restart"

This commit is contained in:
Linux Build Service Account 2016-08-19 05:29:19 -07:00 committed by Gerrit - the friendly Code Review server
commit 521c0c89d9
3 changed files with 104 additions and 40 deletions

View file

@ -26,6 +26,9 @@
#include <linux/of_slimbus.h>
#include <linux/timer.h>
#include <linux/msm-sps.h>
#include <soc/qcom/service-locator.h>
#include <soc/qcom/service-notifier.h>
#include <soc/qcom/subsystem_notif.h>
#include "slim-msm.h"
#define NGD_SLIM_NAME "ngd_msm_ctrl"
@ -84,7 +87,9 @@ enum ngd_status {
static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf);
static int ngd_slim_runtime_resume(struct device *device);
static int ngd_slim_power_up(struct msm_slim_ctrl *dev, bool mdm_restart);
static void ngd_adsp_down(struct msm_slim_ctrl *dev);
static void ngd_dom_down(struct msm_slim_ctrl *dev);
static int dsp_domr_notify_cb(struct notifier_block *n, unsigned long code,
void *_cmd);
static irqreturn_t ngd_slim_interrupt(int irq, void *d)
{
@ -162,7 +167,7 @@ static int ngd_qmi_available(struct notifier_block *n, unsigned long code,
SLIM_INFO(dev, "Slimbus QMI NGD CB received event:%ld\n", code);
switch (code) {
case QMI_SERVER_ARRIVE:
schedule_work(&qmi->ssr_up);
schedule_work(&dev->dsp.dom_up);
break;
default:
break;
@ -170,31 +175,97 @@ static int ngd_qmi_available(struct notifier_block *n, unsigned long code,
return 0;
}
static int dsp_ssr_notify_cb(struct notifier_block *n, unsigned long code,
static void ngd_reg_ssr(struct msm_slim_ctrl *dev)
{
int ret;
const char *subsys_name = NULL;
dev->dsp.dom_t = MSM_SLIM_DOM_NONE;
ret = of_property_read_string(dev->dev->of_node,
"qcom,subsys-name", &subsys_name);
if (ret)
subsys_name = "adsp";
dev->dsp.nb.notifier_call = dsp_domr_notify_cb;
dev->dsp.domr = subsys_notif_register_notifier(subsys_name,
&dev->dsp.nb);
if (IS_ERR_OR_NULL(dev->dsp.domr)) {
dev_err(dev->dev,
"subsys_notif_register_notifier failed %ld",
PTR_ERR(dev->dsp.domr));
return;
}
dev->dsp.dom_t = MSM_SLIM_DOM_SS;
SLIM_INFO(dev, "reg-SSR with:%s, PDR not available\n",
subsys_name);
}
static int dsp_domr_notify_cb(struct notifier_block *n, unsigned long code,
void *_cmd)
{
int cur = -1;
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);
struct pd_qmi_client_data *reg;
SLIM_INFO(dev, "SLIM DSP SSR/PDR notify cb:0x%lx, type:%d\n",
code, dsp->dom_t);
switch (code) {
case SUBSYS_BEFORE_SHUTDOWN:
SLIM_INFO(dev, "SLIM DSP SSR notify cb:%lu\n", code);
case SERVREG_NOTIF_SERVICE_STATE_DOWN_V01:
/* 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;
msm_slim_sps_exit(dev, false);
ngd_adsp_down(dev);
ngd_dom_down(dev);
mutex_unlock(&dev->tx_lock);
break;
case LOCATOR_UP:
reg = _cmd;
dev->dsp.domr = service_notif_register_notifier(
reg->domain_list->name,
reg->domain_list->instance_id,
&dev->dsp.nb,
&cur);
SLIM_INFO(dev, "reg-PD client:%s with service:%s\n",
reg->client_name, reg->service_name);
SLIM_INFO(dev, "reg-PD dom:%s instance:%d, cur:%d\n",
reg->domain_list->name,
reg->domain_list->instance_id, cur);
if (IS_ERR_OR_NULL(dev->dsp.domr))
ngd_reg_ssr(dev);
else
dev->dsp.dom_t = MSM_SLIM_DOM_PD;
break;
case LOCATOR_DOWN:
ngd_reg_ssr(dev);
default:
break;
}
return NOTIFY_DONE;
}
static void ngd_dom_init(struct msm_slim_ctrl *dev)
{
struct pd_qmi_client_data reg;
int ret;
memset(&reg, 0, sizeof(struct pd_qmi_client_data));
dev->dsp.nb.priority = 4;
dev->dsp.nb.notifier_call = dsp_domr_notify_cb;
scnprintf(reg.client_name, QMI_SERVREG_LOC_NAME_LENGTH_V01, "appsngd%d",
dev->ctrl.nr);
scnprintf(reg.service_name, QMI_SERVREG_LOC_NAME_LENGTH_V01,
"avs/audio");
ret = get_service_location(reg.client_name, reg.service_name,
&dev->dsp.nb);
if (ret)
ngd_reg_ssr(dev);
}
static int mdm_ssr_notify_cb(struct notifier_block *n, unsigned long code,
void *_cmd)
{
@ -1492,6 +1563,7 @@ static int ngd_notify_slaves(void *data)
* controller is up
*/
slim_ctrl_add_boarddevs(&dev->ctrl);
ngd_dom_init(dev);
} else {
slim_framer_booted(ctrl);
}
@ -1516,7 +1588,7 @@ static int ngd_notify_slaves(void *data)
return 0;
}
static void ngd_adsp_down(struct msm_slim_ctrl *dev)
static void ngd_dom_down(struct msm_slim_ctrl *dev)
{
struct slim_controller *ctrl = &dev->ctrl;
struct slim_device *sbdev;
@ -1530,12 +1602,12 @@ static void ngd_adsp_down(struct msm_slim_ctrl *dev)
mutex_unlock(&dev->ssr_lock);
}
static void ngd_adsp_up(struct work_struct *work)
static void ngd_dom_up(struct work_struct *work)
{
struct msm_slim_qmi *qmi =
container_of(work, struct msm_slim_qmi, ssr_up);
struct msm_slim_ss *dsp =
container_of(work, struct msm_slim_ss, dom_up);
struct msm_slim_ctrl *dev =
container_of(qmi, struct msm_slim_ctrl, qmi);
container_of(dsp, struct msm_slim_ctrl, dsp);
mutex_lock(&dev->ssr_lock);
ngd_slim_enable(dev, true);
mutex_unlock(&dev->ssr_lock);
@ -1572,7 +1644,7 @@ static int ngd_slim_probe(struct platform_device *pdev)
struct resource *irq, *bam_irq;
bool rxreg_access = false;
bool slim_mdm = false;
const char *ext_modem_id = NULL, *subsys_name = NULL;
const char *ext_modem_id = NULL;
slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"slimbus_physical");
@ -1756,33 +1828,17 @@ static int ngd_slim_probe(struct platform_device *pdev)
pm_runtime_set_suspended(dev->dev);
pm_runtime_enable(dev->dev);
dev->dsp.nb.priority = 4;
ret = of_property_read_string(pdev->dev.of_node,
"qcom,subsys-name", &subsys_name);
if (ret) {
dev->dsp.nb.notifier_call = dsp_ssr_notify_cb;
dev->dsp.ssr = subsys_notif_register_notifier("adsp",
&dev->dsp.nb);
} else {
dev->dsp.nb.notifier_call = dsp_ssr_notify_cb;
dev->dsp.ssr = subsys_notif_register_notifier(subsys_name,
&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->ext_mdm.nb.notifier_call = mdm_ssr_notify_cb;
dev->ext_mdm.ssr = subsys_notif_register_notifier(ext_modem_id,
dev->ext_mdm.domr = subsys_notif_register_notifier(ext_modem_id,
&dev->ext_mdm.nb);
if (IS_ERR_OR_NULL(dev->ext_mdm.ssr))
if (IS_ERR_OR_NULL(dev->ext_mdm.domr))
dev_err(dev->dev,
"subsys_notif_register_notifier failed %p",
dev->ext_mdm.ssr);
dev->ext_mdm.domr);
}
INIT_WORK(&dev->qmi.ssr_up, ngd_adsp_up);
INIT_WORK(&dev->dsp.dom_up, ngd_dom_up);
dev->qmi.nb.notifier_call = ngd_qmi_available;
pm_runtime_get_noresume(dev->dev);
@ -1837,11 +1893,14 @@ static int ngd_slim_remove(struct platform_device *pdev)
SLIMBUS_QMI_SVC_V1,
SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
pm_runtime_disable(&pdev->dev);
if (!IS_ERR_OR_NULL(dev->dsp.ssr))
subsys_notif_unregister_notifier(dev->dsp.ssr,
if (dev->dsp.dom_t == MSM_SLIM_DOM_SS)
subsys_notif_unregister_notifier(dev->dsp.domr,
&dev->dsp.nb);
if (!IS_ERR_OR_NULL(dev->ext_mdm.ssr))
subsys_notif_unregister_notifier(dev->ext_mdm.ssr,
if (dev->dsp.dom_t == MSM_SLIM_DOM_PD)
service_notif_unregister_notifier(dev->dsp.domr,
&dev->dsp.nb);
if (!IS_ERR_OR_NULL(dev->ext_mdm.domr))
subsys_notif_unregister_notifier(dev->ext_mdm.domr,
&dev->ext_mdm.nb);
kfree(dev->bulk.base);
free_irq(dev->irq, dev);

View file

@ -16,7 +16,6 @@
#include <linux/irq.h>
#include <linux/kthread.h>
#include <soc/qcom/msm_qmi_interface.h>
#include <soc/qcom/subsystem_notif.h>
#include <linux/ipc_logging.h>
/* Per spec.max 40 bytes per received message */
@ -229,14 +228,20 @@ struct msm_slim_qmi {
struct kthread_worker kworker;
struct completion qmi_comp;
struct notifier_block nb;
struct work_struct ssr_down;
struct work_struct ssr_up;
};
enum msm_slim_dom {
MSM_SLIM_DOM_NONE,
MSM_SLIM_DOM_PD,
MSM_SLIM_DOM_SS,
};
struct msm_slim_ss {
struct notifier_block nb;
void *ssr;
void *domr;
enum msm_ctrl_state state;
struct work_struct dom_up;
enum msm_slim_dom dom_t;
};
struct msm_slim_pdata {

View file

@ -53,7 +53,7 @@ static void *service_notif_register_notifier(const char *service_path,
int instance_id, struct notifier_block *nb,
int *curr_state)
{
return PTR_ERR(-ENODEV);
return ERR_PTR(-ENODEV);
}
static int service_notif_unregister_notifier(void *service_notif_handle,