Skip to content

Commit c3a8b2b

Browse files
committed
Merge tag 'linux-cpupower-6.14-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/shuah/linux
Merge cpupower utility updates for 6.14 from Shuah Khan: "Several fixes, cleanups and AMD support enhancements: - fix TSC MHz calculation - Add install and uninstall options to bindings makefile - Add header changes for cpufreq.h to SWIG bindings - selftests/cpufreq: gitignore output files and clean them in make clean - Remove spurious return statement - Add support for parsing 'enabled' or 'disabled' strings from table - Add support for amd-pstate preferred core rankings - Don't try to read frequency from hardware when kernel uses aperf mperf - Add support for showing energy performance preference - Don't fetch maximum latency when EPP is enabled - Adjust whitespace for amd-pstate specific prints - Fix cross compilation - revise is_valid flag handling for idle_monitor" * tag 'linux-cpupower-6.14-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/shuah/linux: pm: cpupower: Add header changes for cpufreq.h to SWIG bindings pm: cpupower: Add install and uninstall options to bindings makefile cpupower: Adjust whitespace for amd-pstate specific prints cpupower: Don't fetch maximum latency when EPP is enabled cpupower: Add support for showing energy performance preference cpupower: Don't try to read frequency from hardware when kernel uses aperfmperf cpupower: Add support for amd-pstate preferred core rankings cpupower: Add support for parsing 'enabled' or 'disabled' strings from table cpupower: Remove spurious return statement cpupower: fix TSC MHz calculation cpupower: revise is_valid flag handling for idle_monitor pm: cpupower: Makefile: Fix cross compilation selftests/cpufreq: gitignore output files and clean them in make clean
2 parents 9d89551 + 8d09744 commit c3a8b2b

File tree

14 files changed

+137
-19
lines changed

14 files changed

+137
-19
lines changed

tools/power/cpupower/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,19 @@ INSTALL_SCRIPT = ${INSTALL} -m 644
8787
# to something more interesting, like "arm-linux-". If you want
8888
# to compile vs uClibc, that can be done here as well.
8989
CROSS ?= #/usr/i386-linux-uclibc/usr/bin/i386-uclibc-
90+
ifneq ($(CROSS), )
91+
CC = $(CROSS)gcc
92+
LD = $(CROSS)gcc
93+
AR = $(CROSS)ar
94+
STRIP = $(CROSS)strip
95+
RANLIB = $(CROSS)ranlib
96+
else
9097
CC ?= $(CROSS)gcc
9198
LD ?= $(CROSS)gcc
9299
AR ?= $(CROSS)ar
93100
STRIP ?= $(CROSS)strip
94101
RANLIB ?= $(CROSS)ranlib
102+
endif
95103
HOSTCC = gcc
96104
MKDIR = mkdir
97105

