diff mbox series

[V2,09/11] PM / Domain: Implement of_dev_pm_genpd_opp_to_performance_state()

Message ID c43a0175d71935461dfe25ea763cfd5f163efcf6.1523273291.git.viresh.kumar@linaro.org
State Accepted
Commit 6e41766a6a504b605a105cc5ab8d276ea20052ba
Headers show
Series PM / genpd & OPP: Parse performance state from DT | expand

Commit Message

Viresh Kumar April 9, 2018, 11:43 a.m. UTC
This implements of_dev_pm_genpd_opp_to_performance_state() which can be
used from the device drivers or the OPP core to find the performance
state encoded in the "required-opps" property of a node. Normally this
would be called only once for each OPP of the device for which the OPP
table of the device is getting generated.

Different platforms may encode the performance state differently using
the OPP table (they may simply return value of opp-hz or opp-microvolt,
or apply some algorithm on top of those values) and so a new callback
->opp_to_performance_state() is implemented to allow platform specific
drivers to convert the power domain OPP to a performance state value.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

---
 drivers/base/power/domain.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_domain.h   | 12 ++++++++++++
 2 files changed, 60 insertions(+)

-- 
2.15.0.194.g9af6a3dea062

Comments

Ulf Hansson April 9, 2018, 3:23 p.m. UTC | #1
On 9 April 2018 at 13:43, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> This implements of_dev_pm_genpd_opp_to_performance_state() which can be

> used from the device drivers or the OPP core to find the performance

> state encoded in the "required-opps" property of a node. Normally this

> would be called only once for each OPP of the device for which the OPP

> table of the device is getting generated.

>

> Different platforms may encode the performance state differently using

> the OPP table (they may simply return value of opp-hz or opp-microvolt,

> or apply some algorithm on top of those values) and so a new callback

> ->opp_to_performance_state() is implemented to allow platform specific

> drivers to convert the power domain OPP to a performance state value.

>

> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>


Acked-by: Ulf Hansson <ulf.hansson@linaro.org>


Kind regards
Uffe

> ---

>  drivers/base/power/domain.c | 48 +++++++++++++++++++++++++++++++++++++++++++++

>  include/linux/pm_domain.h   | 12 ++++++++++++

>  2 files changed, 60 insertions(+)

>

> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c

> index 5c0019d70d76..5efdf67220f8 100644

> --- a/drivers/base/power/domain.c

> +++ b/drivers/base/power/domain.c

> @@ -2412,6 +2412,54 @@ int of_genpd_parse_idle_states(struct device_node *dn,

>  }

>  EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);

>

> +/**

> + * of_dev_pm_genpd_opp_to_performance_state- Gets performance state of device's

> + * power domain corresponding to a DT node's "required-opps" property.

> + *

> + * @dev: Device for which the performance-state needs to be found.

> + * @opp_node: DT node where the "required-opps" property is present. This can be

> + *     the device node itself (if it doesn't have an OPP table) or a node

> + *     within the OPP table of a device (if device has an OPP table).

> + * @state: Pointer to return performance state.

> + *

> + * Returns performance state corresponding to the "required-opps" property of

> + * a DT node. This calls platform specific genpd->opp_to_performance_state()

> + * callback to translate power domain OPP to performance state.

> + *

> + * Returns performance state on success and 0 on failure.

> + */

> +unsigned int of_dev_pm_genpd_opp_to_performance_state(struct device *dev,

> +                                               struct device_node *opp_node)

> +{

> +       struct generic_pm_domain *genpd;

> +       struct dev_pm_opp *opp;

> +       int state = 0;

> +

> +       genpd = dev_to_genpd(dev);

> +       if (IS_ERR(genpd))

> +               return 0;

> +

> +       if (unlikely(!genpd->set_performance_state))

> +               return 0;

> +

> +       genpd_lock(genpd);

> +

> +       opp = of_dev_pm_opp_find_required_opp(&genpd->dev, opp_node);

> +       if (IS_ERR(opp)) {

> +               state = PTR_ERR(opp);

> +               goto unlock;

> +       }

> +

> +       state = genpd->opp_to_performance_state(genpd, opp);

> +       dev_pm_opp_put(opp);

> +

> +unlock:

> +       genpd_unlock(genpd);

> +

> +       return state;

> +}

