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