aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/intel_pstate.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-02-04 19:45:30 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-03-09 08:40:52 -0500
commita4675fbc4a7abe072ac6ba38c252f22a91ebcd94 (patch)
treeebdf3fb59ee26392b5bfd1291f3c99e980c9ce5e /drivers/cpufreq/intel_pstate.c
parent34e2c555f3e13c90e9284e23d00f03be8a6e06c5 (diff)
cpufreq: intel_pstate: Replace timers with utilization update callbacks
Instead of using a per-CPU deferrable timer for utilization sampling and P-states adjustments, register a utilization update callback that will be invoked from the scheduler on utilization changes. The sampling rate is still the same as what was used for the deferrable timers, so the functional impact of this patch should not be significant. Based on an earlier patch from Srinivas Pandruvada. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
-rw-r--r--drivers/cpufreq/intel_pstate.c103
1 files changed, 39 insertions, 64 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index cd83d477e32d..f4d85c2ae7b1 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -71,7 +71,7 @@ struct sample {
71 u64 mperf; 71 u64 mperf;
72 u64 tsc; 72 u64 tsc;
73 int freq; 73 int freq;
74 ktime_t time; 74 u64 time;
75}; 75};
76 76
77struct pstate_data { 77struct pstate_data {
@@ -103,13 +103,13 @@ struct _pid {
103struct cpudata { 103struct cpudata {
104 int cpu; 104 int cpu;
105 105
106 struct timer_list timer; 106 struct update_util_data update_util;
107 107
108 struct pstate_data pstate; 108 struct pstate_data pstate;
109 struct vid_data vid; 109 struct vid_data vid;
110 struct _pid pid; 110 struct _pid pid;
111 111
112 ktime_t last_sample_time; 112 u64 last_sample_time;
113 u64 prev_aperf; 113 u64 prev_aperf;
114 u64 prev_mperf; 114 u64 prev_mperf;
115 u64 prev_tsc; 115 u64 prev_tsc;
@@ -120,6 +120,7 @@ struct cpudata {
120static struct cpudata **all_cpu_data; 120static struct cpudata **all_cpu_data;
121struct pstate_adjust_policy { 121struct pstate_adjust_policy {
122 int sample_rate_ms; 122 int sample_rate_ms;
123 s64 sample_rate_ns;
123 int deadband; 124 int deadband;
124 int setpoint; 125 int setpoint;
125 int p_gain_pct; 126 int p_gain_pct;
@@ -712,7 +713,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate)
712 if (limits->no_turbo && !limits->turbo_disabled) 713 if (limits->no_turbo && !limits->turbo_disabled)
713 val |= (u64)1 << 32; 714 val |= (u64)1 << 32;
714 715
715 wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); 716 wrmsrl(MSR_IA32_PERF_CTL, val);
716} 717}
717 718
718static int knl_get_turbo_pstate(void) 719static int knl_get_turbo_pstate(void)
@@ -883,7 +884,7 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu)
883 sample->core_pct_busy = (int32_t)core_pct; 884 sample->core_pct_busy = (int32_t)core_pct;
884} 885}
885 886
886static inline void intel_pstate_sample(struct cpudata *cpu) 887static inline void intel_pstate_sample(struct cpudata *cpu, u64 time)
887{ 888{
888 u64 aperf, mperf; 889 u64 aperf, mperf;
889 unsigned long flags; 890 unsigned long flags;
@@ -900,7 +901,7 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
900 local_irq_restore(flags); 901 local_irq_restore(flags);
901 902
902 cpu->last_sample_time = cpu->sample.time; 903 cpu->last_sample_time = cpu->sample.time;
903 cpu->sample.time = ktime_get(); 904 cpu->sample.time = time;
904 cpu->sample.aperf = aperf; 905 cpu->sample.aperf = aperf;
905 cpu->sample.mperf = mperf; 906 cpu->sample.mperf = mperf;
906 cpu->sample.tsc = tsc; 907 cpu->sample.tsc = tsc;
@@ -915,22 +916,6 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
915 cpu->prev_tsc = tsc; 916 cpu->prev_tsc = tsc;
916} 917}
917 918
918static inline void intel_hwp_set_sample_time(struct cpudata *cpu)
919{
920 int delay;
921
922 delay = msecs_to_jiffies(50);
923 mod_timer_pinned(&cpu->timer, jiffies + delay);
924}
925
926static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
927{
928 int delay;
929
930 delay = msecs_to_jiffies(pid_params.sample_rate_ms);
931 mod_timer_pinned(&cpu->timer, jiffies + delay);
932}
933
934static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu) 919static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
935{ 920{
936 struct sample *sample = &cpu->sample; 921 struct sample *sample = &cpu->sample;
@@ -970,8 +955,7 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
970static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu) 955static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
971{ 956{
972 int32_t core_busy, max_pstate, current_pstate, sample_ratio; 957 int32_t core_busy, max_pstate, current_pstate, sample_ratio;
973 s64 duration_us; 958 u64 duration_ns;
974 u32 sample_time;
975 959
976 /* 960 /*
977 * core_busy is the ratio of actual performance to max 961 * core_busy is the ratio of actual performance to max
@@ -990,18 +974,16 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
990 core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); 974 core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
991 975
992 /* 976 /*
993 * Since we have a deferred timer, it will not fire unless 977 * Since our utilization update callback will not run unless we are
994 * we are in C0. So, determine if the actual elapsed time 978 * in C0, check if the actual elapsed time is significantly greater (3x)
995 * is significantly greater (3x) than our sample interval. If it 979 * than our sample interval. If it is, then we were idle for a long
996 * is, then we were idle for a long enough period of time 980 * enough period of time to adjust our busyness.
997 * to adjust our busyness.
998 */ 981 */
999 sample_time = pid_params.sample_rate_ms * USEC_PER_MSEC; 982 duration_ns = cpu->sample.time - cpu->last_sample_time;
1000 duration_us = ktime_us_delta(cpu->sample.time, 983 if ((s64)duration_ns > pid_params.sample_rate_ns * 3
1001 cpu->last_sample_time); 984 && cpu->last_sample_time > 0) {
1002 if (duration_us > sample_time * 3) { 985 sample_ratio = div_fp(int_tofp(pid_params.sample_rate_ns),
1003 sample_ratio = div_fp(int_tofp(sample_time), 986 int_tofp(duration_ns));
1004 int_tofp(duration_us));
1005 core_busy = mul_fp(core_busy, sample_ratio); 987 core_busy = mul_fp(core_busy, sample_ratio);
1006 } 988 }
1007 989
@@ -1031,23 +1013,17 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
1031 sample->freq); 1013 sample->freq);
1032} 1014}
1033 1015
1034static void intel_hwp_timer_func(unsigned long __data) 1016static void intel_pstate_update_util(struct update_util_data *data, u64 time,
1035{ 1017 unsigned long util, unsigned long max)
1036 struct cpudata *cpu = (struct cpudata *) __data;
1037
1038 intel_pstate_sample(cpu);
1039 intel_hwp_set_sample_time(cpu);
1040}
1041
1042static void intel_pstate_timer_func(unsigned long __data)
1043{ 1018{
1044 struct cpudata *cpu = (struct cpudata *) __data; 1019 struct cpudata *cpu = container_of(data, struct cpudata, update_util);
1045 1020 u64 delta_ns = time - cpu->sample.time;
1046 intel_pstate_sample(cpu);
1047 1021
1048 intel_pstate_adjust_busy_pstate(cpu); 1022 if ((s64)delta_ns >= pid_params.sample_rate_ns) {
1049 1023 intel_pstate_sample(cpu, time);
1050 intel_pstate_set_sample_time(cpu); 1024 if (!hwp_active)
1025 intel_pstate_adjust_busy_pstate(cpu);
1026 }
1051} 1027}
1052 1028
1053#define ICPU(model, policy) \ 1029#define ICPU(model, policy) \
@@ -1095,24 +1071,19 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
1095 1071
1096 cpu->cpu = cpunum; 1072 cpu->cpu = cpunum;
1097 1073
1098 if (hwp_active) 1074 if (hwp_active) {
1099 intel_pstate_hwp_enable(cpu); 1075 intel_pstate_hwp_enable(cpu);
1076 pid_params.sample_rate_ms = 50;
1077 pid_params.sample_rate_ns = 50 * NSEC_PER_MSEC;
1078 }
1100 1079
1101 intel_pstate_get_cpu_pstates(cpu); 1080 intel_pstate_get_cpu_pstates(cpu);
1102 1081
1103 init_timer_deferrable(&cpu->timer);
1104 cpu->timer.data = (unsigned long)cpu;
1105 cpu->timer.expires = jiffies + HZ/100;
1106
1107 if (!hwp_active)
1108 cpu->timer.function = intel_pstate_timer_func;
1109 else
1110 cpu->timer.function = intel_hwp_timer_func;
1111
1112 intel_pstate_busy_pid_reset(cpu); 1082 intel_pstate_busy_pid_reset(cpu);
1113 intel_pstate_sample(cpu); 1083 intel_pstate_sample(cpu, 0);
1114 1084
1115 add_timer_on(&cpu->timer, cpunum); 1085 cpu->update_util.func = intel_pstate_update_util;
1086 cpufreq_set_update_util_data(cpunum, &cpu->update_util);
1116 1087
1117 pr_debug("intel_pstate: controlling: cpu %d\n", cpunum); 1088 pr_debug("intel_pstate: controlling: cpu %d\n", cpunum);
1118 1089
@@ -1196,7 +1167,9 @@ static void intel_pstate_stop_cpu(struct cpufreq_policy *policy)
1196 1167
1197 pr_debug("intel_pstate: CPU %d exiting\n", cpu_num); 1168 pr_debug("intel_pstate: CPU %d exiting\n", cpu_num);
1198 1169
1199 del_timer_sync(&all_cpu_data[cpu_num]->timer); 1170 cpufreq_set_update_util_data(cpu_num, NULL);
1171 synchronize_rcu();
1172
1200 if (hwp_active) 1173 if (hwp_active)
1201 return; 1174 return;
1202 1175
@@ -1260,6 +1233,7 @@ static int intel_pstate_msrs_not_valid(void)
1260static void copy_pid_params(struct pstate_adjust_policy *policy) 1233static void copy_pid_params(struct pstate_adjust_policy *policy)
1261{ 1234{
1262 pid_params.sample_rate_ms = policy->sample_rate_ms; 1235 pid_params.sample_rate_ms = policy->sample_rate_ms;
1236 pid_params.sample_rate_ns = pid_params.sample_rate_ms * NSEC_PER_MSEC;
1263 pid_params.p_gain_pct = policy->p_gain_pct; 1237 pid_params.p_gain_pct = policy->p_gain_pct;
1264 pid_params.i_gain_pct = policy->i_gain_pct; 1238 pid_params.i_gain_pct = policy->i_gain_pct;
1265 pid_params.d_gain_pct = policy->d_gain_pct; 1239 pid_params.d_gain_pct = policy->d_gain_pct;
@@ -1451,7 +1425,8 @@ out:
1451 get_online_cpus(); 1425 get_online_cpus();
1452 for_each_online_cpu(cpu) { 1426 for_each_online_cpu(cpu) {
1453 if (all_cpu_data[cpu]) { 1427 if (all_cpu_data[cpu]) {
1454 del_timer_sync(&all_cpu_data[cpu]->timer); 1428 cpufreq_set_update_util_data(cpu, NULL);
1429 synchronize_rcu();
1455 kfree(all_cpu_data[cpu]); 1430 kfree(all_cpu_data[cpu]);
1456 } 1431 }
1457 } 1432 }