eaa8be06edfa1dd5a311ae3dacdeda07def4b776
[linux-2.6.git] / tools / power / cpupower / utils / cpufreq-info.c
1 /*
2  *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
3  *
4  *  Licensed under the terms of the GNU GPL License version 2.
5  */
6
7
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include <getopt.h>
15
16 #include "cpufreq.h"
17 #include "helpers/helpers.h"
18 #include "helpers/bitmask.h"
19
20 #define LINE_LEN 10
21
22 static unsigned int count_cpus(void)
23 {
24         FILE *fp;
25         char value[LINE_LEN];
26         unsigned int ret = 0;
27         unsigned int cpunr = 0;
28
29         fp = fopen("/proc/stat", "r");
30         if(!fp) {
31                 printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno));
32                 return 1;
33         }
34
35         while (!feof(fp)) {
36                 if (!fgets(value, LINE_LEN, fp))
37                         continue;
38                 value[LINE_LEN - 1] = '\0';
39                 if (strlen(value) < (LINE_LEN - 2))
40                         continue;
41                 if (strstr(value, "cpu "))
42                         continue;
43                 if (sscanf(value, "cpu%d ", &cpunr) != 1)
44                         continue;
45                 if (cpunr > ret)
46                         ret = cpunr;
47         }
48         fclose(fp);
49
50         /* cpu count starts from 0, on error return 1 (UP) */
51         return (ret+1);
52 }
53
54
55 static void proc_cpufreq_output(void)
56 {
57         unsigned int cpu, nr_cpus;
58         struct cpufreq_policy *policy;
59         unsigned int min_pctg = 0;
60         unsigned int max_pctg = 0;
61         unsigned long min, max;
62
63         printf(_("          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"));
64
65         nr_cpus = count_cpus();
66         for (cpu=0; cpu < nr_cpus; cpu++) {
67                 policy = cpufreq_get_policy(cpu);
68                 if (!policy)
69                         continue;
70
71                 if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
72                         max = 0;
73                 } else {
74                         min_pctg = (policy->min * 100) / max;
75                         max_pctg = (policy->max * 100) / max;
76                 }
77                 printf("CPU%3d    %9lu kHz (%3d %%)  -  %9lu kHz (%3d %%)  -  %s\n",
78                        cpu , policy->min, max ? min_pctg : 0, policy->max, max ? max_pctg : 0, policy->governor);
79
80                 cpufreq_put_policy(policy);
81         }
82 }
83
84 static void print_speed(unsigned long speed)
85 {
86         unsigned long tmp;
87
88         if (speed > 1000000) {
89                 tmp = speed % 10000;
90                 if (tmp >= 5000)
91                         speed += 10000;
92                 printf ("%u.%02u GHz", ((unsigned int) speed/1000000),
93                         ((unsigned int) (speed%1000000)/10000));
94         } else if (speed > 100000) {
95                 tmp = speed % 1000;
96                 if (tmp >= 500)
97                         speed += 1000;
98                 printf ("%u MHz", ((unsigned int) speed / 1000));
99         } else if (speed > 1000) {
100                 tmp = speed % 100;
101                 if (tmp >= 50)
102                         speed += 100;
103                 printf ("%u.%01u MHz", ((unsigned int) speed/1000),
104                         ((unsigned int) (speed%1000)/100));
105         } else
106                 printf ("%lu kHz", speed);
107
108         return;
109 }
110
111 static void print_duration(unsigned long duration)
112 {
113         unsigned long tmp;
114
115         if (duration > 1000000) {
116                 tmp = duration % 10000;
117                 if (tmp >= 5000)
118                         duration += 10000;
119                 printf ("%u.%02u ms", ((unsigned int) duration/1000000),
120                         ((unsigned int) (duration%1000000)/10000));
121         } else if (duration > 100000) {
122                 tmp = duration % 1000;
123                 if (tmp >= 500)
124                         duration += 1000;
125                 printf ("%u us", ((unsigned int) duration / 1000));
126         } else if (duration > 1000) {
127                 tmp = duration % 100;
128                 if (tmp >= 50)
129                         duration += 100;
130                 printf ("%u.%01u us", ((unsigned int) duration/1000),
131                         ((unsigned int) (duration%1000)/100));
132         } else
133                 printf ("%lu ns", duration);
134
135         return;
136 }
137
138 /* --boost / -b */
139
140 static int get_boost_mode(unsigned int cpu) {
141         int support, active, b_states = 0, ret, pstate_no, i;
142         /* ToDo: Make this more global */
143         unsigned long pstates[MAX_HW_PSTATES] = {0,};
144
145         if (cpupower_cpu_info.vendor != X86_VENDOR_AMD &&
146             cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
147                 return 0;
148
149         ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states);
150         if (ret) {
151                 printf(_("Error while evaluating Boost Capabilities"
152                                 " on CPU %d -- are you root?\n"), cpu);
153                 return ret;
154         }
155         /* P state changes via MSR are identified via cpuid 80000007
156            on Intel and AMD, but we assume boost capable machines can do that
157            if (cpuid_eax(0x80000000) >= 0x80000007
158            && (cpuid_edx(0x80000007) & (1 << 7)))
159         */
160
161         printf(_("  boost state support: \n"));
162
163         printf(_("    Supported: %s\n"), support ? _("yes") : _("no"));
164         printf(_("    Active: %s\n"), active ? _("yes") : _("no"));
165
166         /* ToDo: Only works for AMD for now... */
167         
168         if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
169             cpupower_cpu_info.family >= 0x10) {
170                 ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states,
171                                      pstates, &pstate_no);
172                 if (ret)
173                         return ret;
174         } else
175                 return 0;
176
177         printf(_("    Boost States: %d\n"), b_states);
178         printf(_("    Total States: %d\n"), pstate_no);
179         for (i = 0; i < pstate_no; i++) {
180                 if (i < b_states)
181                         printf(_("    Pstate-Pb%d: %luMHz (boost state)\n"),
182                                i, pstates[i]);
183                 else
184                         printf(_("    Pstate-P%d:  %luMHz\n"),
185                                i - b_states, pstates[i]);
186         }
187         return 0;
188 }
189
190 static void debug_output_one(unsigned int cpu)
191 {
192         char *driver;
193         struct cpufreq_affected_cpus *cpus;
194         struct cpufreq_available_frequencies *freqs;
195         unsigned long min, max, freq_kernel, freq_hardware;
196         unsigned long total_trans, latency;
197         unsigned long long total_time;
198         struct cpufreq_policy *policy;
199         struct cpufreq_available_governors * governors;
200         struct cpufreq_stats *stats;
201
202         if (cpufreq_cpu_exists(cpu)) {
203                 return;
204         }
205
206         freq_kernel = cpufreq_get_freq_kernel(cpu);
207         freq_hardware = cpufreq_get_freq_hardware(cpu);
208
209         driver = cpufreq_get_driver(cpu);
210         if (!driver) {
211                 printf(_("  no or unknown cpufreq driver is active on this CPU\n"));
212         } else {
213                 printf(_("  driver: %s\n"), driver);
214                 cpufreq_put_driver(driver);
215         }
216
217         cpus = cpufreq_get_related_cpus(cpu);
218         if (cpus) {
219                 printf(_("  CPUs which run at the same hardware frequency: "));
220                 while (cpus->next) {
221                         printf("%d ", cpus->cpu);
222                         cpus = cpus->next;
223                 }
224                 printf("%d\n", cpus->cpu);
225                 cpufreq_put_related_cpus(cpus);
226         }
227
228         cpus = cpufreq_get_affected_cpus(cpu);
229         if (cpus) {
230                 printf(_("  CPUs which need to have their frequency coordinated by software: "));
231                 while (cpus->next) {
232                         printf("%d ", cpus->cpu);
233                         cpus = cpus->next;
234                 }
235                 printf("%d\n", cpus->cpu);
236                 cpufreq_put_affected_cpus(cpus);
237         }
238
239         latency = cpufreq_get_transition_latency(cpu);
240         if (latency) {
241                 printf(_("  maximum transition latency: "));
242                 print_duration(latency);
243                 printf(".\n");
244         }
245
246         if (!(cpufreq_get_hardware_limits(cpu, &min, &max))) {
247                 printf(_("  hardware limits: "));
248                 print_speed(min);
249                 printf(" - ");
250                 print_speed(max);
251                 printf("\n");
252         }
253
254         freqs = cpufreq_get_available_frequencies(cpu);
255         if (freqs) {
256                 printf(_("  available frequency steps: "));
257                 while (freqs->next) {
258                         print_speed(freqs->frequency);
259                         printf(", ");
260                         freqs = freqs->next;
261                 }
262                 print_speed(freqs->frequency);
263                 printf("\n");
264                 cpufreq_put_available_frequencies(freqs);
265         }
266
267         governors = cpufreq_get_available_governors(cpu);
268         if (governors) {
269                 printf(_("  available cpufreq governors: "));
270                 while (governors->next) {
271                         printf("%s, ", governors->governor);
272                         governors = governors->next;
273                 }
274                 printf("%s\n", governors->governor);
275                 cpufreq_put_available_governors(governors);
276         }
277
278         policy = cpufreq_get_policy(cpu);
279         if (policy) {
280                 printf(_("  current policy: frequency should be within "));
281                 print_speed(policy->min);
282                 printf(_(" and "));
283                 print_speed(policy->max);
284
285                 printf(".\n                  ");
286                 printf(_("The governor \"%s\" may"
287                        " decide which speed to use\n                  within this range.\n"),
288                        policy->governor);
289                 cpufreq_put_policy(policy);
290         }
291
292         if (freq_kernel || freq_hardware) {
293                 printf(_("  current CPU frequency is "));
294                 if (freq_hardware) {
295                         print_speed(freq_hardware);
296                         printf(_(" (asserted by call to hardware)"));
297                 }
298                 else
299                         print_speed(freq_kernel);
300                 printf(".\n");
301         }
302         stats = cpufreq_get_stats(cpu, &total_time);
303         if (stats) {
304                 printf(_("  cpufreq stats: "));
305                 while (stats) {
306                         print_speed(stats->frequency);
307                         printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
308                         stats = stats->next;
309                         if (stats)
310                                 printf(", ");
311                 }
312                 cpufreq_put_stats(stats);
313                 total_trans = cpufreq_get_transitions(cpu);
314                 if (total_trans)
315                         printf("  (%lu)\n", total_trans);
316                 else
317                         printf("\n");
318         }
319         get_boost_mode(cpu);
320
321 }
322
323 /* --freq / -f */
324
325 static int get_freq_kernel(unsigned int cpu, unsigned int human) {
326         unsigned long freq = cpufreq_get_freq_kernel(cpu);
327         if (!freq)
328                 return -EINVAL;
329         if (human) {
330                 print_speed(freq);
331                 printf("\n");
332         } else
333                 printf("%lu\n", freq);
334         return 0;
335 }
336
337
338 /* --hwfreq / -w */
339
340 static int get_freq_hardware(unsigned int cpu, unsigned int human) {
341         unsigned long freq = cpufreq_get_freq_hardware(cpu);
342         if (!freq)
343                 return -EINVAL;
344         if (human) {
345                 print_speed(freq);
346                 printf("\n");
347         } else
348                 printf("%lu\n", freq);
349         return 0;
350 }
351
352 /* --hwlimits / -l */
353
354 static int get_hardware_limits(unsigned int cpu) {
355         unsigned long min, max;
356         if (cpufreq_get_hardware_limits(cpu, &min, &max))
357                 return -EINVAL;
358         printf("%lu %lu\n", min, max);
359         return 0;
360 }
361
362 /* --driver / -d */
363
364 static int get_driver(unsigned int cpu) {
365         char *driver = cpufreq_get_driver(cpu);
366         if (!driver)
367                 return -EINVAL;
368         printf("%s\n", driver);
369         cpufreq_put_driver(driver);
370         return 0;
371 }
372
373 /* --policy / -p */
374
375 static int get_policy(unsigned int cpu) {
376         struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
377         if (!policy)
378                 return -EINVAL;
379         printf("%lu %lu %s\n", policy->min, policy->max, policy->governor);
380         cpufreq_put_policy(policy);
381         return 0;
382 }
383
384 /* --governors / -g */
385
386 static int get_available_governors(unsigned int cpu) {
387         struct cpufreq_available_governors *governors = cpufreq_get_available_governors(cpu);
388         if (!governors)
389                 return -EINVAL;
390
391         while (governors->next) {
392                 printf("%s ", governors->governor);
393                 governors = governors->next;
394         }
395         printf("%s\n", governors->governor);
396         cpufreq_put_available_governors(governors);
397         return 0;
398 }
399
400
401 /* --affected-cpus  / -a */
402
403 static int get_affected_cpus(unsigned int cpu) {
404         struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
405         if (!cpus)
406                 return -EINVAL;
407
408         while (cpus->next) {
409                 printf("%d ", cpus->cpu);
410                 cpus = cpus->next;
411         }
412         printf("%d\n", cpus->cpu);
413         cpufreq_put_affected_cpus(cpus);
414         return 0;
415 }
416
417 /* --related-cpus  / -r */
418
419 static int get_related_cpus(unsigned int cpu) {
420         struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
421         if (!cpus)
422                 return -EINVAL;
423
424         while (cpus->next) {
425                 printf("%d ", cpus->cpu);
426                 cpus = cpus->next;
427         }
428         printf("%d\n", cpus->cpu);
429         cpufreq_put_related_cpus(cpus);
430         return 0;
431 }
432
433 /* --stats / -s */
434
435 static int get_freq_stats(unsigned int cpu, unsigned int human) {
436         unsigned long total_trans = cpufreq_get_transitions(cpu);
437         unsigned long long total_time;
438         struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
439         while (stats) {
440                 if (human) {
441                         print_speed(stats->frequency);
442                         printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
443                 }
444                 else
445                         printf("%lu:%llu", stats->frequency, stats->time_in_state);
446                 stats = stats->next;
447                 if (stats)
448                         printf(", ");
449         }
450         cpufreq_put_stats(stats);
451         if (total_trans)
452                 printf("  (%lu)\n", total_trans);
453         return 0;
454 }
455
456 /* --latency / -y */
457
458 static int get_latency(unsigned int cpu, unsigned int human) {
459         unsigned long latency = cpufreq_get_transition_latency(cpu);
460         if (!latency)
461                 return -EINVAL;
462
463         if (human) {
464                 print_duration(latency);
465                 printf("\n");
466         } else
467                 printf("%lu\n", latency);
468         return 0;
469 }
470
471 void freq_info_help(void) {
472         printf(_("Usage: cpupower freqinfo [options]\n"));
473         printf(_("Options:\n"));
474         printf(_("  -e, --debug          Prints out debug information [default]\n"));
475         printf(_("  -f, --freq           Get frequency the CPU currently runs at, according\n"
476                "                       to the cpufreq core *\n"));
477         printf(_("  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
478                "                       it from hardware (only available to root) *\n"));
479         printf(_("  -l, --hwlimits       Determine the minimum and maximum CPU frequency allowed *\n"));
480         printf(_("  -d, --driver         Determines the used cpufreq kernel driver *\n"));
481         printf(_("  -p, --policy         Gets the currently used cpufreq policy *\n"));
482         printf(_("  -g, --governors      Determines available cpufreq governors *\n"));
483         printf(_("  -r, --related-cpus   Determines which CPUs run at the same hardware frequency *\n"));
484         printf(_("  -a, --affected-cpus  Determines which CPUs need to have their frequency\n"
485                         "                       coordinated by software *\n"));
486         printf(_("  -s, --stats          Shows cpufreq statistics if available\n"));
487         printf(_("  -y, --latency        Determines the maximum latency on CPU frequency changes *\n"));
488         printf(_("  -b, --boost          Checks for turbo or boost modes  *\n"));
489         printf(_("  -o, --proc           Prints out information like provided by the /proc/cpufreq\n"
490                "                       interface in 2.4. and early 2.6. kernels\n"));
491         printf(_("  -m, --human          human-readable output for the -f, -w, -s and -y parameters\n"));
492         printf(_("  -h, --help           Prints out this screen\n"));
493
494         printf("\n");
495         printf(_("If no argument is given, full output about\n"
496                "cpufreq is printed which is useful e.g. for reporting bugs.\n\n"));
497         printf(_("By default info of CPU 0 is shown which can be overridden \n"
498                  "with the cpupower --cpu main command option.\n"));
499 }
500
501 static struct option info_opts[] = {
502         { .name="debug",        .has_arg=no_argument,           .flag=NULL,     .val='e'},
503         { .name="boost",        .has_arg=no_argument,           .flag=NULL,     .val='b'},
504         { .name="freq",         .has_arg=no_argument,           .flag=NULL,     .val='f'},
505         { .name="hwfreq",       .has_arg=no_argument,           .flag=NULL,     .val='w'},
506         { .name="hwlimits",     .has_arg=no_argument,           .flag=NULL,     .val='l'},
507         { .name="driver",       .has_arg=no_argument,           .flag=NULL,     .val='d'},
508         { .name="policy",       .has_arg=no_argument,           .flag=NULL,     .val='p'},
509         { .name="governors",    .has_arg=no_argument,           .flag=NULL,     .val='g'},
510         { .name="related-cpus", .has_arg=no_argument,           .flag=NULL,     .val='r'},
511         { .name="affected-cpus",.has_arg=no_argument,           .flag=NULL,     .val='a'},
512         { .name="stats",        .has_arg=no_argument,           .flag=NULL,     .val='s'},
513         { .name="latency",      .has_arg=no_argument,           .flag=NULL,     .val='y'},
514         { .name="proc",         .has_arg=no_argument,           .flag=NULL,     .val='o'},
515         { .name="human",        .has_arg=no_argument,           .flag=NULL,     .val='m'},
516         { .name="help",         .has_arg=no_argument,           .flag=NULL,     .val='h'},
517         { },
518 };
519
520 int cmd_freq_info(int argc, char **argv)
521 {
522         extern char *optarg;
523         extern int optind, opterr, optopt;
524         int ret = 0, cont = 1;
525         unsigned int cpu = 0;
526         unsigned int human = 0;
527         int output_param = 0;
528
529         do {
530                 ret = getopt_long(argc, argv, "hoefwldpgrasmyb", info_opts, NULL);
531                 switch (ret) {
532                 case '?':
533                         output_param = '?';
534                         cont = 0;
535                         break;
536                 case 'h':
537                         output_param = 'h';
538                         cont = 0;
539                         break;
540                 case -1:
541                         cont = 0;
542                         break;
543                 case 'b':
544                 case 'o':
545                 case 'a':
546                 case 'r':
547                 case 'g':
548                 case 'p':
549                 case 'd':
550                 case 'l':
551                 case 'w':
552                 case 'f':
553                 case 'e':
554                 case 's':
555                 case 'y':
556                         if (output_param) {
557                                 output_param = -1;
558                                 cont = 0;
559                                 break;
560                         }
561                         output_param = ret;
562                         break;
563                 case 'm':
564                         if (human) {
565                                 output_param = -1;
566                                 cont = 0;
567                                 break;
568                         }
569                         human = 1;
570                         break;
571                 default:
572                         fprintf(stderr, "invalid or unknown argument\n");
573                         return EXIT_FAILURE;
574                 }
575         } while(cont);
576
577         switch (output_param) {
578         case 'o':
579                 if (!bitmask_isallclear(cpus_chosen)) {
580                         printf(_("The argument passed to this tool can't be "
581                                  "combined with passing a --cpu argument\n"));
582                         return -EINVAL;
583                 }
584                 break;
585         case 0:
586                 output_param = 'e';
587         }
588
589         ret = 0;
590
591         /* Default is: show output of CPU 0 only */
592         if (bitmask_isallclear(cpus_chosen))
593                 bitmask_setbit(cpus_chosen, 0);
594                 
595         switch (output_param) {
596         case -1:
597                 printf(_("You can't specify more than one --cpu parameter and/or\n"
598                        "more than one output-specific argument\n"));
599                 return -EINVAL;
600         case '?':
601                 printf(_("invalid or unknown argument\n"));
602                 freq_info_help();
603                 return -EINVAL;
604         case 'h':
605                 freq_info_help();
606                 return EXIT_SUCCESS;
607         case 'o':
608                 proc_cpufreq_output();
609                 return EXIT_SUCCESS;
610         }
611
612         for (cpu = bitmask_first(cpus_chosen);
613              cpu <= bitmask_last(cpus_chosen); cpu++) {
614
615                 if (!bitmask_isbitset(cpus_chosen, cpu))
616                         continue;
617                 if (cpufreq_cpu_exists(cpu)) {
618                         printf(_("couldn't analyze CPU %d as it doesn't seem to be present\n"), cpu);
619                         continue;
620                 }
621                 printf(_("analyzing CPU %d:\n"), cpu);
622
623                 switch (output_param) {
624                 case 'b':
625                         get_boost_mode(cpu);
626                         break;
627                 case 'e':
628                         debug_output_one(cpu);
629                         break;
630                 case 'a':
631                         ret = get_affected_cpus(cpu);
632                         break;
633                 case 'r':
634                         ret = get_related_cpus(cpu);
635                         break;
636                 case 'g':
637                         ret = get_available_governors(cpu);
638                         break;
639                 case 'p':
640                         ret = get_policy(cpu);
641                         break;
642                 case 'd':
643                         ret = get_driver(cpu);
644                         break;
645                 case 'l':
646                         ret = get_hardware_limits(cpu);
647                         break;
648                 case 'w':
649                         ret = get_freq_hardware(cpu, human);
650                         break;
651                 case 'f':
652                         ret = get_freq_kernel(cpu, human);
653                         break;
654                 case 's':
655                         ret = get_freq_stats(cpu, human);
656                         break;
657                 case 'y':
658                         ret = get_latency(cpu, human);
659                         break;
660                 }
661                 if (ret)
662                         return (ret);
663         }
664         return ret;
665 }