All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: Sibi Sankar <sibis@codeaurora.org>
Cc: srinivas.kandagatla@linaro.org, robh+dt@kernel.org,
	agross@kernel.org, mark.rutland@arm.com,
	linux-arm-msm@vger.kernel.org, linux-remoteproc@vger.kernel.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	tsoni@codeaurora.org, vnkgutta@codeaurora.org
Subject: Re: [PATCH v4 3/3] soc: qcom: apr: Add avs/audio tracking functionality
Date: Thu, 27 Feb 2020 21:38:32 -0800	[thread overview]
Message-ID: <20200228053832.GE210720@yoga> (raw)
In-Reply-To: <20200226170001.24234-4-sibis@codeaurora.org>

On Wed 26 Feb 09:00 PST 2020, Sibi Sankar wrote:

> Use PDR helper functions to track the protection domains that the apr
> services are dependent upon on SDM845 SoC, specifically the "avs/audio"
> service running on ADSP Q6.
> 
> Signed-off-by: Sibi Sankar <sibis@codeaurora.org>

Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>

> ---

Please do include a changelog as you respin your patches.

Regards,
Bjorn

>  drivers/soc/qcom/Kconfig     |   1 +
>  drivers/soc/qcom/apr.c       | 123 ++++++++++++++++++++++++++++++++---
>  include/linux/soc/qcom/apr.h |   1 +
>  3 files changed, 116 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> index cca6a43e771d9..57000f1615ada 100644
> --- a/drivers/soc/qcom/Kconfig
> +++ b/drivers/soc/qcom/Kconfig
> @@ -202,6 +202,7 @@ config QCOM_APR
>  	tristate "Qualcomm APR Bus (Asynchronous Packet Router)"
>  	depends on ARCH_QCOM || COMPILE_TEST
>  	depends on RPMSG
> +	select QCOM_PDR_HELPERS
>  	help
>  	  Enable APR IPC protocol support between
>  	  application processor and QDSP6. APR is
> diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c
> index 4fcc32420c474..1f35b097c6356 100644
> --- a/drivers/soc/qcom/apr.c
> +++ b/drivers/soc/qcom/apr.c
> @@ -11,6 +11,7 @@
>  #include <linux/workqueue.h>
>  #include <linux/of_device.h>
>  #include <linux/soc/qcom/apr.h>
> +#include <linux/soc/qcom/pdr.h>
>  #include <linux/rpmsg.h>
>  #include <linux/of.h>
>  
> @@ -21,6 +22,7 @@ struct apr {
>  	spinlock_t rx_lock;
>  	struct idr svcs_idr;
>  	int dest_domain_id;
> +	struct pdr_handle *pdr;
>  	struct workqueue_struct *rxwq;
>  	struct work_struct rx_work;
>  	struct list_head rx_list;
> @@ -289,6 +291,9 @@ static int apr_add_device(struct device *dev, struct device_node *np,
>  		  id->svc_id + 1, GFP_ATOMIC);
>  	spin_unlock(&apr->svcs_lock);
>  
> +	of_property_read_string_index(np, "qcom,protection-domain",
> +				      1, &adev->service_path);
> +
>  	dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev));
>  
>  	ret = device_register(&adev->dev);
> @@ -300,14 +305,75 @@ static int apr_add_device(struct device *dev, struct device_node *np,
>  	return ret;
>  }
>  
> -static void of_register_apr_devices(struct device *dev)
> +static int of_apr_add_pd_lookups(struct device *dev)
> +{
> +	const char *service_name, *service_path;
> +	struct apr *apr = dev_get_drvdata(dev);
> +	struct device_node *node;
> +	struct pdr_service *pds;
> +	int ret;
> +
> +	for_each_child_of_node(dev->of_node, node) {
> +		ret = of_property_read_string_index(node, "qcom,protection-domain",
> +						    0, &service_name);
> +		if (ret < 0)
> +			continue;
> +
> +		ret = of_property_read_string_index(node, "qcom,protection-domain",
> +						    1, &service_path);
> +		if (ret < 0) {
> +			dev_err(dev, "pdr service path missing: %d\n", ret);
> +			return ret;
> +		}
> +
> +		pds = pdr_add_lookup(apr->pdr, service_name, service_path);
> +		if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
> +			dev_err(dev, "pdr add lookup failed: %d\n", ret);
> +			return PTR_ERR(pds);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static void of_register_apr_devices(struct device *dev, const char *svc_path)
>  {
>  	struct apr *apr = dev_get_drvdata(dev);
>  	struct device_node *node;
> +	const char *service_path;
> +	int ret;
>  
>  	for_each_child_of_node(dev->of_node, node) {
>  		struct apr_device_id id = { {0} };
>  
> +		/*
> +		 * This function is called with svc_path NULL during
> +		 * apr_probe(), in which case we register any apr devices
> +		 * without a qcom,protection-domain specified.
> +		 *
> +		 * Then as the protection domains becomes available
> +		 * (if applicable) this function is again called, but with
> +		 * svc_path representing the service becoming available. In
> +		 * this case we register any apr devices with a matching
> +		 * qcom,protection-domain.
> +		 */
> +
> +		ret = of_property_read_string_index(node, "qcom,protection-domain",
> +						    1, &service_path);
> +		if (svc_path) {
> +			/* skip APR services that are PD independent */
> +			if (ret)
> +				continue;
> +
> +			/* skip APR services whose PD paths don't match */
> +			if (strcmp(service_path, svc_path))
> +				continue;
> +		} else {
> +			/* skip APR services whose PD lookups are registered */
> +			if (ret == 0)
> +				continue;
> +		}
> +
>  		if (of_property_read_u32(node, "reg", &id.svc_id))
>  			continue;
>  
> @@ -318,6 +384,34 @@ static void of_register_apr_devices(struct device *dev)
>  	}
>  }
>  
> +static int apr_remove_device(struct device *dev, void *svc_path)
> +{
> +	struct apr_device *adev = to_apr_device(dev);
> +
> +	if (svc_path && adev->service_path) {
> +		if (!strcmp(adev->service_path, (char *)svc_path))
> +			device_unregister(&adev->dev);
> +	} else {
> +		device_unregister(&adev->dev);
> +	}
> +
> +	return 0;
> +}
> +
> +static void apr_pd_status(int state, char *svc_path, void *priv)
> +{
> +	struct apr *apr = (struct apr *)priv;
> +
> +	switch (state) {
> +	case SERVREG_SERVICE_STATE_UP:
> +		of_register_apr_devices(apr->dev, svc_path);
> +		break;
> +	case SERVREG_SERVICE_STATE_DOWN:
> +		device_for_each_child(apr->dev, svc_path, apr_remove_device);
> +		break;
> +	}
> +}
> +
>  static int apr_probe(struct rpmsg_device *rpdev)
>  {
>  	struct device *dev = &rpdev->dev;
> @@ -343,28 +437,39 @@ static int apr_probe(struct rpmsg_device *rpdev)
>  		return -ENOMEM;
>  	}
>  	INIT_WORK(&apr->rx_work, apr_rxwq);
> +
> +	apr->pdr = pdr_handle_alloc(apr_pd_status, apr);
> +	if (IS_ERR(apr->pdr)) {
> +		dev_err(dev, "Failed to init PDR handle\n");
> +		ret = PTR_ERR(apr->pdr);
> +		goto destroy_wq;
> +	}
> +
>  	INIT_LIST_HEAD(&apr->rx_list);
>  	spin_lock_init(&apr->rx_lock);
>  	spin_lock_init(&apr->svcs_lock);
>  	idr_init(&apr->svcs_idr);
> -	of_register_apr_devices(dev);
> -
> -	return 0;
> -}
>  
> -static int apr_remove_device(struct device *dev, void *null)
> -{
> -	struct apr_device *adev = to_apr_device(dev);
> +	ret = of_apr_add_pd_lookups(dev);
> +	if (ret)
> +		goto handle_release;
>  
> -	device_unregister(&adev->dev);
> +	of_register_apr_devices(dev, NULL);
>  
>  	return 0;
> +
> +handle_release:
> +	pdr_handle_release(apr->pdr);
> +destroy_wq:
> +	destroy_workqueue(apr->rxwq);
> +	return ret;
>  }
>  
>  static void apr_remove(struct rpmsg_device *rpdev)
>  {
>  	struct apr *apr = dev_get_drvdata(&rpdev->dev);
>  
> +	pdr_handle_release(apr->pdr);
>  	device_for_each_child(&rpdev->dev, NULL, apr_remove_device);
>  	flush_workqueue(apr->rxwq);
>  	destroy_workqueue(apr->rxwq);
> diff --git a/include/linux/soc/qcom/apr.h b/include/linux/soc/qcom/apr.h
> index c5d52e2cb275f..7f0bc3cf4d610 100644
> --- a/include/linux/soc/qcom/apr.h
> +++ b/include/linux/soc/qcom/apr.h
> @@ -85,6 +85,7 @@ struct apr_device {
>  	uint16_t	domain_id;
>  	uint32_t	version;
>  	char name[APR_NAME_SIZE];
> +	const char *service_path;
>  	spinlock_t	lock;
>  	struct list_head node;
>  };
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project

WARNING: multiple messages have this Message-ID (diff)
From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: Sibi Sankar <sibis@codeaurora.org>
Cc: srinivas.kandagatla@linaro.org, robh+dt@kernel.org,
	agross@kernel.org, mark.rutland@arm.com,
	linux-arm-msm@vger.kernel.org, linux-remoteproc@vger.kernel.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	tsoni@codeaurora.org, vnkgutta@codeaurora.org
Subject: Re: [PATCH v4 3/3] soc: qcom: apr: Add avs/audio tracking functionality
Date: Thu, 27 Feb 2020 21:38:36 -0800	[thread overview]
Message-ID: <20200228053832.GE210720@yoga> (raw)
In-Reply-To: <20200226170001.24234-4-sibis@codeaurora.org>

On Wed 26 Feb 09:00 PST 2020, Sibi Sankar wrote:

> Use PDR helper functions to track the protection domains that the apr
> services are dependent upon on SDM845 SoC, specifically the "avs/audio"
> service running on ADSP Q6.
> 
> Signed-off-by: Sibi Sankar <sibis@codeaurora.org>

Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>

> ---

Please do include a changelog as you respin your patches.

Regards,
Bjorn

>  drivers/soc/qcom/Kconfig     |   1 +
>  drivers/soc/qcom/apr.c       | 123 ++++++++++++++++++++++++++++++++---
>  include/linux/soc/qcom/apr.h |   1 +
>  3 files changed, 116 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> index cca6a43e771d9..57000f1615ada 100644
> --- a/drivers/soc/qcom/Kconfig
> +++ b/drivers/soc/qcom/Kconfig
> @@ -202,6 +202,7 @@ config QCOM_APR
>  	tristate "Qualcomm APR Bus (Asynchronous Packet Router)"
>  	depends on ARCH_QCOM || COMPILE_TEST
>  	depends on RPMSG
> +	select QCOM_PDR_HELPERS
>  	help
>  	  Enable APR IPC protocol support between
>  	  application processor and QDSP6. APR is
> diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c
> index 4fcc32420c474..1f35b097c6356 100644
> --- a/drivers/soc/qcom/apr.c
> +++ b/drivers/soc/qcom/apr.c
> @@ -11,6 +11,7 @@
>  #include <linux/workqueue.h>
>  #include <linux/of_device.h>
>  #include <linux/soc/qcom/apr.h>
> +#include <linux/soc/qcom/pdr.h>
>  #include <linux/rpmsg.h>
>  #include <linux/of.h>
>  
> @@ -21,6 +22,7 @@ struct apr {
>  	spinlock_t rx_lock;
>  	struct idr svcs_idr;
>  	int dest_domain_id;
> +	struct pdr_handle *pdr;
>  	struct workqueue_struct *rxwq;
>  	struct work_struct rx_work;
>  	struct list_head rx_list;
> @@ -289,6 +291,9 @@ static int apr_add_device(struct device *dev, struct device_node *np,
>  		  id->svc_id + 1, GFP_ATOMIC);
>  	spin_unlock(&apr->svcs_lock);
>  
> +	of_property_read_string_index(np, "qcom,protection-domain",
> +				      1, &adev->service_path);
> +
>  	dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev));
>  
>  	ret = device_register(&adev->dev);
> @@ -300,14 +305,75 @@ static int apr_add_device(struct device *dev, struct device_node *np,
>  	return ret;
>  }
>  
> -static void of_register_apr_devices(struct device *dev)
> +static int of_apr_add_pd_lookups(struct device *dev)
> +{
> +	const char *service_name, *service_path;
> +	struct apr *apr = dev_get_drvdata(dev);
> +	struct device_node *node;
> +	struct pdr_service *pds;
> +	int ret;
> +
> +	for_each_child_of_node(dev->of_node, node) {
> +		ret = of_property_read_string_index(node, "qcom,protection-domain",
> +						    0, &service_name);
> +		if (ret < 0)
> +			continue;
> +
> +		ret = of_property_read_string_index(node, "qcom,protection-domain",
> +						    1, &service_path);
> +		if (ret < 0) {
> +			dev_err(dev, "pdr service path missing: %d\n", ret);
> +			return ret;
> +		}
> +
> +		pds = pdr_add_lookup(apr->pdr, service_name, service_path);
> +		if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
> +			dev_err(dev, "pdr add lookup failed: %d\n", ret);
> +			return PTR_ERR(pds);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static void of_register_apr_devices(struct device *dev, const char *svc_path)
>  {
>  	struct apr *apr = dev_get_drvdata(dev);
>  	struct device_node *node;
> +	const char *service_path;
> +	int ret;
>  
>  	for_each_child_of_node(dev->of_node, node) {
>  		struct apr_device_id id = { {0} };
>  
> +		/*
> +		 * This function is called with svc_path NULL during
> +		 * apr_probe(), in which case we register any apr devices
> +		 * without a qcom,protection-domain specified.
> +		 *
> +		 * Then as the protection domains becomes available
> +		 * (if applicable) this function is again called, but with
> +		 * svc_path representing the service becoming available. In
> +		 * this case we register any apr devices with a matching
> +		 * qcom,protection-domain.
> +		 */
> +
> +		ret = of_property_read_string_index(node, "qcom,protection-domain",
> +						    1, &service_path);
> +		if (svc_path) {
> +			/* skip APR services that are PD independent */
> +			if (ret)
> +				continue;
> +
> +			/* skip APR services whose PD paths don't match */
> +			if (strcmp(service_path, svc_path))
> +				continue;
> +		} else {
> +			/* skip APR services whose PD lookups are registered */
> +			if (ret == 0)
> +				continue;
> +		}
> +
>  		if (of_property_read_u32(node, "reg", &id.svc_id))
>  			continue;
>  
> @@ -318,6 +384,34 @@ static void of_register_apr_devices(struct device *dev)
>  	}
>  }
>  
> +static int apr_remove_device(struct device *dev, void *svc_path)
> +{
> +	struct apr_device *adev = to_apr_device(dev);
> +
> +	if (svc_path && adev->service_path) {
> +		if (!strcmp(adev->service_path, (char *)svc_path))
> +			device_unregister(&adev->dev);
> +	} else {
> +		device_unregister(&adev->dev);
> +	}
> +
> +	return 0;
> +}
> +
> +static void apr_pd_status(int state, char *svc_path, void *priv)
> +{
> +	struct apr *apr = (struct apr *)priv;
> +
> +	switch (state) {
> +	case SERVREG_SERVICE_STATE_UP:
> +		of_register_apr_devices(apr->dev, svc_path);
> +		break;
> +	case SERVREG_SERVICE_STATE_DOWN:
> +		device_for_each_child(apr->dev, svc_path, apr_remove_device);
> +		break;
> +	}
> +}
> +
>  static int apr_probe(struct rpmsg_device *rpdev)
>  {
>  	struct device *dev = &rpdev->dev;
> @@ -343,28 +437,39 @@ static int apr_probe(struct rpmsg_device *rpdev)
>  		return -ENOMEM;
>  	}
>  	INIT_WORK(&apr->rx_work, apr_rxwq);
> +
> +	apr->pdr = pdr_handle_alloc(apr_pd_status, apr);
> +	if (IS_ERR(apr->pdr)) {
> +		dev_err(dev, "Failed to init PDR handle\n");
> +		ret = PTR_ERR(apr->pdr);
> +		goto destroy_wq;
> +	}
> +
>  	INIT_LIST_HEAD(&apr->rx_list);
>  	spin_lock_init(&apr->rx_lock);
>  	spin_lock_init(&apr->svcs_lock);
>  	idr_init(&apr->svcs_idr);
> -	of_register_apr_devices(dev);
> -
> -	return 0;
> -}
>  
> -static int apr_remove_device(struct device *dev, void *null)
> -{
> -	struct apr_device *adev = to_apr_device(dev);
> +	ret = of_apr_add_pd_lookups(dev);
> +	if (ret)
> +		goto handle_release;
>  
> -	device_unregister(&adev->dev);
> +	of_register_apr_devices(dev, NULL);
>  
>  	return 0;
> +
> +handle_release:
> +	pdr_handle_release(apr->pdr);
> +destroy_wq:
> +	destroy_workqueue(apr->rxwq);
> +	return ret;
>  }
>  
>  static void apr_remove(struct rpmsg_device *rpdev)
>  {
>  	struct apr *apr = dev_get_drvdata(&rpdev->dev);
>  
> +	pdr_handle_release(apr->pdr);
>  	device_for_each_child(&rpdev->dev, NULL, apr_remove_device);
>  	flush_workqueue(apr->rxwq);
>  	destroy_workqueue(apr->rxwq);
> diff --git a/include/linux/soc/qcom/apr.h b/include/linux/soc/qcom/apr.h
> index c5d52e2cb275f..7f0bc3cf4d610 100644
> --- a/include/linux/soc/qcom/apr.h
> +++ b/include/linux/soc/qcom/apr.h
> @@ -85,6 +85,7 @@ struct apr_device {
>  	uint16_t	domain_id;
>  	uint32_t	version;
>  	char name[APR_NAME_SIZE];
> +	const char *service_path;
>  	spinlock_t	lock;
>  	struct list_head node;
>  };
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project

  reply	other threads:[~2020-02-28  5:38 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-26 16:59 [PATCH v4 0/3] Introduce Protection Domain Restart (PDR) Helpers Sibi Sankar
2020-02-26 16:59 ` [PATCH v4 1/3] soc: qcom: Introduce Protection Domain Restart helpers Sibi Sankar
2020-02-28  5:34   ` Bjorn Andersson
2020-02-28  5:34     ` Bjorn Andersson
2020-02-26 17:00 ` [PATCH v4 2/3] dt-bindings: soc: qcom: apr: Add protection domain bindings Sibi Sankar
2020-02-28  5:35   ` Bjorn Andersson
2020-02-28  5:35     ` Bjorn Andersson
2020-02-26 17:00 ` [PATCH v4 3/3] soc: qcom: apr: Add avs/audio tracking functionality Sibi Sankar
2020-02-28  5:38   ` Bjorn Andersson [this message]
2020-02-28  5:38     ` Bjorn Andersson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200228053832.GE210720@yoga \
    --to=bjorn.andersson@linaro.org \
    --cc=agross@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-remoteproc@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=robh+dt@kernel.org \
    --cc=sibis@codeaurora.org \
    --cc=srinivas.kandagatla@linaro.org \
    --cc=tsoni@codeaurora.org \
    --cc=vnkgutta@codeaurora.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.