cpuidle-info.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
  3. * (C) 2010 Thomas Renninger <trenn@suse.de>
  4. *
  5. * Licensed under the terms of the GNU GPL License version 2.
  6. */
  7. #include <unistd.h>
  8. #include <stdio.h>
  9. #include <errno.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <getopt.h>
  13. #include <cpufreq.h>
  14. #include "helpers/helpers.h"
  15. #include "helpers/sysfs.h"
  16. #include "helpers/bitmask.h"
  17. #define LINE_LEN 10
  18. static void cpuidle_cpu_output(unsigned int cpu, int verbose)
  19. {
  20. int idlestates, idlestate;
  21. char *tmp;
  22. printf(_ ("Analyzing CPU %d:\n"), cpu);
  23. idlestates = sysfs_get_idlestate_count(cpu);
  24. if (idlestates == 0) {
  25. printf(_("CPU %u: No idle states\n"), cpu);
  26. return;
  27. }
  28. else if (idlestates <= 0) {
  29. printf(_("CPU %u: Can't read idle state info\n"), cpu);
  30. return;
  31. }
  32. tmp = sysfs_get_idlestate_name(cpu, idlestates - 1);
  33. if (!tmp) {
  34. printf(_("Could not determine max idle state %u\n"),
  35. idlestates - 1);
  36. return;
  37. }
  38. printf(_("Number of idle states: %d\n"), idlestates);
  39. printf(_("Available idle states:"));
  40. for (idlestate = 1; idlestate < idlestates; idlestate++) {
  41. tmp = sysfs_get_idlestate_name(cpu, idlestate);
  42. if (!tmp)
  43. continue;
  44. printf(" %s", tmp);
  45. free(tmp);
  46. }
  47. printf("\n");
  48. if (!verbose)
  49. return;
  50. for (idlestate = 1; idlestate < idlestates; idlestate++) {
  51. tmp = sysfs_get_idlestate_name(cpu, idlestate);
  52. if (!tmp)
  53. continue;
  54. printf("%s:\n", tmp);
  55. free(tmp);
  56. tmp = sysfs_get_idlestate_desc(cpu, idlestate);
  57. if (!tmp)
  58. continue;
  59. printf(_("Flags/Description: %s\n"), tmp);
  60. free(tmp);
  61. printf(_("Latency: %lu\n"),
  62. sysfs_get_idlestate_latency(cpu, idlestate));
  63. printf(_("Usage: %lu\n"),
  64. sysfs_get_idlestate_usage(cpu, idlestate));
  65. printf(_("Duration: %llu\n"),
  66. sysfs_get_idlestate_time(cpu, idlestate));
  67. }
  68. printf("\n");
  69. }
  70. static void cpuidle_general_output(void)
  71. {
  72. char *tmp;
  73. tmp = sysfs_get_cpuidle_driver();
  74. if (!tmp) {
  75. printf(_("Could not determine cpuidle driver\n"));
  76. return;
  77. }
  78. printf(_("CPUidle driver: %s\n"), tmp);
  79. free (tmp);
  80. tmp = sysfs_get_cpuidle_governor();
  81. if (!tmp) {
  82. printf(_("Could not determine cpuidle governor\n"));
  83. return;
  84. }
  85. printf(_("CPUidle governor: %s\n"), tmp);
  86. free (tmp);
  87. }
  88. static void proc_cpuidle_cpu_output(unsigned int cpu)
  89. {
  90. long max_allowed_cstate = 2000000000;
  91. int cstates, cstate;
  92. cstates = sysfs_get_idlestate_count(cpu);
  93. if (cstates == 0) {
  94. /*
  95. * Go on and print same useless info as you'd see with
  96. * cat /proc/acpi/processor/../power
  97. * printf(_("CPU %u: No C-states available\n"), cpu);
  98. * return;
  99. */
  100. }
  101. else if (cstates <= 0) {
  102. printf(_("CPU %u: Can't read C-state info\n"), cpu);
  103. return;
  104. }
  105. /* printf("Cstates: %d\n", cstates); */
  106. printf(_("active state: C0\n"));
  107. printf(_("max_cstate: C%u\n"), cstates-1);
  108. printf(_("maximum allowed latency: %lu usec\n"), max_allowed_cstate);
  109. printf(_("states:\t\n"));
  110. for (cstate = 1; cstate < cstates; cstate++) {
  111. printf(_(" C%d: "
  112. "type[C%d] "), cstate, cstate);
  113. printf(_("promotion[--] demotion[--] "));
  114. printf(_("latency[%03lu] "),
  115. sysfs_get_idlestate_latency(cpu, cstate));
  116. printf(_("usage[%08lu] "),
  117. sysfs_get_idlestate_usage(cpu, cstate));
  118. printf(_("duration[%020Lu] \n"),
  119. sysfs_get_idlestate_time(cpu, cstate));
  120. }
  121. }
  122. /* --freq / -f */
  123. void idle_info_help(void) {
  124. printf(_ ("Usage: cpupower idleinfo [options]\n"));
  125. printf(_ ("Options:\n"));
  126. printf(_ (" -s, --silent Only show general C-state information\n"));
  127. printf(_ (" -o, --proc Prints out information like provided by the /proc/acpi/processor/*/power\n"
  128. " interface in older kernels\n"));
  129. printf(_ (" -h, --help Prints out this screen\n"));
  130. printf("\n");
  131. }
  132. static struct option info_opts[] = {
  133. { .name="silent", .has_arg=no_argument, .flag=NULL, .val='s'},
  134. { .name="proc", .has_arg=no_argument, .flag=NULL, .val='o'},
  135. { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'},
  136. { },
  137. };
  138. static inline void cpuidle_exit(int fail)
  139. {
  140. idle_info_help();
  141. exit(EXIT_FAILURE);
  142. }
  143. int cmd_idle_info(int argc, char **argv)
  144. {
  145. extern char *optarg;
  146. extern int optind, opterr, optopt;
  147. int ret = 0, cont = 1, output_param = 0, verbose = 1;
  148. unsigned int cpu = 0;
  149. do {
  150. ret = getopt_long(argc, argv, "hos", info_opts, NULL);
  151. if (ret == -1)
  152. break;
  153. switch (ret) {
  154. case '?':
  155. output_param = '?';
  156. cont = 0;
  157. break;
  158. case 'h':
  159. output_param = 'h';
  160. cont = 0;
  161. break;
  162. case 's':
  163. verbose = 0;
  164. break;
  165. case -1:
  166. cont = 0;
  167. break;
  168. case 'o':
  169. if (output_param) {
  170. output_param = -1;
  171. cont = 0;
  172. break;
  173. }
  174. output_param = ret;
  175. break;
  176. }
  177. } while(cont);
  178. switch (output_param) {
  179. case -1:
  180. printf(_("You can't specify more than one "
  181. "output-specific argument\n"));
  182. cpuidle_exit(EXIT_FAILURE);
  183. case '?':
  184. printf(_("invalid or unknown argument\n"));
  185. cpuidle_exit(EXIT_FAILURE);
  186. case 'h':
  187. cpuidle_exit(EXIT_SUCCESS);
  188. }
  189. /* Default is: show output of CPU 0 only */
  190. if (bitmask_isallclear(cpus_chosen))
  191. bitmask_setbit(cpus_chosen, 0);
  192. if (output_param == 0)
  193. cpuidle_general_output();
  194. for (cpu = bitmask_first(cpus_chosen);
  195. cpu <= bitmask_last(cpus_chosen); cpu++) {
  196. if (!bitmask_isbitset(cpus_chosen, cpu) ||
  197. cpufreq_cpu_exists(cpu))
  198. continue;
  199. switch (output_param) {
  200. case 'o':
  201. proc_cpuidle_cpu_output(cpu);
  202. break;
  203. case 0:
  204. printf("\n");
  205. cpuidle_cpu_output(cpu, verbose);
  206. break;
  207. }
  208. }
  209. return (EXIT_SUCCESS);
  210. }