1 /*
2  *  utility.c - misc functions for cpufreq driver and Px statistic
3  *
4  *  Copyright (C) 2001 Russell King
5  *            (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
6  *
7  *  Oct 2005 - Ashok Raj <ashok.raj@intel.com>
8  *    Added handling for CPU hotplug
9  *  Feb 2006 - Jacob Shin <jacob.shin@amd.com>
10  *    Fix handling for CPU hotplug -- affected CPUs
11  *  Feb 2008 - Liu Jinsong <jinsong.liu@intel.com>
12  *    1. Merge cpufreq.c and freq_table.c of linux 2.6.23
13  *    And poring to Xen hypervisor
14  *    2. some Px statistic interface funcdtions
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License version 2 as
18  * published by the Free Software Foundation.
19  *
20  */
21 
22 #include <xen/errno.h>
23 #include <xen/cpumask.h>
24 #include <xen/types.h>
25 #include <xen/spinlock.h>
26 #include <xen/percpu.h>
27 #include <xen/types.h>
28 #include <xen/sched.h>
29 #include <xen/timer.h>
30 #include <xen/trace.h>
31 #include <acpi/cpufreq/cpufreq.h>
32 #include <public/sysctl.h>
33 
34 struct cpufreq_driver __read_mostly cpufreq_driver;
35 struct processor_pminfo *__read_mostly processor_pminfo[NR_CPUS];
36 DEFINE_PER_CPU_READ_MOSTLY(struct cpufreq_policy *, cpufreq_cpu_policy);
37 
38 DEFINE_PER_CPU(spinlock_t, cpufreq_statistic_lock);
39 
40 /*********************************************************************
41  *                    Px STATISTIC INFO                              *
42  *********************************************************************/
43 
cpufreq_residency_update(unsigned int cpu,uint8_t state)44 void cpufreq_residency_update(unsigned int cpu, uint8_t state)
45 {
46     uint64_t now, total_idle_ns;
47     int64_t delta;
48     struct pm_px *pxpt = per_cpu(cpufreq_statistic_data, cpu);
49 
50     total_idle_ns = get_cpu_idle_time(cpu);
51     now = NOW();
52 
53     delta = (now - pxpt->prev_state_wall) -
54             (total_idle_ns - pxpt->prev_idle_wall);
55 
56     if ( likely(delta >= 0) )
57         pxpt->u.pt[state].residency += delta;
58 
59     pxpt->prev_state_wall = now;
60     pxpt->prev_idle_wall = total_idle_ns;
61 }
62 
cpufreq_statistic_update(unsigned int cpu,uint8_t from,uint8_t to)63 void cpufreq_statistic_update(unsigned int cpu, uint8_t from, uint8_t to)
64 {
65     struct pm_px *pxpt;
66     struct processor_pminfo *pmpt = processor_pminfo[cpu];
67     spinlock_t *cpufreq_statistic_lock =
68                &per_cpu(cpufreq_statistic_lock, cpu);
69 
70     spin_lock(cpufreq_statistic_lock);
71 
72     pxpt = per_cpu(cpufreq_statistic_data, cpu);
73     if ( !pxpt || !pmpt ) {
74         spin_unlock(cpufreq_statistic_lock);
75         return;
76     }
77 
78     pxpt->u.last = from;
79     pxpt->u.cur = to;
80     pxpt->u.pt[to].count++;
81 
82     cpufreq_residency_update(cpu, from);
83 
84     (*(pxpt->u.trans_pt + from * pmpt->perf.state_count + to))++;
85 
86     spin_unlock(cpufreq_statistic_lock);
87 }
88 
cpufreq_statistic_init(unsigned int cpuid)89 int cpufreq_statistic_init(unsigned int cpuid)
90 {
91     uint32_t i, count;
92     struct pm_px *pxpt;
93     const struct processor_pminfo *pmpt = processor_pminfo[cpuid];
94     spinlock_t *cpufreq_statistic_lock =
95                           &per_cpu(cpufreq_statistic_lock, cpuid);
96 
97     spin_lock_init(cpufreq_statistic_lock);
98 
99     if ( !pmpt )
100         return -EINVAL;
101 
102     spin_lock(cpufreq_statistic_lock);
103 
104     pxpt = per_cpu(cpufreq_statistic_data, cpuid);
105     if ( pxpt ) {
106         spin_unlock(cpufreq_statistic_lock);
107         return 0;
108     }
109 
110     count = pmpt->perf.state_count;
111 
112     pxpt = xzalloc(struct pm_px);
113     if ( !pxpt ) {
114         spin_unlock(cpufreq_statistic_lock);
115         return -ENOMEM;
116     }
117     per_cpu(cpufreq_statistic_data, cpuid) = pxpt;
118 
119     pxpt->u.trans_pt = xzalloc_array(uint64_t, count * count);
120     if (!pxpt->u.trans_pt) {
121         xfree(pxpt);
122         spin_unlock(cpufreq_statistic_lock);
123         return -ENOMEM;
124     }
125 
126     pxpt->u.pt = xzalloc_array(struct pm_px_val, count);
127     if (!pxpt->u.pt) {
128         xfree(pxpt->u.trans_pt);
129         xfree(pxpt);
130         spin_unlock(cpufreq_statistic_lock);
131         return -ENOMEM;
132     }
133 
134     pxpt->u.total = pmpt->perf.state_count;
135     pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.platform_limit;
136 
137     for (i=0; i < pmpt->perf.state_count; i++)
138         pxpt->u.pt[i].freq = pmpt->perf.states[i].core_frequency;
139 
140     pxpt->prev_state_wall = NOW();
141     pxpt->prev_idle_wall = get_cpu_idle_time(cpuid);
142 
143     spin_unlock(cpufreq_statistic_lock);
144 
145     return 0;
146 }
147 
cpufreq_statistic_exit(unsigned int cpuid)148 void cpufreq_statistic_exit(unsigned int cpuid)
149 {
150     struct pm_px *pxpt;
151     spinlock_t *cpufreq_statistic_lock =
152                &per_cpu(cpufreq_statistic_lock, cpuid);
153 
154     spin_lock(cpufreq_statistic_lock);
155 
156     pxpt = per_cpu(cpufreq_statistic_data, cpuid);
157     if (!pxpt) {
158         spin_unlock(cpufreq_statistic_lock);
159         return;
160     }
161 
162     xfree(pxpt->u.trans_pt);
163     xfree(pxpt->u.pt);
164     xfree(pxpt);
165     per_cpu(cpufreq_statistic_data, cpuid) = NULL;
166 
167     spin_unlock(cpufreq_statistic_lock);
168 }
169 
cpufreq_statistic_reset(unsigned int cpuid)170 void cpufreq_statistic_reset(unsigned int cpuid)
171 {
172     uint32_t i, j, count;
173     struct pm_px *pxpt;
174     const struct processor_pminfo *pmpt = processor_pminfo[cpuid];
175     spinlock_t *cpufreq_statistic_lock =
176                &per_cpu(cpufreq_statistic_lock, cpuid);
177 
178     spin_lock(cpufreq_statistic_lock);
179 
180     pxpt = per_cpu(cpufreq_statistic_data, cpuid);
181     if ( !pmpt || !pxpt || !pxpt->u.pt || !pxpt->u.trans_pt ) {
182         spin_unlock(cpufreq_statistic_lock);
183         return;
184     }
185 
186     count = pmpt->perf.state_count;
187 
188     for (i=0; i < count; i++) {
189         pxpt->u.pt[i].residency = 0;
190         pxpt->u.pt[i].count = 0;
191 
192         for (j=0; j < count; j++)
193             *(pxpt->u.trans_pt + i*count + j) = 0;
194     }
195 
196     pxpt->prev_state_wall = NOW();
197     pxpt->prev_idle_wall = get_cpu_idle_time(cpuid);
198 
199     spin_unlock(cpufreq_statistic_lock);
200 }
201 
202 
203 /*********************************************************************
204  *                   FREQUENCY TABLE HELPERS                         *
205  *********************************************************************/
206 
cpufreq_frequency_table_cpuinfo(struct cpufreq_policy * policy,struct cpufreq_frequency_table * table)207 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
208                                     struct cpufreq_frequency_table *table)
209 {
210     unsigned int min_freq = ~0;
211     unsigned int max_freq = 0;
212     unsigned int second_max_freq = 0;
213     unsigned int i;
214 
215     for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
216         unsigned int freq = table[i].frequency;
217         if (freq == CPUFREQ_ENTRY_INVALID)
218             continue;
219         if (freq < min_freq)
220             min_freq = freq;
221         if (freq > max_freq)
222             max_freq = freq;
223     }
224     for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
225         unsigned int freq = table[i].frequency;
226         if (freq == CPUFREQ_ENTRY_INVALID || freq == max_freq)
227             continue;
228         if (freq > second_max_freq)
229             second_max_freq = freq;
230     }
231     if (second_max_freq == 0)
232         second_max_freq = max_freq;
233     if (cpufreq_verbose)
234         printk("max_freq: %u    second_max_freq: %u\n",
235                max_freq, second_max_freq);
236 
237     policy->min = policy->cpuinfo.min_freq = min_freq;
238     policy->max = policy->cpuinfo.max_freq = max_freq;
239     policy->cpuinfo.second_max_freq = second_max_freq;
240 
241     if (policy->min == ~0)
242         return -EINVAL;
243     else
244         return 0;
245 }
246 
cpufreq_frequency_table_verify(struct cpufreq_policy * policy,struct cpufreq_frequency_table * table)247 int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
248                                    struct cpufreq_frequency_table *table)
249 {
250     unsigned int next_larger = ~0;
251     unsigned int i;
252     unsigned int count = 0;
253 
254     if (!cpu_online(policy->cpu))
255         return -EINVAL;
256 
257     cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
258                                  policy->cpuinfo.max_freq);
259 
260     for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
261         unsigned int freq = table[i].frequency;
262         if (freq == CPUFREQ_ENTRY_INVALID)
263             continue;
264         if ((freq >= policy->min) && (freq <= policy->max))
265             count++;
266         else if ((next_larger > freq) && (freq > policy->max))
267             next_larger = freq;
268     }
269 
270     if (!count)
271         policy->max = next_larger;
272 
273     cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
274                                  policy->cpuinfo.max_freq);
275 
276     return 0;
277 }
278 
cpufreq_frequency_table_target(struct cpufreq_policy * policy,struct cpufreq_frequency_table * table,unsigned int target_freq,unsigned int relation,unsigned int * index)279 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
280                                    struct cpufreq_frequency_table *table,
281                                    unsigned int target_freq,
282                                    unsigned int relation,
283                                    unsigned int *index)
284 {
285     struct cpufreq_frequency_table optimal = {
286         .index = ~0,
287         .frequency = 0,
288     };
289     struct cpufreq_frequency_table suboptimal = {
290         .index = ~0,
291         .frequency = 0,
292     };
293     unsigned int i;
294 
295     switch (relation) {
296     case CPUFREQ_RELATION_H:
297         suboptimal.frequency = ~0;
298         break;
299     case CPUFREQ_RELATION_L:
300         optimal.frequency = ~0;
301         break;
302     }
303 
304     if (!cpu_online(policy->cpu))
305         return -EINVAL;
306 
307     for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
308         unsigned int freq = table[i].frequency;
309         if (freq == CPUFREQ_ENTRY_INVALID)
310             continue;
311         if ((freq < policy->min) || (freq > policy->max))
312             continue;
313         switch(relation) {
314         case CPUFREQ_RELATION_H:
315             if (freq <= target_freq) {
316                 if (freq >= optimal.frequency) {
317                     optimal.frequency = freq;
318                     optimal.index = i;
319                 }
320             } else {
321                 if (freq <= suboptimal.frequency) {
322                     suboptimal.frequency = freq;
323                     suboptimal.index = i;
324                 }
325             }
326             break;
327         case CPUFREQ_RELATION_L:
328             if (freq >= target_freq) {
329                 if (freq <= optimal.frequency) {
330                     optimal.frequency = freq;
331                     optimal.index = i;
332                 }
333             } else {
334                 if (freq >= suboptimal.frequency) {
335                     suboptimal.frequency = freq;
336                     suboptimal.index = i;
337                 }
338             }
339             break;
340         }
341     }
342     if (optimal.index > i) {
343         if (suboptimal.index > i)
344             return -EINVAL;
345         *index = suboptimal.index;
346     } else
347         *index = optimal.index;
348 
349     return 0;
350 }
351 
352 
353 /*********************************************************************
354  *               GOVERNORS                                           *
355  *********************************************************************/
356 
__cpufreq_driver_target(struct cpufreq_policy * policy,unsigned int target_freq,unsigned int relation)357 int __cpufreq_driver_target(struct cpufreq_policy *policy,
358                             unsigned int target_freq,
359                             unsigned int relation)
360 {
361     int retval = -EINVAL;
362 
363     if (cpu_online(policy->cpu) && cpufreq_driver.target)
364     {
365         unsigned int prev_freq = policy->cur;
366 
367         retval = alternative_call(cpufreq_driver.target,
368                                   policy, target_freq, relation);
369         if ( retval == 0 )
370             TRACE_2D(TRC_PM_FREQ_CHANGE, prev_freq/1000, policy->cur/1000);
371     }
372 
373     return retval;
374 }
375 
cpufreq_driver_getavg(unsigned int cpu,unsigned int flag)376 int cpufreq_driver_getavg(unsigned int cpu, unsigned int flag)
377 {
378     struct cpufreq_policy *policy;
379     int freq_avg;
380 
381     if (!cpu_online(cpu) || !(policy = per_cpu(cpufreq_cpu_policy, cpu)))
382         return 0;
383 
384     if (cpufreq_driver.getavg)
385     {
386         freq_avg = cpufreq_driver.getavg(cpu, flag);
387         if (freq_avg > 0)
388             return freq_avg;
389     }
390 
391     return policy->cur;
392 }
393 
cpufreq_update_turbo(int cpuid,int new_state)394 int cpufreq_update_turbo(int cpuid, int new_state)
395 {
396     struct cpufreq_policy *policy;
397     int curr_state;
398     int ret = 0;
399 
400     if (new_state != CPUFREQ_TURBO_ENABLED &&
401         new_state != CPUFREQ_TURBO_DISABLED)
402         return -EINVAL;
403 
404     policy = per_cpu(cpufreq_cpu_policy, cpuid);
405     if (!policy)
406         return -EACCES;
407 
408     if (policy->turbo == CPUFREQ_TURBO_UNSUPPORTED)
409         return -EOPNOTSUPP;
410 
411     curr_state = policy->turbo;
412     if (curr_state == new_state)
413         return 0;
414 
415     policy->turbo = new_state;
416     if (cpufreq_driver.update)
417     {
418         ret = cpufreq_driver.update(cpuid, policy);
419         if (ret)
420             policy->turbo = curr_state;
421     }
422 
423     return ret;
424 }
425 
426 
cpufreq_get_turbo_status(int cpuid)427 int cpufreq_get_turbo_status(int cpuid)
428 {
429     struct cpufreq_policy *policy;
430 
431     policy = per_cpu(cpufreq_cpu_policy, cpuid);
432     return policy && policy->turbo == CPUFREQ_TURBO_ENABLED;
433 }
434 
435 /*********************************************************************
436  *                 POLICY                                            *
437  *********************************************************************/
438 
439 /*
440  * data   : current policy.
441  * policy : policy to be set.
442  */
__cpufreq_set_policy(struct cpufreq_policy * data,struct cpufreq_policy * policy)443 int __cpufreq_set_policy(struct cpufreq_policy *data,
444                                 struct cpufreq_policy *policy)
445 {
446     int ret = 0;
447 
448     memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
449 
450     if (policy->min > data->min && policy->min > policy->max)
451         return -EINVAL;
452 
453     /* verify the cpu speed can be set within this limit */
454     ret = cpufreq_driver.verify(policy);
455     if (ret)
456         return ret;
457 
458     data->min = policy->min;
459     data->max = policy->max;
460     data->limits = policy->limits;
461     if (cpufreq_driver.setpolicy)
462         return cpufreq_driver.setpolicy(data);
463 
464     if (policy->governor != data->governor) {
465         /* save old, working values */
466         struct cpufreq_governor *old_gov = data->governor;
467 
468         /* end old governor */
469         if (data->governor)
470             __cpufreq_governor(data, CPUFREQ_GOV_STOP);
471 
472         /* start new governor */
473         data->governor = policy->governor;
474         if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
475             printk(KERN_WARNING "Fail change to %s governor\n",
476                                  data->governor->name);
477 
478             /* new governor failed, so re-start old one */
479             data->governor = old_gov;
480             if (old_gov) {
481                 __cpufreq_governor(data, CPUFREQ_GOV_START);
482                 printk(KERN_WARNING "Still stay at %s governor\n",
483                                      data->governor->name);
484             }
485             return -EINVAL;
486         }
487         /* might be a policy change, too, so fall through */
488     }
489 
490     return __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
491 }
492