> +EXPORT_SYMBOL_GPL(of_dev_pm_genpd_opp_to_performance_state);

> +

>  #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */

>

>

> diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h

> index aaacaa35005d..fc1b723b03a1 100644

> --- a/include/linux/pm_domain.h

> +++ b/include/linux/pm_domain.h

> @@ -47,6 +47,7 @@ struct genpd_power_state {

>  };

>

>  struct genpd_lock_ops;

> +struct dev_pm_opp;

>

>  struct generic_pm_domain {

>         struct device dev;

> @@ -68,6 +69,8 @@ struct generic_pm_domain {

>         unsigned int performance_state; /* Aggregated max performance state */

>         int (*power_off)(struct generic_pm_domain *domain);

>         int (*power_on)(struct generic_pm_domain *domain);

> +       unsigned int (*opp_to_performance_state)(struct generic_pm_domain *genpd,

> +                                                struct dev_pm_opp *opp);

>         int (*set_performance_state)(struct generic_pm_domain *genpd,

>                                      unsigned int state);

>         struct gpd_dev_ops dev_ops;

> @@ -244,6 +247,8 @@ extern int of_genpd_add_subdomain(struct of_phandle_args *parent,

>  extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);

>  extern int of_genpd_parse_idle_states(struct device_node *dn,

>                         struct genpd_power_state **states, int *n);

> +extern unsigned int of_dev_pm_genpd_opp_to_performance_state(struct device *dev,

> +                               struct device_node *opp_node);

>

>  int genpd_dev_pm_attach(struct device *dev);

>  #else /* !CONFIG_PM_GENERIC_DOMAINS_OF */

> @@ -279,6 +284,13 @@ static inline int of_genpd_parse_idle_states(struct device_node *dn,

>         return -ENODEV;

>  }

>

> +static inline unsigned int

> +of_dev_pm_genpd_opp_to_performance_state(struct device *dev,

> +                                        struct device_node *opp_node)

> +{

> +       return -ENODEV;

> +}

> +

>  static inline int genpd_dev_pm_attach(struct device *dev)

>  {

>         return -ENODEV;

> --

> 2.15.0.194.g9af6a3dea062

>
Ulf Hansson May 7, 2018, 12:10 p.m. UTC | #2
On 9 April 2018 at 17:23, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> On 9 April 2018 at 13:43, Viresh Kumar <viresh.kumar@linaro.org> wrote:

>> This implements of_dev_pm_genpd_opp_to_performance_state() which can be

>> used from the device drivers or the OPP core to find the performance

>> state encoded in the "required-opps" property of a node. Normally this

>> would be called only once for each OPP of the device for which the OPP

>> table of the device is getting generated.

>>

>> Different platforms may encode the performance state differently using

>> the OPP table (they may simply return value of opp-hz or opp-microvolt,

>> or apply some algorithm on top of those values) and so a new callback

>> ->opp_to_performance_state() is implemented to allow platform specific

>> drivers to convert the power domain OPP to a performance state value.

>>

>> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

>

> Acked-by: Ulf Hansson <ulf.hansson@linaro.org>


[...]

>> +unsigned int of_dev_pm_genpd_opp_to_performance_state(struct device *dev,

>> +                                               struct device_node *opp_node)


While working on multiple PM domains support, I decided to use your
series as a base from your opp tree.

Assuming you are preparing a pull-request with this series to Rafael!?

Anyway, my eyes got stuck looking at the very long function name
above, again :-).

To keep names consistent with naming conventions for genpd, would you
mind renaming it to "of_genpd_opp_to_performance_state()"? It's long
enough. :-)

No need to re-send, amending the patch before sending the PR is fine.

[...]

Kind regards
Uffe
Viresh Kumar May 8, 2018, 3:32 a.m. UTC | #3
On 07-05-18, 14:10, Ulf Hansson wrote:
> While working on multiple PM domains support, I decided to use your

> series as a base from your opp tree.

> 

> Assuming you are preparing a pull-request with this series to Rafael!?


I was waiting for Rob to Ack one of the DT patches, it seems I should send the
pull request now.

> Anyway, my eyes got stuck looking at the very long function name

> above, again :-).

> 

> To keep names consistent with naming conventions for genpd, would you

> mind renaming it to "of_genpd_opp_to_performance_state()"? It's long

> enough. :-)

> 

