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/of_slimbus.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/msm-sps.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" #include "slim-msm.h"
#define NGD_SLIM_NAME "ngd_msm_ctrl" #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 void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf);
static int ngd_slim_runtime_resume(struct device *device); static int ngd_slim_runtime_resume(struct device *device);
static int ngd_slim_power_up(struct msm_slim_ctrl *dev, bool mdm_restart); 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) 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); SLIM_INFO(dev, "Slimbus QMI NGD CB received event:%ld\n", code);
switch (code) { switch (code) {
case QMI_SERVER_ARRIVE: case QMI_SERVER_ARRIVE:
schedule_work(&qmi->ssr_up); schedule_work(&dev->dsp.dom_up);
break; break;
default: default:
break; break;
@ -170,31 +175,97 @@ static int ngd_qmi_available(struct notifier_block *n, unsigned long code,
return 0; 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) void *_cmd)
{ {
int cur = -1;
struct msm_slim_ss *dsp = container_of(n, struct msm_slim_ss, nb); 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, struct msm_slim_ctrl *dev = container_of(dsp, struct msm_slim_ctrl,
dsp); 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) { switch (code) {
case SUBSYS_BEFORE_SHUTDOWN: 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 */ /* wait for current transaction */
mutex_lock(&dev->tx_lock); mutex_lock(&dev->tx_lock);
/* make sure autosuspend is not called until ADSP comes up*/ /* make sure autosuspend is not called until ADSP comes up*/
pm_runtime_get_noresume(dev->dev); pm_runtime_get_noresume(dev->dev);
dev->state = MSM_CTRL_DOWN; dev->state = MSM_CTRL_DOWN;
msm_slim_sps_exit(dev, false); msm_slim_sps_exit(dev, false);
ngd_adsp_down(dev); ngd_dom_down(dev);
mutex_unlock(&dev->tx_lock); mutex_unlock(&dev->tx_lock);
break; 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: default:
break; break;
} }
return NOTIFY_DONE; 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, static int mdm_ssr_notify_cb(struct notifier_block *n, unsigned long code,
void *_cmd) void *_cmd)
{ {
@ -1492,6 +1563,7 @@ static int ngd_notify_slaves(void *data)
* controller is up * controller is up
*/ */
slim_ctrl_add_boarddevs(&dev->ctrl); slim_ctrl_add_boarddevs(&dev->ctrl);
ngd_dom_init(dev);
} else { } else {
slim_framer_booted(ctrl); slim_framer_booted(ctrl);
} }
@ -1516,7 +1588,7 @@ static int ngd_notify_slaves(void *data)
return 0; 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_controller *ctrl = &dev->ctrl;
struct slim_device *sbdev; struct slim_device *sbdev;
@ -1530,12 +1602,12 @@ static void ngd_adsp_down(struct msm_slim_ctrl *dev)
mutex_unlock(&dev->ssr_lock); 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 = struct msm_slim_ss *dsp =
container_of(work, struct msm_slim_qmi, ssr_up); container_of(work, struct msm_slim_ss, dom_up);
struct msm_slim_ctrl *dev = 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); mutex_lock(&dev->ssr_lock);
ngd_slim_enable(dev, true); ngd_slim_enable(dev, true);
mutex_unlock(&dev->ssr_lock); mutex_unlock(&dev->ssr_lock);
@ -1572,7 +1644,7 @@ static int ngd_slim_probe(struct platform_device *pdev)
struct resource *irq, *bam_irq; struct resource *irq, *bam_irq;
bool rxreg_access = false; bool rxreg_access = false;
bool slim_mdm = 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, slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"slimbus_physical"); "slimbus_physical");
@ -1756,33 +1828,17 @@ static int ngd_slim_probe(struct platform_device *pdev)
pm_runtime_set_suspended(dev->dev); pm_runtime_set_suspended(dev->dev);
pm_runtime_enable(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) { if (slim_mdm) {
dev->ext_mdm.nb.notifier_call = mdm_ssr_notify_cb; 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); &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, dev_err(dev->dev,
"subsys_notif_register_notifier failed %p", "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; dev->qmi.nb.notifier_call = ngd_qmi_available;
pm_runtime_get_noresume(dev->dev); 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_SVC_V1,
SLIMBUS_QMI_INS_ID, &dev->qmi.nb); SLIMBUS_QMI_INS_ID, &dev->qmi.nb);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
if (!IS_ERR_OR_NULL(dev->dsp.ssr)) if (dev->dsp.dom_t == MSM_SLIM_DOM_SS)
subsys_notif_unregister_notifier(dev->dsp.ssr, subsys_notif_unregister_notifier(dev->dsp.domr,
&dev->dsp.nb); &dev->dsp.nb);
if (!IS_ERR_OR_NULL(dev->ext_mdm.ssr)) if (dev->dsp.dom_t == MSM_SLIM_DOM_PD)
subsys_notif_unregister_notifier(dev->ext_mdm.ssr, 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); &dev->ext_mdm.nb);
kfree(dev->bulk.base); kfree(dev->bulk.base);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);

View file

@ -16,7 +16,6 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <soc/qcom/msm_qmi_interface.h> #include <soc/qcom/msm_qmi_interface.h>
#include <soc/qcom/subsystem_notif.h>
#include <linux/ipc_logging.h> #include <linux/ipc_logging.h>
/* Per spec.max 40 bytes per received message */ /* Per spec.max 40 bytes per received message */
@ -229,14 +228,20 @@ struct msm_slim_qmi {
struct kthread_worker kworker; struct kthread_worker kworker;
struct completion qmi_comp; struct completion qmi_comp;
struct notifier_block nb; 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 msm_slim_ss {
struct notifier_block nb; struct notifier_block nb;
void *ssr; void *domr;
enum msm_ctrl_state state; enum msm_ctrl_state state;
struct work_struct dom_up;
enum msm_slim_dom dom_t;
}; };
struct msm_slim_pdata { 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 instance_id, struct notifier_block *nb,
int *curr_state) int *curr_state)
{ {
return PTR_ERR(-ENODEV); return ERR_PTR(-ENODEV);
} }
static int service_notif_unregister_notifier(void *service_notif_handle, static int service_notif_unregister_notifier(void *service_notif_handle,