mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-29 17:22:07 +00:00
cpupower: fix TSC MHz calculation
Commit 'cpupower: Make TSC read per CPU for Mperf monitor' (c2adb1877b
) changes TSC counter reads per cpu, but left time diff global (from start of all cpus to end of all cpus), thus diff(time) is too large for a cpu's tsc counting, resulting in far less than acutal TSC_Mhz and thus `cpupower monitor` showing far less than actual cpu realtime frequency. /proc/cpuinfo shows frequency: cat /proc/cpuinfo | egrep -e 'processor' -e 'MHz' ... processor : 171 cpu MHz : 4108.498 ... before fix (System 100% busy): | Mperf || Idle_Stats CPU| C0 | Cx | Freq || POLL | C1 | C2 171| 0.77| 99.23| 2279|| 0.00| 0.00| 0.00 after fix (System 100% busy): | Mperf || Idle_Stats CPU| C0 | Cx | Freq || POLL | C1 | C2 171| 0.46| 99.54| 4095|| 0.00| 0.00| 0.00 Fixes:c2adb1877b
("cpupower: Make TSC read per CPU for Mperf monitor") Signed-off-by: He Rongguang <herongguang@linux.alibaba.com> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
This commit is contained in:
parent
46fd8c707b
commit
9d6c0e5851
@ -33,7 +33,7 @@ static int mperf_get_count_percent(unsigned int self_id, double *percent,
|
||||
unsigned int cpu);
|
||||
static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
|
||||
unsigned int cpu);
|
||||
static struct timespec time_start, time_end;
|
||||
static struct timespec *time_start, *time_end;
|
||||
|
||||
static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = {
|
||||
{
|
||||
@ -174,7 +174,7 @@ static int mperf_get_count_percent(unsigned int id, double *percent,
|
||||
dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
|
||||
mperf_cstates[id].name, mperf_diff, tsc_diff);
|
||||
} else if (max_freq_mode == MAX_FREQ_SYSFS) {
|
||||
timediff = max_frequency * timespec_diff_us(time_start, time_end);
|
||||
timediff = max_frequency * timespec_diff_us(time_start[cpu], time_end[cpu]);
|
||||
*percent = 100.0 * mperf_diff / timediff;
|
||||
dprint("%s: MAXFREQ - mperf_diff: %llu, time_diff: %llu\n",
|
||||
mperf_cstates[id].name, mperf_diff, timediff);
|
||||
@ -207,7 +207,7 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
|
||||
if (max_freq_mode == MAX_FREQ_TSC_REF) {
|
||||
/* Calculate max_freq from TSC count */
|
||||
tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
|
||||
time_diff = timespec_diff_us(time_start, time_end);
|
||||
time_diff = timespec_diff_us(time_start[cpu], time_end[cpu]);
|
||||
max_frequency = tsc_diff / time_diff;
|
||||
}
|
||||
|
||||
@ -226,9 +226,8 @@ static int mperf_start(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &time_start);
|
||||
|
||||
for (cpu = 0; cpu < cpu_count; cpu++) {
|
||||
clock_gettime(CLOCK_REALTIME, &time_start[cpu]);
|
||||
mperf_get_tsc(&tsc_at_measure_start[cpu]);
|
||||
mperf_init_stats(cpu);
|
||||
}
|
||||
@ -243,9 +242,9 @@ static int mperf_stop(void)
|
||||
for (cpu = 0; cpu < cpu_count; cpu++) {
|
||||
mperf_measure_stats(cpu);
|
||||
mperf_get_tsc(&tsc_at_measure_end[cpu]);
|
||||
clock_gettime(CLOCK_REALTIME, &time_end[cpu]);
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &time_end);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -349,6 +348,8 @@ struct cpuidle_monitor *mperf_register(void)
|
||||
aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
|
||||
tsc_at_measure_start = calloc(cpu_count, sizeof(unsigned long long));
|
||||
tsc_at_measure_end = calloc(cpu_count, sizeof(unsigned long long));
|
||||
time_start = calloc(cpu_count, sizeof(struct timespec));
|
||||
time_end = calloc(cpu_count, sizeof(struct timespec));
|
||||
mperf_monitor.name_len = strlen(mperf_monitor.name);
|
||||
return &mperf_monitor;
|
||||
}
|
||||
@ -361,6 +362,8 @@ void mperf_unregister(void)
|
||||
free(aperf_current_count);
|
||||
free(tsc_at_measure_start);
|
||||
free(tsc_at_measure_end);
|
||||
free(time_start);
|
||||
free(time_end);
|
||||
free(is_valid);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user