From fa2187cf82ced867cf17ea4836c3565cba92dbc5 Mon Sep 17 00:00:00 2001 From: Fabio Belavenuto Date: Wed, 11 Jan 2023 20:58:13 -0300 Subject: [PATCH] Adding cpufreq modules --- apollolake-4.4.180/cpufreq_conservative.ko | Bin 0 -> 16392 bytes apollolake-4.4.180/cpufreq_ondemand.ko | Bin 0 -> 20640 bytes apollolake-4.4.180/cpufreq_userspace.ko | Bin 0 -> 6368 bytes broadwell-4.4.180/cpufreq_conservative.ko | Bin 0 -> 16392 bytes broadwell-4.4.180/cpufreq_ondemand.ko | Bin 0 -> 20576 bytes broadwell-4.4.180/cpufreq_userspace.ko | Bin 0 -> 6368 bytes broadwellnk-4.4.180/cpufreq_conservative.ko | Bin 0 -> 16392 bytes broadwellnk-4.4.180/cpufreq_ondemand.ko | Bin 0 -> 20576 bytes broadwellnk-4.4.180/cpufreq_userspace.ko | Bin 0 -> 6368 bytes bromolow-3.10.108/cpufreq_conservative.ko | Bin 0 -> 16192 bytes bromolow-3.10.108/cpufreq_ondemand.ko | Bin 0 -> 20728 bytes bromolow-3.10.108/cpufreq_userspace.ko | Bin 0 -> 10408 bytes denverton-4.4.180/cpufreq_conservative.ko | Bin 0 -> 16392 bytes denverton-4.4.180/cpufreq_ondemand.ko | Bin 0 -> 20640 bytes denverton-4.4.180/cpufreq_userspace.ko | Bin 0 -> 6368 bytes epyc7002-5.10.55/scsi_transport_sas.ko | Bin 0 -> 61720 bytes geminilake-4.4.180/cpufreq_conservative.ko | Bin 0 -> 16392 bytes geminilake-4.4.180/cpufreq_ondemand.ko | Bin 0 -> 20576 bytes geminilake-4.4.180/cpufreq_userspace.ko | Bin 0 -> 6368 bytes r1000-4.4.180/cpufreq_conservative.ko | Bin 0 -> 16392 bytes r1000-4.4.180/cpufreq_ondemand.ko | Bin 0 -> 20576 bytes r1000-4.4.180/cpufreq_userspace.ko | Bin 0 -> 6368 bytes src/.compile.sh | 10 +- src/PLATFORMS | 9 +- src/cpufreq/3.x/Makefile | 39 + src/cpufreq/3.x/cpufreq_conservative.c | 416 ++++++ src/cpufreq/3.x/cpufreq_governor.h | 270 ++++ src/cpufreq/3.x/cpufreq_ondemand.c | 642 ++++++++ src/cpufreq/3.x/cpufreq_userspace.c | 222 +++ src/cpufreq/3.x/intel_pstate.c | 764 ++++++++++ src/cpufreq/4.x/Makefile | 37 + src/cpufreq/4.x/cpufreq_conservative.c | 406 ++++++ src/cpufreq/4.x/cpufreq_governor.h | 281 ++++ src/cpufreq/4.x/cpufreq_ondemand.c | 620 ++++++++ src/cpufreq/4.x/cpufreq_powersave.c | 64 + src/cpufreq/4.x/cpufreq_userspace.c | 156 ++ src/cpufreq/4.x/intel_pstate.c | 1460 +++++++++++++++++++ v1000-4.4.180/cpufreq_conservative.ko | Bin 0 -> 16392 bytes v1000-4.4.180/cpufreq_ondemand.ko | Bin 0 -> 20576 bytes v1000-4.4.180/cpufreq_userspace.ko | Bin 0 -> 6368 bytes 40 files changed, 5383 insertions(+), 13 deletions(-) create mode 100644 apollolake-4.4.180/cpufreq_conservative.ko create mode 100644 apollolake-4.4.180/cpufreq_ondemand.ko create mode 100644 apollolake-4.4.180/cpufreq_userspace.ko create mode 100644 broadwell-4.4.180/cpufreq_conservative.ko create mode 100644 broadwell-4.4.180/cpufreq_ondemand.ko create mode 100644 broadwell-4.4.180/cpufreq_userspace.ko create mode 100644 broadwellnk-4.4.180/cpufreq_conservative.ko create mode 100644 broadwellnk-4.4.180/cpufreq_ondemand.ko create mode 100644 broadwellnk-4.4.180/cpufreq_userspace.ko create mode 100644 bromolow-3.10.108/cpufreq_conservative.ko create mode 100644 bromolow-3.10.108/cpufreq_ondemand.ko create mode 100644 bromolow-3.10.108/cpufreq_userspace.ko create mode 100644 denverton-4.4.180/cpufreq_conservative.ko create mode 100644 denverton-4.4.180/cpufreq_ondemand.ko create mode 100644 denverton-4.4.180/cpufreq_userspace.ko create mode 100644 epyc7002-5.10.55/scsi_transport_sas.ko create mode 100644 geminilake-4.4.180/cpufreq_conservative.ko create mode 100644 geminilake-4.4.180/cpufreq_ondemand.ko create mode 100644 geminilake-4.4.180/cpufreq_userspace.ko create mode 100644 r1000-4.4.180/cpufreq_conservative.ko create mode 100644 r1000-4.4.180/cpufreq_ondemand.ko create mode 100644 r1000-4.4.180/cpufreq_userspace.ko create mode 100644 src/cpufreq/3.x/Makefile create mode 100644 src/cpufreq/3.x/cpufreq_conservative.c create mode 100644 src/cpufreq/3.x/cpufreq_governor.h create mode 100644 src/cpufreq/3.x/cpufreq_ondemand.c create mode 100644 src/cpufreq/3.x/cpufreq_userspace.c create mode 100644 src/cpufreq/3.x/intel_pstate.c create mode 100644 src/cpufreq/4.x/Makefile create mode 100644 src/cpufreq/4.x/cpufreq_conservative.c create mode 100644 src/cpufreq/4.x/cpufreq_governor.h create mode 100644 src/cpufreq/4.x/cpufreq_ondemand.c create mode 100644 src/cpufreq/4.x/cpufreq_powersave.c create mode 100644 src/cpufreq/4.x/cpufreq_userspace.c create mode 100644 src/cpufreq/4.x/intel_pstate.c create mode 100644 v1000-4.4.180/cpufreq_conservative.ko create mode 100644 v1000-4.4.180/cpufreq_ondemand.ko create mode 100644 v1000-4.4.180/cpufreq_userspace.ko diff --git a/apollolake-4.4.180/cpufreq_conservative.ko b/apollolake-4.4.180/cpufreq_conservative.ko new file mode 100644 index 0000000000000000000000000000000000000000..a6856b0abc72642ae25f329a5ae00a6ae3030ddb GIT binary patch literal 16392 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 literal 0 HcmV?d00001 diff --git a/broadwellnk-4.4.180/cpufreq_conservative.ko b/broadwellnk-4.4.180/cpufreq_conservative.ko new file mode 100644 index 0000000000000000000000000000000000000000..c4511d8bc9d8dfc71feb1f23eb48217d406211c7 GIT binary patch literal 16392 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 literal 0 HcmV?d00001 diff --git a/broadwellnk-4.4.180/cpufreq_ondemand.ko b/broadwellnk-4.4.180/cpufreq_ondemand.ko new file mode 100644 index 0000000000000000000000000000000000000000..ede2bb880a5d7c39304962d2253d3e6b9e9b0b9c GIT binary patch literal 20576 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 literal 0 HcmV?d00001 diff --git a/bromolow-3.10.108/cpufreq_conservative.ko b/bromolow-3.10.108/cpufreq_conservative.ko new file mode 100644 index 0000000000000000000000000000000000000000..74960e1f97a8e1b255d75b943d67d84ce7ea919e GIT binary patch literal 16192 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 literal 0 HcmV?d00001 diff --git a/bromolow-3.10.108/cpufreq_ondemand.ko b/bromolow-3.10.108/cpufreq_ondemand.ko new file mode 100644 index 0000000000000000000000000000000000000000..285ed77644ff14953baa439e2bb1fe5e417cbe07 GIT binary patch literal 20728 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 HrbF>RPqMnR literal 0 HcmV?d00001 diff --git a/bromolow-3.10.108/cpufreq_userspace.ko b/bromolow-3.10.108/cpufreq_userspace.ko new file mode 100644 index 0000000000000000000000000000000000000000..1ded78cd3799dbb60b7077b4577f50e183d4967b GIT binary patch literal 10408 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 literal 0 HcmV?d00001 diff --git a/denverton-4.4.180/cpufreq_conservative.ko b/denverton-4.4.180/cpufreq_conservative.ko new file mode 100644 index 0000000000000000000000000000000000000000..471dc9dfa60cfa369a12f081a2f5a7fffa9da38a GIT binary patch literal 16392 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 literal 0 HcmV?d00001 diff --git a/denverton-4.4.180/cpufreq_ondemand.ko b/denverton-4.4.180/cpufreq_ondemand.ko new file mode 100644 index 0000000000000000000000000000000000000000..9527edf0fb2929d871aef243d88ce9b3632a19b5 GIT binary patch literal 20640 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 hrTsbnpHM&ineoFptycTbFMM?Y z+iYUz`}il@Y@n*`yCqv&{cdRX^&V;X8?yCZjLw@Xbt+Te+#iP4*T{kMr+<@qEHgQI z@*f{AE-rp_KDl-dN2~E{{qk({O*A2M?a`s^e6yA5`N@;Xwb0+H2aCzp3;kcrF7$1y zIk$|}iWAAXb+8n>j+{@&z4ZZD(Xh6UUX$^$l+*>8v5ri$ zuOD@5PB@8n&e!olc%yMR-J7iqM=`K<1KIhJiD<^D#^lM@aT=WegZp5^l2@I;ef!|t z!s6nIPtiIJ);OhyJqlA!o?MRH8C;3!Hu;t6Cd;k{{-%62n0C!4jKDKpubRu7dLAP} z+0RDV%A2-l4)54ArV6H)cde>#Iri|#o^c$kRUL?UN-H`~ny&4*+WI!zdX)?O8OI&o z=2R@(DrvuToq}`FD_Po5*|LK}=_v&Cg1Pk`ZExUtX1T0AY}rL^$gPypIk%#RVY=fM z^`Nx1RZ+pLns&h(R<7w|ZrdE*uON3NSG4lOoAu3lYH;A^+P+w zvUpTo+FkJJ+@KBW_v-`j8C{0x-cuDnH>GsX zcUyXfE!*);y=VveRA7}08?A!UU9+6iee;k{CLB_}^vy$&?-X)=4rx<*3c`gu*cxpZ zQ$f*yq-9g-aPnC8v_rf&ROumsUNv2KW2pnnffKCc*l_mxGnQw-zyJxRJWuI)r&2L( zs4lD>X1>w$bNSLYFLXkMU!i4z3AJJwhCo8C?1Cqk;dsvV3jP_2K!zURIY9nhq;C!J zhzCD^DEB}^o@(eRg>fhkKtud!=qYua4%WRP&ZCv$YgQ%1FQ@1Te-4lyb#)tO>p0=; z!*dkMYlIJx|0~k}3H24^Me1!Zk)P}2h%`bU@rQ5a>?Nx6>p^;EOT?&ww2yeVgyH>(}u9EzCAqKe_ z@ax39cz^E(yi+v;UGPj7d?MtJ)|2@QUE-ZCc&!WmmoE5AUGNiK@Kaszvw*J>@9Cb_ zvMI$E0MGQJOO8=gTfU3nE_D*$?j*N<8ld!m&=7HzndV z97r-KaJkOA1fGD{0~Ehk@XLCNUE<3kUe@z_fy@2+a~GatB3|;mDB?A$5fz?eD7Zdy zUatyV&g)IVFXweZ;2VGo|0ja-p}>CzK0goF&_jbt&WmfndhUkC!rxnr$2$n~TuOYu zh-W_J!P0J|I+zDtyw$M325c0J#m4sn4Qv#~t1UOIP2vQrEEyQjcOryl1di*>KJ#I` z#PNHFg6j6rYW+D)^FaJIfqz>Q&z+w@Bldjhb;|$pCFb7=<2&VVbjXiu9M8X>^4|+u%0DSTa!bKlQCQ>ih<1GZzi2$3%~Ci& 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 EANEDW*Z=?k literal 0 HcmV?d00001 diff --git a/geminilake-4.4.180/cpufreq_conservative.ko b/geminilake-4.4.180/cpufreq_conservative.ko new file mode 100644 index 0000000000000000000000000000000000000000..51708624217c84a8f3df6b45d6675298a2e4e5e3 GIT binary patch literal 16392 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 literal 0 HcmV?d00001 diff --git a/geminilake-4.4.180/cpufreq_ondemand.ko b/geminilake-4.4.180/cpufreq_ondemand.ko new file mode 100644 index 0000000000000000000000000000000000000000..5f6d1d619dcc2a23bfd257991053d6e6bdd765c4 GIT binary patch literal 20576 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 literal 0 HcmV?d00001 diff --git a/src/.compile.sh b/src/.compile.sh index 26339d18c..962dbad59 100755 --- a/src/.compile.sh +++ b/src/.compile.sh @@ -24,11 +24,11 @@ function compile-module() { done < PLATFORMS } -if [ -f ../../arpl/PLATFORMS ]; then - cp ../../arpl/PLATFORMS PLATFORMS -else - curl -sLO "https://github.com/fbelavenuto/arpl/raw/main/PLATFORMS" -fi +#if [ -f ../../arpl/PLATFORMS ]; then +# cp ../../arpl/PLATFORMS PLATFORMS +#else +# curl -sLO "https://github.com/fbelavenuto/arpl/raw/main/PLATFORMS" +#fi if [ $# -ge 1 ]; then for A in $@; do diff --git a/src/PLATFORMS b/src/PLATFORMS index 5173e00d7..39b9e0f48 100644 --- a/src/PLATFORMS +++ b/src/PLATFORMS @@ -1,8 +1 @@ -bromolow 3.10.108 -apollolake 4.4.180 -broadwell 4.4.180 -broadwellnk 4.4.180 -denverton 4.4.180 -geminilake 4.4.180 -v1000 4.4.180 -r1000 4.4.180 +epyc7002 5.10.55 diff --git a/src/cpufreq/3.x/Makefile b/src/cpufreq/3.x/Makefile new file mode 100644 index 000000000..76985a5ee --- /dev/null +++ b/src/cpufreq/3.x/Makefile @@ -0,0 +1,39 @@ +# CPUfreq governors +#obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o +#obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o +obj-m += cpufreq_userspace.o +obj-m += cpufreq_ondemand.o +obj-m += cpufreq_conservative.o +#obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o + +# CPUfreq cross-arch helpers +#obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o + +#obj-$(CONFIG_GENERIC_CPUFREQ_CPU0) += cpufreq-cpu0.o + +################################################################################## +# x86 drivers. +# Link order matters. K8 is preferred to ACPI because of firmware bugs in early +# K8 systems. This is still the case but acpi-cpufreq errors out so that +# powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers. +# speedstep-* is preferred over p4-clockmod. + +#obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o mperf.o +#obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o +#obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o +#obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o +#obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o +#obj-$(CONFIG_X86_LONGHAUL) += longhaul.o +#obj-$(CONFIG_X86_E_POWERSAVER) += e_powersaver.o +#obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o +#obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o +#obj-$(CONFIG_X86_LONGRUN) += longrun.o +#obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o +#obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o +#obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o +#obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o +#obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o +#obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o +#obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o +#obj-m += intel_pstate.o +#obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) += amd_freq_sensitivity.o diff --git a/src/cpufreq/3.x/cpufreq_conservative.c b/src/cpufreq/3.x/cpufreq_conservative.c new file mode 100644 index 000000000..f34e81916 --- /dev/null +++ b/src/cpufreq/3.x/cpufreq_conservative.c @@ -0,0 +1,416 @@ +/* + * drivers/cpufreq/cpufreq_conservative.c + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * (C) 2009 Alexander Clouter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpufreq_governor.h" + +/* Conservative governor macros */ +#define DEF_FREQUENCY_UP_THRESHOLD (80) +#define DEF_FREQUENCY_DOWN_THRESHOLD (20) +#define DEF_FREQUENCY_STEP (5) +#define DEF_SAMPLING_DOWN_FACTOR (1) +#define MAX_SAMPLING_DOWN_FACTOR (10) + +static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info); + +static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners, + struct cpufreq_policy *policy) +{ + unsigned int freq_target = (cs_tuners->freq_step * policy->max) / 100; + + /* max freq cannot be less than 100. But who knows... */ + if (unlikely(freq_target == 0)) + freq_target = DEF_FREQUENCY_STEP; + + return freq_target; +} + +/* + * Every sampling_rate, we check, if current idle time is less than 20% + * (default), then we try to increase frequency. Every sampling_rate * + * sampling_down_factor, we check, if current idle time is more than 80% + * (default), then we try to decrease frequency + * + * Any frequency increase takes it to the maximum frequency. Frequency reduction + * happens at minimum steps of 5% (default) of maximum frequency + */ +static void cs_check_cpu(int cpu, unsigned int load) +{ + struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, cpu); + struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy; + struct dbs_data *dbs_data = policy->governor_data; + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + + /* + * break out if we 'cannot' reduce the speed as the user might + * want freq_step to be zero + */ + if (cs_tuners->freq_step == 0) + return; + + /* Check for frequency increase */ + if (load > cs_tuners->up_threshold) { + dbs_info->down_skip = 0; + + /* if we are already at full speed then break out early */ + if (dbs_info->requested_freq == policy->max) + return; + + dbs_info->requested_freq += get_freq_target(cs_tuners, policy); + if (dbs_info->requested_freq > policy->max) + dbs_info->requested_freq = policy->max; + + __cpufreq_driver_target(policy, dbs_info->requested_freq, + CPUFREQ_RELATION_H); + return; + } + + /* if sampling_down_factor is active break out early */ + if (++dbs_info->down_skip < cs_tuners->sampling_down_factor) + return; + dbs_info->down_skip = 0; + + /* Check for frequency decrease */ + if (load < cs_tuners->down_threshold) { + /* + * if we cannot reduce the frequency anymore, break out early + */ + if (policy->cur == policy->min) + return; + + dbs_info->requested_freq -= get_freq_target(cs_tuners, policy); + if (dbs_info->requested_freq < policy->min) + dbs_info->requested_freq = policy->min; + + __cpufreq_driver_target(policy, dbs_info->requested_freq, + CPUFREQ_RELATION_L); + return; + } +} + +static void cs_dbs_timer(struct work_struct *work) +{ + struct cs_cpu_dbs_info_s *dbs_info = container_of(work, + struct cs_cpu_dbs_info_s, cdbs.work.work); + unsigned int cpu = dbs_info->cdbs.cur_policy->cpu; + struct cs_cpu_dbs_info_s *core_dbs_info = &per_cpu(cs_cpu_dbs_info, + cpu); + struct dbs_data *dbs_data = dbs_info->cdbs.cur_policy->governor_data; + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + int delay = delay_for_sampling_rate(cs_tuners->sampling_rate); + bool modify_all = true; + + mutex_lock(&core_dbs_info->cdbs.timer_mutex); + if (!need_load_eval(&core_dbs_info->cdbs, cs_tuners->sampling_rate)) + modify_all = false; + else + dbs_check_cpu(dbs_data, cpu); + + gov_queue_work(dbs_data, dbs_info->cdbs.cur_policy, delay, modify_all); + mutex_unlock(&core_dbs_info->cdbs.timer_mutex); +} + +static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cpufreq_freqs *freq = data; + struct cs_cpu_dbs_info_s *dbs_info = + &per_cpu(cs_cpu_dbs_info, freq->cpu); + struct cpufreq_policy *policy; + + if (!dbs_info->enable) + return 0; + + policy = dbs_info->cdbs.cur_policy; + + /* + * we only care if our internally tracked freq moves outside the 'valid' + * ranges of frequency available to us otherwise we do not change it + */ + if (dbs_info->requested_freq > policy->max + || dbs_info->requested_freq < policy->min) + dbs_info->requested_freq = freq->new; + + return 0; +} + +/************************** sysfs interface ************************/ +static struct common_dbs_data cs_dbs_cdata; + +static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) + return -EINVAL; + + cs_tuners->sampling_down_factor = input; + return count; +} + +static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1) + return -EINVAL; + + cs_tuners->sampling_rate = max(input, dbs_data->min_sampling_rate); + return count; +} + +static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold) + return -EINVAL; + + cs_tuners->up_threshold = input; + return count; +} + +static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + /* cannot be lower than 1 otherwise freq will not fall */ + if (ret != 1 || input < 1 || input > 100 || + input >= cs_tuners->up_threshold) + return -EINVAL; + + cs_tuners->down_threshold = input; + return count; +} + +static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input, j; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + if (input > 1) + input = 1; + + if (input == cs_tuners->ignore_nice_load) /* nothing to do */ + return count; + + cs_tuners->ignore_nice_load = input; + + /* we need to re-evaluate prev_cpu_idle */ + for_each_online_cpu(j) { + struct cs_cpu_dbs_info_s *dbs_info; + dbs_info = &per_cpu(cs_cpu_dbs_info, j); + dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, + &dbs_info->cdbs.prev_cpu_wall, 0); + if (cs_tuners->ignore_nice_load) + dbs_info->cdbs.prev_cpu_nice = + kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + } + return count; +} + +static ssize_t store_freq_step(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1) + return -EINVAL; + + if (input > 100) + input = 100; + + /* + * no need to test here if freq_step is zero as the user might actually + * want this, they would be crazy though :) + */ + cs_tuners->freq_step = input; + return count; +} + +show_store_one(cs, sampling_rate); +show_store_one(cs, sampling_down_factor); +show_store_one(cs, up_threshold); +show_store_one(cs, down_threshold); +show_store_one(cs, ignore_nice_load); +show_store_one(cs, freq_step); +declare_show_sampling_rate_min(cs); + +gov_sys_pol_attr_rw(sampling_rate); +gov_sys_pol_attr_rw(sampling_down_factor); +gov_sys_pol_attr_rw(up_threshold); +gov_sys_pol_attr_rw(down_threshold); +gov_sys_pol_attr_rw(ignore_nice_load); +gov_sys_pol_attr_rw(freq_step); +gov_sys_pol_attr_ro(sampling_rate_min); + +static struct attribute *dbs_attributes_gov_sys[] = { + &sampling_rate_min_gov_sys.attr, + &sampling_rate_gov_sys.attr, + &sampling_down_factor_gov_sys.attr, + &up_threshold_gov_sys.attr, + &down_threshold_gov_sys.attr, + &ignore_nice_load_gov_sys.attr, + &freq_step_gov_sys.attr, + NULL +}; + +static struct attribute_group cs_attr_group_gov_sys = { + .attrs = dbs_attributes_gov_sys, + .name = "conservative", +}; + +static struct attribute *dbs_attributes_gov_pol[] = { + &sampling_rate_min_gov_pol.attr, + &sampling_rate_gov_pol.attr, + &sampling_down_factor_gov_pol.attr, + &up_threshold_gov_pol.attr, + &down_threshold_gov_pol.attr, + &ignore_nice_load_gov_pol.attr, + &freq_step_gov_pol.attr, + NULL +}; + +static struct attribute_group cs_attr_group_gov_pol = { + .attrs = dbs_attributes_gov_pol, + .name = "conservative", +}; + +/************************** sysfs end ************************/ + +static int cs_init(struct dbs_data *dbs_data) +{ + struct cs_dbs_tuners *tuners; + + tuners = kzalloc(sizeof(struct cs_dbs_tuners), GFP_KERNEL); + if (!tuners) { + pr_err("%s: kzalloc failed\n", __func__); + return -ENOMEM; + } + + tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; + tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; + tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; + tuners->ignore_nice_load = 0; + tuners->freq_step = DEF_FREQUENCY_STEP; + + dbs_data->tuners = tuners; + dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * + jiffies_to_usecs(10); + mutex_init(&dbs_data->mutex); + return 0; +} + +static void cs_exit(struct dbs_data *dbs_data) +{ + kfree(dbs_data->tuners); +} + +define_get_cpu_dbs_routines(cs_cpu_dbs_info); + +static struct notifier_block cs_cpufreq_notifier_block = { + .notifier_call = dbs_cpufreq_notifier, +}; + +static struct cs_ops cs_ops = { + .notifier_block = &cs_cpufreq_notifier_block, +}; + +static struct common_dbs_data cs_dbs_cdata = { + .governor = GOV_CONSERVATIVE, + .attr_group_gov_sys = &cs_attr_group_gov_sys, + .attr_group_gov_pol = &cs_attr_group_gov_pol, + .get_cpu_cdbs = get_cpu_cdbs, + .get_cpu_dbs_info_s = get_cpu_dbs_info_s, + .gov_dbs_timer = cs_dbs_timer, + .gov_check_cpu = cs_check_cpu, + .gov_ops = &cs_ops, + .init = cs_init, + .exit = cs_exit, +}; + +static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + return cpufreq_governor_dbs(policy, &cs_dbs_cdata, event); +} + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE +static +#endif +struct cpufreq_governor cpufreq_gov_conservative = { + .name = "conservative", + .governor = cs_cpufreq_governor_dbs, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, +}; + +static int __init cpufreq_gov_dbs_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_conservative); +} + +static void __exit cpufreq_gov_dbs_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_conservative); +} + +MODULE_AUTHOR("Alexander Clouter "); +MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " + "Low Latency Frequency Transition capable processors " + "optimised for use in a battery environment"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE +fs_initcall(cpufreq_gov_dbs_init); +#else +module_init(cpufreq_gov_dbs_init); +#endif +module_exit(cpufreq_gov_dbs_exit); diff --git a/src/cpufreq/3.x/cpufreq_governor.h b/src/cpufreq/3.x/cpufreq_governor.h new file mode 100644 index 000000000..4a9058aeb --- /dev/null +++ b/src/cpufreq/3.x/cpufreq_governor.h @@ -0,0 +1,270 @@ +/* + * drivers/cpufreq/cpufreq_governor.h + * + * Header file for CPUFreq governors common code + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * (C) 2003 Jun Nakajima + * (C) 2009 Alexander Clouter + * (c) 2012 Viresh Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _CPUFREQ_GOVERNOR_H +#define _CPUFREQ_GOVERNOR_H + +#include +#include +#include +#include +#include + +/* + * The polling frequency depends on the capability of the processor. Default + * polling frequency is 1000 times the transition latency of the processor. The + * governor will work on any processor with transition latency <= 10mS, using + * appropriate sampling rate. + * + * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. All times here are in uS. + */ +#define MIN_SAMPLING_RATE_RATIO (2) +#define LATENCY_MULTIPLIER (1000) +#define MIN_LATENCY_MULTIPLIER (20) +#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) + +/* Ondemand Sampling types */ +enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE}; + +/* + * Macro for creating governors sysfs routines + * + * - gov_sys: One governor instance per whole system + * - gov_pol: One governor instance per policy + */ + +/* Create attributes */ +#define gov_sys_attr_ro(_name) \ +static struct global_attr _name##_gov_sys = \ +__ATTR(_name, 0444, show_##_name##_gov_sys, NULL) + +#define gov_sys_attr_rw(_name) \ +static struct global_attr _name##_gov_sys = \ +__ATTR(_name, 0644, show_##_name##_gov_sys, store_##_name##_gov_sys) + +#define gov_pol_attr_ro(_name) \ +static struct freq_attr _name##_gov_pol = \ +__ATTR(_name, 0444, show_##_name##_gov_pol, NULL) + +#define gov_pol_attr_rw(_name) \ +static struct freq_attr _name##_gov_pol = \ +__ATTR(_name, 0644, show_##_name##_gov_pol, store_##_name##_gov_pol) + +#define gov_sys_pol_attr_rw(_name) \ + gov_sys_attr_rw(_name); \ + gov_pol_attr_rw(_name) + +#define gov_sys_pol_attr_ro(_name) \ + gov_sys_attr_ro(_name); \ + gov_pol_attr_ro(_name) + +/* Create show/store routines */ +#define show_one(_gov, file_name) \ +static ssize_t show_##file_name##_gov_sys \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ +{ \ + struct _gov##_dbs_tuners *tuners = _gov##_dbs_cdata.gdbs_data->tuners; \ + return sprintf(buf, "%u\n", tuners->file_name); \ +} \ + \ +static ssize_t show_##file_name##_gov_pol \ +(struct cpufreq_policy *policy, char *buf) \ +{ \ + struct dbs_data *dbs_data = policy->governor_data; \ + struct _gov##_dbs_tuners *tuners = dbs_data->tuners; \ + return sprintf(buf, "%u\n", tuners->file_name); \ +} + +#define store_one(_gov, file_name) \ +static ssize_t store_##file_name##_gov_sys \ +(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) \ +{ \ + struct dbs_data *dbs_data = _gov##_dbs_cdata.gdbs_data; \ + return store_##file_name(dbs_data, buf, count); \ +} \ + \ +static ssize_t store_##file_name##_gov_pol \ +(struct cpufreq_policy *policy, const char *buf, size_t count) \ +{ \ + struct dbs_data *dbs_data = policy->governor_data; \ + return store_##file_name(dbs_data, buf, count); \ +} + +#define show_store_one(_gov, file_name) \ +show_one(_gov, file_name); \ +store_one(_gov, file_name) + +/* create helper routines */ +#define define_get_cpu_dbs_routines(_dbs_info) \ +static struct cpu_dbs_common_info *get_cpu_cdbs(int cpu) \ +{ \ + return &per_cpu(_dbs_info, cpu).cdbs; \ +} \ + \ +static void *get_cpu_dbs_info_s(int cpu) \ +{ \ + return &per_cpu(_dbs_info, cpu); \ +} + +/* + * Abbreviations: + * dbs: used as a shortform for demand based switching It helps to keep variable + * names smaller, simpler + * cdbs: common dbs + * od_*: On-demand governor + * cs_*: Conservative governor + */ + +/* Per cpu structures */ +struct cpu_dbs_common_info { + int cpu; + u64 prev_cpu_idle; + u64 prev_cpu_wall; + u64 prev_cpu_nice; + struct cpufreq_policy *cur_policy; + struct delayed_work work; + /* + * percpu mutex that serializes governor limit change with gov_dbs_timer + * invocation. We do not want gov_dbs_timer to run when user is changing + * the governor or limits. + */ + struct mutex timer_mutex; + ktime_t time_stamp; +}; + +struct od_cpu_dbs_info_s { + struct cpu_dbs_common_info cdbs; + struct cpufreq_frequency_table *freq_table; + unsigned int freq_lo; + unsigned int freq_lo_jiffies; + unsigned int freq_hi_jiffies; + unsigned int rate_mult; + unsigned int sample_type:1; +}; + +struct cs_cpu_dbs_info_s { + struct cpu_dbs_common_info cdbs; + unsigned int down_skip; + unsigned int requested_freq; + unsigned int enable:1; +}; + +/* Per policy Governers sysfs tunables */ +struct od_dbs_tuners { + unsigned int ignore_nice_load; + unsigned int sampling_rate; + unsigned int sampling_down_factor; + unsigned int up_threshold; + unsigned int powersave_bias; + unsigned int io_is_busy; +}; + +struct cs_dbs_tuners { + unsigned int ignore_nice_load; + unsigned int sampling_rate; + unsigned int sampling_down_factor; + unsigned int up_threshold; + unsigned int down_threshold; + unsigned int freq_step; +}; + +/* Common Governer data across policies */ +struct dbs_data; +struct common_dbs_data { + /* Common across governors */ + #define GOV_ONDEMAND 0 + #define GOV_CONSERVATIVE 1 + int governor; + struct attribute_group *attr_group_gov_sys; /* one governor - system */ + struct attribute_group *attr_group_gov_pol; /* one governor - policy */ + + /* Common data for platforms that don't set have_governor_per_policy */ + struct dbs_data *gdbs_data; + + struct cpu_dbs_common_info *(*get_cpu_cdbs)(int cpu); + void *(*get_cpu_dbs_info_s)(int cpu); + void (*gov_dbs_timer)(struct work_struct *work); + void (*gov_check_cpu)(int cpu, unsigned int load); + int (*init)(struct dbs_data *dbs_data); + void (*exit)(struct dbs_data *dbs_data); + + /* Governor specific ops, see below */ + void *gov_ops; +}; + +/* Governer Per policy data */ +struct dbs_data { + struct common_dbs_data *cdata; + unsigned int min_sampling_rate; + int usage_count; + void *tuners; + + /* dbs_mutex protects dbs_enable in governor start/stop */ + struct mutex mutex; +}; + +/* Governor specific ops, will be passed to dbs_data->gov_ops */ +struct od_ops { + void (*powersave_bias_init_cpu)(int cpu); + unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy, + unsigned int freq_next, unsigned int relation); + void (*freq_increase)(struct cpufreq_policy *p, unsigned int freq); +}; + +struct cs_ops { + struct notifier_block *notifier_block; +}; + +static inline int delay_for_sampling_rate(unsigned int sampling_rate) +{ + int delay = usecs_to_jiffies(sampling_rate); + + /* We want all CPUs to do sampling nearly on same jiffy */ + if (num_online_cpus() > 1) + delay -= jiffies % delay; + + return delay; +} + +#define declare_show_sampling_rate_min(_gov) \ +static ssize_t show_sampling_rate_min_gov_sys \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ +{ \ + struct dbs_data *dbs_data = _gov##_dbs_cdata.gdbs_data; \ + return sprintf(buf, "%u\n", dbs_data->min_sampling_rate); \ +} \ + \ +static ssize_t show_sampling_rate_min_gov_pol \ +(struct cpufreq_policy *policy, char *buf) \ +{ \ + struct dbs_data *dbs_data = policy->governor_data; \ + return sprintf(buf, "%u\n", dbs_data->min_sampling_rate); \ +} + +u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy); +void dbs_check_cpu(struct dbs_data *dbs_data, int cpu); +bool need_load_eval(struct cpu_dbs_common_info *cdbs, + unsigned int sampling_rate); +int cpufreq_governor_dbs(struct cpufreq_policy *policy, + struct common_dbs_data *cdata, unsigned int event); +void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy, + unsigned int delay, bool all_cpus); +void od_register_powersave_bias_handler(unsigned int (*f) + (struct cpufreq_policy *, unsigned int, unsigned int), + unsigned int powersave_bias); +void od_unregister_powersave_bias_handler(void); +#endif /* _CPUFREQ_GOVERNOR_H */ diff --git a/src/cpufreq/3.x/cpufreq_ondemand.c b/src/cpufreq/3.x/cpufreq_ondemand.c new file mode 100644 index 000000000..25438bbf9 --- /dev/null +++ b/src/cpufreq/3.x/cpufreq_ondemand.c @@ -0,0 +1,642 @@ +/* + * drivers/cpufreq/cpufreq_ondemand.c + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpufreq_governor.h" + +/* On-demand governor macros */ +#define DEF_FREQUENCY_UP_THRESHOLD (80) +#define DEF_SAMPLING_DOWN_FACTOR (1) +#define MAX_SAMPLING_DOWN_FACTOR (100000) +#define MICRO_FREQUENCY_UP_THRESHOLD (95) +#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) +#define MIN_FREQUENCY_UP_THRESHOLD (11) +#define MAX_FREQUENCY_UP_THRESHOLD (100) + +static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info); + +static struct od_ops od_ops; + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +static struct cpufreq_governor cpufreq_gov_ondemand; +#endif + +static unsigned int default_powersave_bias; + +static void ondemand_powersave_bias_init_cpu(int cpu) +{ + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu); + + dbs_info->freq_table = cpufreq_frequency_get_table(cpu); + dbs_info->freq_lo = 0; +} + +/* + * Not all CPUs want IO time to be accounted as busy; this depends on how + * efficient idling at a higher frequency/voltage is. + * Pavel Machek says this is not so for various generations of AMD and old + * Intel systems. + * Mike Chan (android.com) claims this is also not true for ARM. + * Because of this, whitelist specific known (series) of CPUs by default, and + * leave all others up to the user. + */ +static int should_io_be_busy(void) +{ +#if defined(CONFIG_X86) + /* + * For Intel, Core 2 (model 15) and later have an efficient idle. + */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_data.x86 == 6 && + boot_cpu_data.x86_model >= 15) + return 1; +#endif + return 0; +} + +/* + * Find right freq to be set now with powersave_bias on. + * Returns the freq_hi to be used right now and will set freq_hi_jiffies, + * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs. + */ +static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy, + unsigned int freq_next, unsigned int relation) +{ + unsigned int freq_req, freq_reduc, freq_avg; + unsigned int freq_hi, freq_lo; + unsigned int index = 0; + unsigned int jiffies_total, jiffies_hi, jiffies_lo; + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, + policy->cpu); + struct dbs_data *dbs_data = policy->governor_data; + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + + if (!dbs_info->freq_table) { + dbs_info->freq_lo = 0; + dbs_info->freq_lo_jiffies = 0; + return freq_next; + } + + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next, + relation, &index); + freq_req = dbs_info->freq_table[index].frequency; + freq_reduc = freq_req * od_tuners->powersave_bias / 1000; + freq_avg = freq_req - freq_reduc; + + /* Find freq bounds for freq_avg in freq_table */ + index = 0; + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, + CPUFREQ_RELATION_H, &index); + freq_lo = dbs_info->freq_table[index].frequency; + index = 0; + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, + CPUFREQ_RELATION_L, &index); + freq_hi = dbs_info->freq_table[index].frequency; + + /* Find out how long we have to be in hi and lo freqs */ + if (freq_hi == freq_lo) { + dbs_info->freq_lo = 0; + dbs_info->freq_lo_jiffies = 0; + return freq_lo; + } + jiffies_total = usecs_to_jiffies(od_tuners->sampling_rate); + jiffies_hi = (freq_avg - freq_lo) * jiffies_total; + jiffies_hi += ((freq_hi - freq_lo) / 2); + jiffies_hi /= (freq_hi - freq_lo); + jiffies_lo = jiffies_total - jiffies_hi; + dbs_info->freq_lo = freq_lo; + dbs_info->freq_lo_jiffies = jiffies_lo; + dbs_info->freq_hi_jiffies = jiffies_hi; + return freq_hi; +} + +static void ondemand_powersave_bias_init(void) +{ + int i; + for_each_online_cpu(i) { + ondemand_powersave_bias_init_cpu(i); + } +} + +static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq) +{ + struct dbs_data *dbs_data = p->governor_data; + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + + if (od_tuners->powersave_bias) + freq = od_ops.powersave_bias_target(p, freq, + CPUFREQ_RELATION_H); + else if (p->cur == p->max) + return; + + __cpufreq_driver_target(p, freq, od_tuners->powersave_bias ? + CPUFREQ_RELATION_L : CPUFREQ_RELATION_H); +} + +/* + * Every sampling_rate, we check, if current idle time is less than 20% + * (default), then we try to increase frequency. Else, we adjust the frequency + * proportional to load. + */ +static void od_check_cpu(int cpu, unsigned int load) +{ + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu); + struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy; + struct dbs_data *dbs_data = policy->governor_data; + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + + dbs_info->freq_lo = 0; + + /* Check for frequency increase */ + if (load > od_tuners->up_threshold) { + /* If switching to max speed, apply sampling_down_factor */ + if (policy->cur < policy->max) + dbs_info->rate_mult = + od_tuners->sampling_down_factor; + dbs_freq_increase(policy, policy->max); + return; + } else { + /* Calculate the next frequency proportional to load */ + unsigned int freq_next; + freq_next = load * policy->cpuinfo.max_freq / 100; + + /* No longer fully busy, reset rate_mult */ + dbs_info->rate_mult = 1; + + if (freq_next < policy->min) + freq_next = policy->min; + + if (!od_tuners->powersave_bias) { + __cpufreq_driver_target(policy, freq_next, + CPUFREQ_RELATION_L); + return; + } + + freq_next = od_ops.powersave_bias_target(policy, freq_next, + CPUFREQ_RELATION_L); + __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); + } +} + +static void od_dbs_timer(struct work_struct *work) +{ + struct od_cpu_dbs_info_s *dbs_info = + container_of(work, struct od_cpu_dbs_info_s, cdbs.work.work); + unsigned int cpu = dbs_info->cdbs.cur_policy->cpu; + struct od_cpu_dbs_info_s *core_dbs_info = &per_cpu(od_cpu_dbs_info, + cpu); + struct dbs_data *dbs_data = dbs_info->cdbs.cur_policy->governor_data; + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + int delay = 0, sample_type = core_dbs_info->sample_type; + bool modify_all = true; + + mutex_lock(&core_dbs_info->cdbs.timer_mutex); + if (!need_load_eval(&core_dbs_info->cdbs, od_tuners->sampling_rate)) { + modify_all = false; + goto max_delay; + } + + /* Common NORMAL_SAMPLE setup */ + core_dbs_info->sample_type = OD_NORMAL_SAMPLE; + if (sample_type == OD_SUB_SAMPLE) { + delay = core_dbs_info->freq_lo_jiffies; + __cpufreq_driver_target(core_dbs_info->cdbs.cur_policy, + core_dbs_info->freq_lo, CPUFREQ_RELATION_H); + } else { + dbs_check_cpu(dbs_data, cpu); + if (core_dbs_info->freq_lo) { + /* Setup timer for SUB_SAMPLE */ + core_dbs_info->sample_type = OD_SUB_SAMPLE; + delay = core_dbs_info->freq_hi_jiffies; + } + } + +max_delay: + if (!delay) + delay = delay_for_sampling_rate(od_tuners->sampling_rate + * core_dbs_info->rate_mult); + + gov_queue_work(dbs_data, dbs_info->cdbs.cur_policy, delay, modify_all); + mutex_unlock(&core_dbs_info->cdbs.timer_mutex); +} + +/************************** sysfs interface ************************/ +static struct common_dbs_data od_dbs_cdata; + +/** + * update_sampling_rate - update sampling rate effective immediately if needed. + * @new_rate: new sampling rate + * + * If new rate is smaller than the old, simply updating + * dbs_tuners_int.sampling_rate might not be appropriate. For example, if the + * original sampling_rate was 1 second and the requested new sampling rate is 10 + * ms because the user needs immediate reaction from ondemand governor, but not + * sure if higher frequency will be required or not, then, the governor may + * change the sampling rate too late; up to 1 second later. Thus, if we are + * reducing the sampling rate, we need to make the new value effective + * immediately. + */ +static void update_sampling_rate(struct dbs_data *dbs_data, + unsigned int new_rate) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + int cpu; + + od_tuners->sampling_rate = new_rate = max(new_rate, + dbs_data->min_sampling_rate); + + for_each_online_cpu(cpu) { + struct cpufreq_policy *policy; + struct od_cpu_dbs_info_s *dbs_info; + unsigned long next_sampling, appointed_at; + + policy = cpufreq_cpu_get(cpu); + if (!policy) + continue; + if (policy->governor != &cpufreq_gov_ondemand) { + cpufreq_cpu_put(policy); + continue; + } + dbs_info = &per_cpu(od_cpu_dbs_info, cpu); + cpufreq_cpu_put(policy); + + mutex_lock(&dbs_info->cdbs.timer_mutex); + + if (!delayed_work_pending(&dbs_info->cdbs.work)) { + mutex_unlock(&dbs_info->cdbs.timer_mutex); + continue; + } + + next_sampling = jiffies + usecs_to_jiffies(new_rate); + appointed_at = dbs_info->cdbs.work.timer.expires; + + if (time_before(next_sampling, appointed_at)) { + + mutex_unlock(&dbs_info->cdbs.timer_mutex); + cancel_delayed_work_sync(&dbs_info->cdbs.work); + mutex_lock(&dbs_info->cdbs.timer_mutex); + + gov_queue_work(dbs_data, dbs_info->cdbs.cur_policy, + usecs_to_jiffies(new_rate), true); + + } + mutex_unlock(&dbs_info->cdbs.timer_mutex); + } +} + +static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + update_sampling_rate(dbs_data, input); + return count; +} + +static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + unsigned int input; + int ret; + unsigned int j; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + od_tuners->io_is_busy = !!input; + + /* we need to re-evaluate prev_cpu_idle */ + for_each_online_cpu(j) { + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, + j); + dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, + &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy); + } + return count; +} + +static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || + input < MIN_FREQUENCY_UP_THRESHOLD) { + return -EINVAL; + } + + od_tuners->up_threshold = input; + return count; +} + +static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + unsigned int input, j; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) + return -EINVAL; + od_tuners->sampling_down_factor = input; + + /* Reset down sampling multiplier in case it was active */ + for_each_online_cpu(j) { + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, + j); + dbs_info->rate_mult = 1; + } + return count; +} + +static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + unsigned int input; + int ret; + + unsigned int j; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + if (input > 1) + input = 1; + + if (input == od_tuners->ignore_nice_load) { /* nothing to do */ + return count; + } + od_tuners->ignore_nice_load = input; + + /* we need to re-evaluate prev_cpu_idle */ + for_each_online_cpu(j) { + struct od_cpu_dbs_info_s *dbs_info; + dbs_info = &per_cpu(od_cpu_dbs_info, j); + dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, + &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy); + if (od_tuners->ignore_nice_load) + dbs_info->cdbs.prev_cpu_nice = + kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + + } + return count; +} + +static ssize_t store_powersave_bias(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1) + return -EINVAL; + + if (input > 1000) + input = 1000; + + od_tuners->powersave_bias = input; + ondemand_powersave_bias_init(); + return count; +} + +show_store_one(od, sampling_rate); +show_store_one(od, io_is_busy); +show_store_one(od, up_threshold); +show_store_one(od, sampling_down_factor); +show_store_one(od, ignore_nice_load); +show_store_one(od, powersave_bias); +declare_show_sampling_rate_min(od); + +gov_sys_pol_attr_rw(sampling_rate); +gov_sys_pol_attr_rw(io_is_busy); +gov_sys_pol_attr_rw(up_threshold); +gov_sys_pol_attr_rw(sampling_down_factor); +gov_sys_pol_attr_rw(ignore_nice_load); +gov_sys_pol_attr_rw(powersave_bias); +gov_sys_pol_attr_ro(sampling_rate_min); + +static struct attribute *dbs_attributes_gov_sys[] = { + &sampling_rate_min_gov_sys.attr, + &sampling_rate_gov_sys.attr, + &up_threshold_gov_sys.attr, + &sampling_down_factor_gov_sys.attr, + &ignore_nice_load_gov_sys.attr, + &powersave_bias_gov_sys.attr, + &io_is_busy_gov_sys.attr, + NULL +}; + +static struct attribute_group od_attr_group_gov_sys = { + .attrs = dbs_attributes_gov_sys, + .name = "ondemand", +}; + +static struct attribute *dbs_attributes_gov_pol[] = { + &sampling_rate_min_gov_pol.attr, + &sampling_rate_gov_pol.attr, + &up_threshold_gov_pol.attr, + &sampling_down_factor_gov_pol.attr, + &ignore_nice_load_gov_pol.attr, + &powersave_bias_gov_pol.attr, + &io_is_busy_gov_pol.attr, + NULL +}; + +static struct attribute_group od_attr_group_gov_pol = { + .attrs = dbs_attributes_gov_pol, + .name = "ondemand", +}; + +/************************** sysfs end ************************/ + +static int od_init(struct dbs_data *dbs_data) +{ + struct od_dbs_tuners *tuners; + u64 idle_time; + int cpu; + + tuners = kzalloc(sizeof(struct od_dbs_tuners), GFP_KERNEL); + if (!tuners) { + pr_err("%s: kzalloc failed\n", __func__); + return -ENOMEM; + } + + cpu = get_cpu(); + idle_time = get_cpu_idle_time_us(cpu, NULL); + put_cpu(); + if (idle_time != -1ULL) { + /* Idle micro accounting is supported. Use finer thresholds */ + tuners->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; + /* + * In nohz/micro accounting case we set the minimum frequency + * not depending on HZ, but fixed (very low). The deferred + * timer might skip some samples if idle/sleeping as needed. + */ + dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; + } else { + tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; + + /* For correct statistics, we need 10 ticks for each measure */ + dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * + jiffies_to_usecs(10); + } + + tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; + tuners->ignore_nice_load = 0; + tuners->powersave_bias = default_powersave_bias; + tuners->io_is_busy = should_io_be_busy(); + + dbs_data->tuners = tuners; + mutex_init(&dbs_data->mutex); + return 0; +} + +static void od_exit(struct dbs_data *dbs_data) +{ + kfree(dbs_data->tuners); +} + +define_get_cpu_dbs_routines(od_cpu_dbs_info); + +static struct od_ops od_ops = { + .powersave_bias_init_cpu = ondemand_powersave_bias_init_cpu, + .powersave_bias_target = generic_powersave_bias_target, + .freq_increase = dbs_freq_increase, +}; + +static struct common_dbs_data od_dbs_cdata = { + .governor = GOV_ONDEMAND, + .attr_group_gov_sys = &od_attr_group_gov_sys, + .attr_group_gov_pol = &od_attr_group_gov_pol, + .get_cpu_cdbs = get_cpu_cdbs, + .get_cpu_dbs_info_s = get_cpu_dbs_info_s, + .gov_dbs_timer = od_dbs_timer, + .gov_check_cpu = od_check_cpu, + .gov_ops = &od_ops, + .init = od_init, + .exit = od_exit, +}; + +static void od_set_powersave_bias(unsigned int powersave_bias) +{ + struct cpufreq_policy *policy; + struct dbs_data *dbs_data; + struct od_dbs_tuners *od_tuners; + unsigned int cpu; + cpumask_t done; + + default_powersave_bias = powersave_bias; + cpumask_clear(&done); + + get_online_cpus(); + for_each_online_cpu(cpu) { + if (cpumask_test_cpu(cpu, &done)) + continue; + + policy = per_cpu(od_cpu_dbs_info, cpu).cdbs.cur_policy; + if (!policy) + continue; + + cpumask_or(&done, &done, policy->cpus); + + if (policy->governor != &cpufreq_gov_ondemand) + continue; + + dbs_data = policy->governor_data; + od_tuners = dbs_data->tuners; + od_tuners->powersave_bias = default_powersave_bias; + } + put_online_cpus(); +} + +void od_register_powersave_bias_handler(unsigned int (*f) + (struct cpufreq_policy *, unsigned int, unsigned int), + unsigned int powersave_bias) +{ + od_ops.powersave_bias_target = f; + od_set_powersave_bias(powersave_bias); +} +EXPORT_SYMBOL_GPL(od_register_powersave_bias_handler); + +void od_unregister_powersave_bias_handler(void) +{ + od_ops.powersave_bias_target = generic_powersave_bias_target; + od_set_powersave_bias(0); +} +EXPORT_SYMBOL_GPL(od_unregister_powersave_bias_handler); + +static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + return cpufreq_governor_dbs(policy, &od_dbs_cdata, event); +} + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +static +#endif +struct cpufreq_governor cpufreq_gov_ondemand = { + .name = "ondemand", + .governor = od_cpufreq_governor_dbs, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, +}; + +static int __init cpufreq_gov_dbs_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_ondemand); +} + +static void __exit cpufreq_gov_dbs_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_ondemand); +} + +MODULE_AUTHOR("Venkatesh Pallipadi "); +MODULE_AUTHOR("Alexey Starikovskiy "); +MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for " + "Low Latency Frequency Transition capable processors"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +fs_initcall(cpufreq_gov_dbs_init); +#else +module_init(cpufreq_gov_dbs_init); +#endif +module_exit(cpufreq_gov_dbs_exit); diff --git a/src/cpufreq/3.x/cpufreq_userspace.c b/src/cpufreq/3.x/cpufreq_userspace.c new file mode 100644 index 000000000..bbeb9c072 --- /dev/null +++ b/src/cpufreq/3.x/cpufreq_userspace.c @@ -0,0 +1,222 @@ + +/* + * linux/drivers/cpufreq/cpufreq_userspace.c + * + * Copyright (C) 2001 Russell King + * (C) 2002 - 2004 Dominik Brodowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * A few values needed by the userspace governor + */ +static DEFINE_PER_CPU(unsigned int, cpu_max_freq); +static DEFINE_PER_CPU(unsigned int, cpu_min_freq); +static DEFINE_PER_CPU(unsigned int, cpu_cur_freq); /* current CPU freq */ +static DEFINE_PER_CPU(unsigned int, cpu_set_freq); /* CPU freq desired by + userspace */ +static DEFINE_PER_CPU(unsigned int, cpu_is_managed); + +static DEFINE_MUTEX(userspace_mutex); +static int cpus_using_userspace_governor; + +/* keep track of frequency transitions */ +static int +userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cpufreq_freqs *freq = data; + + if (!per_cpu(cpu_is_managed, freq->cpu)) + return 0; + + if (val == CPUFREQ_POSTCHANGE) { + pr_debug("saving cpu_cur_freq of cpu %u to be %u kHz\n", + freq->cpu, freq->new); + per_cpu(cpu_cur_freq, freq->cpu) = freq->new; + } + + return 0; +} + +static struct notifier_block userspace_cpufreq_notifier_block = { + .notifier_call = userspace_cpufreq_notifier +}; + + +/** + * cpufreq_set - set the CPU frequency + * @policy: pointer to policy struct where freq is being set + * @freq: target frequency in kHz + * + * Sets the CPU frequency to freq. + */ +static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq) +{ + int ret = -EINVAL; + + pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq); + + mutex_lock(&userspace_mutex); + if (!per_cpu(cpu_is_managed, policy->cpu)) + goto err; + + per_cpu(cpu_set_freq, policy->cpu) = freq; + + if (freq < per_cpu(cpu_min_freq, policy->cpu)) + freq = per_cpu(cpu_min_freq, policy->cpu); + if (freq > per_cpu(cpu_max_freq, policy->cpu)) + freq = per_cpu(cpu_max_freq, policy->cpu); + + /* + * We're safe from concurrent calls to ->target() here + * as we hold the userspace_mutex lock. If we were calling + * cpufreq_driver_target, a deadlock situation might occur: + * A: cpufreq_set (lock userspace_mutex) -> + * cpufreq_driver_target(lock policy->lock) + * B: cpufreq_set_policy(lock policy->lock) -> + * __cpufreq_governor -> + * cpufreq_governor_userspace (lock userspace_mutex) + */ + ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); + + err: + mutex_unlock(&userspace_mutex); + return ret; +} + + +static ssize_t show_speed(struct cpufreq_policy *policy, char *buf) +{ + return sprintf(buf, "%u\n", per_cpu(cpu_cur_freq, policy->cpu)); +} + +static int cpufreq_governor_userspace(struct cpufreq_policy *policy, + unsigned int event) +{ + unsigned int cpu = policy->cpu; + int rc = 0; + + switch (event) { + case CPUFREQ_GOV_START: + BUG_ON(!policy->cur); + mutex_lock(&userspace_mutex); + + if (cpus_using_userspace_governor == 0) { + cpufreq_register_notifier( + &userspace_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + } + cpus_using_userspace_governor++; + + per_cpu(cpu_is_managed, cpu) = 1; + per_cpu(cpu_min_freq, cpu) = policy->min; + per_cpu(cpu_max_freq, cpu) = policy->max; + per_cpu(cpu_cur_freq, cpu) = policy->cur; + per_cpu(cpu_set_freq, cpu) = policy->cur; + pr_debug("managing cpu %u started " + "(%u - %u kHz, currently %u kHz)\n", + cpu, + per_cpu(cpu_min_freq, cpu), + per_cpu(cpu_max_freq, cpu), + per_cpu(cpu_cur_freq, cpu)); + + mutex_unlock(&userspace_mutex); + break; + case CPUFREQ_GOV_STOP: + mutex_lock(&userspace_mutex); + cpus_using_userspace_governor--; + if (cpus_using_userspace_governor == 0) { + cpufreq_unregister_notifier( + &userspace_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + } + + per_cpu(cpu_is_managed, cpu) = 0; + per_cpu(cpu_min_freq, cpu) = 0; + per_cpu(cpu_max_freq, cpu) = 0; + per_cpu(cpu_set_freq, cpu) = 0; + pr_debug("managing cpu %u stopped\n", cpu); + mutex_unlock(&userspace_mutex); + break; + case CPUFREQ_GOV_LIMITS: + mutex_lock(&userspace_mutex); + pr_debug("limit event for cpu %u: %u - %u kHz, " + "currently %u kHz, last set to %u kHz\n", + cpu, policy->min, policy->max, + per_cpu(cpu_cur_freq, cpu), + per_cpu(cpu_set_freq, cpu)); + if (policy->max < per_cpu(cpu_set_freq, cpu)) { + __cpufreq_driver_target(policy, policy->max, + CPUFREQ_RELATION_H); + } else if (policy->min > per_cpu(cpu_set_freq, cpu)) { + __cpufreq_driver_target(policy, policy->min, + CPUFREQ_RELATION_L); + } else { + __cpufreq_driver_target(policy, + per_cpu(cpu_set_freq, cpu), + CPUFREQ_RELATION_L); + } + per_cpu(cpu_min_freq, cpu) = policy->min; + per_cpu(cpu_max_freq, cpu) = policy->max; + per_cpu(cpu_cur_freq, cpu) = policy->cur; + mutex_unlock(&userspace_mutex); + break; + } + return rc; +} + + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE +static +#endif +struct cpufreq_governor cpufreq_gov_userspace = { + .name = "userspace", + .governor = cpufreq_governor_userspace, + .store_setspeed = cpufreq_set, + .show_setspeed = show_speed, + .owner = THIS_MODULE, +}; + +static int __init cpufreq_gov_userspace_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_userspace); +} + + +static void __exit cpufreq_gov_userspace_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_userspace); +} + + +MODULE_AUTHOR("Dominik Brodowski , " + "Russell King "); +MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE +fs_initcall(cpufreq_gov_userspace_init); +#else +module_init(cpufreq_gov_userspace_init); +#endif +module_exit(cpufreq_gov_userspace_exit); diff --git a/src/cpufreq/3.x/intel_pstate.c b/src/cpufreq/3.x/intel_pstate.c new file mode 100644 index 000000000..decf84e71 --- /dev/null +++ b/src/cpufreq/3.x/intel_pstate.c @@ -0,0 +1,764 @@ +/* + * intel_pstate.c: Native P state management for Intel processors + * + * (C) Copyright 2012 Intel Corporation + * Author: Dirk Brandewie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define SAMPLE_COUNT 3 + +#define FRAC_BITS 8 +#define int_tofp(X) ((int64_t)(X) << FRAC_BITS) +#define fp_toint(X) ((X) >> FRAC_BITS) + +static inline int32_t mul_fp(int32_t x, int32_t y) +{ + return ((int64_t)x * (int64_t)y) >> FRAC_BITS; +} + +static inline int32_t div_fp(int32_t x, int32_t y) +{ + return div_s64((int64_t)x << FRAC_BITS, (int64_t)y); +} + +struct sample { + int32_t core_pct_busy; + u64 aperf; + u64 mperf; + int freq; +}; + +struct pstate_data { + int current_pstate; + int min_pstate; + int max_pstate; + int turbo_pstate; +}; + +struct _pid { + int setpoint; + int32_t integral; + int32_t p_gain; + int32_t i_gain; + int32_t d_gain; + int deadband; + int32_t last_err; +}; + +struct cpudata { + int cpu; + + char name[64]; + + struct timer_list timer; + + struct pstate_adjust_policy *pstate_policy; + struct pstate_data pstate; + struct _pid pid; + + int min_pstate_count; + + u64 prev_aperf; + u64 prev_mperf; + int sample_ptr; + struct sample samples[SAMPLE_COUNT]; +}; + +static struct cpudata **all_cpu_data; +struct pstate_adjust_policy { + int sample_rate_ms; + int deadband; + int setpoint; + int p_gain_pct; + int d_gain_pct; + int i_gain_pct; +}; + +static struct pstate_adjust_policy default_policy = { + .sample_rate_ms = 10, + .deadband = 0, + .setpoint = 97, + .p_gain_pct = 20, + .d_gain_pct = 0, + .i_gain_pct = 0, +}; + +struct perf_limits { + int no_turbo; + int max_perf_pct; + int min_perf_pct; + int32_t max_perf; + int32_t min_perf; + int max_policy_pct; + int max_sysfs_pct; +}; + +static struct perf_limits limits = { + .no_turbo = 0, + .max_perf_pct = 100, + .max_perf = int_tofp(1), + .min_perf_pct = 0, + .min_perf = 0, + .max_policy_pct = 100, + .max_sysfs_pct = 100, +}; + +static inline void pid_reset(struct _pid *pid, int setpoint, int busy, + int deadband, int integral) { + pid->setpoint = setpoint; + pid->deadband = deadband; + pid->integral = int_tofp(integral); + pid->last_err = setpoint - busy; +} + +static inline void pid_p_gain_set(struct _pid *pid, int percent) +{ + pid->p_gain = div_fp(int_tofp(percent), int_tofp(100)); +} + +static inline void pid_i_gain_set(struct _pid *pid, int percent) +{ + pid->i_gain = div_fp(int_tofp(percent), int_tofp(100)); +} + +static inline void pid_d_gain_set(struct _pid *pid, int percent) +{ + + pid->d_gain = div_fp(int_tofp(percent), int_tofp(100)); +} + +static signed int pid_calc(struct _pid *pid, int32_t busy) +{ + signed int result; + int32_t pterm, dterm, fp_error; + int32_t integral_limit; + + fp_error = int_tofp(pid->setpoint) - busy; + + if (abs(fp_error) <= int_tofp(pid->deadband)) + return 0; + + pterm = mul_fp(pid->p_gain, fp_error); + + pid->integral += fp_error; + + /* limit the integral term */ + integral_limit = int_tofp(30); + if (pid->integral > integral_limit) + pid->integral = integral_limit; + if (pid->integral < -integral_limit) + pid->integral = -integral_limit; + + dterm = mul_fp(pid->d_gain, fp_error - pid->last_err); + pid->last_err = fp_error; + + result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm; + + return (signed int)fp_toint(result); +} + +static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu) +{ + pid_p_gain_set(&cpu->pid, cpu->pstate_policy->p_gain_pct); + pid_d_gain_set(&cpu->pid, cpu->pstate_policy->d_gain_pct); + pid_i_gain_set(&cpu->pid, cpu->pstate_policy->i_gain_pct); + + pid_reset(&cpu->pid, + cpu->pstate_policy->setpoint, + 100, + cpu->pstate_policy->deadband, + 0); +} + +static inline void intel_pstate_reset_all_pid(void) +{ + unsigned int cpu; + for_each_online_cpu(cpu) { + if (all_cpu_data[cpu]) + intel_pstate_busy_pid_reset(all_cpu_data[cpu]); + } +} + +/************************** debugfs begin ************************/ +static int pid_param_set(void *data, u64 val) +{ + *(u32 *)data = val; + intel_pstate_reset_all_pid(); + return 0; +} +static int pid_param_get(void *data, u64 *val) +{ + *val = *(u32 *)data; + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get, + pid_param_set, "%llu\n"); + +struct pid_param { + char *name; + void *value; +}; + +static struct pid_param pid_files[] = { + {"sample_rate_ms", &default_policy.sample_rate_ms}, + {"d_gain_pct", &default_policy.d_gain_pct}, + {"i_gain_pct", &default_policy.i_gain_pct}, + {"deadband", &default_policy.deadband}, + {"setpoint", &default_policy.setpoint}, + {"p_gain_pct", &default_policy.p_gain_pct}, + {NULL, NULL} +}; + +static struct dentry *debugfs_parent; +static void intel_pstate_debug_expose_params(void) +{ + int i = 0; + + debugfs_parent = debugfs_create_dir("pstate_snb", NULL); + if (IS_ERR_OR_NULL(debugfs_parent)) + return; + while (pid_files[i].name) { + debugfs_create_file(pid_files[i].name, 0660, + debugfs_parent, pid_files[i].value, + &fops_pid_param); + i++; + } +} + +/************************** debugfs end ************************/ + +/************************** sysfs begin ************************/ +#define show_one(file_name, object) \ + static ssize_t show_##file_name \ + (struct kobject *kobj, struct attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%u\n", limits.object); \ + } + +static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + limits.no_turbo = clamp_t(int, input, 0 , 1); + + return count; +} + +static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + limits.max_sysfs_pct = clamp_t(int, input, 0 , 100); + limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct); + limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); + return count; +} + +static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + limits.min_perf_pct = clamp_t(int, input, 0 , 100); + limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); + + return count; +} + +show_one(no_turbo, no_turbo); +show_one(max_perf_pct, max_perf_pct); +show_one(min_perf_pct, min_perf_pct); + +define_one_global_rw(no_turbo); +define_one_global_rw(max_perf_pct); +define_one_global_rw(min_perf_pct); + +static struct attribute *intel_pstate_attributes[] = { + &no_turbo.attr, + &max_perf_pct.attr, + &min_perf_pct.attr, + NULL +}; + +static struct attribute_group intel_pstate_attr_group = { + .attrs = intel_pstate_attributes, +}; +static struct kobject *intel_pstate_kobject; + +static void intel_pstate_sysfs_expose_params(void) +{ + int rc; + + intel_pstate_kobject = kobject_create_and_add("intel_pstate", + &cpu_subsys.dev_root->kobj); + BUG_ON(!intel_pstate_kobject); + rc = sysfs_create_group(intel_pstate_kobject, + &intel_pstate_attr_group); + BUG_ON(rc); +} + +/************************** sysfs end ************************/ + +static int intel_pstate_min_pstate(void) +{ + u64 value; + rdmsrl(MSR_PLATFORM_INFO, value); + return (value >> 40) & 0xFF; +} + +static int intel_pstate_max_pstate(void) +{ + u64 value; + rdmsrl(MSR_PLATFORM_INFO, value); + return (value >> 8) & 0xFF; +} + +static int intel_pstate_turbo_pstate(void) +{ + u64 value; + int nont, ret; + rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value); + nont = intel_pstate_max_pstate(); + ret = ((value) & 255); + if (ret <= nont) + ret = nont; + return ret; +} + +static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) +{ + int max_perf = cpu->pstate.turbo_pstate; + int max_perf_adj; + int min_perf; + if (limits.no_turbo) + max_perf = cpu->pstate.max_pstate; + + max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf)); + *max = clamp_t(int, max_perf_adj, + cpu->pstate.min_pstate, cpu->pstate.turbo_pstate); + + min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf)); + *min = clamp_t(int, min_perf, + cpu->pstate.min_pstate, max_perf); +} + +static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) +{ + int max_perf, min_perf; + + intel_pstate_get_min_max(cpu, &min_perf, &max_perf); + + pstate = clamp_t(int, pstate, min_perf, max_perf); + + if (pstate == cpu->pstate.current_pstate) + return; + + trace_cpu_frequency(pstate * 100000, cpu->cpu); + + cpu->pstate.current_pstate = pstate; + if (limits.no_turbo) + wrmsrl(MSR_IA32_PERF_CTL, BIT(32) | (pstate << 8)); + else + wrmsrl(MSR_IA32_PERF_CTL, pstate << 8); + +} + +static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) +{ + int target; + target = cpu->pstate.current_pstate + steps; + + intel_pstate_set_pstate(cpu, target); +} + +static inline void intel_pstate_pstate_decrease(struct cpudata *cpu, int steps) +{ + int target; + target = cpu->pstate.current_pstate - steps; + intel_pstate_set_pstate(cpu, target); +} + +static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) +{ + sprintf(cpu->name, "Intel 2nd generation core"); + + cpu->pstate.min_pstate = intel_pstate_min_pstate(); + cpu->pstate.max_pstate = intel_pstate_max_pstate(); + cpu->pstate.turbo_pstate = intel_pstate_turbo_pstate(); + + /* + * goto max pstate so we don't slow up boot if we are built-in if we are + * a module we will take care of it during normal operation + */ + intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); +} + +static inline void intel_pstate_calc_busy(struct cpudata *cpu, + struct sample *sample) +{ + u64 core_pct; + core_pct = div64_u64(int_tofp(sample->aperf * 100), + sample->mperf); + sample->freq = fp_toint(cpu->pstate.max_pstate * core_pct * 1000); + + sample->core_pct_busy = core_pct; +} + +static inline void intel_pstate_sample(struct cpudata *cpu) +{ + u64 aperf, mperf; + + rdmsrl(MSR_IA32_APERF, aperf); + rdmsrl(MSR_IA32_MPERF, mperf); + cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; + cpu->samples[cpu->sample_ptr].aperf = aperf; + cpu->samples[cpu->sample_ptr].mperf = mperf; + cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; + cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; + + intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); + + cpu->prev_aperf = aperf; + cpu->prev_mperf = mperf; +} + +static inline void intel_pstate_set_sample_time(struct cpudata *cpu) +{ + int sample_time, delay; + + sample_time = cpu->pstate_policy->sample_rate_ms; + delay = msecs_to_jiffies(sample_time); + mod_timer_pinned(&cpu->timer, jiffies + delay); +} + +static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) +{ + int32_t core_busy, max_pstate, current_pstate; + + core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; + max_pstate = int_tofp(cpu->pstate.max_pstate); + current_pstate = int_tofp(cpu->pstate.current_pstate); + return mul_fp(core_busy, div_fp(max_pstate, current_pstate)); +} + +static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) +{ + int32_t busy_scaled; + struct _pid *pid; + signed int ctl = 0; + int steps; + + pid = &cpu->pid; + busy_scaled = intel_pstate_get_scaled_busy(cpu); + + ctl = pid_calc(pid, busy_scaled); + + steps = abs(ctl); + if (ctl < 0) + intel_pstate_pstate_increase(cpu, steps); + else + intel_pstate_pstate_decrease(cpu, steps); +} + +static void intel_pstate_timer_func(unsigned long __data) +{ + struct cpudata *cpu = (struct cpudata *) __data; + + intel_pstate_sample(cpu); + intel_pstate_adjust_busy_pstate(cpu); + + if (cpu->pstate.current_pstate == cpu->pstate.min_pstate) { + cpu->min_pstate_count++; + if (!(cpu->min_pstate_count % 5)) { + intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); + } + } else + cpu->min_pstate_count = 0; + + intel_pstate_set_sample_time(cpu); +} + +#define ICPU(model, policy) \ + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_APERFMPERF,\ + (unsigned long)&policy } + +static const struct x86_cpu_id intel_pstate_cpu_ids[] = { + ICPU(0x2a, default_policy), + ICPU(0x2d, default_policy), + ICPU(0x3a, default_policy), + ICPU(0x3c, default_policy), + ICPU(0x3e, default_policy), + ICPU(0x3f, default_policy), + ICPU(0x45, default_policy), + ICPU(0x46, default_policy), + {} +}; +MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); + +static int intel_pstate_init_cpu(unsigned int cpunum) +{ + + const struct x86_cpu_id *id; + struct cpudata *cpu; + + id = x86_match_cpu(intel_pstate_cpu_ids); + if (!id) + return -ENODEV; + + all_cpu_data[cpunum] = kzalloc(sizeof(struct cpudata), GFP_KERNEL); + if (!all_cpu_data[cpunum]) + return -ENOMEM; + + cpu = all_cpu_data[cpunum]; + + intel_pstate_get_cpu_pstates(cpu); + if (!cpu->pstate.current_pstate) { + all_cpu_data[cpunum] = NULL; + kfree(cpu); + return -ENODATA; + } + + cpu->cpu = cpunum; + cpu->pstate_policy = + (struct pstate_adjust_policy *)id->driver_data; + init_timer_deferrable(&cpu->timer); + cpu->timer.function = intel_pstate_timer_func; + cpu->timer.data = + (unsigned long)cpu; + cpu->timer.expires = jiffies + HZ/100; + intel_pstate_busy_pid_reset(cpu); + intel_pstate_sample(cpu); + intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); + + add_timer_on(&cpu->timer, cpunum); + + pr_info("Intel pstate controlling: cpu %d\n", cpunum); + + return 0; +} + +static unsigned int intel_pstate_get(unsigned int cpu_num) +{ + struct sample *sample; + struct cpudata *cpu; + + cpu = all_cpu_data[cpu_num]; + if (!cpu) + return 0; + sample = &cpu->samples[cpu->sample_ptr]; + return sample->freq; +} + +static int intel_pstate_set_policy(struct cpufreq_policy *policy) +{ + struct cpudata *cpu; + + cpu = all_cpu_data[policy->cpu]; + + if (!policy->cpuinfo.max_freq) + return -ENODEV; + + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { + limits.min_perf_pct = 100; + limits.min_perf = int_tofp(1); + limits.max_policy_pct = 100; + limits.max_perf_pct = 100; + limits.max_perf = int_tofp(1); + limits.no_turbo = 0; + return 0; + } + limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; + limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100); + limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); + + limits.max_policy_pct = policy->max * 100 / policy->cpuinfo.max_freq; + limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100); + limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct); + limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); + + return 0; +} + +static int intel_pstate_verify_policy(struct cpufreq_policy *policy) +{ + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) && + (policy->policy != CPUFREQ_POLICY_PERFORMANCE)) + return -EINVAL; + + return 0; +} + +static int __cpuinit intel_pstate_cpu_exit(struct cpufreq_policy *policy) +{ + int cpu = policy->cpu; + + del_timer(&all_cpu_data[cpu]->timer); + kfree(all_cpu_data[cpu]); + all_cpu_data[cpu] = NULL; + return 0; +} + +static int __cpuinit intel_pstate_cpu_init(struct cpufreq_policy *policy) +{ + struct cpudata *cpu; + int rc; + + rc = intel_pstate_init_cpu(policy->cpu); + if (rc) + return rc; + + cpu = all_cpu_data[policy->cpu]; + + if (!limits.no_turbo && + limits.min_perf_pct == 100 && limits.max_perf_pct == 100) + policy->policy = CPUFREQ_POLICY_PERFORMANCE; + else + policy->policy = CPUFREQ_POLICY_POWERSAVE; + + policy->min = cpu->pstate.min_pstate * 100000; + policy->max = cpu->pstate.turbo_pstate * 100000; + + /* cpuinfo and default policy values */ + policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000; + policy->cpuinfo.max_freq = cpu->pstate.turbo_pstate * 100000; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + cpumask_set_cpu(policy->cpu, policy->cpus); + + return 0; +} + +static struct cpufreq_driver intel_pstate_driver = { + .flags = CPUFREQ_CONST_LOOPS, + .verify = intel_pstate_verify_policy, + .setpolicy = intel_pstate_set_policy, + .get = intel_pstate_get, + .init = intel_pstate_cpu_init, + .exit = intel_pstate_cpu_exit, + .name = "intel_pstate", + .owner = THIS_MODULE, +}; + +static int __initdata no_load; + +static int intel_pstate_msrs_not_valid(void) +{ + /* Check that all the msr's we are using are valid. */ + u64 aperf, mperf, tmp; + + rdmsrl(MSR_IA32_APERF, aperf); + rdmsrl(MSR_IA32_MPERF, mperf); + + if (!intel_pstate_min_pstate() || + !intel_pstate_max_pstate() || + !intel_pstate_turbo_pstate()) + return -ENODEV; + + rdmsrl(MSR_IA32_APERF, tmp); + if (!(tmp - aperf)) + return -ENODEV; + + rdmsrl(MSR_IA32_MPERF, tmp); + if (!(tmp - mperf)) + return -ENODEV; + + return 0; +} +static int __init intel_pstate_init(void) +{ + int cpu, rc = 0; + const struct x86_cpu_id *id; + + if (no_load) + return -ENODEV; + + id = x86_match_cpu(intel_pstate_cpu_ids); + if (!id) + return -ENODEV; + + if (intel_pstate_msrs_not_valid()) + return -ENODEV; + + pr_info("Intel P-state driver initializing.\n"); + + all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus()); + if (!all_cpu_data) + return -ENOMEM; + + rc = cpufreq_register_driver(&intel_pstate_driver); + if (rc) + goto out; + + intel_pstate_debug_expose_params(); + intel_pstate_sysfs_expose_params(); + return rc; +out: + get_online_cpus(); + for_each_online_cpu(cpu) { + if (all_cpu_data[cpu]) { + del_timer_sync(&all_cpu_data[cpu]->timer); + kfree(all_cpu_data[cpu]); + } + } + + put_online_cpus(); + vfree(all_cpu_data); + return -ENODEV; +} +device_initcall(intel_pstate_init); + +static int __init intel_pstate_setup(char *str) +{ + if (!str) + return -EINVAL; + + if (!strcmp(str, "disable")) + no_load = 1; + return 0; +} +early_param("intel_pstate", intel_pstate_setup); + +MODULE_AUTHOR("Dirk Brandewie "); +MODULE_DESCRIPTION("'intel_pstate' - P state driver Intel Core processors"); +MODULE_LICENSE("GPL"); diff --git a/src/cpufreq/4.x/Makefile b/src/cpufreq/4.x/Makefile new file mode 100644 index 000000000..1876cbefd --- /dev/null +++ b/src/cpufreq/4.x/Makefile @@ -0,0 +1,37 @@ +# CPUfreq governors +#obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o +#obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o +obj-m += cpufreq_userspace.o +obj-m += cpufreq_ondemand.o +obj-m += cpufreq_conservative.o +#obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o + +#obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o + +################################################################################## +# x86 drivers. +# Link order matters. K8 is preferred to ACPI because of firmware bugs in early +# K8 systems. This is still the case but acpi-cpufreq errors out so that +# powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers. +# speedstep-* is preferred over p4-clockmod. + +#obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o +#obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o +#obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o +#obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o +#obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o +#obj-$(CONFIG_X86_LONGHAUL) += longhaul.o +#obj-$(CONFIG_X86_E_POWERSAVER) += e_powersaver.o +#obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o +#obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o +#obj-$(CONFIG_X86_LONGRUN) += longrun.o +#obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o +#obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o +#obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o +#obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o +#obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o +#obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o +#obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o +#obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) += amd_freq_sensitivity.o +#obj-m += intel_pstate.o +#obj-$(CONFIG_X86_SFI_CPUFREQ) += sfi-cpufreq.o diff --git a/src/cpufreq/4.x/cpufreq_conservative.c b/src/cpufreq/4.x/cpufreq_conservative.c new file mode 100644 index 000000000..c395f9198 --- /dev/null +++ b/src/cpufreq/4.x/cpufreq_conservative.c @@ -0,0 +1,406 @@ +/* + * drivers/cpufreq/cpufreq_conservative.c + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * (C) 2009 Alexander Clouter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include "cpufreq_governor.h" + +/* Conservative governor macros */ +#define DEF_FREQUENCY_UP_THRESHOLD (80) +#define DEF_FREQUENCY_DOWN_THRESHOLD (20) +#define DEF_FREQUENCY_STEP (5) +#define DEF_SAMPLING_DOWN_FACTOR (1) +#define MAX_SAMPLING_DOWN_FACTOR (10) + +static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info); + +static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event); + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE +static +#endif +struct cpufreq_governor cpufreq_gov_conservative = { + .name = "conservative", + .governor = cs_cpufreq_governor_dbs, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, +}; + +static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners, + struct cpufreq_policy *policy) +{ + unsigned int freq_target = (cs_tuners->freq_step * policy->max) / 100; + + /* max freq cannot be less than 100. But who knows... */ + if (unlikely(freq_target == 0)) + freq_target = DEF_FREQUENCY_STEP; + + return freq_target; +} + +/* + * Every sampling_rate, we check, if current idle time is less than 20% + * (default), then we try to increase frequency. Every sampling_rate * + * sampling_down_factor, we check, if current idle time is more than 80% + * (default), then we try to decrease frequency + * + * Any frequency increase takes it to the maximum frequency. Frequency reduction + * happens at minimum steps of 5% (default) of maximum frequency + */ +static void cs_check_cpu(int cpu, unsigned int load) +{ + struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, cpu); + struct cpufreq_policy *policy = dbs_info->cdbs.shared->policy; + struct dbs_data *dbs_data = policy->governor_data; + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + + /* + * break out if we 'cannot' reduce the speed as the user might + * want freq_step to be zero + */ + if (cs_tuners->freq_step == 0) + return; + + /* Check for frequency increase */ + if (load > cs_tuners->up_threshold) { + dbs_info->down_skip = 0; + + /* if we are already at full speed then break out early */ + if (dbs_info->requested_freq == policy->max) + return; + + dbs_info->requested_freq += get_freq_target(cs_tuners, policy); + + if (dbs_info->requested_freq > policy->max) + dbs_info->requested_freq = policy->max; + + __cpufreq_driver_target(policy, dbs_info->requested_freq, + CPUFREQ_RELATION_H); + return; + } + + /* if sampling_down_factor is active break out early */ + if (++dbs_info->down_skip < cs_tuners->sampling_down_factor) + return; + dbs_info->down_skip = 0; + + /* Check for frequency decrease */ + if (load < cs_tuners->down_threshold) { + unsigned int freq_target; + /* + * if we cannot reduce the frequency anymore, break out early + */ + if (policy->cur == policy->min) + return; + + freq_target = get_freq_target(cs_tuners, policy); + if (dbs_info->requested_freq > freq_target) + dbs_info->requested_freq -= freq_target; + else + dbs_info->requested_freq = policy->min; + + __cpufreq_driver_target(policy, dbs_info->requested_freq, + CPUFREQ_RELATION_L); + return; + } +} + +static unsigned int cs_dbs_timer(struct cpu_dbs_info *cdbs, + struct dbs_data *dbs_data, bool modify_all) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + + if (modify_all) + dbs_check_cpu(dbs_data, cdbs->shared->policy->cpu); + + return delay_for_sampling_rate(cs_tuners->sampling_rate); +} + +static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cpufreq_freqs *freq = data; + struct cs_cpu_dbs_info_s *dbs_info = + &per_cpu(cs_cpu_dbs_info, freq->cpu); + struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu); + + if (!policy) + return 0; + + /* policy isn't governed by conservative governor */ + if (policy->governor != &cpufreq_gov_conservative) + return 0; + + /* + * we only care if our internally tracked freq moves outside the 'valid' + * ranges of frequency available to us otherwise we do not change it + */ + if (dbs_info->requested_freq > policy->max + || dbs_info->requested_freq < policy->min) + dbs_info->requested_freq = freq->new; + + return 0; +} + +static struct notifier_block cs_cpufreq_notifier_block = { + .notifier_call = dbs_cpufreq_notifier, +}; + +/************************** sysfs interface ************************/ +static struct common_dbs_data cs_dbs_cdata; + +static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) + return -EINVAL; + + cs_tuners->sampling_down_factor = input; + return count; +} + +static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1) + return -EINVAL; + + cs_tuners->sampling_rate = max(input, dbs_data->min_sampling_rate); + return count; +} + +static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold) + return -EINVAL; + + cs_tuners->up_threshold = input; + return count; +} + +static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + /* cannot be lower than 1 otherwise freq will not fall */ + if (ret != 1 || input < 1 || input > 100 || + input >= cs_tuners->up_threshold) + return -EINVAL; + + cs_tuners->down_threshold = input; + return count; +} + +static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input, j; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + if (input > 1) + input = 1; + + if (input == cs_tuners->ignore_nice_load) /* nothing to do */ + return count; + + cs_tuners->ignore_nice_load = input; + + /* we need to re-evaluate prev_cpu_idle */ + for_each_online_cpu(j) { + struct cs_cpu_dbs_info_s *dbs_info; + dbs_info = &per_cpu(cs_cpu_dbs_info, j); + dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, + &dbs_info->cdbs.prev_cpu_wall, 0); + if (cs_tuners->ignore_nice_load) + dbs_info->cdbs.prev_cpu_nice = + kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + } + return count; +} + +static ssize_t store_freq_step(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1) + return -EINVAL; + + if (input > 100) + input = 100; + + /* + * no need to test here if freq_step is zero as the user might actually + * want this, they would be crazy though :) + */ + cs_tuners->freq_step = input; + return count; +} + +show_store_one(cs, sampling_rate); +show_store_one(cs, sampling_down_factor); +show_store_one(cs, up_threshold); +show_store_one(cs, down_threshold); +show_store_one(cs, ignore_nice_load); +show_store_one(cs, freq_step); +declare_show_sampling_rate_min(cs); + +gov_sys_pol_attr_rw(sampling_rate); +gov_sys_pol_attr_rw(sampling_down_factor); +gov_sys_pol_attr_rw(up_threshold); +gov_sys_pol_attr_rw(down_threshold); +gov_sys_pol_attr_rw(ignore_nice_load); +gov_sys_pol_attr_rw(freq_step); +gov_sys_pol_attr_ro(sampling_rate_min); + +static struct attribute *dbs_attributes_gov_sys[] = { + &sampling_rate_min_gov_sys.attr, + &sampling_rate_gov_sys.attr, + &sampling_down_factor_gov_sys.attr, + &up_threshold_gov_sys.attr, + &down_threshold_gov_sys.attr, + &ignore_nice_load_gov_sys.attr, + &freq_step_gov_sys.attr, + NULL +}; + +static struct attribute_group cs_attr_group_gov_sys = { + .attrs = dbs_attributes_gov_sys, + .name = "conservative", +}; + +static struct attribute *dbs_attributes_gov_pol[] = { + &sampling_rate_min_gov_pol.attr, + &sampling_rate_gov_pol.attr, + &sampling_down_factor_gov_pol.attr, + &up_threshold_gov_pol.attr, + &down_threshold_gov_pol.attr, + &ignore_nice_load_gov_pol.attr, + &freq_step_gov_pol.attr, + NULL +}; + +static struct attribute_group cs_attr_group_gov_pol = { + .attrs = dbs_attributes_gov_pol, + .name = "conservative", +}; + +/************************** sysfs end ************************/ + +static int cs_init(struct dbs_data *dbs_data, bool notify) +{ + struct cs_dbs_tuners *tuners; + + tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); + if (!tuners) { + pr_err("%s: kzalloc failed\n", __func__); + return -ENOMEM; + } + + tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; + tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; + tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; + tuners->ignore_nice_load = 0; + tuners->freq_step = DEF_FREQUENCY_STEP; + + dbs_data->tuners = tuners; + dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * + jiffies_to_usecs(10); + + if (notify) + cpufreq_register_notifier(&cs_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + + return 0; +} + +static void cs_exit(struct dbs_data *dbs_data, bool notify) +{ + if (notify) + cpufreq_unregister_notifier(&cs_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + + kfree(dbs_data->tuners); +} + +define_get_cpu_dbs_routines(cs_cpu_dbs_info); + +static struct common_dbs_data cs_dbs_cdata = { + .governor = GOV_CONSERVATIVE, + .attr_group_gov_sys = &cs_attr_group_gov_sys, + .attr_group_gov_pol = &cs_attr_group_gov_pol, + .get_cpu_cdbs = get_cpu_cdbs, + .get_cpu_dbs_info_s = get_cpu_dbs_info_s, + .gov_dbs_timer = cs_dbs_timer, + .gov_check_cpu = cs_check_cpu, + .init = cs_init, + .exit = cs_exit, + .mutex = __MUTEX_INITIALIZER(cs_dbs_cdata.mutex), +}; + +static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + return cpufreq_governor_dbs(policy, &cs_dbs_cdata, event); +} + +static int __init cpufreq_gov_dbs_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_conservative); +} + +static void __exit cpufreq_gov_dbs_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_conservative); +} + +MODULE_AUTHOR("Alexander Clouter "); +MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " + "Low Latency Frequency Transition capable processors " + "optimised for use in a battery environment"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE +fs_initcall(cpufreq_gov_dbs_init); +#else +module_init(cpufreq_gov_dbs_init); +#endif +module_exit(cpufreq_gov_dbs_exit); diff --git a/src/cpufreq/4.x/cpufreq_governor.h b/src/cpufreq/4.x/cpufreq_governor.h new file mode 100644 index 000000000..f7b340c27 --- /dev/null +++ b/src/cpufreq/4.x/cpufreq_governor.h @@ -0,0 +1,281 @@ +/* + * drivers/cpufreq/cpufreq_governor.h + * + * Header file for CPUFreq governors common code + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * (C) 2003 Jun Nakajima + * (C) 2009 Alexander Clouter + * (c) 2012 Viresh Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _CPUFREQ_GOVERNOR_H +#define _CPUFREQ_GOVERNOR_H + +#include +#include +#include +#include + +/* + * The polling frequency depends on the capability of the processor. Default + * polling frequency is 1000 times the transition latency of the processor. The + * governor will work on any processor with transition latency <= 10ms, using + * appropriate sampling rate. + * + * For CPUs with transition latency > 10ms (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. All times here are in us (micro seconds). + */ +#define MIN_SAMPLING_RATE_RATIO (2) +#define LATENCY_MULTIPLIER (1000) +#define MIN_LATENCY_MULTIPLIER (20) +#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) + +/* Ondemand Sampling types */ +enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE}; + +/* + * Macro for creating governors sysfs routines + * + * - gov_sys: One governor instance per whole system + * - gov_pol: One governor instance per policy + */ + +/* Create attributes */ +#define gov_sys_attr_ro(_name) \ +static struct kobj_attribute _name##_gov_sys = \ +__ATTR(_name, 0444, show_##_name##_gov_sys, NULL) + +#define gov_sys_attr_rw(_name) \ +static struct kobj_attribute _name##_gov_sys = \ +__ATTR(_name, 0644, show_##_name##_gov_sys, store_##_name##_gov_sys) + +#define gov_pol_attr_ro(_name) \ +static struct freq_attr _name##_gov_pol = \ +__ATTR(_name, 0444, show_##_name##_gov_pol, NULL) + +#define gov_pol_attr_rw(_name) \ +static struct freq_attr _name##_gov_pol = \ +__ATTR(_name, 0644, show_##_name##_gov_pol, store_##_name##_gov_pol) + +#define gov_sys_pol_attr_rw(_name) \ + gov_sys_attr_rw(_name); \ + gov_pol_attr_rw(_name) + +#define gov_sys_pol_attr_ro(_name) \ + gov_sys_attr_ro(_name); \ + gov_pol_attr_ro(_name) + +/* Create show/store routines */ +#define show_one(_gov, file_name) \ +static ssize_t show_##file_name##_gov_sys \ +(struct kobject *kobj, struct kobj_attribute *attr, char *buf) \ +{ \ + struct _gov##_dbs_tuners *tuners = _gov##_dbs_cdata.gdbs_data->tuners; \ + return sprintf(buf, "%u\n", tuners->file_name); \ +} \ + \ +static ssize_t show_##file_name##_gov_pol \ +(struct cpufreq_policy *policy, char *buf) \ +{ \ + struct dbs_data *dbs_data = policy->governor_data; \ + struct _gov##_dbs_tuners *tuners = dbs_data->tuners; \ + return sprintf(buf, "%u\n", tuners->file_name); \ +} + +#define store_one(_gov, file_name) \ +static ssize_t store_##file_name##_gov_sys \ +(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) \ +{ \ + struct dbs_data *dbs_data = _gov##_dbs_cdata.gdbs_data; \ + return store_##file_name(dbs_data, buf, count); \ +} \ + \ +static ssize_t store_##file_name##_gov_pol \ +(struct cpufreq_policy *policy, const char *buf, size_t count) \ +{ \ + struct dbs_data *dbs_data = policy->governor_data; \ + return store_##file_name(dbs_data, buf, count); \ +} + +#define show_store_one(_gov, file_name) \ +show_one(_gov, file_name); \ +store_one(_gov, file_name) + +/* create helper routines */ +#define define_get_cpu_dbs_routines(_dbs_info) \ +static struct cpu_dbs_info *get_cpu_cdbs(int cpu) \ +{ \ + return &per_cpu(_dbs_info, cpu).cdbs; \ +} \ + \ +static void *get_cpu_dbs_info_s(int cpu) \ +{ \ + return &per_cpu(_dbs_info, cpu); \ +} + +/* + * Abbreviations: + * dbs: used as a shortform for demand based switching It helps to keep variable + * names smaller, simpler + * cdbs: common dbs + * od_*: On-demand governor + * cs_*: Conservative governor + */ + +/* Common to all CPUs of a policy */ +struct cpu_common_dbs_info { + struct cpufreq_policy *policy; + /* + * percpu mutex that serializes governor limit change with dbs_timer + * invocation. We do not want dbs_timer to run when user is changing + * the governor or limits. + */ + struct mutex timer_mutex; + ktime_t time_stamp; +}; + +/* Per cpu structures */ +struct cpu_dbs_info { + u64 prev_cpu_idle; + u64 prev_cpu_wall; + u64 prev_cpu_nice; + /* + * Used to keep track of load in the previous interval. However, when + * explicitly set to zero, it is used as a flag to ensure that we copy + * the previous load to the current interval only once, upon the first + * wake-up from idle. + */ + unsigned int prev_load; + struct delayed_work dwork; + struct cpu_common_dbs_info *shared; +}; + +struct od_cpu_dbs_info_s { + struct cpu_dbs_info cdbs; + struct cpufreq_frequency_table *freq_table; + unsigned int freq_lo; + unsigned int freq_lo_jiffies; + unsigned int freq_hi_jiffies; + unsigned int rate_mult; + unsigned int sample_type:1; +}; + +struct cs_cpu_dbs_info_s { + struct cpu_dbs_info cdbs; + unsigned int down_skip; + unsigned int requested_freq; +}; + +/* Per policy Governors sysfs tunables */ +struct od_dbs_tuners { + unsigned int ignore_nice_load; + unsigned int sampling_rate; + unsigned int sampling_down_factor; + unsigned int up_threshold; + unsigned int powersave_bias; + unsigned int io_is_busy; +}; + +struct cs_dbs_tuners { + unsigned int ignore_nice_load; + unsigned int sampling_rate; + unsigned int sampling_down_factor; + unsigned int up_threshold; + unsigned int down_threshold; + unsigned int freq_step; +}; + +/* Common Governor data across policies */ +struct dbs_data; +struct common_dbs_data { + /* Common across governors */ + #define GOV_ONDEMAND 0 + #define GOV_CONSERVATIVE 1 + int governor; + struct attribute_group *attr_group_gov_sys; /* one governor - system */ + struct attribute_group *attr_group_gov_pol; /* one governor - policy */ + + /* + * Common data for platforms that don't set + * CPUFREQ_HAVE_GOVERNOR_PER_POLICY + */ + struct dbs_data *gdbs_data; + + struct cpu_dbs_info *(*get_cpu_cdbs)(int cpu); + void *(*get_cpu_dbs_info_s)(int cpu); + unsigned int (*gov_dbs_timer)(struct cpu_dbs_info *cdbs, + struct dbs_data *dbs_data, + bool modify_all); + void (*gov_check_cpu)(int cpu, unsigned int load); + int (*init)(struct dbs_data *dbs_data, bool notify); + void (*exit)(struct dbs_data *dbs_data, bool notify); + + /* Governor specific ops, see below */ + void *gov_ops; + + /* + * Protects governor's data (struct dbs_data and struct common_dbs_data) + */ + struct mutex mutex; +}; + +/* Governor Per policy data */ +struct dbs_data { + struct common_dbs_data *cdata; + unsigned int min_sampling_rate; + int usage_count; + void *tuners; +}; + +/* Governor specific ops, will be passed to dbs_data->gov_ops */ +struct od_ops { + void (*powersave_bias_init_cpu)(int cpu); + unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy, + unsigned int freq_next, unsigned int relation); + void (*freq_increase)(struct cpufreq_policy *policy, unsigned int freq); +}; + +static inline int delay_for_sampling_rate(unsigned int sampling_rate) +{ + int delay = usecs_to_jiffies(sampling_rate); + + /* We want all CPUs to do sampling nearly on same jiffy */ + if (num_online_cpus() > 1) + delay -= jiffies % delay; + + return delay; +} + +#define declare_show_sampling_rate_min(_gov) \ +static ssize_t show_sampling_rate_min_gov_sys \ +(struct kobject *kobj, struct kobj_attribute *attr, char *buf) \ +{ \ + struct dbs_data *dbs_data = _gov##_dbs_cdata.gdbs_data; \ + return sprintf(buf, "%u\n", dbs_data->min_sampling_rate); \ +} \ + \ +static ssize_t show_sampling_rate_min_gov_pol \ +(struct cpufreq_policy *policy, char *buf) \ +{ \ + struct dbs_data *dbs_data = policy->governor_data; \ + return sprintf(buf, "%u\n", dbs_data->min_sampling_rate); \ +} + +extern struct mutex cpufreq_governor_lock; + +void dbs_check_cpu(struct dbs_data *dbs_data, int cpu); +int cpufreq_governor_dbs(struct cpufreq_policy *policy, + struct common_dbs_data *cdata, unsigned int event); +void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy, + unsigned int delay, bool all_cpus); +void od_register_powersave_bias_handler(unsigned int (*f) + (struct cpufreq_policy *, unsigned int, unsigned int), + unsigned int powersave_bias); +void od_unregister_powersave_bias_handler(void); +#endif /* _CPUFREQ_GOVERNOR_H */ diff --git a/src/cpufreq/4.x/cpufreq_ondemand.c b/src/cpufreq/4.x/cpufreq_ondemand.c new file mode 100644 index 000000000..03ac6ce54 --- /dev/null +++ b/src/cpufreq/4.x/cpufreq_ondemand.c @@ -0,0 +1,620 @@ +/* + * drivers/cpufreq/cpufreq_ondemand.c + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include "cpufreq_governor.h" + +/* On-demand governor macros */ +#define DEF_FREQUENCY_UP_THRESHOLD (80) +#define DEF_SAMPLING_DOWN_FACTOR (1) +#define MAX_SAMPLING_DOWN_FACTOR (100000) +#define MICRO_FREQUENCY_UP_THRESHOLD (95) +#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) +#define MIN_FREQUENCY_UP_THRESHOLD (11) +#define MAX_FREQUENCY_UP_THRESHOLD (100) + +static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info); + +static struct od_ops od_ops; + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +static struct cpufreq_governor cpufreq_gov_ondemand; +#endif + +static unsigned int default_powersave_bias; + +static void ondemand_powersave_bias_init_cpu(int cpu) +{ + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu); + + dbs_info->freq_table = cpufreq_frequency_get_table(cpu); + dbs_info->freq_lo = 0; +} + +/* + * Not all CPUs want IO time to be accounted as busy; this depends on how + * efficient idling at a higher frequency/voltage is. + * Pavel Machek says this is not so for various generations of AMD and old + * Intel systems. + * Mike Chan (android.com) claims this is also not true for ARM. + * Because of this, whitelist specific known (series) of CPUs by default, and + * leave all others up to the user. + */ +static int should_io_be_busy(void) +{ +#if defined(CONFIG_X86) + /* + * For Intel, Core 2 (model 15) and later have an efficient idle. + */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_data.x86 == 6 && + boot_cpu_data.x86_model >= 15) + return 1; +#endif + return 0; +} + +/* + * Find right freq to be set now with powersave_bias on. + * Returns the freq_hi to be used right now and will set freq_hi_jiffies, + * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs. + */ +static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy, + unsigned int freq_next, unsigned int relation) +{ + unsigned int freq_req, freq_reduc, freq_avg; + unsigned int freq_hi, freq_lo; + unsigned int index = 0; + unsigned int jiffies_total, jiffies_hi, jiffies_lo; + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, + policy->cpu); + struct dbs_data *dbs_data = policy->governor_data; + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + + if (!dbs_info->freq_table) { + dbs_info->freq_lo = 0; + dbs_info->freq_lo_jiffies = 0; + return freq_next; + } + + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next, + relation, &index); + freq_req = dbs_info->freq_table[index].frequency; + freq_reduc = freq_req * od_tuners->powersave_bias / 1000; + freq_avg = freq_req - freq_reduc; + + /* Find freq bounds for freq_avg in freq_table */ + index = 0; + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, + CPUFREQ_RELATION_H, &index); + freq_lo = dbs_info->freq_table[index].frequency; + index = 0; + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, + CPUFREQ_RELATION_L, &index); + freq_hi = dbs_info->freq_table[index].frequency; + + /* Find out how long we have to be in hi and lo freqs */ + if (freq_hi == freq_lo) { + dbs_info->freq_lo = 0; + dbs_info->freq_lo_jiffies = 0; + return freq_lo; + } + jiffies_total = usecs_to_jiffies(od_tuners->sampling_rate); + jiffies_hi = (freq_avg - freq_lo) * jiffies_total; + jiffies_hi += ((freq_hi - freq_lo) / 2); + jiffies_hi /= (freq_hi - freq_lo); + jiffies_lo = jiffies_total - jiffies_hi; + dbs_info->freq_lo = freq_lo; + dbs_info->freq_lo_jiffies = jiffies_lo; + dbs_info->freq_hi_jiffies = jiffies_hi; + return freq_hi; +} + +static void ondemand_powersave_bias_init(void) +{ + int i; + for_each_online_cpu(i) { + ondemand_powersave_bias_init_cpu(i); + } +} + +static void dbs_freq_increase(struct cpufreq_policy *policy, unsigned int freq) +{ + struct dbs_data *dbs_data = policy->governor_data; + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + + if (od_tuners->powersave_bias) + freq = od_ops.powersave_bias_target(policy, freq, + CPUFREQ_RELATION_H); + else if (policy->cur == policy->max) + return; + + __cpufreq_driver_target(policy, freq, od_tuners->powersave_bias ? + CPUFREQ_RELATION_L : CPUFREQ_RELATION_H); +} + +/* + * Every sampling_rate, we check, if current idle time is less than 20% + * (default), then we try to increase frequency. Else, we adjust the frequency + * proportional to load. + */ +static void od_check_cpu(int cpu, unsigned int load) +{ + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu); + struct cpufreq_policy *policy = dbs_info->cdbs.shared->policy; + struct dbs_data *dbs_data = policy->governor_data; + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + + dbs_info->freq_lo = 0; + + /* Check for frequency increase */ + if (load > od_tuners->up_threshold) { + /* If switching to max speed, apply sampling_down_factor */ + if (policy->cur < policy->max) + dbs_info->rate_mult = + od_tuners->sampling_down_factor; + dbs_freq_increase(policy, policy->max); + } else { + /* Calculate the next frequency proportional to load */ + unsigned int freq_next, min_f, max_f; + + min_f = policy->cpuinfo.min_freq; + max_f = policy->cpuinfo.max_freq; + freq_next = min_f + load * (max_f - min_f) / 100; + + /* No longer fully busy, reset rate_mult */ + dbs_info->rate_mult = 1; + + if (!od_tuners->powersave_bias) { + __cpufreq_driver_target(policy, freq_next, + CPUFREQ_RELATION_C); + return; + } + + freq_next = od_ops.powersave_bias_target(policy, freq_next, + CPUFREQ_RELATION_L); + __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_C); + } +} + +static unsigned int od_dbs_timer(struct cpu_dbs_info *cdbs, + struct dbs_data *dbs_data, bool modify_all) +{ + struct cpufreq_policy *policy = cdbs->shared->policy; + unsigned int cpu = policy->cpu; + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, + cpu); + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + int delay = 0, sample_type = dbs_info->sample_type; + + if (!modify_all) + goto max_delay; + + /* Common NORMAL_SAMPLE setup */ + dbs_info->sample_type = OD_NORMAL_SAMPLE; + if (sample_type == OD_SUB_SAMPLE) { + delay = dbs_info->freq_lo_jiffies; + __cpufreq_driver_target(policy, dbs_info->freq_lo, + CPUFREQ_RELATION_H); + } else { + dbs_check_cpu(dbs_data, cpu); + if (dbs_info->freq_lo) { + /* Setup timer for SUB_SAMPLE */ + dbs_info->sample_type = OD_SUB_SAMPLE; + delay = dbs_info->freq_hi_jiffies; + } + } + +max_delay: + if (!delay) + delay = delay_for_sampling_rate(od_tuners->sampling_rate + * dbs_info->rate_mult); + + return delay; +} + +/************************** sysfs interface ************************/ +static struct common_dbs_data od_dbs_cdata; + +/** + * update_sampling_rate - update sampling rate effective immediately if needed. + * @new_rate: new sampling rate + * + * If new rate is smaller than the old, simply updating + * dbs_tuners_int.sampling_rate might not be appropriate. For example, if the + * original sampling_rate was 1 second and the requested new sampling rate is 10 + * ms because the user needs immediate reaction from ondemand governor, but not + * sure if higher frequency will be required or not, then, the governor may + * change the sampling rate too late; up to 1 second later. Thus, if we are + * reducing the sampling rate, we need to make the new value effective + * immediately. + */ +static void update_sampling_rate(struct dbs_data *dbs_data, + unsigned int new_rate) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + int cpu; + + od_tuners->sampling_rate = new_rate = max(new_rate, + dbs_data->min_sampling_rate); + + for_each_online_cpu(cpu) { + struct cpufreq_policy *policy; + struct od_cpu_dbs_info_s *dbs_info; + unsigned long next_sampling, appointed_at; + + policy = cpufreq_cpu_get(cpu); + if (!policy) + continue; + if (policy->governor != &cpufreq_gov_ondemand) { + cpufreq_cpu_put(policy); + continue; + } + dbs_info = &per_cpu(od_cpu_dbs_info, cpu); + cpufreq_cpu_put(policy); + + if (!delayed_work_pending(&dbs_info->cdbs.dwork)) + continue; + + next_sampling = jiffies + usecs_to_jiffies(new_rate); + appointed_at = dbs_info->cdbs.dwork.timer.expires; + + if (time_before(next_sampling, appointed_at)) { + cancel_delayed_work_sync(&dbs_info->cdbs.dwork); + + gov_queue_work(dbs_data, policy, + usecs_to_jiffies(new_rate), true); + + } + } +} + +static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + update_sampling_rate(dbs_data, input); + return count; +} + +static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + unsigned int input; + int ret; + unsigned int j; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + od_tuners->io_is_busy = !!input; + + /* we need to re-evaluate prev_cpu_idle */ + for_each_online_cpu(j) { + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, + j); + dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, + &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy); + } + return count; +} + +static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || + input < MIN_FREQUENCY_UP_THRESHOLD) { + return -EINVAL; + } + + od_tuners->up_threshold = input; + return count; +} + +static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + unsigned int input, j; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) + return -EINVAL; + od_tuners->sampling_down_factor = input; + + /* Reset down sampling multiplier in case it was active */ + for_each_online_cpu(j) { + struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, + j); + dbs_info->rate_mult = 1; + } + return count; +} + +static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data, + const char *buf, size_t count) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + unsigned int input; + int ret; + + unsigned int j; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + if (input > 1) + input = 1; + + if (input == od_tuners->ignore_nice_load) { /* nothing to do */ + return count; + } + od_tuners->ignore_nice_load = input; + + /* we need to re-evaluate prev_cpu_idle */ + for_each_online_cpu(j) { + struct od_cpu_dbs_info_s *dbs_info; + dbs_info = &per_cpu(od_cpu_dbs_info, j); + dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j, + &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy); + if (od_tuners->ignore_nice_load) + dbs_info->cdbs.prev_cpu_nice = + kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + + } + return count; +} + +static ssize_t store_powersave_bias(struct dbs_data *dbs_data, const char *buf, + size_t count) +{ + struct od_dbs_tuners *od_tuners = dbs_data->tuners; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1) + return -EINVAL; + + if (input > 1000) + input = 1000; + + od_tuners->powersave_bias = input; + ondemand_powersave_bias_init(); + return count; +} + +show_store_one(od, sampling_rate); +show_store_one(od, io_is_busy); +show_store_one(od, up_threshold); +show_store_one(od, sampling_down_factor); +show_store_one(od, ignore_nice_load); +show_store_one(od, powersave_bias); +declare_show_sampling_rate_min(od); + +gov_sys_pol_attr_rw(sampling_rate); +gov_sys_pol_attr_rw(io_is_busy); +gov_sys_pol_attr_rw(up_threshold); +gov_sys_pol_attr_rw(sampling_down_factor); +gov_sys_pol_attr_rw(ignore_nice_load); +gov_sys_pol_attr_rw(powersave_bias); +gov_sys_pol_attr_ro(sampling_rate_min); + +static struct attribute *dbs_attributes_gov_sys[] = { + &sampling_rate_min_gov_sys.attr, + &sampling_rate_gov_sys.attr, + &up_threshold_gov_sys.attr, + &sampling_down_factor_gov_sys.attr, + &ignore_nice_load_gov_sys.attr, + &powersave_bias_gov_sys.attr, + &io_is_busy_gov_sys.attr, + NULL +}; + +static struct attribute_group od_attr_group_gov_sys = { + .attrs = dbs_attributes_gov_sys, + .name = "ondemand", +}; + +static struct attribute *dbs_attributes_gov_pol[] = { + &sampling_rate_min_gov_pol.attr, + &sampling_rate_gov_pol.attr, + &up_threshold_gov_pol.attr, + &sampling_down_factor_gov_pol.attr, + &ignore_nice_load_gov_pol.attr, + &powersave_bias_gov_pol.attr, + &io_is_busy_gov_pol.attr, + NULL +}; + +static struct attribute_group od_attr_group_gov_pol = { + .attrs = dbs_attributes_gov_pol, + .name = "ondemand", +}; + +/************************** sysfs end ************************/ + +static int od_init(struct dbs_data *dbs_data, bool notify) +{ + struct od_dbs_tuners *tuners; + u64 idle_time; + int cpu; + + tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); + if (!tuners) { + pr_err("%s: kzalloc failed\n", __func__); + return -ENOMEM; + } + + cpu = get_cpu(); + idle_time = get_cpu_idle_time_us(cpu, NULL); + put_cpu(); + if (idle_time != -1ULL) { + /* Idle micro accounting is supported. Use finer thresholds */ + tuners->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; + /* + * In nohz/micro accounting case we set the minimum frequency + * not depending on HZ, but fixed (very low). The deferred + * timer might skip some samples if idle/sleeping as needed. + */ + dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; + } else { + tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; + + /* For correct statistics, we need 10 ticks for each measure */ + dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * + jiffies_to_usecs(10); + } + + tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; + tuners->ignore_nice_load = 0; + tuners->powersave_bias = default_powersave_bias; + tuners->io_is_busy = should_io_be_busy(); + + dbs_data->tuners = tuners; + return 0; +} + +static void od_exit(struct dbs_data *dbs_data, bool notify) +{ + kfree(dbs_data->tuners); +} + +define_get_cpu_dbs_routines(od_cpu_dbs_info); + +static struct od_ops od_ops = { + .powersave_bias_init_cpu = ondemand_powersave_bias_init_cpu, + .powersave_bias_target = generic_powersave_bias_target, + .freq_increase = dbs_freq_increase, +}; + +static struct common_dbs_data od_dbs_cdata = { + .governor = GOV_ONDEMAND, + .attr_group_gov_sys = &od_attr_group_gov_sys, + .attr_group_gov_pol = &od_attr_group_gov_pol, + .get_cpu_cdbs = get_cpu_cdbs, + .get_cpu_dbs_info_s = get_cpu_dbs_info_s, + .gov_dbs_timer = od_dbs_timer, + .gov_check_cpu = od_check_cpu, + .gov_ops = &od_ops, + .init = od_init, + .exit = od_exit, + .mutex = __MUTEX_INITIALIZER(od_dbs_cdata.mutex), +}; + +static void od_set_powersave_bias(unsigned int powersave_bias) +{ + struct cpufreq_policy *policy; + struct dbs_data *dbs_data; + struct od_dbs_tuners *od_tuners; + unsigned int cpu; + cpumask_t done; + + default_powersave_bias = powersave_bias; + cpumask_clear(&done); + + get_online_cpus(); + for_each_online_cpu(cpu) { + struct cpu_common_dbs_info *shared; + + if (cpumask_test_cpu(cpu, &done)) + continue; + + shared = per_cpu(od_cpu_dbs_info, cpu).cdbs.shared; + if (!shared) + continue; + + policy = shared->policy; + cpumask_or(&done, &done, policy->cpus); + + if (policy->governor != &cpufreq_gov_ondemand) + continue; + + dbs_data = policy->governor_data; + od_tuners = dbs_data->tuners; + od_tuners->powersave_bias = default_powersave_bias; + } + put_online_cpus(); +} + +void od_register_powersave_bias_handler(unsigned int (*f) + (struct cpufreq_policy *, unsigned int, unsigned int), + unsigned int powersave_bias) +{ + od_ops.powersave_bias_target = f; + od_set_powersave_bias(powersave_bias); +} +EXPORT_SYMBOL_GPL(od_register_powersave_bias_handler); + +void od_unregister_powersave_bias_handler(void) +{ + od_ops.powersave_bias_target = generic_powersave_bias_target; + od_set_powersave_bias(0); +} +EXPORT_SYMBOL_GPL(od_unregister_powersave_bias_handler); + +static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + return cpufreq_governor_dbs(policy, &od_dbs_cdata, event); +} + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +static +#endif +struct cpufreq_governor cpufreq_gov_ondemand = { + .name = "ondemand", + .governor = od_cpufreq_governor_dbs, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, +}; + +static int __init cpufreq_gov_dbs_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_ondemand); +} + +static void __exit cpufreq_gov_dbs_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_ondemand); +} + +MODULE_AUTHOR("Venkatesh Pallipadi "); +MODULE_AUTHOR("Alexey Starikovskiy "); +MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for " + "Low Latency Frequency Transition capable processors"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +fs_initcall(cpufreq_gov_dbs_init); +#else +module_init(cpufreq_gov_dbs_init); +#endif +module_exit(cpufreq_gov_dbs_exit); diff --git a/src/cpufreq/4.x/cpufreq_powersave.c b/src/cpufreq/4.x/cpufreq_powersave.c new file mode 100644 index 000000000..e3b874c23 --- /dev/null +++ b/src/cpufreq/4.x/cpufreq_powersave.c @@ -0,0 +1,64 @@ +/* + * linux/drivers/cpufreq/cpufreq_powersave.c + * + * Copyright (C) 2002 - 2003 Dominik Brodowski + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include + +static int cpufreq_governor_powersave(struct cpufreq_policy *policy, + unsigned int event) +{ + switch (event) { + case CPUFREQ_GOV_START: + case CPUFREQ_GOV_LIMITS: + pr_debug("setting to %u kHz because of event %u\n", + policy->min, event); + __cpufreq_driver_target(policy, policy->min, + CPUFREQ_RELATION_L); + break; + default: + break; + } + return 0; +} + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE +static +#endif +struct cpufreq_governor cpufreq_gov_powersave = { + .name = "powersave", + .governor = cpufreq_governor_powersave, + .owner = THIS_MODULE, +}; + +static int __init cpufreq_gov_powersave_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_powersave); +} + +static void __exit cpufreq_gov_powersave_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_powersave); +} + +MODULE_AUTHOR("Dominik Brodowski "); +MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE +fs_initcall(cpufreq_gov_powersave_init); +#else +module_init(cpufreq_gov_powersave_init); +#endif +module_exit(cpufreq_gov_powersave_exit); diff --git a/src/cpufreq/4.x/cpufreq_userspace.c b/src/cpufreq/4.x/cpufreq_userspace.c new file mode 100644 index 000000000..9cc8abd3d --- /dev/null +++ b/src/cpufreq/4.x/cpufreq_userspace.c @@ -0,0 +1,156 @@ + +/* + * linux/drivers/cpufreq/cpufreq_userspace.c + * + * Copyright (C) 2001 Russell King + * (C) 2002 - 2004 Dominik Brodowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +static DEFINE_PER_CPU(unsigned int, cpu_is_managed); +static DEFINE_MUTEX(userspace_mutex); + +/** + * cpufreq_set - set the CPU frequency + * @policy: pointer to policy struct where freq is being set + * @freq: target frequency in kHz + * + * Sets the CPU frequency to freq. + */ +static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq) +{ + int ret = -EINVAL; + unsigned int *setspeed = policy->governor_data; + + pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq); + + mutex_lock(&userspace_mutex); + if (!per_cpu(cpu_is_managed, policy->cpu)) + goto err; + + *setspeed = freq; + + ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); + err: + mutex_unlock(&userspace_mutex); + return ret; +} + +static ssize_t show_speed(struct cpufreq_policy *policy, char *buf) +{ + return sprintf(buf, "%u\n", policy->cur); +} + +static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy) +{ + unsigned int *setspeed; + + setspeed = kzalloc(sizeof(*setspeed), GFP_KERNEL); + if (!setspeed) + return -ENOMEM; + + policy->governor_data = setspeed; + return 0; +} + +static int cpufreq_governor_userspace(struct cpufreq_policy *policy, + unsigned int event) +{ + unsigned int *setspeed = policy->governor_data; + unsigned int cpu = policy->cpu; + int rc = 0; + + if (event == CPUFREQ_GOV_POLICY_INIT) + return cpufreq_userspace_policy_init(policy); + + if (!setspeed) + return -EINVAL; + + switch (event) { + case CPUFREQ_GOV_POLICY_EXIT: + mutex_lock(&userspace_mutex); + policy->governor_data = NULL; + kfree(setspeed); + mutex_unlock(&userspace_mutex); + break; + case CPUFREQ_GOV_START: + BUG_ON(!policy->cur); + pr_debug("started managing cpu %u\n", cpu); + + mutex_lock(&userspace_mutex); + per_cpu(cpu_is_managed, cpu) = 1; + *setspeed = policy->cur; + mutex_unlock(&userspace_mutex); + break; + case CPUFREQ_GOV_STOP: + pr_debug("managing cpu %u stopped\n", cpu); + + mutex_lock(&userspace_mutex); + per_cpu(cpu_is_managed, cpu) = 0; + *setspeed = 0; + mutex_unlock(&userspace_mutex); + break; + case CPUFREQ_GOV_LIMITS: + mutex_lock(&userspace_mutex); + pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", + cpu, policy->min, policy->max, policy->cur, *setspeed); + + if (policy->max < *setspeed) + __cpufreq_driver_target(policy, policy->max, + CPUFREQ_RELATION_H); + else if (policy->min > *setspeed) + __cpufreq_driver_target(policy, policy->min, + CPUFREQ_RELATION_L); + else + __cpufreq_driver_target(policy, *setspeed, + CPUFREQ_RELATION_L); + mutex_unlock(&userspace_mutex); + break; + } + return rc; +} + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE +static +#endif +struct cpufreq_governor cpufreq_gov_userspace = { + .name = "userspace", + .governor = cpufreq_governor_userspace, + .store_setspeed = cpufreq_set, + .show_setspeed = show_speed, + .owner = THIS_MODULE, +}; + +static int __init cpufreq_gov_userspace_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_userspace); +} + +static void __exit cpufreq_gov_userspace_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_userspace); +} + +MODULE_AUTHOR("Dominik Brodowski , " + "Russell King "); +MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE +fs_initcall(cpufreq_gov_userspace_init); +#else +module_init(cpufreq_gov_userspace_init); +#endif +module_exit(cpufreq_gov_userspace_exit); diff --git a/src/cpufreq/4.x/intel_pstate.c b/src/cpufreq/4.x/intel_pstate.c new file mode 100644 index 000000000..15fcf2cac --- /dev/null +++ b/src/cpufreq/4.x/intel_pstate.c @@ -0,0 +1,1460 @@ +/* + * intel_pstate.c: Native P state management for Intel processors + * + * (C) Copyright 2012 Intel Corporation + * Author: Dirk Brandewie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define ATOM_RATIOS 0x66a +#define ATOM_VIDS 0x66b +#define ATOM_TURBO_RATIOS 0x66c +#define ATOM_TURBO_VIDS 0x66d + +#define FRAC_BITS 8 +#define int_tofp(X) ((int64_t)(X) << FRAC_BITS) +#define fp_toint(X) ((X) >> FRAC_BITS) + +static inline int32_t mul_fp(int32_t x, int32_t y) +{ + return ((int64_t)x * (int64_t)y) >> FRAC_BITS; +} + +static inline int32_t div_fp(s64 x, s64 y) +{ + return div64_s64((int64_t)x << FRAC_BITS, y); +} + +static inline int ceiling_fp(int32_t x) +{ + int mask, ret; + + ret = fp_toint(x); + mask = (1 << FRAC_BITS) - 1; + if (x & mask) + ret += 1; + return ret; +} + +struct sample { + int32_t core_pct_busy; + u64 aperf; + u64 mperf; + u64 tsc; + int freq; + ktime_t time; +}; + +struct pstate_data { + int current_pstate; + int min_pstate; + int max_pstate; + int max_pstate_physical; + int scaling; + int turbo_pstate; +}; + +struct vid_data { + int min; + int max; + int turbo; + int32_t ratio; +}; + +struct _pid { + int setpoint; + int32_t integral; + int32_t p_gain; + int32_t i_gain; + int32_t d_gain; + int deadband; + int32_t last_err; +}; + +struct cpudata { + int cpu; + + struct timer_list timer; + + struct pstate_data pstate; + struct vid_data vid; + struct _pid pid; + + ktime_t last_sample_time; + u64 prev_aperf; + u64 prev_mperf; + u64 prev_tsc; + struct sample sample; +}; + +static struct cpudata **all_cpu_data; +struct pstate_adjust_policy { + int sample_rate_ms; + int deadband; + int setpoint; + int p_gain_pct; + int d_gain_pct; + int i_gain_pct; +}; + +struct pstate_funcs { + int (*get_max)(void); + int (*get_max_physical)(void); + int (*get_min)(void); + int (*get_turbo)(void); + int (*get_scaling)(void); + void (*set)(struct cpudata*, int pstate); + void (*get_vid)(struct cpudata *); +}; + +struct cpu_defaults { + struct pstate_adjust_policy pid_policy; + struct pstate_funcs funcs; +}; + +static struct pstate_adjust_policy pid_params; +static struct pstate_funcs pstate_funcs; +static int hwp_active; + +struct perf_limits { + int no_turbo; + int turbo_disabled; + int max_perf_pct; + int min_perf_pct; + int32_t max_perf; + int32_t min_perf; + int max_policy_pct; + int max_sysfs_pct; + int min_policy_pct; + int min_sysfs_pct; +}; + +static struct perf_limits performance_limits = { + .no_turbo = 0, + .turbo_disabled = 0, + .max_perf_pct = 100, + .max_perf = int_tofp(1), + .min_perf_pct = 100, + .min_perf = int_tofp(1), + .max_policy_pct = 100, + .max_sysfs_pct = 100, + .min_policy_pct = 0, + .min_sysfs_pct = 0, +}; + +static struct perf_limits powersave_limits = { + .no_turbo = 0, + .turbo_disabled = 0, + .max_perf_pct = 100, + .max_perf = int_tofp(1), + .min_perf_pct = 0, + .min_perf = 0, + .max_policy_pct = 100, + .max_sysfs_pct = 100, + .min_policy_pct = 0, + .min_sysfs_pct = 0, +}; + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE +static struct perf_limits *limits = &performance_limits; +#else +static struct perf_limits *limits = &powersave_limits; +#endif + +static inline void pid_reset(struct _pid *pid, int setpoint, int busy, + int deadband, int integral) { + pid->setpoint = setpoint; + pid->deadband = deadband; + pid->integral = int_tofp(integral); + pid->last_err = int_tofp(setpoint) - int_tofp(busy); +} + +static inline void pid_p_gain_set(struct _pid *pid, int percent) +{ + pid->p_gain = div_fp(int_tofp(percent), int_tofp(100)); +} + +static inline void pid_i_gain_set(struct _pid *pid, int percent) +{ + pid->i_gain = div_fp(int_tofp(percent), int_tofp(100)); +} + +static inline void pid_d_gain_set(struct _pid *pid, int percent) +{ + pid->d_gain = div_fp(int_tofp(percent), int_tofp(100)); +} + +static signed int pid_calc(struct _pid *pid, int32_t busy) +{ + signed int result; + int32_t pterm, dterm, fp_error; + int32_t integral_limit; + + fp_error = int_tofp(pid->setpoint) - busy; + + if (abs(fp_error) <= int_tofp(pid->deadband)) + return 0; + + pterm = mul_fp(pid->p_gain, fp_error); + + pid->integral += fp_error; + + /* + * We limit the integral here so that it will never + * get higher than 30. This prevents it from becoming + * too large an input over long periods of time and allows + * it to get factored out sooner. + * + * The value of 30 was chosen through experimentation. + */ + integral_limit = int_tofp(30); + if (pid->integral > integral_limit) + pid->integral = integral_limit; + if (pid->integral < -integral_limit) + pid->integral = -integral_limit; + + dterm = mul_fp(pid->d_gain, fp_error - pid->last_err); + pid->last_err = fp_error; + + result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm; + result = result + (1 << (FRAC_BITS-1)); + return (signed int)fp_toint(result); +} + +static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu) +{ + pid_p_gain_set(&cpu->pid, pid_params.p_gain_pct); + pid_d_gain_set(&cpu->pid, pid_params.d_gain_pct); + pid_i_gain_set(&cpu->pid, pid_params.i_gain_pct); + + pid_reset(&cpu->pid, pid_params.setpoint, 100, pid_params.deadband, 0); +} + +static inline void intel_pstate_reset_all_pid(void) +{ + unsigned int cpu; + + for_each_online_cpu(cpu) { + if (all_cpu_data[cpu]) + intel_pstate_busy_pid_reset(all_cpu_data[cpu]); + } +} + +static inline void update_turbo_state(void) +{ + u64 misc_en; + struct cpudata *cpu; + + cpu = all_cpu_data[0]; + rdmsrl(MSR_IA32_MISC_ENABLE, misc_en); + limits->turbo_disabled = + (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE || + cpu->pstate.max_pstate == cpu->pstate.turbo_pstate); +} + +static void intel_pstate_hwp_set(void) +{ + int min, hw_min, max, hw_max, cpu, range, adj_range; + u64 value, cap; + + get_online_cpus(); + + for_each_online_cpu(cpu) { + rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap); + hw_min = HWP_LOWEST_PERF(cap); + hw_max = HWP_HIGHEST_PERF(cap); + range = hw_max - hw_min; + + rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value); + adj_range = limits->min_perf_pct * range / 100; + min = hw_min + adj_range; + value &= ~HWP_MIN_PERF(~0L); + value |= HWP_MIN_PERF(min); + + adj_range = limits->max_perf_pct * range / 100; + max = hw_min + adj_range; + if (limits->no_turbo) { + hw_max = HWP_GUARANTEED_PERF(cap); + if (hw_max < max) + max = hw_max; + } + + value &= ~HWP_MAX_PERF(~0L); + value |= HWP_MAX_PERF(max); + wrmsrl_on_cpu(cpu, MSR_HWP_REQUEST, value); + } + + put_online_cpus(); +} + +/************************** debugfs begin ************************/ +static int pid_param_set(void *data, u64 val) +{ + *(u32 *)data = val; + intel_pstate_reset_all_pid(); + return 0; +} + +static int pid_param_get(void *data, u64 *val) +{ + *val = *(u32 *)data; + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get, pid_param_set, "%llu\n"); + +struct pid_param { + char *name; + void *value; +}; + +static struct pid_param pid_files[] = { + {"sample_rate_ms", &pid_params.sample_rate_ms}, + {"d_gain_pct", &pid_params.d_gain_pct}, + {"i_gain_pct", &pid_params.i_gain_pct}, + {"deadband", &pid_params.deadband}, + {"setpoint", &pid_params.setpoint}, + {"p_gain_pct", &pid_params.p_gain_pct}, + {NULL, NULL} +}; + +static void __init intel_pstate_debug_expose_params(void) +{ + struct dentry *debugfs_parent; + int i = 0; + + if (hwp_active) + return; + debugfs_parent = debugfs_create_dir("pstate_snb", NULL); + if (IS_ERR_OR_NULL(debugfs_parent)) + return; + while (pid_files[i].name) { + debugfs_create_file(pid_files[i].name, 0660, + debugfs_parent, pid_files[i].value, + &fops_pid_param); + i++; + } +} + +/************************** debugfs end ************************/ + +/************************** sysfs begin ************************/ +#define show_one(file_name, object) \ + static ssize_t show_##file_name \ + (struct kobject *kobj, struct kobj_attribute *attr, char *buf) \ + { \ + return sprintf(buf, "%u\n", limits->object); \ + } + +static ssize_t show_turbo_pct(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct cpudata *cpu; + int total, no_turbo, turbo_pct; + uint32_t turbo_fp; + + cpu = all_cpu_data[0]; + + total = cpu->pstate.turbo_pstate - cpu->pstate.min_pstate + 1; + no_turbo = cpu->pstate.max_pstate - cpu->pstate.min_pstate + 1; + turbo_fp = div_fp(int_tofp(no_turbo), int_tofp(total)); + turbo_pct = 100 - fp_toint(mul_fp(turbo_fp, int_tofp(100))); + return sprintf(buf, "%u\n", turbo_pct); +} + +static ssize_t show_num_pstates(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct cpudata *cpu; + int total; + + cpu = all_cpu_data[0]; + total = cpu->pstate.turbo_pstate - cpu->pstate.min_pstate + 1; + return sprintf(buf, "%u\n", total); +} + +static ssize_t show_no_turbo(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + ssize_t ret; + + update_turbo_state(); + if (limits->turbo_disabled) + ret = sprintf(buf, "%u\n", limits->turbo_disabled); + else + ret = sprintf(buf, "%u\n", limits->no_turbo); + + return ret; +} + +static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + update_turbo_state(); + if (limits->turbo_disabled) { + pr_warn("intel_pstate: Turbo disabled by BIOS or unavailable on processor\n"); + return -EPERM; + } + + limits->no_turbo = clamp_t(int, input, 0, 1); + + if (hwp_active) + intel_pstate_hwp_set(); + + return count; +} + +static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + limits->max_sysfs_pct = clamp_t(int, input, 0 , 100); + limits->max_perf_pct = min(limits->max_policy_pct, + limits->max_sysfs_pct); + limits->max_perf_pct = max(limits->min_policy_pct, + limits->max_perf_pct); + limits->max_perf_pct = max(limits->min_perf_pct, + limits->max_perf_pct); + limits->max_perf = div_fp(int_tofp(limits->max_perf_pct), + int_tofp(100)); + + if (hwp_active) + intel_pstate_hwp_set(); + return count; +} + +static ssize_t store_min_perf_pct(struct kobject *a, struct kobj_attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + limits->min_sysfs_pct = clamp_t(int, input, 0 , 100); + limits->min_perf_pct = max(limits->min_policy_pct, + limits->min_sysfs_pct); + limits->min_perf_pct = min(limits->max_policy_pct, + limits->min_perf_pct); + limits->min_perf_pct = min(limits->max_perf_pct, + limits->min_perf_pct); + limits->min_perf = div_fp(int_tofp(limits->min_perf_pct), + int_tofp(100)); + + if (hwp_active) + intel_pstate_hwp_set(); + return count; +} + +show_one(max_perf_pct, max_perf_pct); +show_one(min_perf_pct, min_perf_pct); + +define_one_global_rw(no_turbo); +define_one_global_rw(max_perf_pct); +define_one_global_rw(min_perf_pct); +define_one_global_ro(turbo_pct); +define_one_global_ro(num_pstates); + +static struct attribute *intel_pstate_attributes[] = { + &no_turbo.attr, + &max_perf_pct.attr, + &min_perf_pct.attr, + &turbo_pct.attr, + &num_pstates.attr, + NULL +}; + +static struct attribute_group intel_pstate_attr_group = { + .attrs = intel_pstate_attributes, +}; + +static void __init intel_pstate_sysfs_expose_params(void) +{ + struct kobject *intel_pstate_kobject; + int rc; + + intel_pstate_kobject = kobject_create_and_add("intel_pstate", + &cpu_subsys.dev_root->kobj); + BUG_ON(!intel_pstate_kobject); + rc = sysfs_create_group(intel_pstate_kobject, &intel_pstate_attr_group); + BUG_ON(rc); +} +/************************** sysfs end ************************/ + +static void intel_pstate_hwp_enable(struct cpudata *cpudata) +{ + wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1); +} + +static int atom_get_min_pstate(void) +{ + u64 value; + + rdmsrl(ATOM_RATIOS, value); + return (value >> 8) & 0x7F; +} + +static int atom_get_max_pstate(void) +{ + u64 value; + + rdmsrl(ATOM_RATIOS, value); + return (value >> 16) & 0x7F; +} + +static int atom_get_turbo_pstate(void) +{ + u64 value; + + rdmsrl(ATOM_TURBO_RATIOS, value); + return value & 0x7F; +} + +static void atom_set_pstate(struct cpudata *cpudata, int pstate) +{ + u64 val; + int32_t vid_fp; + u32 vid; + + val = (u64)pstate << 8; + if (limits->no_turbo && !limits->turbo_disabled) + val |= (u64)1 << 32; + + vid_fp = cpudata->vid.min + mul_fp( + int_tofp(pstate - cpudata->pstate.min_pstate), + cpudata->vid.ratio); + + vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max); + vid = ceiling_fp(vid_fp); + + if (pstate > cpudata->pstate.max_pstate) + vid = cpudata->vid.turbo; + + val |= vid; + + wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); +} + +static int silvermont_get_scaling(void) +{ + u64 value; + int i; + /* Defined in Table 35-6 from SDM (Sept 2015) */ + static int silvermont_freq_table[] = { + 83300, 100000, 133300, 116700, 80000}; + + rdmsrl(MSR_FSB_FREQ, value); + i = value & 0x7; + WARN_ON(i > 4); + + return silvermont_freq_table[i]; +} + +static int airmont_get_scaling(void) +{ + u64 value; + int i; + /* Defined in Table 35-10 from SDM (Sept 2015) */ + static int airmont_freq_table[] = { + 83300, 100000, 133300, 116700, 80000, + 93300, 90000, 88900, 87500}; + + rdmsrl(MSR_FSB_FREQ, value); + i = value & 0xF; + WARN_ON(i > 8); + + return airmont_freq_table[i]; +} + +static void atom_get_vid(struct cpudata *cpudata) +{ + u64 value; + + rdmsrl(ATOM_VIDS, value); + cpudata->vid.min = int_tofp((value >> 8) & 0x7f); + cpudata->vid.max = int_tofp((value >> 16) & 0x7f); + cpudata->vid.ratio = div_fp( + cpudata->vid.max - cpudata->vid.min, + int_tofp(cpudata->pstate.max_pstate - + cpudata->pstate.min_pstate)); + + rdmsrl(ATOM_TURBO_VIDS, value); + cpudata->vid.turbo = value & 0x7f; +} + +static int core_get_min_pstate(void) +{ + u64 value; + + rdmsrl(MSR_PLATFORM_INFO, value); + return (value >> 40) & 0xFF; +} + +static int core_get_max_pstate_physical(void) +{ + u64 value; + + rdmsrl(MSR_PLATFORM_INFO, value); + return (value >> 8) & 0xFF; +} + +static int core_get_max_pstate(void) +{ + u64 tar; + u64 plat_info; + int max_pstate; + int err; + + rdmsrl(MSR_PLATFORM_INFO, plat_info); + max_pstate = (plat_info >> 8) & 0xFF; + + err = rdmsrl_safe(MSR_TURBO_ACTIVATION_RATIO, &tar); + if (!err) { + /* Do some sanity checking for safety */ + if (plat_info & 0x600000000) { + u64 tdp_ctrl; + u64 tdp_ratio; + int tdp_msr; + + err = rdmsrl_safe(MSR_CONFIG_TDP_CONTROL, &tdp_ctrl); + if (err) + goto skip_tar; + + tdp_msr = MSR_CONFIG_TDP_NOMINAL + (tdp_ctrl & 0x3); + err = rdmsrl_safe(tdp_msr, &tdp_ratio); + if (err) + goto skip_tar; + + /* For level 1 and 2, bits[23:16] contain the ratio */ + if (tdp_ctrl) + tdp_ratio >>= 16; + + tdp_ratio &= 0xff; /* ratios are only 8 bits long */ + if (tdp_ratio - 1 == tar) { + max_pstate = tar; + pr_debug("max_pstate=TAC %x\n", max_pstate); + } else { + goto skip_tar; + } + } + } + +skip_tar: + return max_pstate; +} + +static int core_get_turbo_pstate(void) +{ + u64 value; + int nont, ret; + + rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value); + nont = core_get_max_pstate(); + ret = (value) & 255; + if (ret <= nont) + ret = nont; + return ret; +} + +static inline int core_get_scaling(void) +{ + return 100000; +} + +static void core_set_pstate(struct cpudata *cpudata, int pstate) +{ + u64 val; + + val = (u64)pstate << 8; + if (limits->no_turbo && !limits->turbo_disabled) + val |= (u64)1 << 32; + + wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); +} + +static int knl_get_turbo_pstate(void) +{ + u64 value; + int nont, ret; + + rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value); + nont = core_get_max_pstate(); + ret = (((value) >> 8) & 0xFF); + if (ret <= nont) + ret = nont; + return ret; +} + +static struct cpu_defaults core_params = { + .pid_policy = { + .sample_rate_ms = 10, + .deadband = 0, + .setpoint = 97, + .p_gain_pct = 20, + .d_gain_pct = 0, + .i_gain_pct = 0, + }, + .funcs = { + .get_max = core_get_max_pstate, + .get_max_physical = core_get_max_pstate_physical, + .get_min = core_get_min_pstate, + .get_turbo = core_get_turbo_pstate, + .get_scaling = core_get_scaling, + .set = core_set_pstate, + }, +}; + +static struct cpu_defaults silvermont_params = { + .pid_policy = { + .sample_rate_ms = 10, + .deadband = 0, + .setpoint = 60, + .p_gain_pct = 14, + .d_gain_pct = 0, + .i_gain_pct = 4, + }, + .funcs = { + .get_max = atom_get_max_pstate, + .get_max_physical = atom_get_max_pstate, + .get_min = atom_get_min_pstate, + .get_turbo = atom_get_turbo_pstate, + .set = atom_set_pstate, + .get_scaling = silvermont_get_scaling, + .get_vid = atom_get_vid, + }, +}; + +static struct cpu_defaults airmont_params = { + .pid_policy = { + .sample_rate_ms = 10, + .deadband = 0, + .setpoint = 60, + .p_gain_pct = 14, + .d_gain_pct = 0, + .i_gain_pct = 4, + }, + .funcs = { + .get_max = atom_get_max_pstate, + .get_max_physical = atom_get_max_pstate, + .get_min = atom_get_min_pstate, + .get_turbo = atom_get_turbo_pstate, + .set = atom_set_pstate, + .get_scaling = airmont_get_scaling, + .get_vid = atom_get_vid, + }, +}; + +static struct cpu_defaults knl_params = { + .pid_policy = { + .sample_rate_ms = 10, + .deadband = 0, + .setpoint = 97, + .p_gain_pct = 20, + .d_gain_pct = 0, + .i_gain_pct = 0, + }, + .funcs = { + .get_max = core_get_max_pstate, + .get_max_physical = core_get_max_pstate_physical, + .get_min = core_get_min_pstate, + .get_turbo = knl_get_turbo_pstate, + .get_scaling = core_get_scaling, + .set = core_set_pstate, + }, +}; + +static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) +{ + int max_perf = cpu->pstate.turbo_pstate; + int max_perf_adj; + int min_perf; + + if (limits->no_turbo || limits->turbo_disabled) + max_perf = cpu->pstate.max_pstate; + + /* + * performance can be limited by user through sysfs, by cpufreq + * policy, or by cpu specific default values determined through + * experimentation. + */ + max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits->max_perf)); + *max = clamp_t(int, max_perf_adj, + cpu->pstate.min_pstate, cpu->pstate.turbo_pstate); + + min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits->min_perf)); + *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf); +} + +static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate, bool force) +{ + int max_perf, min_perf; + + if (force) { + update_turbo_state(); + + intel_pstate_get_min_max(cpu, &min_perf, &max_perf); + + pstate = clamp_t(int, pstate, min_perf, max_perf); + + if (pstate == cpu->pstate.current_pstate) + return; + } + trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu); + + cpu->pstate.current_pstate = pstate; + + pstate_funcs.set(cpu, pstate); +} + +static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) +{ + cpu->pstate.min_pstate = pstate_funcs.get_min(); + cpu->pstate.max_pstate = pstate_funcs.get_max(); + cpu->pstate.max_pstate_physical = pstate_funcs.get_max_physical(); + cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); + cpu->pstate.scaling = pstate_funcs.get_scaling(); + + if (pstate_funcs.get_vid) + pstate_funcs.get_vid(cpu); + intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate, false); +} + +static inline void intel_pstate_calc_busy(struct cpudata *cpu) +{ + struct sample *sample = &cpu->sample; + int64_t core_pct; + + core_pct = int_tofp(sample->aperf) * int_tofp(100); + core_pct = div64_u64(core_pct, int_tofp(sample->mperf)); + + sample->freq = fp_toint( + mul_fp(int_tofp( + cpu->pstate.max_pstate_physical * + cpu->pstate.scaling / 100), + core_pct)); + + sample->core_pct_busy = (int32_t)core_pct; +} + +static inline void intel_pstate_sample(struct cpudata *cpu) +{ + u64 aperf, mperf; + unsigned long flags; + u64 tsc; + + local_irq_save(flags); + rdmsrl(MSR_IA32_APERF, aperf); + rdmsrl(MSR_IA32_MPERF, mperf); + if (cpu->prev_mperf == mperf) { + local_irq_restore(flags); + return; + } + + tsc = rdtsc(); + local_irq_restore(flags); + + cpu->last_sample_time = cpu->sample.time; + cpu->sample.time = ktime_get(); + cpu->sample.aperf = aperf; + cpu->sample.mperf = mperf; + cpu->sample.tsc = tsc; + cpu->sample.aperf -= cpu->prev_aperf; + cpu->sample.mperf -= cpu->prev_mperf; + cpu->sample.tsc -= cpu->prev_tsc; + + intel_pstate_calc_busy(cpu); + + cpu->prev_aperf = aperf; + cpu->prev_mperf = mperf; + cpu->prev_tsc = tsc; +} + +static inline void intel_hwp_set_sample_time(struct cpudata *cpu) +{ + int delay; + + delay = msecs_to_jiffies(50); + mod_timer_pinned(&cpu->timer, jiffies + delay); +} + +static inline void intel_pstate_set_sample_time(struct cpudata *cpu) +{ + int delay; + + delay = msecs_to_jiffies(pid_params.sample_rate_ms); + mod_timer_pinned(&cpu->timer, jiffies + delay); +} + +static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) +{ + int32_t core_busy, max_pstate, current_pstate, sample_ratio; + s64 duration_us; + u32 sample_time; + + /* + * core_busy is the ratio of actual performance to max + * max_pstate is the max non turbo pstate available + * current_pstate was the pstate that was requested during + * the last sample period. + * + * We normalize core_busy, which was our actual percent + * performance to what we requested during the last sample + * period. The result will be a percentage of busy at a + * specified pstate. + */ + core_busy = cpu->sample.core_pct_busy; + max_pstate = int_tofp(cpu->pstate.max_pstate_physical); + current_pstate = int_tofp(cpu->pstate.current_pstate); + core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); + + /* + * Since we have a deferred timer, it will not fire unless + * we are in C0. So, determine if the actual elapsed time + * is significantly greater (3x) than our sample interval. If it + * is, then we were idle for a long enough period of time + * to adjust our busyness. + */ + sample_time = pid_params.sample_rate_ms * USEC_PER_MSEC; + duration_us = ktime_us_delta(cpu->sample.time, + cpu->last_sample_time); + if (duration_us > sample_time * 3) { + sample_ratio = div_fp(int_tofp(sample_time), + int_tofp(duration_us)); + core_busy = mul_fp(core_busy, sample_ratio); + } + + return core_busy; +} + +static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) +{ + int32_t busy_scaled; + struct _pid *pid; + signed int ctl; + int from; + struct sample *sample; + + from = cpu->pstate.current_pstate; + + pid = &cpu->pid; + busy_scaled = intel_pstate_get_scaled_busy(cpu); + + ctl = pid_calc(pid, busy_scaled); + + /* Negative values of ctl increase the pstate and vice versa */ + intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl, true); + + sample = &cpu->sample; + trace_pstate_sample(fp_toint(sample->core_pct_busy), + fp_toint(busy_scaled), + from, + cpu->pstate.current_pstate, + sample->mperf, + sample->aperf, + sample->tsc, + sample->freq); +} + +static void intel_hwp_timer_func(unsigned long __data) +{ + struct cpudata *cpu = (struct cpudata *) __data; + + intel_pstate_sample(cpu); + intel_hwp_set_sample_time(cpu); +} + +static void intel_pstate_timer_func(unsigned long __data) +{ + struct cpudata *cpu = (struct cpudata *) __data; + + intel_pstate_sample(cpu); + + intel_pstate_adjust_busy_pstate(cpu); + + intel_pstate_set_sample_time(cpu); +} + +#define ICPU(model, policy) \ + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_APERFMPERF,\ + (unsigned long)&policy } + +static const struct x86_cpu_id intel_pstate_cpu_ids[] = { + ICPU(0x2a, core_params), + ICPU(0x2d, core_params), + ICPU(0x37, silvermont_params), + ICPU(0x3a, core_params), + ICPU(0x3c, core_params), + ICPU(0x3d, core_params), + ICPU(0x3e, core_params), + ICPU(0x3f, core_params), + ICPU(0x45, core_params), + ICPU(0x46, core_params), + ICPU(0x47, core_params), + ICPU(0x4c, airmont_params), + ICPU(0x4e, core_params), + ICPU(0x4f, core_params), + ICPU(0x5e, core_params), + ICPU(0x56, core_params), + ICPU(0x57, knl_params), + {} +}; +MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); + +static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] = { + ICPU(0x56, core_params), + {} +}; + +static int intel_pstate_init_cpu(unsigned int cpunum) +{ + struct cpudata *cpu; + + if (!all_cpu_data[cpunum]) + all_cpu_data[cpunum] = kzalloc(sizeof(struct cpudata), + GFP_KERNEL); + if (!all_cpu_data[cpunum]) + return -ENOMEM; + + cpu = all_cpu_data[cpunum]; + + cpu->cpu = cpunum; + + if (hwp_active) + intel_pstate_hwp_enable(cpu); + + intel_pstate_get_cpu_pstates(cpu); + + init_timer_deferrable(&cpu->timer); + cpu->timer.data = (unsigned long)cpu; + cpu->timer.expires = jiffies + HZ/100; + + if (!hwp_active) + cpu->timer.function = intel_pstate_timer_func; + else + cpu->timer.function = intel_hwp_timer_func; + + intel_pstate_busy_pid_reset(cpu); + intel_pstate_sample(cpu); + + add_timer_on(&cpu->timer, cpunum); + + pr_debug("intel_pstate: controlling: cpu %d\n", cpunum); + + return 0; +} + +static unsigned int intel_pstate_get(unsigned int cpu_num) +{ + struct sample *sample; + struct cpudata *cpu; + + cpu = all_cpu_data[cpu_num]; + if (!cpu) + return 0; + sample = &cpu->sample; + return sample->freq; +} + +static int intel_pstate_set_policy(struct cpufreq_policy *policy) +{ + if (!policy->cpuinfo.max_freq) + return -ENODEV; + + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && + policy->max >= policy->cpuinfo.max_freq) { + pr_debug("intel_pstate: set performance\n"); + limits = &performance_limits; + if (hwp_active) + intel_pstate_hwp_set(); + return 0; + } + + pr_debug("intel_pstate: set powersave\n"); + limits = &powersave_limits; + limits->min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq; + limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, 0 , 100); + limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100, + policy->cpuinfo.max_freq); + limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0 , 100); + + /* Normalize user input to [min_policy_pct, max_policy_pct] */ + limits->min_perf_pct = max(limits->min_policy_pct, + limits->min_sysfs_pct); + limits->min_perf_pct = min(limits->max_policy_pct, + limits->min_perf_pct); + limits->max_perf_pct = min(limits->max_policy_pct, + limits->max_sysfs_pct); + limits->max_perf_pct = max(limits->min_policy_pct, + limits->max_perf_pct); + limits->max_perf = round_up(limits->max_perf, FRAC_BITS); + + /* Make sure min_perf_pct <= max_perf_pct */ + limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct); + + limits->min_perf = div_fp(int_tofp(limits->min_perf_pct), + int_tofp(100)); + limits->max_perf = div_fp(int_tofp(limits->max_perf_pct), + int_tofp(100)); + + if (hwp_active) + intel_pstate_hwp_set(); + + return 0; +} + +static int intel_pstate_verify_policy(struct cpufreq_policy *policy) +{ + cpufreq_verify_within_cpu_limits(policy); + + if (policy->policy != CPUFREQ_POLICY_POWERSAVE && + policy->policy != CPUFREQ_POLICY_PERFORMANCE) + return -EINVAL; + + return 0; +} + +static void intel_pstate_stop_cpu(struct cpufreq_policy *policy) +{ + int cpu_num = policy->cpu; + struct cpudata *cpu = all_cpu_data[cpu_num]; + + pr_debug("intel_pstate: CPU %d exiting\n", cpu_num); + + del_timer_sync(&all_cpu_data[cpu_num]->timer); + if (hwp_active) + return; + + intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate, false); +} + +static int intel_pstate_cpu_init(struct cpufreq_policy *policy) +{ + struct cpudata *cpu; + int rc; + + rc = intel_pstate_init_cpu(policy->cpu); + if (rc) + return rc; + + cpu = all_cpu_data[policy->cpu]; + + if (limits->min_perf_pct == 100 && limits->max_perf_pct == 100) + policy->policy = CPUFREQ_POLICY_PERFORMANCE; + else + policy->policy = CPUFREQ_POLICY_POWERSAVE; + + policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling; + policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling; + + /* cpuinfo and default policy values */ + policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling; + policy->cpuinfo.max_freq = + cpu->pstate.turbo_pstate * cpu->pstate.scaling; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + cpumask_set_cpu(policy->cpu, policy->cpus); + + return 0; +} + +static struct cpufreq_driver intel_pstate_driver = { + .flags = CPUFREQ_CONST_LOOPS, + .verify = intel_pstate_verify_policy, + .setpolicy = intel_pstate_set_policy, + .get = intel_pstate_get, + .init = intel_pstate_cpu_init, + .stop_cpu = intel_pstate_stop_cpu, + .name = "intel_pstate", +}; + +static int __initdata no_load; +static int __initdata no_hwp; +static int __initdata hwp_only; +static unsigned int force_load; + +static int intel_pstate_msrs_not_valid(void) +{ + if (!pstate_funcs.get_max() || + !pstate_funcs.get_min() || + !pstate_funcs.get_turbo()) + return -ENODEV; + + return 0; +} + +static void copy_pid_params(struct pstate_adjust_policy *policy) +{ + pid_params.sample_rate_ms = policy->sample_rate_ms; + pid_params.p_gain_pct = policy->p_gain_pct; + pid_params.i_gain_pct = policy->i_gain_pct; + pid_params.d_gain_pct = policy->d_gain_pct; + pid_params.deadband = policy->deadband; + pid_params.setpoint = policy->setpoint; +} + +static void copy_cpu_funcs(struct pstate_funcs *funcs) +{ + pstate_funcs.get_max = funcs->get_max; + pstate_funcs.get_max_physical = funcs->get_max_physical; + pstate_funcs.get_min = funcs->get_min; + pstate_funcs.get_turbo = funcs->get_turbo; + pstate_funcs.get_scaling = funcs->get_scaling; + pstate_funcs.set = funcs->set; + pstate_funcs.get_vid = funcs->get_vid; +} + +#if IS_ENABLED(CONFIG_ACPI) +#include + +static bool intel_pstate_no_acpi_pss(void) +{ + int i; + + for_each_possible_cpu(i) { + acpi_status status; + union acpi_object *pss; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_processor *pr = per_cpu(processors, i); + + if (!pr) + continue; + + status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); + if (ACPI_FAILURE(status)) + continue; + + pss = buffer.pointer; + if (pss && pss->type == ACPI_TYPE_PACKAGE) { + kfree(pss); + return false; + } + + kfree(pss); + } + + return true; +} + +static bool intel_pstate_has_acpi_ppc(void) +{ + int i; + + for_each_possible_cpu(i) { + struct acpi_processor *pr = per_cpu(processors, i); + + if (!pr) + continue; + if (acpi_has_method(pr->handle, "_PPC")) + return true; + } + return false; +} + +enum { + PSS, + PPC, +}; + +struct hw_vendor_info { + u16 valid; + char oem_id[ACPI_OEM_ID_SIZE]; + char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; + int oem_pwr_table; +}; + +/* Hardware vendor-specific info that has its own power management modes */ +static struct hw_vendor_info vendor_info[] = { + {1, "HP ", "ProLiant", PSS}, + {1, "ORACLE", "X4-2 ", PPC}, + {1, "ORACLE", "X4-2L ", PPC}, + {1, "ORACLE", "X4-2B ", PPC}, + {1, "ORACLE", "X3-2 ", PPC}, + {1, "ORACLE", "X3-2L ", PPC}, + {1, "ORACLE", "X3-2B ", PPC}, + {1, "ORACLE", "X4470M2 ", PPC}, + {1, "ORACLE", "X4270M3 ", PPC}, + {1, "ORACLE", "X4270M2 ", PPC}, + {1, "ORACLE", "X4170M2 ", PPC}, + {1, "ORACLE", "X4170 M3", PPC}, + {1, "ORACLE", "X4275 M3", PPC}, + {1, "ORACLE", "X6-2 ", PPC}, + {1, "ORACLE", "Sudbury ", PPC}, + {0, "", ""}, +}; + +static bool intel_pstate_platform_pwr_mgmt_exists(void) +{ + struct acpi_table_header hdr; + struct hw_vendor_info *v_info; + const struct x86_cpu_id *id; + u64 misc_pwr; + + id = x86_match_cpu(intel_pstate_cpu_oob_ids); + if (id) { + rdmsrl(MSR_MISC_PWR_MGMT, misc_pwr); + if ( misc_pwr & (1 << 8)) + return true; + } + + if (acpi_disabled || + ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr))) + return false; + + for (v_info = vendor_info; v_info->valid; v_info++) { + if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE) && + !strncmp(hdr.oem_table_id, v_info->oem_table_id, + ACPI_OEM_TABLE_ID_SIZE)) + switch (v_info->oem_pwr_table) { + case PSS: + return intel_pstate_no_acpi_pss(); + case PPC: + return intel_pstate_has_acpi_ppc() && + (!force_load); + } + } + + return false; +} +#else /* CONFIG_ACPI not enabled */ +static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; } +static inline bool intel_pstate_has_acpi_ppc(void) { return false; } +#endif /* CONFIG_ACPI */ + +static const struct x86_cpu_id hwp_support_ids[] __initconst = { + { X86_VENDOR_INTEL, 6, X86_MODEL_ANY, X86_FEATURE_HWP }, + {} +}; + +static int __init intel_pstate_init(void) +{ + int cpu, rc = 0; + const struct x86_cpu_id *id; + struct cpu_defaults *cpu_def; + + if (no_load) + return -ENODEV; + + if (x86_match_cpu(hwp_support_ids) && !no_hwp) { + copy_cpu_funcs(&core_params.funcs); + hwp_active++; + goto hwp_cpu_matched; + } + + id = x86_match_cpu(intel_pstate_cpu_ids); + if (!id) + return -ENODEV; + + cpu_def = (struct cpu_defaults *)id->driver_data; + + copy_pid_params(&cpu_def->pid_policy); + copy_cpu_funcs(&cpu_def->funcs); + + if (intel_pstate_msrs_not_valid()) + return -ENODEV; + +hwp_cpu_matched: + /* + * The Intel pstate driver will be ignored if the platform + * firmware has its own power management modes. + */ + if (intel_pstate_platform_pwr_mgmt_exists()) + return -ENODEV; + + pr_info("Intel P-state driver initializing.\n"); + + all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus()); + if (!all_cpu_data) + return -ENOMEM; + + if (!hwp_active && hwp_only) + goto out; + + rc = cpufreq_register_driver(&intel_pstate_driver); + if (rc) + goto out; + + intel_pstate_debug_expose_params(); + intel_pstate_sysfs_expose_params(); + + if (hwp_active) + pr_info("intel_pstate: HWP enabled\n"); + + return rc; +out: + get_online_cpus(); + for_each_online_cpu(cpu) { + if (all_cpu_data[cpu]) { + del_timer_sync(&all_cpu_data[cpu]->timer); + kfree(all_cpu_data[cpu]); + } + } + + put_online_cpus(); + vfree(all_cpu_data); + return -ENODEV; +} +device_initcall(intel_pstate_init); + +static int __init intel_pstate_setup(char *str) +{ + if (!str) + return -EINVAL; + + if (!strcmp(str, "disable")) + no_load = 1; + if (!strcmp(str, "no_hwp")) { + pr_info("intel_pstate: HWP disabled\n"); + no_hwp = 1; + } + if (!strcmp(str, "force")) + force_load = 1; + if (!strcmp(str, "hwp_only")) + hwp_only = 1; + return 0; +} +early_param("intel_pstate", intel_pstate_setup); + +MODULE_AUTHOR("Dirk Brandewie "); +MODULE_DESCRIPTION("'intel_pstate' - P state driver Intel Core processors"); +MODULE_LICENSE("GPL"); diff --git a/v1000-4.4.180/cpufreq_conservative.ko b/v1000-4.4.180/cpufreq_conservative.ko new file mode 100644 index 0000000000000000000000000000000000000000..560f1cf531b3984b7dee657ee06425947766f724 GIT binary patch literal 16392 zcmeI2e{dYteZZeAI|#@0gmFP_oOsiS;YaF2vYk}InBL(ZTBS0**cO-?u{zzYq>D~> z>h7H+hne<>?3SIw#50)zXOd<#g?4Du4$d^wI8JcRV`4eYG*t}+Q_@D$;^1J1aRLPo zq`2Sj+wa@^-qWpYNd9VgqrH9mdEfW_e&6@~*xk4K)6G3w7Bw^ol^VqDqI#vM5N2mJ zACuXb_>gE3iy^-Pjz&1T?(7xk|K?kNd1~9_3$Jdy(Gb<;gIQ{gRsf*@J z1+UD;#s4eM-s!$$kyU#zFD_Z`{oI^6PSwufx$oHE{=sOqzIS@N>AfA>^G0!*S-!tn z%IxYp*8YY$GlTLH@RG#Rx!Pqo^tDVtF`x53QNrgCKE^s zSMF-B#P5yw^&RVJ`0w%;9s;&L(J_8ayu7)|o5IWX$}V4EePW&auV;VE{FUK2ih6p@ z#$|py$`6#_+VoDFKbvZiz(~OX{Dxr&sPUfycfFJ^qw*I z^}b|IoonhT5A6g6Tg%y2f8c=K;z#1;9j#5BAmN>gZ0vn0?)5GINI%_w`?ot@@?(m+uA_t8IYRZfk}hmbb0&<7yr_#>Q8#8799x5U-s- zVe;Gji1b~q{%y+w1DEB`wx)L}?~j#B`cvN41mOvEYvX~&6b!?l+sZK+&qUpLhRavO z!{Zq)pQu(~@mWB=Zaf!|uN%(=`Zq$|cFF$z@jL!Nfc`z)f_~#5jC-#isgz=i@Nt70B^zVztwiL*jQLFr z1wJIm2M_U`rC9YaJ}zN zPHmSn!N1$kT<j3*13 zaa*{_(XnhMH)J`)_fMo;E0fCAP7BOAIBJtA$pDJL^l$mDYyZb*$4r4QWC z8;sRP+(_@vB}X$UgCvZh{J8CakH#PzJ^2Zv2O5z}?KZYR8;UZw!%61c3@SEK$+6@> z);7kRe9Cs+yyF^qFgcoW?X=WTbZsM(Gm^$YvQV&{-G-eT&p7$qsGTc_WU(-ucQ(Yc z_GB`bwjE<*HeUoOANjkg*%!q(wUMo07$ z(KgsdoJXSW?$JVWKt$bwy zwH$jan@rjAnWHKYg~x-;h@IU{mGB9QYDy*cWbL(5S4`ofj|;W(>0}{^Zna0-)uo8S zlSd{um?y0$BBD|-I%YdCv#9{xh9{Vjd@f~23&R=Lf{MkgEusT1C{N`_eSc*eAwsL& zLNYaS>2c5~7S$DMl)JU_iyGzYNIibldBkF5YyFeB56&nb!;Nf6 zO8+F}QGOaBB-=lUeQ-wkev-$xJWPKL2g*0o4fJhEh4=@>$)6@z<4p;(tUu0&&N7#jfxHj!R5yh))y$4$g8sy0$X_9zQF=6v;~3WmXtYd99<~uAuW0&L5-(}|6U1X0?^5#QhiX@! z(oZ}_=K^s<)AKO#Y0b~aiT7*#sM4eH=ZMc~`hTkQYy1N+ALRO}@fOJ=VvhV)BjYCG zKOwIAALl2Ilm8+9J9NfVBb3xjjcgq9@fEq%b`E zW(G61V-3J=>xhuDw3VrfgnC&9#a7LR1Nt>=r$*2_WeN5sZP-JFja1tTwpZmoEmns; z#n3W$w<}W1DHXZF0mNi(+r7SDD zX3ZzpDjT6rF3`kkQEjZHZJLcZ75w>*6Ig?CR$Er@o!y`A-E4JlvgkX-8t}0S*$0dE zngahbK^wLcJ|Z~QkdudQP?Ha>BF+rJrvo>@K||+{{+iD-N=+cIk5TNsy1ia!oSVd1<6Ny9atqGTiy*KH6M)HVo-MSB<) zeW40;>mFflq9f8?E!(b+twsNpT zW(~kxmABODU6OPLwE}0c@p;%V%fT1Tq&otU_5&<~?fQ?K!IL#UF~cK8kkp$Ta`jG# zg*T9dE`JN-Tz(7V@Msw9@7zfoUrYMo_yv6G#pE!)lkqQ$udGx2B{JEB1Vf6T{Vw~%LlsM`iX8M;P zfTZ(}GMDRSwcunS2VU(*JUZd;`S^ zi!pA`DmlivozQJl>%sjSOu9dR!Q{D~uQSf|90}3$Jtoif zysXLlUI@{IN+Dr9Q*fyHn;@?IL>Wx|A@WZ%j#)LYUk=gJM2oL(w~M%LcQ`~I-={I@ z^2bBu-(vEVmGzgvdow2Vhp(T@86SZ%6`vNyZN^swIY7ur?#-%cj~876-> zlc%W+r9$MHJokT+aXt>e5u)c`m^{~WigB*zI@;gX$H^_kvER9#4#v42j1?x-LsLp# zlXx%=)!0(sw@`l?4i(SelC}Ie<0C*T`K@B5;;f!4)cz^z8D)AdM}C0GLsll#gLcia_r6(E=6fv#g3S6jNK#!F-*q45}Td}hO>^edcD?UyB&uYA%_$iGW#OE|VNBYlbe46-q zjrS85bjB05>t>Qu-#3xt(N7(2gvhrsj#>2`F2*>jxD5_W3C1z2)`y)MSKsaW8RvS& z7{{#o9yzIT^}VXZIO^E~2d4duV^)17*{a7Kp5bQAnQ zsxWyJy<1WtW*L|Aw2++AISx8VbBuF6=NZSW`u=)B;}y~)XnbKY>KTLs6Mm<~gd7j` zUAaZ$bEHR&Q(aG+CU4N9*r9Rt-7&^E`lH@M6O5w`=`5UfYCJ{@Yd_;$&luyVM}2Re z)H$uUCB{+DgK%Kl&p7I7!$L?0G_LATGtTuKWE}OBC_aZYK1bIl7{}0;;J`Giai79C zVO++I3eITUAbwus&2)W1=SmrkQ@q4OeV=a9ct7bk7)Srr^^GB1trJTBH0haS@>mul z{siOd+cp;ML?K9cQvZ{I*QZ#!)LcaV%cc*30vw8@K2R5O4BRg z>VB0`4-{0=97yl@)Z1^Oee5<_Fo{o{MiOIQg|^d z(+>EpSN}h$zIsj|@p<+C5DMz~U&4P7g48d6g+Tw&7v2A1VD;?3P4?AyQ&Ka}ehLce z*`Fi(ZB!BMV?XQmCxO+oe-%EsLAsQET=(kPZ(bv-3vM5~Qn&vgFto3azg1*k|4%TK ze-Lgv5zWs`(FfxI!PRIe)?Uq|A+!~R`%8T3E-I5{XaqVl|7|KzdjgJf0pWB zrwow-z5WrZPs@oiBLoHRpjKd1C1mcK@LMl_V-%1lXkz2|!MUsKx5(N;JPl`bQ8Obd zC=6-8e+qt$Am?YEhf}@!rK?F$Qye3#PA4H#&;OQAU!si!(f@1U(Ea}zG0lu9sTUrq zuTENbh&P}BnX;qgRQ*;3=&b6i^F`n)&qW`f`_C@uXc!+xpl=`9t(C gBPCjgej6CRzw7bCIbF|whXDnU)V_m%HNUO@2L>RaF#rGn literal 0 HcmV?d00001 diff --git a/v1000-4.4.180/cpufreq_ondemand.ko b/v1000-4.4.180/cpufreq_ondemand.ko new file mode 100644 index 0000000000000000000000000000000000000000..522a69249eafdcd50258649a79fbdc5d0b42764d GIT binary patch literal 20576 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 Dn=G~# literal 0 HcmV?d00001 diff --git a/v1000-4.4.180/cpufreq_userspace.ko b/v1000-4.4.180/cpufreq_userspace.ko new file mode 100644 index 0000000000000000000000000000000000000000..2f15c111bfab8c62835048f2f9dc86ca4e2546a2 GIT binary patch literal 6368 zcmeHLYls_F6u!Gzb$!NaeSpuT$x(~VYbWw#`5*QUCy)w;Mv%a~1OvqO@ZI1gJz zu&`S+=Fh626%+*(Q9=EsML~iUgMtbLwLcUq)VIQdfbiIaL zy1Mie9IHLu`)dB`;fkr!l`j*AHdVd}H7f_DUFGoYsXJ1;b{%}{hxz&WACFGNmrtX$ zf_Ssl+XmA0_fSe#>JUG)-<95fFuok;!+bEA^wdwiBh~!armC}SYOW_fy%H+1b>GqW z^iE)==DOq4AA*y+w@l5&;?s`+o2X6A9T(`7NoDwG=sH~=8pCKKm2XKF3miV0o_e>J zvYndi3X;{$1N&<6>0iJ?F6oBq(x1@_)uZ0ijr&p^8c0=o`lKTIOVr4toJduB`l{ag z4YTnFuozWuUEPGO;?7-7Nqwku7RU}e>Ln?{Nw|;W#4}@H$Q*iSL8kiZj^#IckAF{kBzUA11 zL)%BuSSvfAagUaF?lxW9akW)VZ>v-$@FyL2aFbKAY^$JM=Q=rOw^y*Vfudyxdy?Y_ z=s9!a<=QQQ=b6Q#cB5tIwE?$ONM_uU9;)e%o7aQF#zsatvuxTqZ&10WkFjlYaHoRU zrA*$+4zAPJ>529ImuWk;Zr4gq&Is(HlgVkk8l{@)wV;2L!~Oa%Xwhc=7fJjd^ZyF` z+ZEV6G<2=D8a|zuXzTT>^nUn^E<$wgo|2y#SGwoBjd7AW+wo03ZwLB#U=?#~tenza zvzXC+bB|9f99F)R%{?vI$z}Wux=rW_P#5C*hP7dg2YCa67EPtY31rz54*5k>rH2mm zvgyJbOB0w5oMZ*ZhBMfov^)b019UL%c}mYZrIKkwc46+Y@-?2H$rk>)&@mN$i54lw zRPQ1TftWhA10G+5<2lzY{O3snJ#>MeJ4s$mS>p)dPmn6d`Hk@B313Mg4zaeKB;u|03U$C+>s^R*77|52&;Ycdn5d7Oj;Yh7 z*yLl)syCsKiK#Oe0wl%4j(6eIsj#0*qGnq1l;Q@!GyPVRW0V3o*l^CkQzc_( z@@7tXlg@6#E1STw758tgW>8MGPy-Lg4pVqeD#IAvw&mv0VPnfCgL=m+7J#COOe~ma zbc_8;9~r`l#t~>xzqdfM+4?PXz+GTJD9ckcTQoCvQ07Cm0DY?oDsTiFSQuww0&7+% znI$8e$xfO^rdV{chVMd4tZ=<-85Yxkxk9r7f$f@k%k#k(mk?ZYRdcQdNx|2^%|isQ z>{_-zp&D+mGZl^&yD5|!d4xH6&4>`DwH->GP5XZ`jQ9%ON%DC#;uqjTxc-1&3P=|b zj{2>)K&dqX*NDeqn0WMqw(Msc;nBD|g#Id_f3MJ&U!{FQ|6-wkSm?`j9TEC+U9$pT z4m{_H=Pgn+&p#S4d|{N5d9Hx>3n{99G2zjA>Ox-&EgQG11TO1*gTUpwZW8`wKG_cX zlR{tC;UR&`{d%;6pZ!8#`gum^%XPgVaJjBm1TNS0j_@zn^{K!wfs)~WB1m5gd3KtW9Z&4q65cYE{`h7y5{h=RBZ3*SUeo(}&hUIgCM?zh^W>5gq z!g~uZlg#}Q>l3WfLZ5pggeC=!b!M6Up&yCk_YMh%l_A%-9j0|4eu2RME{o^R32>47 zrn@9@SX)V4H^#0626KvbHoU%75yz*qA&okW=rc(&4>P9`hs6QHa}!;t`+6cJ?*0$Fo@y$7lQdU=n#!Z>oMt0KeBf!FDX~2BzKmXWOhF zyJ3#c`~M(d?c&c;{5l7sk?k3NjO^(#V_4M)K>w07DFFX4T?=#zHyz?4!vH6{?r^ a;T*v5yAZ7({_<-Ve?PrAzeNH@MD-_ffFh&- literal 0 HcmV?d00001