Commit 8a05c311 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'pm-cpufreq-x86', 'pm-cpufreq-docs' and 'intel_pstate'

* pm-cpufreq-x86:
  cpufreq: x86: Make scaling_cur_freq behave more as expected

* pm-cpufreq-docs:
  cpufreq: docs: Add missing cpuinfo_cur_freq description

* intel_pstate:
  cpufreq: intel_pstate: Drop ->get from intel_pstate structure
...@@ -237,6 +237,14 @@ are the following: ...@@ -237,6 +237,14 @@ are the following:
This attribute is not present if the scaling driver in use does not This attribute is not present if the scaling driver in use does not
support it. support it.
``cpuinfo_cur_freq``
Current frequency of the CPUs belonging to this policy as obtained from
the hardware (in KHz).
This is expected to be the frequency the hardware actually runs at.
If that frequency cannot be determined, this attribute should not
be present.
``cpuinfo_max_freq`` ``cpuinfo_max_freq``
Maximum possible operating frequency the CPUs belonging to this policy Maximum possible operating frequency the CPUs belonging to this policy
can run at (in kHz). can run at (in kHz).
......
...@@ -8,20 +8,25 @@ ...@@ -8,20 +8,25 @@
* This file is licensed under GPLv2. * This file is licensed under GPLv2.
*/ */
#include <linux/jiffies.h> #include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/math64.h> #include <linux/math64.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/smp.h> #include <linux/smp.h>
struct aperfmperf_sample { struct aperfmperf_sample {
unsigned int khz; unsigned int khz;
unsigned long jiffies; ktime_t time;
u64 aperf; u64 aperf;
u64 mperf; u64 mperf;
}; };
static DEFINE_PER_CPU(struct aperfmperf_sample, samples); static DEFINE_PER_CPU(struct aperfmperf_sample, samples);
#define APERFMPERF_CACHE_THRESHOLD_MS 10
#define APERFMPERF_REFRESH_DELAY_MS 20
#define APERFMPERF_STALE_THRESHOLD_MS 1000
/* /*
* aperfmperf_snapshot_khz() * aperfmperf_snapshot_khz()
* On the current CPU, snapshot APERF, MPERF, and jiffies * On the current CPU, snapshot APERF, MPERF, and jiffies
...@@ -33,9 +38,11 @@ static void aperfmperf_snapshot_khz(void *dummy) ...@@ -33,9 +38,11 @@ static void aperfmperf_snapshot_khz(void *dummy)
u64 aperf, aperf_delta; u64 aperf, aperf_delta;
u64 mperf, mperf_delta; u64 mperf, mperf_delta;
struct aperfmperf_sample *s = this_cpu_ptr(&samples); struct aperfmperf_sample *s = this_cpu_ptr(&samples);
ktime_t now = ktime_get();
s64 time_delta = ktime_ms_delta(now, s->time);
/* Don't bother re-computing within 10 ms */ /* Don't bother re-computing within the cache threshold time. */
if (time_before(jiffies, s->jiffies + HZ/100)) if (time_delta < APERFMPERF_CACHE_THRESHOLD_MS)
return; return;
rdmsrl(MSR_IA32_APERF, aperf); rdmsrl(MSR_IA32_APERF, aperf);
...@@ -51,22 +58,21 @@ static void aperfmperf_snapshot_khz(void *dummy) ...@@ -51,22 +58,21 @@ static void aperfmperf_snapshot_khz(void *dummy)
if (mperf_delta == 0) if (mperf_delta == 0)
return; return;
/* s->time = now;
* if (cpu_khz * aperf_delta) fits into ULLONG_MAX, then
* khz = (cpu_khz * aperf_delta) / mperf_delta
*/
if (div64_u64(ULLONG_MAX, cpu_khz) > aperf_delta)
s->khz = div64_u64((cpu_khz * aperf_delta), mperf_delta);
else /* khz = aperf_delta / (mperf_delta / cpu_khz) */
s->khz = div64_u64(aperf_delta,
div64_u64(mperf_delta, cpu_khz));
s->jiffies = jiffies;
s->aperf = aperf; s->aperf = aperf;
s->mperf = mperf; s->mperf = mperf;
/* If the previous iteration was too long ago, discard it. */
if (time_delta > APERFMPERF_STALE_THRESHOLD_MS)
s->khz = 0;
else
s->khz = div64_u64((cpu_khz * aperf_delta), mperf_delta);
} }
unsigned int arch_freq_get_on_cpu(int cpu) unsigned int arch_freq_get_on_cpu(int cpu)
{ {
unsigned int khz;
if (!cpu_khz) if (!cpu_khz)
return 0; return 0;
...@@ -74,6 +80,12 @@ unsigned int arch_freq_get_on_cpu(int cpu) ...@@ -74,6 +80,12 @@ unsigned int arch_freq_get_on_cpu(int cpu)
return 0; return 0;
smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1); smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1);
khz = per_cpu(samples.khz, cpu);
if (khz)
return khz;
msleep(APERFMPERF_REFRESH_DELAY_MS);
smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1);
return per_cpu(samples.khz, cpu); return per_cpu(samples.khz, cpu);
} }
...@@ -1922,13 +1922,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum) ...@@ -1922,13 +1922,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
return 0; return 0;
} }
static unsigned int intel_pstate_get(unsigned int cpu_num)
{
struct cpudata *cpu = all_cpu_data[cpu_num];
return cpu ? get_avg_frequency(cpu) : 0;
}
static void intel_pstate_set_update_util_hook(unsigned int cpu_num) static void intel_pstate_set_update_util_hook(unsigned int cpu_num)
{ {
struct cpudata *cpu = all_cpu_data[cpu_num]; struct cpudata *cpu = all_cpu_data[cpu_num];
...@@ -2169,7 +2162,6 @@ static struct cpufreq_driver intel_pstate = { ...@@ -2169,7 +2162,6 @@ static struct cpufreq_driver intel_pstate = {
.setpolicy = intel_pstate_set_policy, .setpolicy = intel_pstate_set_policy,
.suspend = intel_pstate_hwp_save_state, .suspend = intel_pstate_hwp_save_state,
.resume = intel_pstate_resume, .resume = intel_pstate_resume,
.get = intel_pstate_get,
.init = intel_pstate_cpu_init, .init = intel_pstate_cpu_init,
.exit = intel_pstate_cpu_exit, .exit = intel_pstate_cpu_exit,
.stop_cpu = intel_pstate_stop_cpu, .stop_cpu = intel_pstate_stop_cpu,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment