DPDK patches and discussions
 help / color / mirror / Atom feed
From: "Tummala, Sivaprasad" <Sivaprasad.Tummala@amd.com>
To: "Yigit, Ferruh" <Ferruh.Yigit@amd.com>,
	"david.hunt@intel.com" <david.hunt@intel.com>,
	"anatoly.burakov@intel.com" <anatoly.burakov@intel.com>,
	"jerinj@marvell.com" <jerinj@marvell.com>,
	"radu.nicolau@intel.com" <radu.nicolau@intel.com>,
	"gakhil@marvell.com" <gakhil@marvell.com>,
	"cristian.dumitrescu@intel.com" <cristian.dumitrescu@intel.com>,
	"konstantin.ananyev@huawei.com" <konstantin.ananyev@huawei.com>
Cc: "dev@dpdk.org" <dev@dpdk.org>
Subject: RE: [RFC PATCH 1/2] power: refactor core power management library
Date: Thu, 29 Feb 2024 07:10:18 +0000	[thread overview]
Message-ID: <CH3PR12MB823332E136B730141B52F9D4865F2@CH3PR12MB8233.namprd12.prod.outlook.com> (raw)
In-Reply-To: <dcffa52f-d159-46c7-87c6-132466610762@amd.com>

[AMD Official Use Only - General]

Hi Ferruh,

> -----Original Message-----
> From: Yigit, Ferruh <Ferruh.Yigit@amd.com>
> Sent: Tuesday, February 27, 2024 9:48 PM
> To: Tummala, Sivaprasad <Sivaprasad.Tummala@amd.com>;
> david.hunt@intel.com; anatoly.burakov@intel.com; jerinj@marvell.com;
> radu.nicolau@intel.com; gakhil@marvell.com; cristian.dumitrescu@intel.com;
> konstantin.ananyev@huawei.com
> Cc: dev@dpdk.org
> Subject: Re: [RFC PATCH 1/2] power: refactor core power management library
>
> On 2/20/2024 3:33 PM, Sivaprasad Tummala wrote:
> > This patch introduces a comprehensive refactor to the core power
> > management library. The primary focus is on improving modularity and
> > organization by relocating specific driver implementations from the
> > 'lib/power' directory to dedicated directories within
> > 'drivers/power/core/*'. The adjustment of meson.build files enables
> > the selective activation of individual drivers.
> >
> > These changes contribute to a significant enhancement in code
> > organization, providing a clearer structure for driver implementations.
> > The refactor aims to improve overall code clarity and boost
> > maintainability. Additionally, it establishes a foundation for future
> > development, allowing for more focused work on individual drivers and
> > seamless integration of forthcoming enhancements.
> >
> > Signed-off-by: Sivaprasad Tummala <sivaprasad.tummala@amd.com>
> >
>
> +1 to refactor, thanks for the work.
>
> There are multiple power implementations but all are managed withing the power
> library, it is good idea to extract different implementations as drivers.
>
> <...>
>
> > diff --git a/drivers/power/core/acpi/meson.build
> > b/drivers/power/core/acpi/meson.build
> > new file mode 100644
> > index 0000000000..d10ec8ee94
> > --- /dev/null
> > +++ b/drivers/power/core/acpi/meson.build
> > @@ -0,0 +1,8 @@
> > +# SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2024 AMD
> > +Limited
> >
>
> It should be as following, same for all:
>
> Copyright (C) 2024, Advanced Micro Devices, Inc.
>
ACK

