@@ -36,11 +36,11 @@ static DEFINE_PER_CPU(struct aperfmperf_sample, samples);
* unless we already did it within 10ms
* calculate kHz, save snapshot
*/
-static void aperfmperf_snapshot_khz(void *dummy)
+static void aperfmperf_snapshot_khz(void *prev_sample)
{
u64 aperf, aperf_delta;
u64 mperf, mperf_delta;
- struct aperfmperf_sample *s = this_cpu_ptr(&samples);
+ struct aperfmperf_sample *s = prev_sample;
unsigned long flags;
local_irq_save(flags);
@@ -72,7 +72,8 @@ static bool aperfmperf_snapshot_cpu(int cpu, ktime_t now, bool wait)
if (time_delta < APERFMPERF_CACHE_THRESHOLD_MS)
return true;
- smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, wait);
+ smp_call_function_single(cpu, aperfmperf_snapshot_khz,
+ per_cpu_ptr(&samples, cpu), wait);
/* Return false if the previous iteration was too long ago. */
return time_delta <= APERFMPERF_STALE_THRESHOLD_MS;
@@ -131,7 +132,29 @@ unsigned int arch_freq_get_on_cpu(int cpu)
return per_cpu(samples.khz, cpu);
msleep(APERFMPERF_REFRESH_DELAY_MS);
- smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1);
+ smp_call_function_single(cpu, aperfmperf_snapshot_khz,
+ per_cpu_ptr(&samples, cpu), 1);
return per_cpu(samples.khz, cpu);
}
+
+unsigned int arch_freq_get_on_cpu_from_sample(int cpu, void *sample)
+{
+ struct aperfmperf_sample *s = sample;
+
+ if (!sample)
+ return 0;
+
+ if (!cpu_khz)
+ return 0;
+
+ if (!boot_cpu_has(X86_FEATURE_APERFMPERF))
+ return 0;
+
+ if (!housekeeping_cpu(cpu, HK_FLAG_MISC))
+ return 0;
+
+ smp_call_function_single(cpu, aperfmperf_snapshot_khz, s, 1);
+
+ return s->khz;
+}
@@ -695,6 +695,11 @@ __weak unsigned int arch_freq_get_on_cpu(int cpu)
return 0;
}
+__weak unsigned int arch_freq_get_on_cpu_from_sample(int cpu, void *sample)
+{
+ return 0;
+}
+
static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf)
{
ssize_t ret;
@@ -1005,6 +1005,7 @@ static inline void sched_cpufreq_governor_change(struct cpufreq_policy *policy,
extern void arch_freq_prepare_all(void);
extern unsigned int arch_freq_get_on_cpu(int cpu);
+extern unsigned int arch_freq_get_on_cpu_from_sample(int cpu, void *sample);
extern void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq,
unsigned long max_freq);