[PATCH v4 2/2] PM / devfreq: Add HiSilicon uncore frequency scaling driver
Jie Zhan
zhanjie9 at hisilicon.com
Thu Jun 19 07:18:00 PDT 2025
On 16/06/2025 17:35, Jonathan Cameron wrote:
> On Fri, 30 May 2025 16:17:22 +0800
> Jie Zhan <zhanjie9 at hisilicon.com> wrote:
>
>> Add the HiSilicon uncore frequency scaling driver for Kunpeng SoCs based on
>> the devfreq framework. The uncore domain contains shared computing
>> resources, including system interconnects and L3 cache. The uncore
>> frequency significantly impacts the system-wide performance as well as
>> power consumption. This driver adds support for runtime management of
>> uncore frequency from kernel and userspace. The main function includes
>> setting and getting frequencies, changing frequency scaling policies, and
>> querying the list of CPUs whose performance is significantly related to
>> this uncore frequency domain, etc. The driver communicates with a platform
>> controller through an ACPI PCC mailbox to take the actual actions of
>> frequency scaling.
>>
>> Co-developed-by: Lifeng Zheng <zhenglifeng1 at huawei.com>
>> Signed-off-by: Lifeng Zheng <zhenglifeng1 at huawei.com>
>> Signed-off-by: Jie Zhan <zhanjie9 at hisilicon.com>
> Hi Zhanjie,
>
> A few comments inline. In general nice and clean.
>
> I think only one that really needs a change it the one around the
> CPU association firmware handling.
>
> Jonathan
>
Thanks again!
All accepted, except for the cleanup of putting devm_add_action_or_reset()
before opp_add().
See inline replies below.
Jie
>
>> ---
>> Documentation/ABI/testing/sysfs-class-devfreq | 9 +
>> drivers/devfreq/Kconfig | 11 +
>> drivers/devfreq/Makefile | 1 +
>> drivers/devfreq/hisi_uncore_freq.c | 656 ++++++++++++++++++
>> 4 files changed, 677 insertions(+)
>> create mode 100644 drivers/devfreq/hisi_uncore_freq.c
>>
>> + rc = dev_pm_opp_add(dev, freq_mhz * HZ_PER_MHZ, 1000000);
>> + if (rc) {
>> + dev_pm_opp_remove_all_dynamic(dev);
>> + return dev_err_probe(dev, rc,
>> + "Add OPP %lu failed\n", freq_mhz);
>> + }
>> + }
>> +
>> + return devm_add_action_or_reset(dev, devm_hisi_uncore_remove_opp, uncore);
> Hmm. I'm normally a fan of registering these after the calls, but this is one
> of the rare cases where pushing it before (with a comment) cleans up the code.
>
> If you do that, then all the error cases in the loop just need to return and not
> call the cleanup manually.
I'd prefer to keep the current order so as to keep logic and style
consistent across places where devm_add_action is used. It would be easier
for people to follow.
>
...
>> +static int hisi_uncore_mark_related_cpus(struct hisi_uncore_freq *uncore,
>> + char *property, int (*get_topo_id)(int cpu),
>> + const struct cpumask *(*get_cpumask)(int cpu))
>> +{
>> + unsigned int i, cpu;
>> + size_t len;
>> + int rc;
>> +
>> + rc = device_property_count_u32(uncore->dev, property);
>> + if (rc < 0)
>> + return rc;
> Most of the errors here don't reflect it not being found and are things
> were we should probably fail the driver probe (so someone can fix whatever
> is wrong with the firmware.) I think only -EINVAL means not here
> (technically arguments are not valid)
>
Thanks for spotting this.
Had a dig.
In the case here:
rc > 0, success, rc is the number of elements in this property.
rc == 0, property found but no elements in it, the firmware might have a
property without values.
rc == -EINVAL, property not found, or invalid arguments received in any of
the subroutine, e.g. NULL pointer.
rc < 0 && rc != -EINVAL, firmware probably broken.
I think we can take 0 and -EINVAL as not found, and try the other property
name. If rc == 0, the firmware might just have some redundant code, not a
big issue. If rc == -EINVAL, it's likely that the property is not found
unless some data go wrong and make arguments invalid.
Other negative error codes should fail the driver probe.
The device_property_read_u32_array() below is similar.
I'll put this in comments and update hisi_uncore_mark_related_cpus_wrap().
This function doesn't need to change.
>> + if (rc == 0)
>> + return -EINVAL;
>> +
>> + len = rc;
>> + u32 *num __free(kfree) = kcalloc(len, sizeof(*num), GFP_KERNEL);
>> + if (!num)
>> + return -ENOMEM;
>
...
>> +static int hisi_uncore_devfreq_register(struct hisi_uncore_freq *uncore)
>> +{
>> + struct devfreq_dev_profile *profile;
>> + struct device *dev = uncore->dev;
>> + unsigned long freq;
>> + u32 data;
>> + int rc;
>> +
>> + rc = hisi_uncore_get_cur_freq(dev, &freq);
> One for another day:
> Whilst we do indeed need to do this, it seems like a small optimization to
> devfreq would be to check for initial_freq == 0 and if it is try get_cur_freq()
> after registration. Mind you I checked and this only seems to apply to
> the imx drivers and this one.
>
Yeah, understood.
Let's check and improve that later.
More information about the linux-arm-kernel
mailing list