Re: [RESEND][PATCH v8 4/8] PM / EM: add support for other devices than CPUs in Energy Model

2020-06-25 Thread Lukasz Luba




On 6/24/20 4:21 PM, Rafael J. Wysocki wrote:

On Wed, Jun 10, 2020 at 12:12 PM Lukasz Luba  wrote:


Add support for other devices than CPUs. The registration function
does not require a valid cpumask pointer and is ready to handle new
devices. Some of the internal structures has been reorganized in order to
keep consistent view (like removing per_cpu pd pointers).

Signed-off-by: Lukasz Luba 
---
Hi all,

This is just a small change compared to v8 addressing Rafael's
comments an Dan's static analyzes.
Here are the changes:
- added comment about mutex usage in the unregister function
- changed 'dev' into @dev in the kerneldoc comments
- removed 'else' statement from em_create_pd() to calm down static analizers


I've applied the series as 5.9 material with patch [4/8] replaced with this one.

Sorry for the delays in handling this!


No worries. Thank you very much!

Regards,
Lukasz



Thanks!


  include/linux/device.h   |   5 +
  include/linux/energy_model.h |  29 -
  kernel/power/energy_model.c  | 244 ---
  3 files changed, 194 insertions(+), 84 deletions(-)

diff --git a/include/linux/device.h b/include/linux/device.h
index ac8e37cd716a..7023d3ea189b 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -13,6 +13,7 @@
  #define _DEVICE_H_

  #include 
+#include 
  #include 
  #include 
  #include 
