Merge branches 'pm-devfreq' and 'pm-tools'

Merge devfreq changes and power management tools changes for 6.6-rc1:

 - Fix memory leak in devfreq_dev_release() (Boris Brezillon).

 - Rewrite devfreq_monitor_start() kerneldoc comment (Manivannan
   Sadhasivam).

 - Explicitly include correct DT includes in devfreq (Rob Herring).

 - Add turbo-boost support to cpupower (Wyes Karny).

 - Add support for amd_pstate mode change to cpupower (Wyes Karny).

 - Fix 'cpupower idle_set' command to accept only numeric values of
   arguments (Likhitha Korrapati).

* pm-devfreq:
  PM / devfreq: Fix leak in devfreq_dev_release()
  PM / devfreq: Reword the kernel-doc comment for devfreq_monitor_start() API
  PM / devfreq: Explicitly include correct DT includes

* pm-tools:
  cpupower: Fix cpuidle_set to accept only numeric values for idle-set operation.
  cpupower: Add turbo-boost support in cpupower
  cpupower: Add support for amd_pstate mode change
  cpupower: Add EPP value change support
  cpupower: Add is_valid_path API
  cpupower: Recognise amd-pstate active mode driver
  cpupower: Bump soname version
This commit is contained in:
Rafael J. Wysocki 2023-08-25 21:29:59 +02:00
commit 885c429e06
12 changed files with 155 additions and 21 deletions

View File

@ -472,10 +472,11 @@ static void devfreq_monitor(struct work_struct *work)
* devfreq_monitor_start() - Start load monitoring of devfreq instance
* @devfreq: the devfreq instance.
*
* Helper function for starting devfreq device load monitoring. By
* default delayed work based monitoring is supported. Function
* to be called from governor in response to DEVFREQ_GOV_START
* event when device is added to devfreq framework.
* Helper function for starting devfreq device load monitoring. By default,
* deferrable timer is used for load monitoring. But the users can change this
* behavior using the "timer" type in devfreq_dev_profile. This function will be
* called by devfreq governor in response to the DEVFREQ_GOV_START event
* generated while adding a device to the devfreq framework.
*/
void devfreq_monitor_start(struct devfreq *devfreq)
{
@ -763,6 +764,7 @@ static void devfreq_dev_release(struct device *dev)
dev_pm_opp_put_opp_table(devfreq->opp_table);
mutex_destroy(&devfreq->lock);
srcu_cleanup_notifier_head(&devfreq->transition_notifier_list);
kfree(devfreq);
}

View File

@ -7,7 +7,7 @@
#include <linux/devfreq.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/pm_opp.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

View File

@ -3,9 +3,9 @@
* Copyright 2019 NXP
*/
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/devfreq.h>
#include <linux/pm_opp.h>

View File

@ -8,7 +8,6 @@
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/regulator/consumer.h>

View File

@ -13,7 +13,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/reset.h>

View File

@ -53,7 +53,7 @@ DESTDIR ?=
VERSION:= $(shell ./utils/version-gen.sh)
LIB_MAJ= 0.0.1
LIB_MIN= 0
LIB_MIN= 1
PACKAGE = cpupower
PACKAGE_BUGREPORT = linux-pm@vger.kernel.org

View File

@ -14,6 +14,13 @@
#include "cpupower.h"
#include "cpupower_intern.h"
int is_valid_path(const char *path)
{
if (access(path, F_OK) == -1)
return 0;
return 1;
}
unsigned int cpupower_read_sysfs(const char *path, char *buf, size_t buflen)
{
ssize_t numread;

View File

@ -7,5 +7,6 @@
#define SYSFS_PATH_MAX 255
int is_valid_path(const char *path);
unsigned int cpupower_read_sysfs(const char *path, char *buf, size_t buflen);
unsigned int cpupower_write_sysfs(const char *path, char *buf, size_t buflen);

View File

@ -41,14 +41,6 @@ int cmd_idle_set(int argc, char **argv)
cont = 0;
break;
case 'd':
if (param) {
param = -1;
cont = 0;
break;
}
param = ret;
idlestate = atoi(optarg);
break;
case 'e':
if (param) {
param = -1;
@ -56,7 +48,13 @@ int cmd_idle_set(int argc, char **argv)
break;
}
param = ret;
idlestate = atoi(optarg);
strtol(optarg, &endptr, 10);
if (*endptr != '\0') {
printf(_("Bad value: %s, Integer expected\n"), optarg);
exit(EXIT_FAILURE);
} else {
idlestate = atoi(optarg);
}
break;
case 'D':
if (param) {

View File

@ -18,6 +18,9 @@
static struct option set_opts[] = {
{"perf-bias", required_argument, NULL, 'b'},
{"epp", required_argument, NULL, 'e'},
{"amd-pstate-mode", required_argument, NULL, 'm'},
{"turbo-boost", required_argument, NULL, 't'},
{ },
};
@ -37,11 +40,15 @@ int cmd_set(int argc, char **argv)
union {
struct {
int perf_bias:1;
int epp:1;
int mode:1;
int turbo_boost:1;
};
int params;
} params;
int perf_bias = 0;
int perf_bias = 0, turbo_boost = 1;
int ret = 0;
char epp[30], mode[20];
ret = uname(&uts);
if (!ret && (!strcmp(uts.machine, "ppc64le") ||
@ -55,7 +62,7 @@ int cmd_set(int argc, char **argv)
params.params = 0;
/* parameter parsing */
while ((ret = getopt_long(argc, argv, "b:",
while ((ret = getopt_long(argc, argv, "b:e:m:",
set_opts, NULL)) != -1) {
switch (ret) {
case 'b':
@ -69,6 +76,38 @@ int cmd_set(int argc, char **argv)
}
params.perf_bias = 1;
break;
case 'e':
if (params.epp)
print_wrong_arg_exit();
if (sscanf(optarg, "%29s", epp) != 1) {
print_wrong_arg_exit();
return -EINVAL;
}
params.epp = 1;
break;
case 'm':
if (cpupower_cpu_info.vendor != X86_VENDOR_AMD)
print_wrong_arg_exit();
if (params.mode)
print_wrong_arg_exit();
if (sscanf(optarg, "%19s", mode) != 1) {
print_wrong_arg_exit();
return -EINVAL;
}
params.mode = 1;
break;
case 't':
if (params.turbo_boost)
print_wrong_arg_exit();
turbo_boost = atoi(optarg);
if (turbo_boost < 0 || turbo_boost > 1) {
printf("--turbo-boost param out of range [0-1]\n");
print_wrong_arg_exit();
}
params.turbo_boost = 1;
break;
default:
print_wrong_arg_exit();
}
@ -77,6 +116,18 @@ int cmd_set(int argc, char **argv)
if (!params.params)
print_wrong_arg_exit();
if (params.mode) {
ret = cpupower_set_amd_pstate_mode(mode);
if (ret)
fprintf(stderr, "Error setting mode\n");
}
if (params.turbo_boost) {
ret = cpupower_set_turbo_boost(turbo_boost);
if (ret)
fprintf(stderr, "Error setting turbo-boost\n");
}
/* Default is: set all CPUs */
if (bitmask_isallclear(cpus_chosen))
bitmask_setall(cpus_chosen);
@ -102,6 +153,16 @@ int cmd_set(int argc, char **argv)
break;
}
}
if (params.epp) {
ret = cpupower_set_epp(cpu, epp);
if (ret) {
fprintf(stderr,
"Error setting epp value on CPU %d\n", cpu);
break;
}
}
}
return ret;
}

View File

@ -116,6 +116,10 @@ extern int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val);
extern int cpupower_intel_get_perf_bias(unsigned int cpu);
extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu);
extern int cpupower_set_epp(unsigned int cpu, char *epp);
extern int cpupower_set_amd_pstate_mode(char *mode);
extern int cpupower_set_turbo_boost(int turbo_boost);
/* Read/Write msr ****************************/
/* PCI stuff ****************************/
@ -173,6 +177,13 @@ static inline int cpupower_intel_get_perf_bias(unsigned int cpu)
static inline unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu)
{ return 0; };
static inline int cpupower_set_epp(unsigned int cpu, char *epp)
{ return -1; };
static inline int cpupower_set_amd_pstate_mode(char *mode)
{ return -1; };
static inline int cpupower_set_turbo_boost(int turbo_boost)
{ return -1; };
/* Read/Write msr ****************************/
static inline int cpufreq_has_boost_support(unsigned int cpu, int *support,

View File

@ -87,6 +87,61 @@ int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val)
return 0;
}
int cpupower_set_epp(unsigned int cpu, char *epp)
{
char path[SYSFS_PATH_MAX];
char linebuf[30] = {};
snprintf(path, sizeof(path),
PATH_TO_CPU "cpu%u/cpufreq/energy_performance_preference", cpu);
if (!is_valid_path(path))
return -1;
snprintf(linebuf, sizeof(linebuf), "%s", epp);
if (cpupower_write_sysfs(path, linebuf, 30) <= 0)
return -1;
return 0;
}
int cpupower_set_amd_pstate_mode(char *mode)
{
char path[SYSFS_PATH_MAX];
char linebuf[20] = {};
snprintf(path, sizeof(path), PATH_TO_CPU "amd_pstate/status");
if (!is_valid_path(path))
return -1;
snprintf(linebuf, sizeof(linebuf), "%s\n", mode);
if (cpupower_write_sysfs(path, linebuf, 20) <= 0)
return -1;
return 0;
}
int cpupower_set_turbo_boost(int turbo_boost)
{
char path[SYSFS_PATH_MAX];
char linebuf[2] = {};
snprintf(path, sizeof(path), PATH_TO_CPU "cpufreq/boost");
if (!is_valid_path(path))
return -1;
snprintf(linebuf, sizeof(linebuf), "%d", turbo_boost);
if (cpupower_write_sysfs(path, linebuf, 2) <= 0)
return -1;
return 0;
}
bool cpupower_amd_pstate_enabled(void)
{
char *driver = cpufreq_get_driver(0);
@ -95,7 +150,7 @@ bool cpupower_amd_pstate_enabled(void)
if (!driver)
return ret;
if (!strcmp(driver, "amd-pstate"))
if (!strncmp(driver, "amd", 3))
ret = true;
cpufreq_put_driver(driver);