> No need to re-send, amending the patch before sending the PR is fine.


-------------------------8<-------------------------
Subject: [PATCH] PM / Domain: Implement of_genpd_opp_to_performance_state()

This implements of_genpd_opp_to_performance_state() which can be used
from the device drivers or the OPP core to find the performance state
encoded in the "required-opps" property of a node. Normally this would
be called only once for each OPP of the device for which the OPP table
of the device is getting generated.

Different platforms may encode the performance state differently using
the OPP table (they may simply return value of opp-hz or opp-microvolt,
or apply some algorithm on top of those values) and so a new callback
->opp_to_performance_state() is implemented to allow platform specific
drivers to convert the power domain OPP to a performance state value.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

Acked-by: Ulf Hansson <ulf.hansson@linaro.org>

---
 drivers/base/power/domain.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_domain.h   | 12 ++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 5c0019d70d76..29e25dc0584c 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -2412,6 +2412,54 @@ int of_genpd_parse_idle_states(struct device_node *dn,
 }
 EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);
 
+/**
+ * of_genpd_opp_to_performance_state- Gets performance state of device's
+ * power domain corresponding to a DT node's "required-opps" property.
+ *
+ * @dev: Device for which the performance-state needs to be found.
+ * @opp_node: DT node where the "required-opps" property is present. This can be
+ *	the device node itself (if it doesn't have an OPP table) or a node
+ *	within the OPP table of a device (if device has an OPP table).
+ * @state: Pointer to return performance state.
+ *
+ * Returns performance state corresponding to the "required-opps" property of
+ * a DT node. This calls platform specific genpd->opp_to_performance_state()
+ * callback to translate power domain OPP to performance state.
+ *
+ * Returns performance state on success and 0 on failure.
+ */
+unsigned int of_genpd_opp_to_performance_state(struct device *dev,
+					       struct device_node *opp_node)
+{
+	struct generic_pm_domain *genpd;
+	struct dev_pm_opp *opp;
+	int state = 0;
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return 0;
+
+	if (unlikely(!genpd->set_performance_state))
+		return 0;
+
+	genpd_lock(genpd);
+
+	opp = of_dev_pm_opp_find_required_opp(&genpd->dev, opp_node);
+	if (IS_ERR(opp)) {
+		state = PTR_ERR(opp);
+		goto unlock;
+	}
+
+	state = genpd->opp_to_performance_state(genpd, opp);
+	dev_pm_opp_put(opp);
+
+unlock:
+	genpd_unlock(genpd);
+
+	return state;
+}
+EXPORT_SYMBOL_GPL(of_genpd_opp_to_performance_state);
+
 #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
 
 
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index aaacaa35005d..a2fa297e96f7 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -47,6 +47,7 @@ struct genpd_power_state {
 };
 
 struct genpd_lock_ops;
+struct dev_pm_opp;
 
 struct generic_pm_domain {
 	struct device dev;
@@ -68,6 +69,8 @@ struct generic_pm_domain {
 	unsigned int performance_state;	/* Aggregated max performance state */
 	int (*power_off)(struct generic_pm_domain *domain);
 	int (*power_on)(struct generic_pm_domain *domain);
+	unsigned int (*opp_to_performance_state)(struct generic_pm_domain *genpd,
+						 struct dev_pm_opp *opp);
 	int (*set_performance_state)(struct generic_pm_domain *genpd,
 				     unsigned int state);
 	struct gpd_dev_ops dev_ops;
@@ -244,6 +247,8 @@ extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
 extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
 extern int of_genpd_parse_idle_states(struct device_node *dn,
 			struct genpd_power_state **states, int *n);
+extern unsigned int of_genpd_opp_to_performance_state(struct device *dev,
+				struct device_node *opp_node);
 
 int genpd_dev_pm_attach(struct device *dev);
 #else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
@@ -279,6 +284,13 @@ static inline int of_genpd_parse_idle_states(struct device_node *dn,
 	return -ENODEV;
 }
 
+static inline unsigned int
+of_genpd_opp_to_performance_state(struct device *dev,
+				  struct device_node *opp_node)
+{
+	return -ENODEV;
+}
+
 static inline int genpd_dev_pm_attach(struct device *dev)
 {
 	return -ENODEV;
Rajendra Nayak May 22, 2018, 9:28 a.m. UTC | #4
On 04/09/2018 05:13 PM, Viresh Kumar wrote:
> This implements of_dev_pm_genpd_opp_to_performance_state() which can be

> used from the device drivers or the OPP core to find the performance

> state encoded in the "required-opps" property of a node. Normally this

> would be called only once for each OPP of the device for which the OPP

> table of the device is getting generated.

> 

> Different platforms may encode the performance state differently using

> the OPP table (they may simply return value of opp-hz or opp-microvolt,

> or apply some algorithm on top of those values) and so a new callback

> ->opp_to_performance_state() is implemented to allow platform specific

> drivers to convert the power domain OPP to a performance state value.

> 

> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

> ---

>  drivers/base/power/domain.c | 48 +++++++++++++++++++++++++++++++++++++++++++++

>  include/linux/pm_domain.h   | 12 ++++++++++++

>  2 files changed, 60 insertions(+)

> 

> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c

> index 5c0019d70d76..5efdf67220f8 100644

> --- a/drivers/base/power/domain.c

> +++ b/drivers/base/power/domain.c

> @@ -2412,6 +2412,54 @@ int of_genpd_parse_idle_states(struct device_node *dn,

>  }

>  EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);

>  

> +/**

> + * of_dev_pm_genpd_opp_to_performance_state- Gets performance state of device's

> + * power domain corresponding to a DT node's "required-opps" property.

> + *

> + * @dev: Device for which the performance-state needs to be found.

> + * @opp_node: DT node where the "required-opps" property is present. This can be

> + *	the device node itself (if it doesn't have an OPP table) or a node

> + *	within the OPP table of a device (if device has an OPP table).

> + * @state: Pointer to return performance state.

> + *

> + * Returns performance state corresponding to the "required-opps" property of

> + * a DT node. This calls platform specific genpd->opp_to_performance_state()

> + * callback to translate power domain OPP to performance state.

> + *

> + * Returns performance state on success and 0 on failure.


This does not seem to be true, you do return 'state = PTR_ERR(opp);' below.

> + */

> +unsigned int of_dev_pm_genpd_opp_to_performance_state(struct device *dev,

> +						struct device_node *opp_node)

> +{

> +	struct generic_pm_domain *genpd;

> +	struct dev_pm_opp *opp;

> +	int state = 0;

> +

> +	genpd = dev_to_genpd(dev);

> +	if (IS_ERR(genpd))

> +		return 0;

> +

> +	if (unlikely(!genpd->set_performance_state))

> +		return 0;

> +

> +	genpd_lock(genpd);

> +

> +	opp = of_dev_pm_opp_find_required_opp(&genpd->dev, opp_node);

> +	if (IS_ERR(opp)) {

> +		state = PTR_ERR(opp);

> +		goto unlock;

> +	}

> +

> +	state = genpd->opp_to_performance_state(genpd, opp);

> +	dev_pm_opp_put(opp);

> +

> +unlock:

> +	genpd_unlock(genpd);

> +

> +	return state;

> +}

> +EXPORT_SYMBOL_GPL(of_dev_pm_genpd_opp_to_performance_state);

> +

>  #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */

>  

>  

> diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h

> index aaacaa35005d..fc1b723b03a1 100644

> --- a/include/linux/pm_domain.h

> +++ b/include/linux/pm_domain.h

> @@ -47,6 +47,7 @@ struct genpd_power_state {

>  };

>  

>  struct genpd_lock_ops;

> +struct dev_pm_opp;

>  

>  struct generic_pm_domain {

>  	struct device dev;

> @@ -68,6 +69,8 @@ struct generic_pm_domain {

>  	unsigned int performance_state;	/* Aggregated max performance state */

>  	int (*power_off)(struct generic_pm_domain *domain);

>  	int (*power_on)(struct generic_pm_domain *domain);

> +	unsigned int (*opp_to_performance_state)(struct generic_pm_domain *genpd,

> +						 struct dev_pm_opp *opp);

>  	int (*set_performance_state)(struct generic_pm_domain *genpd,

>  				     unsigned int state);

>  	struct gpd_dev_ops dev_ops;

> @@ -244,6 +247,8 @@ extern int of_genpd_add_subdomain(struct of_phandle_args *parent,

>  extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);

>  extern int of_genpd_parse_idle_states(struct device_node *dn,

>  			struct genpd_power_state **states, int *n);

> +extern unsigned int of_dev_pm_genpd_opp_to_performance_state(struct device *dev,

> +				struct device_node *opp_node);

>  

>  int genpd_dev_pm_attach(struct device *dev);

>  #else /* !CONFIG_PM_GENERIC_DOMAINS_OF */

> @@ -279,6 +284,13 @@ static inline int of_genpd_parse_idle_states(struct device_node *dn,

>  	return -ENODEV;

>  }

>  

> +static inline unsigned int

> +of_dev_pm_genpd_opp_to_performance_state(struct device *dev,

> +					 struct device_node *opp_node)

> +{

> +	return -ENODEV;

> +}

> +

>  static inline int genpd_dev_pm_attach(struct device *dev)

>  {

>  	return -ENODEV;

> 


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
diff mbox series

Patch

diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 5c0019d70d76..5efdf67220f8 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -2412,6 +2412,54 @@  int of_genpd_parse_idle_states(struct device_node *dn,
 }
 EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);
 
+/**
+ * of_dev_pm_genpd_opp_to_performance_state- Gets performance state of device's
+ * power domain corresponding to a DT node's "required-opps" property.
+ *
+ * @dev: Device for which the performance-state needs to be found.
+ * @opp_node: DT node where the "required-opps" property is present. This can be
+ *	the device node itself (if it doesn't have an OPP table) or a node
+ *	within the OPP table of a device (if device has an OPP table).
+ * @state: Pointer to return performance state.
+ *
+ * Returns performance state corresponding to the "required-opps" property of
+ * a DT node. This calls platform specific genpd->opp_to_performance_state()
+ * callback to translate power domain OPP to performance state.
+ *
+ * Returns performance state on success and 0 on failure.
+ */
+unsigned int of_dev_pm_genpd_opp_to_performance_state(struct device *dev,
+						struct device_node *opp_node)
+{
+	struct generic_pm_domain *genpd;
+	struct dev_pm_opp *opp;
+	int state = 0;
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return 0;
+
+	if (unlikely(!genpd->set_performance_state))
+		return 0;
+
+	genpd_lock(genpd);
+
+	opp = of_dev_pm_opp_find_required_opp(&genpd->dev, opp_node);
+	if (IS_ERR(opp)) {
+		state = PTR_ERR(opp);
+		goto unlock;
+	}
+
+	state = genpd->opp_to_performance_state(genpd, opp);
+	dev_pm_opp_put(opp);
+
+unlock:
+	genpd_unlock(genpd);
+
+	return state;
+}
+EXPORT_SYMBOL_GPL(of_dev_pm_genpd_opp_to_performance_state);
+
 #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
 
 
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index aaacaa35005d..fc1b723b03a1 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -47,6 +47,7 @@  struct genpd_power_state {
 };
 
 struct genpd_lock_ops;
+struct dev_pm_opp;
 
 struct generic_pm_domain {
 	struct device dev;
@@ -68,6 +69,8 @@  struct generic_pm_domain {
 	unsigned int performance_state;	/* Aggregated max performance state */
 	int (*power_off)(struct generic_pm_domain *domain);
 	int (*power_on)(struct generic_pm_domain *domain);
+	unsigned int (*opp_to_performance_state)(struct generic_pm_domain *genpd,
+						 struct dev_pm_opp *opp);
 	int (*set_performance_state)(struct generic_pm_domain *genpd,
 				     unsigned int state);
 	struct gpd_dev_ops dev_ops;
@@ -244,6 +247,8 @@  extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
 extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
 extern int of_genpd_parse_idle_states(struct device_node *dn,
 			struct genpd_power_state **states, int *n);
+extern unsigned int of_dev_pm_genpd_opp_to_performance_state(struct device *dev,
+				struct device_node *opp_node);
 
 int genpd_dev_pm_attach(struct device *dev);
 #else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
@@ -279,6 +284,13 @@  static inline int of_genpd_parse_idle_states(struct device_node *dn,
 	return -ENODEV;
 }
 
+static inline unsigned int
+of_dev_pm_genpd_opp_to_performance_state(struct device *dev,
+					 struct device_node *opp_node)
+{
+	return -ENODEV;
+}
+
 static inline int genpd_dev_pm_attach(struct device *dev)
 {
 	return -ENODEV;