2011-03-30 16:30:11 +02:00
/*
* ( C ) 2004 - 2009 Dominik Brodowski < linux @ dominikbrodowski . de >
* ( C ) 2010 Thomas Renninger < trenn @ suse . de >
*
* Licensed under the terms of the GNU GPL License version 2.
*/
# include <unistd.h>
# include <stdio.h>
# include <errno.h>
# include <stdlib.h>
# include <string.h>
# include <getopt.h>
# include <cpufreq.h>
# include "helpers/helpers.h"
# include "helpers/sysfs.h"
# include "helpers/bitmask.h"
# define LINE_LEN 10
static void cpuidle_cpu_output ( unsigned int cpu , int verbose )
{
2013-06-28 15:34:29 +02:00
unsigned int idlestates , idlestate ;
2011-03-30 16:30:11 +02:00
char * tmp ;
printf ( _ ( " Analyzing CPU %d: \n " ) , cpu ) ;
idlestates = sysfs_get_idlestate_count ( cpu ) ;
if ( idlestates = = 0 ) {
printf ( _ ( " CPU %u: No idle states \n " ) , cpu ) ;
return ;
}
2013-06-28 15:34:29 +02:00
2011-03-30 16:30:11 +02:00
printf ( _ ( " Number of idle states: %d \n " ) , idlestates ) ;
printf ( _ ( " Available idle states: " ) ) ;
2011-12-16 15:35:53 +01:00
for ( idlestate = 0 ; idlestate < idlestates ; idlestate + + ) {
2011-03-30 16:30:11 +02:00
tmp = sysfs_get_idlestate_name ( cpu , idlestate ) ;
if ( ! tmp )
continue ;
printf ( " %s " , tmp ) ;
free ( tmp ) ;
}
printf ( " \n " ) ;
if ( ! verbose )
return ;
2011-12-16 15:35:53 +01:00
for ( idlestate = 0 ; idlestate < idlestates ; idlestate + + ) {
2013-06-28 15:34:31 +02:00
int disabled = sysfs_is_idlestate_disabled ( cpu , idlestate ) ;
/* Disabled interface not supported on older kernels */
if ( disabled < 0 )
disabled = 0 ;
2011-03-30 16:30:11 +02:00
tmp = sysfs_get_idlestate_name ( cpu , idlestate ) ;
if ( ! tmp )
continue ;
2013-06-28 15:34:31 +02:00
printf ( " %s%s: \n " , tmp , ( disabled ) ? " (DISABLED) " : " " ) ;
2011-03-30 16:30:11 +02:00
free ( tmp ) ;
tmp = sysfs_get_idlestate_desc ( cpu , idlestate ) ;
if ( ! tmp )
continue ;
printf ( _ ( " Flags/Description: %s \n " ) , tmp ) ;
free ( tmp ) ;
printf ( _ ( " Latency: %lu \n " ) ,
sysfs_get_idlestate_latency ( cpu , idlestate ) ) ;
printf ( _ ( " Usage: %lu \n " ) ,
sysfs_get_idlestate_usage ( cpu , idlestate ) ) ;
printf ( _ ( " Duration: %llu \n " ) ,
sysfs_get_idlestate_time ( cpu , idlestate ) ) ;
}
printf ( " \n " ) ;
}
static void cpuidle_general_output ( void )
{
char * tmp ;
tmp = sysfs_get_cpuidle_driver ( ) ;
if ( ! tmp ) {
printf ( _ ( " Could not determine cpuidle driver \n " ) ) ;
return ;
}
printf ( _ ( " CPUidle driver: %s \n " ) , tmp ) ;
2011-04-19 20:33:50 +02:00
free ( tmp ) ;
2011-03-30 16:30:11 +02:00
tmp = sysfs_get_cpuidle_governor ( ) ;
if ( ! tmp ) {
printf ( _ ( " Could not determine cpuidle governor \n " ) ) ;
return ;
}
printf ( _ ( " CPUidle governor: %s \n " ) , tmp ) ;
2011-04-19 20:33:50 +02:00
free ( tmp ) ;
2011-03-30 16:30:11 +02:00
}
static void proc_cpuidle_cpu_output ( unsigned int cpu )
{
long max_allowed_cstate = 2000000000 ;
2013-06-28 15:34:29 +02:00
unsigned int cstate , cstates ;
2011-03-30 16:30:11 +02:00
cstates = sysfs_get_idlestate_count ( cpu ) ;
if ( cstates = = 0 ) {
2013-06-28 15:34:29 +02:00
printf ( _ ( " CPU %u: No C-states info \n " ) , cpu ) ;
2011-03-30 16:30:11 +02:00
return ;
}
printf ( _ ( " active state: C0 \n " ) ) ;
printf ( _ ( " max_cstate: C%u \n " ) , cstates - 1 ) ;
printf ( _ ( " maximum allowed latency: %lu usec \n " ) , max_allowed_cstate ) ;
printf ( _ ( " states: \t \n " ) ) ;
for ( cstate = 1 ; cstate < cstates ; cstate + + ) {
printf ( _ ( " C%d: "
" type[C%d] " ) , cstate , cstate ) ;
printf ( _ ( " promotion[--] demotion[--] " ) ) ;
printf ( _ ( " latency[%03lu] " ) ,
sysfs_get_idlestate_latency ( cpu , cstate ) ) ;
printf ( _ ( " usage[%08lu] " ) ,
sysfs_get_idlestate_usage ( cpu , cstate ) ) ;
printf ( _ ( " duration[%020Lu] \n " ) ,
sysfs_get_idlestate_time ( cpu , cstate ) ) ;
}
}
static struct option info_opts [ ] = {
2015-10-23 09:52:45 +02:00
{ " silent " , no_argument , NULL , ' s ' } ,
{ " proc " , no_argument , NULL , ' o ' } ,
2011-03-30 16:30:11 +02:00
{ } ,
} ;
static inline void cpuidle_exit ( int fail )
{
exit ( EXIT_FAILURE ) ;
}
int cmd_idle_info ( int argc , char * * argv )
{
extern char * optarg ;
extern int optind , opterr , optopt ;
int ret = 0 , cont = 1 , output_param = 0 , verbose = 1 ;
unsigned int cpu = 0 ;
do {
2011-08-06 18:11:43 +02:00
ret = getopt_long ( argc , argv , " os " , info_opts , NULL ) ;
2011-03-30 16:30:11 +02:00
if ( ret = = - 1 )
break ;
switch ( ret ) {
case ' ? ' :
output_param = ' ? ' ;
cont = 0 ;
break ;
case ' s ' :
verbose = 0 ;
break ;
case - 1 :
cont = 0 ;
break ;
case ' o ' :
if ( output_param ) {
output_param = - 1 ;
cont = 0 ;
break ;
}
output_param = ret ;
break ;
}
2011-04-19 20:33:50 +02:00
} while ( cont ) ;
2011-03-30 16:30:11 +02:00
switch ( output_param ) {
case - 1 :
printf ( _ ( " You can't specify more than one "
" output-specific argument \n " ) ) ;
cpuidle_exit ( EXIT_FAILURE ) ;
case ' ? ' :
printf ( _ ( " invalid or unknown argument \n " ) ) ;
cpuidle_exit ( EXIT_FAILURE ) ;
}
/* Default is: show output of CPU 0 only */
if ( bitmask_isallclear ( cpus_chosen ) )
bitmask_setbit ( cpus_chosen , 0 ) ;
2011-04-19 20:33:50 +02:00
2011-03-30 16:30:11 +02:00
if ( output_param = = 0 )
cpuidle_general_output ( ) ;
2011-04-19 20:33:50 +02:00
2011-03-30 16:30:11 +02:00
for ( cpu = bitmask_first ( cpus_chosen ) ;
cpu < = bitmask_last ( cpus_chosen ) ; cpu + + ) {
if ( ! bitmask_isbitset ( cpus_chosen , cpu ) | |
cpufreq_cpu_exists ( cpu ) )
continue ;
switch ( output_param ) {
case ' o ' :
proc_cpuidle_cpu_output ( cpu ) ;
break ;
case 0 :
printf ( " \n " ) ;
cpuidle_cpu_output ( cpu , verbose ) ;
break ;
}
}
2011-04-19 20:33:50 +02:00
return EXIT_SUCCESS ;
2011-03-30 16:30:11 +02:00
}