Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * x86 APERF/MPERF KHz calculation for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * /sys/.../cpufreq/scaling_cur_freq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2017 Intel Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Author: Len Brown <len.brown@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/math64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/percpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/sched/isolation.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include "cpu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) struct aperfmperf_sample {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	unsigned int	khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	ktime_t	time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	u64	aperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	u64	mperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static DEFINE_PER_CPU(struct aperfmperf_sample, samples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define APERFMPERF_CACHE_THRESHOLD_MS	10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define APERFMPERF_REFRESH_DELAY_MS	10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define APERFMPERF_STALE_THRESHOLD_MS	1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  * aperfmperf_snapshot_khz()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  * On the current CPU, snapshot APERF, MPERF, and jiffies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  * unless we already did it within 10ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  * calculate kHz, save snapshot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) static void aperfmperf_snapshot_khz(void *dummy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	u64 aperf, aperf_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	u64 mperf, mperf_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	struct aperfmperf_sample *s = this_cpu_ptr(&samples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	rdmsrl(MSR_IA32_APERF, aperf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	rdmsrl(MSR_IA32_MPERF, mperf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	aperf_delta = aperf - s->aperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	mperf_delta = mperf - s->mperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	 * There is no architectural guarantee that MPERF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	 * increments faster than we can read it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	if (mperf_delta == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	s->time = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	s->aperf = aperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	s->mperf = mperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	s->khz = div64_u64((cpu_khz * aperf_delta), mperf_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) static bool aperfmperf_snapshot_cpu(int cpu, ktime_t now, bool wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	s64 time_delta = ktime_ms_delta(now, per_cpu(samples.time, cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	/* Don't bother re-computing within the cache threshold time. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	if (time_delta < APERFMPERF_CACHE_THRESHOLD_MS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	/* Return false if the previous iteration was too long ago. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	return time_delta <= APERFMPERF_STALE_THRESHOLD_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) unsigned int aperfmperf_get_khz(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	if (!cpu_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	if (!boot_cpu_has(X86_FEATURE_APERFMPERF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	if (!housekeeping_cpu(cpu, HK_FLAG_MISC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	aperfmperf_snapshot_cpu(cpu, ktime_get(), true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	return per_cpu(samples.khz, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) void arch_freq_prepare_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	ktime_t now = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	bool wait = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	if (!cpu_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	if (!boot_cpu_has(X86_FEATURE_APERFMPERF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	for_each_online_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		if (!housekeeping_cpu(cpu, HK_FLAG_MISC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		if (!aperfmperf_snapshot_cpu(cpu, now, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 			wait = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	if (wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		msleep(APERFMPERF_REFRESH_DELAY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned int arch_freq_get_on_cpu(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	if (!cpu_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	if (!boot_cpu_has(X86_FEATURE_APERFMPERF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	if (!housekeeping_cpu(cpu, HK_FLAG_MISC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (aperfmperf_snapshot_cpu(cpu, ktime_get(), true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		return per_cpu(samples.khz, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	msleep(APERFMPERF_REFRESH_DELAY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	return per_cpu(samples.khz, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }