Skip to content

Commit c224584

Browse files
committed
Merge tag 'devfreq-next-for-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux
Merge devfreq updates for v6.17 from Chanwoo Choi: "- Clean devfreq core and fix bugs : Replace sscanf with kstrtoul : Remove redundant devfreq_get_freq_range() on adding devfreq driver : Check missing NULL pointer check on removing devfreq driver : Limit max_freq and min_freq to avoid unreachable value : Fix wrong index on trans_stat sysfs node - Use devm_* managed function for clock control on sun81-a33-mbus driver - Add HiSilicon uncore frequencye scaling driver for for HiSilicon Kunpeng SoCs : The uncore domain includes shared system resources such as interconnects and L3 cache, and its frequency has a significant impact on system performance and power consumption. The driver provides the following functions: - Support to scale frequency scaling with governor and user setting - Support to query CPUs whose performance is closely related to the uncore domain - Communication with the platform controller via an ACPI PCC mailbox to perform actual frequency changes" * tag 'devfreq-next-for-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux: PM / devfreq: Add HiSilicon uncore frequency scaling driver PM / devfreq: Allow devfreq driver to add custom sysfs ABIs PM / devfreq: sun8i-a33-mbus: Simplify by using more devm functions PM / devfreq: Fix a index typo in trans_stat PM / devfreq: Check governor before using governor->name PM / devfreq: Remove redundant devfreq_get_freq_range() calling in devfreq_add_device() PM / devfreq: Limit max_freq with scaling_min_freq PM / devfreq: governor: Replace sscanf() with kstrtoul() in set_freq_store()
2 parents 347e9f5 + 7da2fda commit c224584

8 files changed

Lines changed: 704 additions & 46 deletions

File tree

Documentation/ABI/testing/sysfs-class-devfreq

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,12 @@ Description:
132132

133133
A list of governors that support the node:
134134
- simple_ondemand
135+
136+
What: /sys/class/devfreq/.../related_cpus
137+
Date: June 2025
138+
Contact: Linux power management list <linux-pm@vger.kernel.org>
139+
Description: The list of CPUs whose performance is closely related to the
140+
frequency of this devfreq domain.
141+
142+
This file is only present if a specific devfreq device is
143+
closely associated with a subset of CPUs.

drivers/devfreq/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,17 @@ config ARM_EXYNOS_BUS_DEVFREQ
9090
and adjusts the operating frequencies and voltages with OPP support.
9191
This does not yet operate with optimal voltages.
9292

93+
config ARM_HISI_UNCORE_DEVFREQ
94+
tristate "HiSilicon uncore DEVFREQ Driver"
95+
depends on ACPI && ACPI_PPTT && PCC
96+
select DEVFREQ_GOV_PERFORMANCE
97+
select DEVFREQ_GOV_USERSPACE
98+
help
99+
This adds a DEVFREQ driver that manages uncore frequency scaling for
100+
HiSilicon Kunpeng SoCs. This enables runtime management of uncore
101+
frequency scaling from kernel and userspace. The uncore domain
102+
contains system interconnects and L3 cache.
103+
93104
config ARM_IMX_BUS_DEVFREQ
94105
tristate "i.MX Generic Bus DEVFREQ Driver"
95106
depends on ARCH_MXC || COMPILE_TEST

drivers/devfreq/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o
99

1010
# DEVFREQ Drivers
1111
obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o
12+
obj-$(CONFIG_ARM_HISI_UNCORE_DEVFREQ) += hisi_uncore_freq.o
1213
obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.o
1314
obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o
1415
obj-$(CONFIG_ARM_MEDIATEK_CCI_DEVFREQ) += mtk-cci-devfreq.o

drivers/devfreq/devfreq.c

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,8 @@ void devfreq_get_freq_range(struct devfreq *devfreq,
152152
(unsigned long)HZ_PER_KHZ * qos_max_freq);
153153

154154
/* Apply constraints from OPP interface */
155-
*min_freq = max(*min_freq, devfreq->scaling_min_freq);
156-
*max_freq = min(*max_freq, devfreq->scaling_max_freq);
157-
158-
if (*min_freq > *max_freq)
159-
*min_freq = *max_freq;
155+
*max_freq = clamp(*max_freq, devfreq->scaling_min_freq, devfreq->scaling_max_freq);
156+
*min_freq = clamp(*min_freq, devfreq->scaling_min_freq, *max_freq);
160157
}
161158
EXPORT_SYMBOL(devfreq_get_freq_range);
162159

@@ -807,7 +804,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
807804
{
808805
struct devfreq *devfreq;
809806
struct devfreq_governor *governor;
810-
unsigned long min_freq, max_freq;
811807
int err = 0;
812808

813809
if (!dev || !profile || !governor_name) {
@@ -835,6 +831,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
835831
mutex_lock(&devfreq->lock);
836832
devfreq->dev.parent = dev;
837833
devfreq->dev.class = devfreq_class;
834+
devfreq->dev.groups = profile->dev_groups;
838835
devfreq->dev.release = devfreq_dev_release;
839836
INIT_LIST_HEAD(&devfreq->node);
840837
devfreq->profile = profile;
@@ -875,8 +872,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
875872
goto err_dev;
876873
}
877874

878-
devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
879-
880875
devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
881876
devfreq->opp_table = dev_pm_opp_get_opp_table(dev);
882877
if (IS_ERR(devfreq->opp_table))
@@ -1382,15 +1377,11 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
13821377
int ret;
13831378
struct device *dev = devfreq->dev.parent;
13841379

1380+
if (!devfreq->governor)
1381+
continue;
1382+
13851383
if (!strncmp(devfreq->governor->name, governor->name,
13861384
DEVFREQ_NAME_LEN)) {
1387-
/* we should have a devfreq governor! */
1388-
if (!devfreq->governor) {
1389-
dev_warn(dev, "%s: Governor %s NOT present\n",
1390-
__func__, governor->name);
1391-
continue;
1392-
/* Fall through */
1393-
}
13941385
ret = devfreq->governor->event_handler(devfreq,
13951386
DEVFREQ_GOV_STOP, NULL);
13961387
if (ret) {
@@ -1743,7 +1734,7 @@ static ssize_t trans_stat_show(struct device *dev,
17431734
for (i = 0; i < max_state; i++) {
17441735
if (len >= PAGE_SIZE - 1)
17451736
break;
1746-
if (df->freq_table[2] == df->previous_freq)
1737+
if (df->freq_table[i] == df->previous_freq)
17471738
len += sysfs_emit_at(buf, len, "*");
17481739
else
17491740
len += sysfs_emit_at(buf, len, " ");

drivers/devfreq/governor_userspace.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/slab.h>
1010
#include <linux/device.h>
1111
#include <linux/devfreq.h>
12+
#include <linux/kstrtox.h>
1213
#include <linux/pm.h>
1314
#include <linux/mutex.h>
1415
#include <linux/module.h>
@@ -39,10 +40,13 @@ static ssize_t set_freq_store(struct device *dev, struct device_attribute *attr,
3940
unsigned long wanted;
4041
int err = 0;
4142

43+
err = kstrtoul(buf, 0, &wanted);
44+
if (err)
45+
return err;
46+
4247
mutex_lock(&devfreq->lock);
4348
data = devfreq->governor_data;
4449

45-
sscanf(buf, "%lu", &wanted);
4650
data->user_frequency = wanted;
4751
data->valid = true;
4852
err = update_devfreq(devfreq);

0 commit comments

Comments
 (0)