tools/power/cpupower/bindings/python/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ HAVE_PYCONFIG := $(shell if which python-config >/dev/null 2>&1; then echo 1; el
1111
LIB_DIR := ../../lib
1212
PY_INCLUDE = $(firstword $(shell python-config --includes))
1313
OBJECTS_LIB = $(wildcard $(LIB_DIR)/*.o)
14+
INSTALL_DIR = $(shell python3 -c "import site; print(site.getsitepackages()[0])")
1415

1516
all: _raw_pylibcpupower.so
1617

@@ -28,6 +29,15 @@ else ifeq ($(HAVE_PYCONFIG),0)
2829
endif
2930
swig -python raw_pylibcpupower.swg
3031

32+
# Only installs the Python bindings
33+
install: _raw_pylibcpupower.so
34+
install -D _raw_pylibcpupower.so $(INSTALL_DIR)/_raw_pylibcpupower.so
35+
install -D raw_pylibcpupower.py $(INSTALL_DIR)/raw_pylibcpupower.py
36+
37+
uninstall:
38+
rm -f $(INSTALL_DIR)/_raw_pylibcpupower.so
39+
rm -f $(INSTALL_DIR)/raw_pylibcpupower.py
40+
3141
# Will only clean the bindings folder; will not clean the actual cpupower folder
3242
clean:
3343
rm -f raw_pylibcpupower.py raw_pylibcpupower_wrap.c raw_pylibcpupower_wrap.o _raw_pylibcpupower.so

tools/power/cpupower/bindings/python/README

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,31 @@ To run the test script:
4848
$ python test_raw_pylibcpupower.py
4949

5050

51+
developing/using the bindings directly
52+
--------------------------------------
53+
54+
You need to add the Python bindings directory to your $PYTHONPATH.
55+
56+
You would set the path in the Bash terminal or in the Bash profile:
57+
58+
PYTHONPATH=~/linux/tools/power/cpupower/bindings/python:$PYTHONPATH
59+
60+
This allows you to set a specific repo of the bindings to use.
61+
62+
63+
installing/uninstalling
64+
-----------------------
65+
66+
Python uses a system specific site-packages folder to look up modules to import
67+
by default. You do not need to install cpupower to use the SWIG bindings.
68+
69+
You can install and uninstall the bindings to the site-packages with:
70+
71+
sudo make install
72+
73+
sudo make uninstall
74+
75+
5176
credits
5277
-------
5378

tools/power/cpupower/bindings/python/raw_pylibcpupower.swg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ void cpufreq_put_stats(struct cpufreq_stats *stats);
134134

135135
unsigned long cpufreq_get_transitions(unsigned int cpu);
136136

137+
char *cpufreq_get_energy_performance_preference(unsigned int cpu);
138+
void cpufreq_put_energy_performance_preference(char *ptr);
139+
137140
int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
138141

139142
int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq);

tools/power/cpupower/lib/cpufreq.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ unsigned long cpufreq_get_sysfs_value_from_table(unsigned int cpu,
102102
if (len == 0)
103103
return 0;
104104

105+
if (!strcmp(linebuf, "enabled\n"))
106+
return 1;
107+
if (!strcmp(linebuf, "disabled\n"))
108+
return 0;
105109
value = strtoul(linebuf, &endp, 0);
106110

107111
if (endp == linebuf || errno == ERANGE)
@@ -123,12 +127,14 @@ static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
123127
enum cpufreq_string {
124128
SCALING_DRIVER,
125129
SCALING_GOVERNOR,
130+
ENERGY_PERFORMANCE_PREFERENCE,
126131
MAX_CPUFREQ_STRING_FILES
127132
};
128133

129134
static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
130135
[SCALING_DRIVER] = "scaling_driver",
131136
[SCALING_GOVERNOR] = "scaling_governor",
137+
[ENERGY_PERFORMANCE_PREFERENCE] = "energy_performance_preference",
132138
};
133139

134140

@@ -203,6 +209,18 @@ unsigned long cpufreq_get_transition_latency(unsigned int cpu)
203209
return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
204210
}
205211

212+
char *cpufreq_get_energy_performance_preference(unsigned int cpu)
213+
{
214+
return sysfs_cpufreq_get_one_string(cpu, ENERGY_PERFORMANCE_PREFERENCE);
215+
}
216+
217+
void cpufreq_put_energy_performance_preference(char *ptr)
218+
{
219+
if (!ptr)
220+
return;
221+
free(ptr);
222+
}
223+
206224
int cpufreq_get_hardware_limits(unsigned int cpu,
207225
unsigned long *min,
208226
unsigned long *max)

tools/power/cpupower/lib/cpufreq.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
6868
unsigned long cpufreq_get_transition_latency(unsigned int cpu);
6969

7070

71+
/* determine energy performance preference
72+
*
73+
* returns NULL on failure, else the string that represents the energy performance
74+
* preference requested.
75+
*/
76+
char *cpufreq_get_energy_performance_preference(unsigned int cpu);
77+
void cpufreq_put_energy_performance_preference(char *ptr);
78+
7179
/* determine hardware CPU frequency limits
7280
*
7381
* These may be limited further by thermal, energy or other

tools/power/cpupower/utils/cpufreq-info.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ static void print_duration(unsigned long duration)
120120
} else
121121
printf("%lu ns", duration);
122122
}
123-
return;
124123
}
125124

126125
static int get_boost_mode_x86(unsigned int cpu)
@@ -255,7 +254,12 @@ static int get_freq_kernel(unsigned int cpu, unsigned int human)
255254

256255
static int get_freq_hardware(unsigned int cpu, unsigned int human)
257256
{
258-
unsigned long freq = cpufreq_get_freq_hardware(cpu);
257+
unsigned long freq;
258+
259+
if (cpupower_cpu_info.caps & CPUPOWER_CAP_APERF)
260+
return -EINVAL;
261+
262+
freq = cpufreq_get_freq_hardware(cpu);
259263
printf(_(" current CPU frequency: "));
260264
if (!freq) {
261265
printf("Unable to call hardware\n");
@@ -418,12 +422,32 @@ static int get_freq_stats(unsigned int cpu, unsigned int human)
418422
return 0;
419423
}
420424

425+
/* --epp / -z */
426+
427+
static int get_epp(unsigned int cpu, bool interactive)
428+
{
429+
char *epp;
430+
431+
epp = cpufreq_get_energy_performance_preference(cpu);
432+
if (!epp)
433+
return -EINVAL;
434+
if (interactive)
435+
printf(_(" energy performance preference: %s\n"), epp);
436+
437+
cpufreq_put_energy_performance_preference(epp);
438+
439+
return 0;
440+
}
441+
421442
/* --latency / -y */
422443

423444
static int get_latency(unsigned int cpu, unsigned int human)
424445
{
425446
unsigned long latency = cpufreq_get_transition_latency(cpu);
426447

448+
if (!get_epp(cpu, false))
449+
return -EINVAL;
450+
427451
printf(_(" maximum transition latency: "));
428452
if (!latency || latency == UINT_MAX) {
429453
printf(_(" Cannot determine or is not supported.\n"));
@@ -457,6 +481,7 @@ static void debug_output_one(unsigned int cpu)
457481
get_related_cpus(cpu);
458482
get_affected_cpus(cpu);
459483
get_latency(cpu, 1);
484+
get_epp(cpu, true);
460485
get_hardware_limits(cpu, 1);
461486

462487
freqs = cpufreq_get_available_frequencies(cpu);
@@ -497,6 +522,7 @@ static struct option info_opts[] = {
497522
{"human", no_argument, NULL, 'm'},
498523
{"no-rounding", no_argument, NULL, 'n'},
499524
{"performance", no_argument, NULL, 'c'},
525+
{"epp", no_argument, NULL, 'z'},
500526
{ },
501527
};
502528

@@ -510,7 +536,7 @@ int cmd_freq_info(int argc, char **argv)
510536
int output_param = 0;
511537

512538
do {
513-
ret = getopt_long(argc, argv, "oefwldpgrasmybnc", info_opts,
539+
ret = getopt_long(argc, argv, "oefwldpgrasmybncz", info_opts,
514540
NULL);
515541
switch (ret) {
516542
case '?':
@@ -534,6 +560,7 @@ int cmd_freq_info(int argc, char **argv)
534560
case 's':
535561
case 'y':
536562
case 'c':
563+
case 'z':
537564
if (output_param) {
538565
output_param = -1;
539566
cont = 0;
@@ -643,6 +670,9 @@ int cmd_freq_info(int argc, char **argv)
643670
case 'c':
644671
ret = get_perf_cap(cpu);
645672
break;
673+
case 'z':
674+
ret = get_epp(cpu, true);
675+
break;
646676
}
647677
if (ret)
648678
return ret;

tools/power/cpupower/utils/helpers/amd.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,17 @@ enum amd_pstate_value {
177177
AMD_PSTATE_HIGHEST_PERF,
178178
AMD_PSTATE_MAX_FREQ,
179179
AMD_PSTATE_LOWEST_NONLINEAR_FREQ,
180+
AMD_PSTATE_HW_PREFCORE,
181+
AMD_PSTATE_PREFCORE_RANKING,
180182
MAX_AMD_PSTATE_VALUE_READ_FILES,
181183
};
182184

183185
static const char *amd_pstate_value_files[MAX_AMD_PSTATE_VALUE_READ_FILES] = {
184186
[AMD_PSTATE_HIGHEST_PERF] = "amd_pstate_highest_perf",
185187
[AMD_PSTATE_MAX_FREQ] = "amd_pstate_max_freq",
186188
[AMD_PSTATE_LOWEST_NONLINEAR_FREQ] = "amd_pstate_lowest_nonlinear_freq",
189+
[AMD_PSTATE_HW_PREFCORE] = "amd_pstate_hw_prefcore",
190+
[AMD_PSTATE_PREFCORE_RANKING] = "amd_pstate_prefcore_ranking",
187191
};
188192

189193
static unsigned long amd_pstate_get_data(unsigned int cpu,
@@ -215,7 +219,9 @@ void amd_pstate_boost_init(unsigned int cpu, int *support, int *active)
215219

216220
void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding)
217221
{
218-
printf(_(" AMD PSTATE Highest Performance: %lu. Maximum Frequency: "),
222+
223+
printf(_(" amd-pstate limits:\n"));
224+
printf(_(" Highest Performance: %lu. Maximum Frequency: "),
219225
amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF));
220226
/*
221227
* If boost isn't active, the cpuinfo_max doesn't indicate real max
@@ -224,22 +230,26 @@ void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding)
224230
print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ), no_rounding);
225231
printf(".\n");
226232

227-
printf(_(" AMD PSTATE Nominal Performance: %lu. Nominal Frequency: "),
233+
printf(_(" Nominal Performance: %lu. Nominal Frequency: "),
228234
acpi_cppc_get_data(cpu, NOMINAL_PERF));
229235
print_speed(acpi_cppc_get_data(cpu, NOMINAL_FREQ) * 1000,
230236
no_rounding);
231237
printf(".\n");
232238

233-
printf(_(" AMD PSTATE Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "),
239+
printf(_(" Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "),
234240
acpi_cppc_get_data(cpu, LOWEST_NONLINEAR_PERF));
235241
print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_LOWEST_NONLINEAR_FREQ),
236242
no_rounding);
237243
printf(".\n");
238244

239-
printf(_(" AMD PSTATE Lowest Performance: %lu. Lowest Frequency: "),
245+
printf(_(" Lowest Performance: %lu. Lowest Frequency: "),
240246
acpi_cppc_get_data(cpu, LOWEST_PERF));
241247
print_speed(acpi_cppc_get_data(cpu, LOWEST_FREQ) * 1000, no_rounding);
242248
printf(".\n");
249+
250+
printf(_(" Preferred Core Support: %lu. Preferred Core Ranking: %lu.\n"),
251+
amd_pstate_get_data(cpu, AMD_PSTATE_HW_PREFCORE),
252+
amd_pstate_get_data(cpu, AMD_PSTATE_PREFCORE_RANKING));
243253
}
244254

245255
/* AMD P-State Helper Functions ************************************/

tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ static int hsw_ext_start(void)
117117

118118
for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) {
119119
for (cpu = 0; cpu < cpu_count; cpu++) {
120-
hsw_ext_get_count(num, &val, cpu);
120+
is_valid[cpu] = !hsw_ext_get_count(num, &val, cpu);
121121
previous_count[num][cpu] = val;
122122
}
123123
}
@@ -134,7 +134,7 @@ static int hsw_ext_stop(void)
134134

135135
for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) {
136136
for (cpu = 0; cpu < cpu_count; cpu++) {
137-
is_valid[cpu] = !hsw_ext_get_count(num, &val, cpu);
137+
is_valid[cpu] |= !hsw_ext_get_count(num, &val, cpu);
138138
current_count[num][cpu] = val;
139139
}
140140
}

tools/power/cpupower/utils/idle_monitor/mperf_monitor.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static int mperf_get_count_percent(unsigned int self_id, double *percent,
3333
unsigned int cpu);
3434
static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
3535
unsigned int cpu);
36-
static struct timespec time_start, time_end;
36+
static struct timespec *time_start, *time_end;
3737

3838
static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = {
3939
{
@@ -148,7 +148,7 @@ static int mperf_measure_stats(unsigned int cpu)
148148
ret = get_aperf_mperf(cpu, &aval, &mval);
149149
aperf_current_count[cpu] = aval;
150150
mperf_current_count[cpu] = mval;
151-
is_valid[cpu] = !ret;
151+
is_valid[cpu] |= !ret;
152152

153153
return 0;
154154
}
@@ -174,7 +174,7 @@ static int mperf_get_count_percent(unsigned int id, double *percent,
174174
dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
175175
mperf_cstates[id].name, mperf_diff, tsc_diff);
176176
} else if (max_freq_mode == MAX_FREQ_SYSFS) {
177-
timediff = max_frequency * timespec_diff_us(time_start, time_end);
177+
timediff = max_frequency * timespec_diff_us(time_start[cpu], time_end[cpu]);
178178
*percent = 100.0 * mperf_diff / timediff;
179179
dprint("%s: MAXFREQ - mperf_diff: %llu, time_diff: %llu\n",
180180
mperf_cstates[id].name, mperf_diff, timediff);
@@ -207,7 +207,7 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
207207
if (max_freq_mode == MAX_FREQ_TSC_REF) {
208208
/* Calculate max_freq from TSC count */
209209
tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
210-
time_diff = timespec_diff_us(time_start, time_end);
210+
time_diff = timespec_diff_us(time_start[cpu], time_end[cpu]);
211211
max_frequency = tsc_diff / time_diff;
212212
}
213213

@@ -226,9 +226,8 @@ static int mperf_start(void)
226226
{
227227
int cpu;
228228

229-
clock_gettime(CLOCK_REALTIME, &time_start);
230-
231229
for (cpu = 0; cpu < cpu_count; cpu++) {
230+
clock_gettime(CLOCK_REALTIME, &time_start[cpu]);
232231
mperf_get_tsc(&tsc_at_measure_start[cpu]);
233232
mperf_init_stats(cpu);
234233
}
@@ -243,9 +242,9 @@ static int mperf_stop(void)
243242
for (cpu = 0; cpu < cpu_count; cpu++) {
244243
mperf_measure_stats(cpu);
245244
mperf_get_tsc(&tsc_at_measure_end[cpu]);
245+
clock_gettime(CLOCK_REALTIME, &time_end[cpu]);
246246
}
247247

248-
clock_gettime(CLOCK_REALTIME, &time_end);
249248
return 0;
250249
}
251250

@@ -349,6 +348,8 @@ struct cpuidle_monitor *mperf_register(void)
349348
aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
350349
tsc_at_measure_start = calloc(cpu_count, sizeof(unsigned long long));
351350
tsc_at_measure_end = calloc(cpu_count, sizeof(unsigned long long));
351+
time_start = calloc(cpu_count, sizeof(struct timespec));
352+
time_end = calloc(cpu_count, sizeof(struct timespec));
352353
mperf_monitor.name_len = strlen(mperf_monitor.name);
353354
return &mperf_monitor;
354355
}
@@ -361,6 +362,8 @@ void mperf_unregister(void)
361362
free(aperf_current_count);
362363
free(tsc_at_measure_start);
363364
free(tsc_at_measure_end);
365+
free(time_start);
366+
free(time_end);
364367
free(is_valid);
365368
}
366369

0 commit comments

Comments
 (0)