Re: [PATCH v2 06/17] PM: EM: Add update_power() callback for runtime modifications

From: Dietmar Eggemann
Date: Tue May 30 2023 - 05:32:37 EST


On 12/05/2023 11:57, Lukasz Luba wrote:
> The Energy Model (EM) is going to support runtime modifications. This
> new callback would be used in the upcoming EM changes. The drivers
> or frameworks which want to modify the EM have to implement the
> update_power() callback and provide it via EM API
> em_dev_update_perf_domain(). The callback is then used by the EM
> framework to get new power values for each frequency in existing EM.

Do we have any numbers or feedback that the chosen design (i.e. update
per performance state through update_power()) is performant enough for
the anticipated use case on real devices?

> Signed-off-by: Lukasz Luba <lukasz.luba@xxxxxxx>
> ---
> include/linux/energy_model.h | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h
> index 8069f526c9d8..cc2bf607191e 100644
> --- a/include/linux/energy_model.h
> +++ b/include/linux/energy_model.h
> @@ -158,6 +158,26 @@ struct em_data_callback {
> */
> int (*get_cost)(struct device *dev, unsigned long freq,
> unsigned long *cost);
> +
> + /**
> + * update_power() - Provide new power at the given performance state of
> + * a device
> + * @dev : Device for which we do this operation (can be a CPU)
> + * @freq : Frequency at the performance state in kHz
> + * @power : New power value at the performance state
> + * (modified)
> + * @priv : Pointer to private data useful for tracking context
> + * during run-time modifications of EM.
> + *
> + * The update_power() is used by run-time modifiable EM. It aims to
> + * provide updated power value for a given frequency, which is stored
> + * in the performance state. The power value provided by this callback
> + * should fit in the [0, EM_MAX_POWER] range.
> + *
> + * Return 0 on success, or appropriate error value in case of failure.
> + */
> + int (*update_power)(struct device *dev, unsigned long freq,
> + unsigned long *power, void *priv);
> };
> #define EM_SET_ACTIVE_POWER_CB(em_cb, cb) ((em_cb).active_power = cb)
> #define EM_ADV_DATA_CB(_active_power_cb, _cost_cb) \
> @@ -165,6 +185,7 @@ struct em_data_callback {
> .get_cost = _cost_cb }
> #define EM_DATA_CB(_active_power_cb) \
> EM_ADV_DATA_CB(_active_power_cb, NULL)
> +#define EM_UPDATE_CB(_update_power_cb) { .update_power = &_update_power_cb }
>
> struct em_perf_domain *em_cpu_get(int cpu);
> struct em_perf_domain *em_pd_get(struct device *dev);