@@ -559,6 +560,10 @@ struct device {
 struct dev_pm_info  power;
 struct dev_pm_domain*pm_domain;

+#ifdef CONFIG_ENERGY_MODEL
+   struct em_perf_domain   *em_pd;
+#endif
+
  #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
 struct irq_domain   *msi_domain;
  #endif
diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h
index 7076cb22b247..2d4689964029 100644
--- a/include/linux/energy_model.h
+++ b/include/linux/energy_model.h
@@ -12,8 +12,10 @@

  /**
   * em_perf_state - Performance state of a performance domain
- * @frequency: The CPU frequency in KHz, for consistency with CPUFreq
- * @power: The power consumed by 1 CPU at this level, in milli-watts
+ * @frequency: The frequency in KHz, for consistency with CPUFreq
+ * @power: The power consumed at this level, in milli-watts (by 1 CPU or
+   by a registered device). It can be a total power: static and
+   dynamic.
   * @cost:  The cost coefficient associated with this level, used during
   * energy calculation. Equal to: power * max_frequency / frequency
   */
@@ -27,12 +29,16 @@ struct em_perf_state {
   * em_perf_domain - Performance domain
   * @table: List of performance states, in ascending order
   * @nr_perf_states:Number of performance states
- * @cpus:  Cpumask covering the CPUs of the domain
+ * @cpus:  Cpumask covering the CPUs of the domain. It's here
+ * for performance reasons to avoid potential cache
+ * misses during energy calculations in the scheduler
+ * and simplifies allocating/freeing that memory region.
   *
- * A "performance domain" represents a group of CPUs whose performance is
- * scaled together. All CPUs of a performance domain must have the same
- * micro-architecture. Performance domains often have a 1-to-1 mapping with
- * CPUFreq policies.
+ * In case of CPU device, a "performance domain" represents a group of CPUs
+ * whose performance is scaled together. All CPUs of a performance domain
+ * must have the same micro-architecture. Performance domains often have
+ * a 1-to-1 mapping with CPUFreq policies. In case of other devices the @cpus
+ * field is unused.
   */
  struct em_perf_domain {
 struct em_perf_state *table;
@@ -71,10 +77,12 @@ struct em_data_callback {
  #define EM_DATA_CB(_active_power_cb) { .active_power = &_active_power_cb }

  struct em_perf_domain *em_cpu_get(int cpu);
+struct em_perf_domain *em_pd_get(struct device *dev);
  int em_register_perf_domain(cpumask_t *span, unsigned int nr_states,
 struct em_data_callback *cb);
  int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
 struct em_data_callback *cb, cpumask_t *span);
+void em_dev_unregister_perf_domain(struct device *dev);

  /**
   * em_pd_energy() - Estimates the energy consumed by the CPUs of a perf. 
domain
@@ -184,10 +192,17 @@ int em_dev_register_perf_domain(struct device *dev, 
unsigned int nr_states,
  {
 return -EINVAL;
  }
+static inline void em_dev_unregister_perf_domain(struct device *dev)
+{
+}
  static inline struct em_perf_domain *em_cpu_get(int cpu)
  {
 return NULL;
  }
+static inline struct em_perf_domain *em_pd_get(struct device *dev)
+{
+   return NULL;
+}
  static inline unsigned long em_pd_energy(struct em_perf_domain *pd,
 unsigned long max_util, unsigned long sum_util)
  {
diff --git a/kernel/power/energy_model.c b/kernel/pow

Re: [RESEND][PATCH v8 4/8] PM / EM: add support for other devices than CPUs in Energy Model

2020-06-24 Thread Rafael J. Wysocki
On Wed, Jun 10, 2020 at 12:12 PM Lukasz Luba  wrote:
>
> Add support for other devices than CPUs. The registration function
> does not require a valid cpumask pointer and is ready to handle new
> devices. Some of the internal structures has been reorganized in order to
> keep consistent view (like removing per_cpu pd pointers).
>
> Signed-off-by: Lukasz Luba 
> ---
> Hi all,
>
> This is just a small change compared to v8 addressing Rafael's
> comments an Dan's static analyzes.
> Here are the changes:
> - added comment about mutex usage in the unregister function
> - changed 'dev' into @dev in the kerneldoc comments
> - removed 'else' statement from em_create_pd() to calm down static analizers

I've applied the series as 5.9 material with patch [4/8] replaced with this one.

Sorry for the delays in handling this!

Thanks!

>  include/linux/device.h   |   5 +
>  include/linux/energy_model.h |  29 -
>  kernel/power/energy_model.c  | 244 ---
>  3 files changed, 194 insertions(+), 84 deletions(-)
>
> diff --git a/include/linux/device.h b/include/linux/device.h
> index ac8e37cd716a..7023d3ea189b 100644
> --- a/include/linux/device.h
> +++ b/include/linux/device.h
> @@ -13,6 +13,7 @@
>  #define _DEVICE_H_
>
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -559,6 +560,10 @@ struct device {
> struct dev_pm_info  power;
> struct dev_pm_domain*pm_domain;
>
> +#ifdef CONFIG_ENERGY_MODEL
> +   struct em_perf_domain   *em_pd;
> +#endif
> +
>  #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> struct irq_domain   *msi_domain;
>  #endif
> diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h
> index 7076cb22b247..2d4689964029 100644
> --- a/include/linux/energy_model.h
> +++ b/include/linux/energy_model.h
> @@ -12,8 +12,10 @@
>
>  /**
>   * em_perf_state - Performance state of a performance domain
> - * @frequency: The CPU frequency in KHz, for consistency with CPUFreq
> - * @power: The power consumed by 1 CPU at this level, in milli-watts
> + * @frequency: The frequency in KHz, for consistency with CPUFreq
> + * @power: The power consumed at this level, in milli-watts (by 1 CPU or
> +   by a registered device). It can be a total power: static and
> +   dynamic.
>   * @cost:  The cost coefficient associated with this level, used during
>   * energy calculation. Equal to: power * max_frequency / 
> frequency
>   */
> @@ -27,12 +29,16 @@ struct em_perf_state {
>   * em_perf_domain - Performance domain
>   * @table: List of performance states, in ascending order
>   * @nr_perf_states:Number of performance states
> - * @cpus:  Cpumask covering the CPUs of the domain
> + * @cpus:  Cpumask covering the CPUs of the domain. It's here
> + * for performance reasons to avoid potential cache
> + * misses during energy calculations in the scheduler
> + * and simplifies allocating/freeing that memory region.
>   *
> - * A "performance domain" represents a group of CPUs whose performance is
> - * scaled together. All CPUs of a performance domain must have the same
> - * micro-architecture. Performance domains often have a 1-to-1 mapping with
> - * CPUFreq policies.
> + * In case of CPU device, a "performance domain" represents a group of CPUs
> + * whose performance is scaled together. All CPUs of a performance domain
> + * must have the same micro-architecture. Performance domains often have
> + * a 1-to-1 mapping with CPUFreq policies. In case of other devices the @cpus
> + * field is unused.
>   */
>  struct em_perf_domain {
> struct em_perf_state *table;
> @@ -71,10 +77,12 @@ struct em_data_callback {
>  #define EM_DATA_CB(_active_power_cb) { .active_power = &_active_power_cb }
>
>  struct em_perf_domain *em_cpu_get(int cpu);
> +struct em_perf_domain *em_pd_get(struct device *dev);
>  int em_register_perf_domain(cpumask_t *span, unsigned int nr_states,
> struct em_data_callback *cb);
>  int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
> struct em_data_callback *cb, cpumask_t *span);
> +void em_dev_unregister_perf_domain(struct device *dev);
>
>  /**
>   * em_pd_energy() - Estimates the energy consumed by the CPUs of a perf. 
> domain
> @@ -184,10 +192,17 @@ int em_dev_register_perf_domain(struct device *dev, 
> unsigned int nr_states,
>  {
> return -EINVAL;
>  }
> +static inline void em_dev_unregister_perf_domain(struct device *dev)
> +{
> +}
>  static inline struct em_perf_domain *em_cpu_get(int cpu)
>  {
> return NULL;
>  }
> +static inline struct em_perf_domain *em_pd_get(struct device *dev)
> +{
> +   return NULL;
> +}
>  static inline unsigned long em_pd_energy(struct em_perf_domain *pd,
> unsigned long max_util, unsigne