> > +
> > +sources = files('power_acpi_cpufreq.c')
> > +
> > +headers = files('power_acpi_cpufreq.h')
> >
>
> In meson, 'headers' variable is used to install the header, this is required for the
> case user needs to include the header but I guess that is not the case for power
> libraries.
> Can you please check if the 'header' variable in meson is required?
>
> <...>
>
> > @@ -577,3 +577,22 @@ int power_acpi_get_capabilities(unsigned int
> > lcore_id,
> >
> >     return 0;
> >  }
> > +
> > +static struct rte_power_ops acpi_ops = {
> > +   .init = power_acpi_cpufreq_init,
> > +   .exit = power_acpi_cpufreq_exit,
> > +   .check_env_support = power_acpi_cpufreq_check_supported,
> > +   .get_avail_freqs = power_acpi_cpufreq_freqs,
> > +   .get_freq = power_acpi_cpufreq_get_freq,
> > +   .set_freq = power_acpi_cpufreq_set_freq,
> > +   .freq_down = power_acpi_cpufreq_freq_down,
> > +   .freq_up = power_acpi_cpufreq_freq_up,
> > +   .freq_max = power_acpi_cpufreq_freq_max,
> > +   .freq_min = power_acpi_cpufreq_freq_min,
> > +   .turbo_status = power_acpi_turbo_status,
> > +   .enable_turbo = power_acpi_enable_turbo,
> > +   .disable_turbo = power_acpi_disable_turbo,
> > +   .get_caps = power_acpi_get_capabilities };
> > +
>
> With current usage of the ops struct, I guess all can be "static const".
ACK
>
> <...>
>
> > diff --git a/drivers/power/core/kvm-vm/meson.build
> > b/drivers/power/core/kvm-vm/meson.build
> > new file mode 100644
> > index 0000000000..3150c6674b
> > --- /dev/null
> > +++ b/drivers/power/core/kvm-vm/meson.build
> > @@ -0,0 +1,20 @@
> > +# SPDX-License-Identifier: BSD-3-Clause # Copyright(C) 2024 AMD
> > +Limited.
> > +#
> > +
> > +if not is_linux
> > +    build = false
> > +    reason = 'only supported on Linux'
> > +    subdir_done()
> > +endif
> >
>
> Before refactoring, in lib/power was supported only for Linux, I assume this means
> all existing power libraries supported only for Linux.
> If so above check can be added to all drivers.
ACK
>
> <...>
>
> > +/* register the ops struct in rte_power_ops, return 0 on success. */
> > +int rte_power_register_ops(const struct rte_power_ops *op) {
> > +   struct rte_power_ops *ops;
> > +
> > +   if (op->env >= PM_ENV_MAX) {
> > +           POWER_LOG(ERR, "Unsupported power management
> environment\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (op->status != 0) {
> > +           POWER_LOG(ERR, "Power management env[%d] ops registered
> already\n",
> > +                   op->env);
> > +           return -EINVAL;
> > +   }
> > +
> > +   if (!op->init || !op->exit || !op->check_env_support ||
> > +           !op->get_avail_freqs || !op->get_freq || !op->set_freq ||
> > +           !op->freq_up || !op->freq_down || !op->freq_max ||
> > +           !op->freq_min || !op->turbo_status || !op->enable_turbo ||
> > +           !op->disable_turbo || !op->get_caps) {
> > +           POWER_LOG(ERR, "Missing callbacks while registering power
> ops\n");
> > +           return -EINVAL;
> > +   }
> > +
> > +   ops = &rte_power_ops[op->env];
> >
>
> I don't see all drivers set 'op->env',
>
> This 'rte_power_register_ops()' function copies ops from driver proved struct to
> library global 'rte_power_ops[]' array,
>
> it can be possible to store ops pointer provided by driver, instead of copying it.
>
> And it can be possible to link the ops in this function, instead of putting them to
> specific index, as only one ops can be active in a given time, it can be possible to
> store active ops pointer in a global variable which removes the need to have index
> accessible array for ops.
Agreed. I will rework this to a new struct which can hold a reference to the respective ops struct.

>
> <...>
>
> > @@ -177,59 +138,76 @@ int
> >  rte_power_init(unsigned int lcore_id)  {
> >     int ret = -1;
> > +   struct rte_power_ops *ops;
> >
> > -   switch (global_default_env) {
> > -   case PM_ENV_ACPI_CPUFREQ:
> > -           return power_acpi_cpufreq_init(lcore_id);
> > -   case PM_ENV_KVM_VM:
> > -           return power_kvm_vm_init(lcore_id);
> > -   case PM_ENV_PSTATE_CPUFREQ:
> > -           return power_pstate_cpufreq_init(lcore_id);
> > -   case PM_ENV_CPPC_CPUFREQ:
> > -           return power_cppc_cpufreq_init(lcore_id);
> > -   case PM_ENV_AMD_PSTATE_CPUFREQ:
> > -           return power_amd_pstate_cpufreq_init(lcore_id);
> > -   default:
> > -           POWER_LOG(INFO, "Env isn't set yet!");
> > +   if (global_default_env != PM_ENV_NOT_SET) {
> > +           ops = &rte_power_ops[global_default_env];
> > +           if (!ops->status) {
> > +                   POWER_LOG(ERR, "Power management env[%d] not"
> > +                           " supported\n", global_default_env);
> > +                   goto out;
> > +           }
> > +           return ops->init(lcore_id);
> >     }
> > +   POWER_LOG(INFO, POWER, "Env isn't set yet!\n");
> >
> >     /* Auto detect Environment */
> > -   POWER_LOG(INFO, "Attempting to initialise ACPI cpufreq power
> management...");
> > -   ret = power_acpi_cpufreq_init(lcore_id);
> > -   if (ret == 0) {
> > -           rte_power_set_env(PM_ENV_ACPI_CPUFREQ);
> > -           goto out;
> > +   POWER_LOG(INFO, "Attempting to initialise ACPI cpufreq"
> > +                   " power management...\n");
> >
>
> Shouldn't break the log, can break the line by keeping message whole:
> POWER_LOG(INFO,
>       "Attempting to initialise ACPI cpufreq power management...");
>
> <...>
ACK

>
> > @@ -21,7 +22,7 @@ extern "C" {
> >  /* Power Management Environment State */  enum power_management_env
> > {PM_ENV_NOT_SET, PM_ENV_ACPI_CPUFREQ, PM_ENV_KVM_VM,
> >             PM_ENV_PSTATE_CPUFREQ, PM_ENV_CPPC_CPUFREQ,
> > -           PM_ENV_AMD_PSTATE_CPUFREQ};
> > +           PM_ENV_AMD_PSTATE_CPUFREQ, PM_ENV_MAX};
> >
>
> Syntax. Can we have enum item per line?
ACK

>
> >  /**
> >   * Check if a specific power management environment type is supported
> > on a @@ -66,6 +67,97 @@ void rte_power_unset_env(void);
> >   */
> >  enum power_management_env rte_power_get_env(void);
> >
> > +typedef int (*rte_power_cpufreq_init_t)(unsigned int lcore_id);
> > +typedef int (*rte_power_cpufreq_exit_t)(unsigned int lcore_id);
> > +typedef int (*rte_power_check_env_support_t)(void);
> > +
> > +typedef uint32_t (*rte_power_freqs_t)(unsigned int lcore_id, uint32_t *freqs,
> > +                                   uint32_t num);
> > +typedef uint32_t (*rte_power_get_freq_t)(unsigned int lcore_id);
> > +typedef int (*rte_power_set_freq_t)(unsigned int lcore_id, uint32_t
> > +index); typedef int (*rte_power_freq_change_t)(unsigned int
> > +lcore_id);
> > +
> >
>
> I guess above is not required for users, what do you think to create a driver header
> file and move these to driver header file?

>
> <...>
>
> > +
> > +/**
> > + * Macro to statically register the ops of a cpufreq driver.
> > + */
> > +#define RTE_POWER_REGISTER_OPS(ops)                \
> > +   (RTE_INIT(power_hdlr_init_##ops)        \
> > +   {                                       \
> > +           rte_power_register_ops(&ops);   \
> > +   })
> >
>
> is () required around RTE_INIT()
This was added to address the checkpatch errors.
>
> > +
> > +/**
> > + * @internal Get the power ops struct from its index.
> > + *
> > + * @param ops_index
> > + *   The index of the ops struct in the ops struct table.
> > + * @return
> > + *   The pointer to the ops struct in the table if registered.
> > + */
> > +struct rte_power_ops *
> > +rte_power_get_ops(int ops_index);
> > +
> >  /**
> >   * Initialize power management for a specific lcore. If rte_power_set_env() has
> >   * not been called then an auto-detect of the environment will start
> > and @@ -108,10 +200,14 @@ int rte_power_exit(unsigned int lcore_id);
> >   * @return
> >   *  The number of available frequencies.
> >   */
> > -typedef uint32_t (*rte_power_freqs_t)(unsigned int lcore_id, uint32_t *freqs,
> > -           uint32_t num);
> > +static inline uint32_t
> > +rte_power_freqs(unsigned int lcore_id, uint32_t *freqs, uint32_t n) {
> > +   struct rte_power_ops *ops;
> >
> > -extern rte_power_freqs_t rte_power_freqs;
> > +   ops = rte_power_get_ops(rte_power_get_env());
> > +   return ops->get_avail_freqs(lcore_id, freqs, n); }
> >
>
> Why not proper functions but "static inline functions"?
These inline functions are expected to be called from datapath and to avoid additional cycles with the refactor.

>
> >
> >  /**
> >   * Return the current index of available frequencies of a specific lcore.
> > @@ -124,9 +220,14 @@ extern rte_power_freqs_t rte_power_freqs;
> >   * @return
> >   *  The current index of available frequencies.
> >   */
> > -typedef uint32_t (*rte_power_get_freq_t)(unsigned int lcore_id);
> > +static inline uint32_t
> > +rte_power_get_freq(unsigned int lcore_id) {
> > +   struct rte_power_ops *ops;
> >
> > -extern rte_power_get_freq_t rte_power_get_freq;
> > +   ops = rte_power_get_ops(rte_power_get_env());
> >
>
> As 'rte_power_get_env()' already returns a global variable, why not set a global ops
> pointer and directly access to them, is above abstraction providing any benefit?
rte_power_get_ops() internally will check if the respective ops struct is registered or not.
I will rework it and keep global ops to get populated in rte_power_set_env().

>
>


  reply	other threads:[~2024-02-29  7:10 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-20 15:33 [RFC PATCH 0/2] power: refactor " Sivaprasad Tummala
2024-02-20 15:33 ` Sivaprasad Tummala
2024-02-20 15:33 ` [RFC PATCH 1/2] power: refactor core " Sivaprasad Tummala
2024-02-27 16:18   ` Ferruh Yigit
2024-02-29  7:10     ` Tummala, Sivaprasad [this message]
2024-02-28 12:51   ` Ferruh Yigit
2024-03-01  2:56   ` lihuisong (C)
2024-03-01 10:39     ` Hunt, David
2024-03-05  4:35     ` Tummala, Sivaprasad
2024-02-20 15:33 ` [RFC PATCH 2/2] power: refactor uncore " Sivaprasad Tummala
2024-03-01  3:33   ` lihuisong (C)
2024-03-01  6:06     ` Tummala, Sivaprasad

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=CH3PR12MB823332E136B730141B52F9D4865F2@CH3PR12MB8233.namprd12.prod.outlook.com \
    --to=sivaprasad.tummala@amd.com \
    --cc=Ferruh.Yigit@amd.com \
    --cc=anatoly.burakov@intel.com \
    --cc=cristian.dumitrescu@intel.com \
    --cc=david.hunt@intel.com \
    --cc=dev@dpdk.org \
    --cc=gakhil@marvell.com \
    --cc=jerinj@marvell.com \
    --cc=konstantin.ananyev@huawei.com \
    --cc=radu.nicolau@intel.com \
    /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 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).