From e7761f93acafa00f93ba427c0c4101212ea996c1 Mon Sep 17 00:00:00 2001 From: Prudhvi Yarlagadda Date: Fri, 24 Jan 2020 15:20:41 +0530 Subject: [PATCH 1/2] slim-msm-ngd: Prevent system suspend during initialization Prevent system suspend from happening during slimbus initialization process where the NGD Slimbus component gets enummerated with ADSP slimbus component and then queries the logical addresses of the clients connected. This is to prevent the issue where the slimbus driver goes to suspend due to system suspend after the enumeration phase is done after an SSR/PDR. Driver again resumes for querying logical addresses of clients connected assuming enumeration process is already done whereas it has to be re-enumerated as driver got suspened and resumed. Change-Id: I42ab3f7a6061a1c464d436aa13e43d27eb312fd4 Signed-off-by: Prudhvi Yarlagadda --- drivers/slimbus/slim-msm-ngd.c | 35 +++++++++++++++++++++++++++++++++- drivers/slimbus/slim-msm.h | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c index e6982560dfb8..5ae189bfff80 100644 --- a/drivers/slimbus/slim-msm-ngd.c +++ b/drivers/slimbus/slim-msm-ngd.c @@ -275,6 +275,7 @@ static int dsp_domr_notify_cb(struct notifier_block *n, unsigned long code, SLIM_INFO(dev, "SLIM DSP SSR notify cb:%lu\n", code); /* Hold wake lock until notify slaves thread is done */ pm_stay_awake(dev->dev); + atomic_set(&dev->init_in_progress, 1); if (dev->lpass_mem_usage) { dev->lpass_mem->start = dev->lpass_phy_base; dev->lpass.base = dev->lpass_virt_base; @@ -1570,6 +1571,7 @@ static int ngd_slim_rx_msgq_thread(void *data) struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data; struct completion *notify = &dev->rx_msgq_notify; int ret = 0; + bool release_wake_lock = false; while (!kthread_should_stop()) { struct slim_msg_txn txn; @@ -1607,17 +1609,36 @@ capability_retry: /* ADSP SSR, send device_up notifications */ if (prev_state == MSM_CTRL_DOWN) complete(&dev->qmi.slave_notify); + else + release_wake_lock = true; } else if (ret == -EIO) { SLIM_WARN(dev, "capability message NACKed, retrying\n"); if (retries < INIT_MX_RETRIES) { msleep(DEF_RETRY_MS); retries++; goto capability_retry; + } else { + release_wake_lock = true; } } else { SLIM_WARN(dev, "SLIM: capability TX failed:%d\n", ret); + release_wake_lock = true; + } + + if (release_wake_lock) { + /* + * As we are not going to reset the + * init_in_progress flag and release wake + * lock from notify slave thread, we are + * doing it here. + */ + atomic_set(&dev->init_in_progress, 0); + pm_relax(dev->dev); + release_wake_lock = false; } } + atomic_set(&dev->init_in_progress, 0); + pm_relax(dev->dev); return 0; } @@ -1672,7 +1693,10 @@ static int ngd_notify_slaves(void *data) mutex_lock(&ctrl->m_ctrl); } mutex_unlock(&ctrl->m_ctrl); + atomic_set(&dev->init_in_progress, 0); + pm_relax(dev->dev); } + atomic_set(&dev->init_in_progress, 0); pm_relax(dev->dev); return 0; } @@ -1702,7 +1726,10 @@ static void ngd_dom_up(struct work_struct *work) wait_for_completion_interruptible(&dev->qmi_up); mutex_lock(&dev->ssr_lock); - ngd_slim_enable(dev, true); + if (ngd_slim_enable(dev, true)) { + atomic_set(&dev->init_in_progress, 0); + pm_relax(dev->dev); + } mutex_unlock(&dev->ssr_lock); } @@ -2203,6 +2230,12 @@ static int ngd_slim_suspend(struct device *dev) cdev = platform_get_drvdata(pdev); + if (atomic_read(&cdev->init_in_progress)) { + ret = -EBUSY; + SLIM_INFO(cdev, "system suspend due to ssr: %d\n", ret); + return ret; + } + if (cdev->state == MSM_CTRL_AWAKE) { ret = -EBUSY; SLIM_INFO(cdev, "system suspend: %d\n", ret); diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h index 4c17696b74ed..d8b40e5a23b6 100644 --- a/drivers/slimbus/slim-msm.h +++ b/drivers/slimbus/slim-msm.h @@ -326,6 +326,7 @@ struct msm_slim_ctrl { u32 current_rx_buf[10]; int current_count; atomic_t ssr_in_progress; + atomic_t init_in_progress; struct completion qmi_up; }; From 80269d295fc800bed444000b4ccba455677b9f73 Mon Sep 17 00:00:00 2001 From: Prudhvi Yarlagadda Date: Sat, 8 Feb 2020 16:42:09 +0530 Subject: [PATCH 2/2] slim-msm-ngd: Check current state of sub system restart notifier Check for the current state of sub system restart notifier when the LOCATOR_UP notification is given to slimbus driver and do the slimbus initialization if the current state is already set to SERVREG_NOTIF_SERVICE_STATE_UP_V01. This change is needed in the cases where LOCATOR_UP notification to slimbus driver got delayed and the state of the sub system restart notifier is already set to SERVREG_NOTIF_SERVICE_STATE_UP_V01 as slimbus will be expecting the SERVREG_NOTIF_SERVICE_STATE_UP_V01 notification which is not going to come as the notifier state is already changed. Change-Id: I4804bbb13e065ac78be7a442993286532402db9d Signed-off-by: Prudhvi Yarlagadda --- drivers/slimbus/slim-msm-ngd.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c index 5ae189bfff80..ee9844113f67 100644 --- a/drivers/slimbus/slim-msm-ngd.c +++ b/drivers/slimbus/slim-msm-ngd.c @@ -272,7 +272,7 @@ static int dsp_domr_notify_cb(struct notifier_block *n, unsigned long code, break; case SUBSYS_AFTER_POWERUP: case SERVREG_NOTIF_SERVICE_STATE_UP_V01: - SLIM_INFO(dev, "SLIM DSP SSR notify cb:%lu\n", code); + SLIM_INFO(dev, "SLIM DSP SSR notify cb:0x%x\n", code); /* Hold wake lock until notify slaves thread is done */ pm_stay_awake(dev->dev); atomic_set(&dev->init_in_progress, 1); @@ -302,9 +302,21 @@ static int dsp_domr_notify_cb(struct notifier_block *n, unsigned long code, &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", + SLIM_INFO(dev, "reg-PD dom:%s instance:%d, cur:0x%x\n", reg->domain_list->name, reg->domain_list->instance_id, cur); + + if (cur == SERVREG_NOTIF_SERVICE_STATE_UP_V01) { + pm_stay_awake(dev->dev); + atomic_set(&dev->init_in_progress, 1); + if (dev->lpass_mem_usage) { + dev->lpass_mem->start = dev->lpass_phy_base; + dev->lpass.base = dev->lpass_virt_base; + } + atomic_set(&dev->ssr_in_progress, 0); + schedule_work(&dev->dsp.dom_up); + } + if (IS_ERR_OR_NULL(dev->dsp.domr)) ngd_reg_ssr(dev); else