linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 1/2] slimbus: qcom-ngd-ctrl: add Sub System Restart support
@ 2021-07-20  4:30 Yassine Oudjana
  0 siblings, 0 replies; 2+ messages in thread
From: Yassine Oudjana @ 2021-07-20  4:30 UTC (permalink / raw)
  To: srinivas.kandagatla, srini
  Cc: bjorn.andersson, alsa-devel, linux-kernel, sidgup

In-Reply-To: <20201118170246.16588-2-srinivas.kandagatla@linaro.org>

On Wed, 18 Nov 2020 17:02:45 +0000, Srinivas Kandagatla wrote:
> This patch adds SSR(SubSystem Restart) support which includes, synchronisation
> between SSR and QMI server notifications. Also with this patch now NGD is taken
> down by SSR instead of QMI server down notification.
>
> NGD up path now relies on both SSR and QMI notifications and particularly
> sequence of SSR up followed by QMI server up notification.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> ---
>  drivers/slimbus/Kconfig         |  1 +
>  drivers/slimbus/qcom-ngd-ctrl.c | 97 +++++++++++++++++++++++++++++++--
>  2 files changed, 94 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/slimbus/Kconfig b/drivers/slimbus/Kconfig
> index 8cd595148d17..7c950948a9ec 100644
> --- a/drivers/slimbus/Kconfig
> +++ b/drivers/slimbus/Kconfig
> @@ -25,6 +25,7 @@ config SLIM_QCOM_NGD_CTRL
>  	depends on HAS_IOMEM && DMA_ENGINE && NET
>  	depends on ARCH_QCOM || COMPILE_TEST
>  	select QCOM_QMI_HELPERS
> +	select QCOM_RPROC_COMMON
>  	help
>  	  Select driver if Qualcomm's SLIMbus Satellite Non-Generic Device
>  	  Component is programmed using Linux kernel.
> diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
> index 218aefc3531c..f62693653d2b 100644
> --- a/drivers/slimbus/qcom-ngd-ctrl.c
> +++ b/drivers/slimbus/qcom-ngd-ctrl.c
> @@ -13,6 +13,9 @@
>  #include <linux/slimbus.h>
>  #include <linux/delay.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/mutex.h>
> +#include <linux/notifier.h>
> +#include <linux/remoteproc/qcom_rproc.h>
>  #include <linux/of.h>
>  #include <linux/io.h>
>  #include <linux/soc/qcom/qmi.h>
> @@ -155,8 +158,14 @@ struct qcom_slim_ngd_ctrl {
>  	struct qcom_slim_ngd_dma_desc txdesc[QCOM_SLIM_NGD_DESC_NUM];
>  	struct completion reconf;
>  	struct work_struct m_work;
> +	struct work_struct ngd_up_work;
>  	struct workqueue_struct *mwq;
> +	struct completion qmi_up;
>  	spinlock_t tx_buf_lock;
> +	struct mutex tx_lock;
> +	struct mutex ssr_lock;
> +	struct notifier_block nb;
> +	void *notifier;
>  	enum qcom_slim_ngd_state state;
>  	dma_addr_t rx_phys_base;
>  	dma_addr_t tx_phys_base;
> @@ -868,14 +877,18 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
>  	if (txn->msg && txn->msg->wbuf)
>  		memcpy(puc, txn->msg->wbuf, txn->msg->num_bytes);
>
> +	mutex_lock(&ctrl->tx_lock);
>  	ret = qcom_slim_ngd_tx_msg_post(ctrl, pbuf, txn->rl);
> -	if (ret)
> +	if (ret) {
> +		mutex_unlock(&ctrl->tx_lock);
>  		return ret;
> +	}
>
>  	timeout = wait_for_completion_timeout(&tx_sent, HZ);
>  	if (!timeout) {
>  		dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
>  					txn->mt);
> +		mutex_unlock(&ctrl->tx_lock);
>  		return -ETIMEDOUT;
>  	}
>
> @@ -884,10 +897,12 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
>  		if (!timeout) {
>  			dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x",
>  				txn->mc, txn->mt);
> +			mutex_unlock(&ctrl->tx_lock);
>  			return -ETIMEDOUT;
>  		}
>  	}
>
> +	mutex_unlock(&ctrl->tx_lock);
>  	return 0;
>  }
>
> @@ -1200,6 +1215,13 @@ static void qcom_slim_ngd_master_worker(struct work_struct *work)
>  	}
>  }
>
> +static int qcom_slim_ngd_update_device_status(struct device *dev, void *null)
> +{
> +	slim_report_absent(to_slim_device(dev));
> +
> +	return 0;
> +}
> +
>  static int qcom_slim_ngd_runtime_resume(struct device *dev)
>  {
>  	struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
> @@ -1267,7 +1289,7 @@ static int qcom_slim_ngd_qmi_new_server(struct qmi_handle *hdl,
>  	qmi->svc_info.sq_node = service->node;
>  	qmi->svc_info.sq_port = service->port;
>
> -	qcom_slim_ngd_enable(ctrl, true);
> +	complete(&ctrl->qmi_up);
>
>  	return 0;
>  }
> @@ -1280,10 +1302,9 @@ static void qcom_slim_ngd_qmi_del_server(struct qmi_handle *hdl,
>  	struct qcom_slim_ngd_ctrl *ctrl =
>  		container_of(qmi, struct qcom_slim_ngd_ctrl, qmi);
>
> +	reinit_completion(&ctrl->qmi_up);
>  	qmi->svc_info.sq_node = 0;
>  	qmi->svc_info.sq_port = 0;
> -
> -	qcom_slim_ngd_enable(ctrl, false);
>  }
>
>  static struct qmi_ops qcom_slim_ngd_qmi_svc_event_ops = {
> @@ -1333,6 +1354,64 @@ static const struct of_device_id qcom_slim_ngd_dt_match[] = {
>
>  MODULE_DEVICE_TABLE(of, qcom_slim_ngd_dt_match);
>
> +static void qcom_slim_ngd_down(struct qcom_slim_ngd_ctrl *ctrl)
> +{
> +	mutex_lock(&ctrl->ssr_lock);
> +	device_for_each_child(ctrl->ctrl.dev, NULL,
> +			      qcom_slim_ngd_update_device_status);
> +	qcom_slim_ngd_enable(ctrl, false);
> +	mutex_unlock(&ctrl->ssr_lock);
> +}
> +
> +static void qcom_slim_ngd_up_worker(struct work_struct *work)
> +{
> +	struct qcom_slim_ngd_ctrl *ctrl;
> +
> +	ctrl = container_of(work, struct qcom_slim_ngd_ctrl, ngd_up_work);
> +
> +	/* Make sure qmi service is up before continuing */
> +	wait_for_completion_interruptible(&ctrl->qmi_up);
> +
> +	mutex_lock(&ctrl->ssr_lock);
> +	qcom_slim_ngd_enable(ctrl, true);
> +	mutex_unlock(&ctrl->ssr_lock);
> +}
> +
> +static int qcom_slim_ngd_ssr_pdr_notify(struct qcom_slim_ngd_ctrl *ctrl,
> +					unsigned long action)
> +{
> +	switch (action) {
> +        case QCOM_SSR_BEFORE_SHUTDOWN:
> +		/* Make sure the last dma xfer is finished */
> +		mutex_lock(&ctrl->tx_lock);
> +		if (ctrl->state != QCOM_SLIM_NGD_CTRL_DOWN) {
> +			pm_runtime_get_noresume(ctrl->dev);
> +			ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
> +			qcom_slim_ngd_down(ctrl);
> +			qcom_slim_ngd_exit_dma(ctrl);
> +		}
> +		mutex_unlock(&ctrl->tx_lock);
> +                break;
> +        case QCOM_SSR_AFTER_POWERUP:
> +		schedule_work(&ctrl->ngd_up_work);
> +		break;
> +        default:
> +                break;
> +        }
> +
> +        return NOTIFY_OK;
> +}
> +
> +static int qcom_slim_ngd_ssr_notify(struct notifier_block *nb,
> +				    unsigned long action,
> +				    void *data)
> +{
> +	struct qcom_slim_ngd_ctrl *ctrl = container_of(nb,
> +					       struct qcom_slim_ngd_ctrl, nb);
> +
> +	return qcom_slim_ngd_ssr_pdr_notify(ctrl, action);
> +}
> +
>  static int of_qcom_slim_ngd_register(struct device *parent,
>  				     struct qcom_slim_ngd_ctrl *ctrl)
>  {
> @@ -1397,6 +1476,7 @@ static int qcom_slim_ngd_probe(struct platform_device *pdev)
>  	}
>
>  	INIT_WORK(&ctrl->m_work, qcom_slim_ngd_master_worker);
> +	INIT_WORK(&ctrl->ngd_up_work, qcom_slim_ngd_up_worker);
>  	ctrl->mwq = create_singlethread_workqueue("ngd_master");
>  	if (!ctrl->mwq) {
>  		dev_err(&pdev->dev, "Failed to start master worker\n");
> @@ -1444,6 +1524,11 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>
> +	ctrl->nb.notifier_call = qcom_slim_ngd_ssr_notify;
> +	ctrl->notifier = qcom_register_ssr_notifier("lpass", &ctrl->nb);
> +	if (IS_ERR(ctrl->notifier))
> +		return PTR_ERR(ctrl->notifier);
> +
>  	ctrl->dev = dev;
>  	ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
>  	ctrl->framer.superfreq =
> @@ -1457,9 +1542,12 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
>  	ctrl->ctrl.wakeup = NULL;
>  	ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
>
> +	mutex_init(&ctrl->tx_lock);
> +	mutex_init(&ctrl->ssr_lock);
>  	spin_lock_init(&ctrl->tx_buf_lock);
>  	init_completion(&ctrl->reconf);
>  	init_completion(&ctrl->qmi.qmi_comp);
> +	init_completion(&ctrl->qmi_up);
>
>  	platform_driver_register(&qcom_slim_ngd_driver);
>  	return of_qcom_slim_ngd_register(dev, ctrl);
> @@ -1477,6 +1565,7 @@ static int qcom_slim_ngd_remove(struct platform_device *pdev)
>  	struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
>
>  	pm_runtime_disable(&pdev->dev);
> +	qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
>  	qcom_slim_ngd_enable(ctrl, false);
>  	qcom_slim_ngd_exit_dma(ctrl);
>  	qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
> --
> 2.21.0

This makes NGD never come up if probed after ADSP is powered on since it registers its SSR notifier
after ADSP sent its after powerup notification.

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH 1/2] slimbus: qcom-ngd-ctrl: add Sub System Restart support
  2020-11-18 17:02 [PATCH 0/2] slimbus: qcom-ngd: Add SSR and PDR support Srinivas Kandagatla
@ 2020-11-18 17:02 ` Srinivas Kandagatla
  0 siblings, 0 replies; 2+ messages in thread
From: Srinivas Kandagatla @ 2020-11-18 17:02 UTC (permalink / raw)
  To: srinivas.kandagatla, srini
  Cc: bjorn.andersson, alsa-devel, linux-kernel, linux-arm-msm

This patch adds SSR(SubSystem Restart) support which includes, synchronisation
between SSR and QMI server notifications. Also with this patch now NGD is taken
down by SSR instead of QMI server down notification.

NGD up path now relies on both SSR and QMI notifications and particularly
sequence of SSR up followed by QMI server up notification.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/slimbus/Kconfig         |  1 +
 drivers/slimbus/qcom-ngd-ctrl.c | 97 +++++++++++++++++++++++++++++++--
 2 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/drivers/slimbus/Kconfig b/drivers/slimbus/Kconfig
index 8cd595148d17..7c950948a9ec 100644
--- a/drivers/slimbus/Kconfig
+++ b/drivers/slimbus/Kconfig
@@ -25,6 +25,7 @@ config SLIM_QCOM_NGD_CTRL
 	depends on HAS_IOMEM && DMA_ENGINE && NET
 	depends on ARCH_QCOM || COMPILE_TEST
 	select QCOM_QMI_HELPERS
+	select QCOM_RPROC_COMMON
 	help
 	  Select driver if Qualcomm's SLIMbus Satellite Non-Generic Device
 	  Component is programmed using Linux kernel.
diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
index 218aefc3531c..f62693653d2b 100644
--- a/drivers/slimbus/qcom-ngd-ctrl.c
+++ b/drivers/slimbus/qcom-ngd-ctrl.c
@@ -13,6 +13,9 @@
 #include <linux/slimbus.h>
 #include <linux/delay.h>
 #include <linux/pm_runtime.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/remoteproc/qcom_rproc.h>
 #include <linux/of.h>
 #include <linux/io.h>
 #include <linux/soc/qcom/qmi.h>
@@ -155,8 +158,14 @@ struct qcom_slim_ngd_ctrl {
 	struct qcom_slim_ngd_dma_desc txdesc[QCOM_SLIM_NGD_DESC_NUM];
 	struct completion reconf;
 	struct work_struct m_work;
+	struct work_struct ngd_up_work;
 	struct workqueue_struct *mwq;
+	struct completion qmi_up;
 	spinlock_t tx_buf_lock;
+	struct mutex tx_lock;
+	struct mutex ssr_lock;
+	struct notifier_block nb;
+	void *notifier;
 	enum qcom_slim_ngd_state state;
 	dma_addr_t rx_phys_base;
 	dma_addr_t tx_phys_base;
@@ -868,14 +877,18 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
 	if (txn->msg && txn->msg->wbuf)
 		memcpy(puc, txn->msg->wbuf, txn->msg->num_bytes);
 
+	mutex_lock(&ctrl->tx_lock);
 	ret = qcom_slim_ngd_tx_msg_post(ctrl, pbuf, txn->rl);
-	if (ret)
+	if (ret) {
+		mutex_unlock(&ctrl->tx_lock);
 		return ret;
+	}
 
 	timeout = wait_for_completion_timeout(&tx_sent, HZ);
 	if (!timeout) {
 		dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
 					txn->mt);
+		mutex_unlock(&ctrl->tx_lock);
 		return -ETIMEDOUT;
 	}
 
@@ -884,10 +897,12 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
 		if (!timeout) {
 			dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x",
 				txn->mc, txn->mt);
+			mutex_unlock(&ctrl->tx_lock);
 			return -ETIMEDOUT;
 		}
 	}
 
+	mutex_unlock(&ctrl->tx_lock);
 	return 0;
 }
 
@@ -1200,6 +1215,13 @@ static void qcom_slim_ngd_master_worker(struct work_struct *work)
 	}
 }
 
+static int qcom_slim_ngd_update_device_status(struct device *dev, void *null)
+{
+	slim_report_absent(to_slim_device(dev));
+
+	return 0;
+}
+
 static int qcom_slim_ngd_runtime_resume(struct device *dev)
 {
 	struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
@@ -1267,7 +1289,7 @@ static int qcom_slim_ngd_qmi_new_server(struct qmi_handle *hdl,
 	qmi->svc_info.sq_node = service->node;
 	qmi->svc_info.sq_port = service->port;
 
-	qcom_slim_ngd_enable(ctrl, true);
+	complete(&ctrl->qmi_up);
 
 	return 0;
 }
@@ -1280,10 +1302,9 @@ static void qcom_slim_ngd_qmi_del_server(struct qmi_handle *hdl,
 	struct qcom_slim_ngd_ctrl *ctrl =
 		container_of(qmi, struct qcom_slim_ngd_ctrl, qmi);
 
+	reinit_completion(&ctrl->qmi_up);
 	qmi->svc_info.sq_node = 0;
 	qmi->svc_info.sq_port = 0;
-
-	qcom_slim_ngd_enable(ctrl, false);
 }
 
 static struct qmi_ops qcom_slim_ngd_qmi_svc_event_ops = {
@@ -1333,6 +1354,64 @@ static const struct of_device_id qcom_slim_ngd_dt_match[] = {
 
 MODULE_DEVICE_TABLE(of, qcom_slim_ngd_dt_match);
 
+static void qcom_slim_ngd_down(struct qcom_slim_ngd_ctrl *ctrl)
+{
+	mutex_lock(&ctrl->ssr_lock);
+	device_for_each_child(ctrl->ctrl.dev, NULL,
+			      qcom_slim_ngd_update_device_status);
+	qcom_slim_ngd_enable(ctrl, false);
+	mutex_unlock(&ctrl->ssr_lock);
+}
+
+static void qcom_slim_ngd_up_worker(struct work_struct *work)
+{
+	struct qcom_slim_ngd_ctrl *ctrl;
+
+	ctrl = container_of(work, struct qcom_slim_ngd_ctrl, ngd_up_work);
+
+	/* Make sure qmi service is up before continuing */
+	wait_for_completion_interruptible(&ctrl->qmi_up);
+
+	mutex_lock(&ctrl->ssr_lock);
+	qcom_slim_ngd_enable(ctrl, true);
+	mutex_unlock(&ctrl->ssr_lock);
+}
+
+static int qcom_slim_ngd_ssr_pdr_notify(struct qcom_slim_ngd_ctrl *ctrl,
+					unsigned long action)
+{
+	switch (action) {
+        case QCOM_SSR_BEFORE_SHUTDOWN:
+		/* Make sure the last dma xfer is finished */
+		mutex_lock(&ctrl->tx_lock);
+		if (ctrl->state != QCOM_SLIM_NGD_CTRL_DOWN) {
+			pm_runtime_get_noresume(ctrl->dev);
+			ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
+			qcom_slim_ngd_down(ctrl);
+			qcom_slim_ngd_exit_dma(ctrl);
+		}
+		mutex_unlock(&ctrl->tx_lock);
+                break;
+        case QCOM_SSR_AFTER_POWERUP:
+		schedule_work(&ctrl->ngd_up_work);
+		break;
+        default:
+                break;
+        }
+
+        return NOTIFY_OK;
+}
+
+static int qcom_slim_ngd_ssr_notify(struct notifier_block *nb,
+				    unsigned long action,
+				    void *data)
+{
+	struct qcom_slim_ngd_ctrl *ctrl = container_of(nb,
+					       struct qcom_slim_ngd_ctrl, nb);
+
+	return qcom_slim_ngd_ssr_pdr_notify(ctrl, action);
+}
+
 static int of_qcom_slim_ngd_register(struct device *parent,
 				     struct qcom_slim_ngd_ctrl *ctrl)
 {
@@ -1397,6 +1476,7 @@ static int qcom_slim_ngd_probe(struct platform_device *pdev)
 	}
 
 	INIT_WORK(&ctrl->m_work, qcom_slim_ngd_master_worker);
+	INIT_WORK(&ctrl->ngd_up_work, qcom_slim_ngd_up_worker);
 	ctrl->mwq = create_singlethread_workqueue("ngd_master");
 	if (!ctrl->mwq) {
 		dev_err(&pdev->dev, "Failed to start master worker\n");
@@ -1444,6 +1524,11 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	ctrl->nb.notifier_call = qcom_slim_ngd_ssr_notify;
+	ctrl->notifier = qcom_register_ssr_notifier("lpass", &ctrl->nb);
+	if (IS_ERR(ctrl->notifier))
+		return PTR_ERR(ctrl->notifier);
+
 	ctrl->dev = dev;
 	ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
 	ctrl->framer.superfreq =
@@ -1457,9 +1542,12 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
 	ctrl->ctrl.wakeup = NULL;
 	ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
 
+	mutex_init(&ctrl->tx_lock);
+	mutex_init(&ctrl->ssr_lock);
 	spin_lock_init(&ctrl->tx_buf_lock);
 	init_completion(&ctrl->reconf);
 	init_completion(&ctrl->qmi.qmi_comp);
+	init_completion(&ctrl->qmi_up);
 
 	platform_driver_register(&qcom_slim_ngd_driver);
 	return of_qcom_slim_ngd_register(dev, ctrl);
@@ -1477,6 +1565,7 @@ static int qcom_slim_ngd_remove(struct platform_device *pdev)
 	struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
 
 	pm_runtime_disable(&pdev->dev);
+	qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
 	qcom_slim_ngd_enable(ctrl, false);
 	qcom_slim_ngd_exit_dma(ctrl);
 	qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-07-20  4:32 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-20  4:30 [PATCH 1/2] slimbus: qcom-ngd-ctrl: add Sub System Restart support Yassine Oudjana
  -- strict thread matches above, loose matches on Subject: below --
2020-11-18 17:02 [PATCH 0/2] slimbus: qcom-ngd: Add SSR and PDR support Srinivas Kandagatla
2020-11-18 17:02 ` [PATCH 1/2] slimbus: qcom-ngd-ctrl: add Sub System Restart support Srinivas Kandagatla

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).