@ -65,7 +65,7 @@
# include <asm/mwait.h>
# include <asm/msr.h>
# define INTEL_IDLE_VERSION "0.4"
# define INTEL_IDLE_VERSION "0.4.1 "
# define PREFIX "intel_idle: "
static struct cpuidle_driver intel_idle_driver = {
@ -994,36 +994,92 @@ static void intel_idle_cpuidle_devices_uninit(void)
}
/*
* intel_idle_state_table_update ( )
*
* Update the default state_table for this CPU - id
* ivt_idle_state_table_update ( void )
*
* Currently used to access tuned IVT multi - socket targets
* Tune IVT multi - socket targets
* Assumption : num_sockets = = ( max_package_num + 1 )
*/
void intel _idle_state_table_update( void )
static void ivt _idle_state_table_update( void )
{
/* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
if ( boot_cpu_data . x86_model = = 0x3e ) { /* IVT */
int cpu , package_num , num_sockets = 1 ;
for_each_online_cpu ( cpu ) {
package_num = topology_physical_package_id ( cpu ) ;
if ( package_num + 1 > num_sockets ) {
num_sockets = package_num + 1 ;
if ( num_sockets > 4 ) {
cpuidle_state_table = ivt_cstates_8s ;
return ;
}
int cpu , package_num , num_sockets = 1 ;
for_each_online_cpu ( cpu ) {
package_num = topology_physical_package_id ( cpu ) ;
if ( package_num + 1 > num_sockets ) {
num_sockets = package_num + 1 ;
if ( num_sockets > 4 ) {
cpuidle_state_table = ivt_cstates_8s ;
return ;
}
}
}
if ( num_sockets > 2 )
cpuidle_state_table = ivt_cstates_4s ;
/* else, 1 and 2 socket systems use default ivt_cstates */
}
/*
* sklh_idle_state_table_update ( void )
*
* On SKL - H ( model 0x5e ) disable C8 and C9 if :
* C10 is enabled and SGX disabled
*/
static void sklh_idle_state_table_update ( void )
{
unsigned long long msr ;
unsigned int eax , ebx , ecx , edx ;
/* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */
if ( max_cstate < = 7 )
return ;
/* if PC10 not present in CPUID.MWAIT.EDX */
if ( ( mwait_substates & ( 0xF < < 28 ) ) = = 0 )
return ;
rdmsrl ( MSR_NHM_SNB_PKG_CST_CFG_CTL , msr ) ;
/* PC10 is not enabled in PKG C-state limit */
if ( ( msr & 0xF ) ! = 8 )
return ;
ecx = 0 ;
cpuid ( 7 , & eax , & ebx , & ecx , & edx ) ;
/* if SGX is present */
if ( ebx & ( 1 < < 2 ) ) {
if ( num_sockets > 2 )
cpuidle_state_table = ivt_cstates_4s ;
/* else, 1 and 2 socket systems use default ivt_cstates */
rdmsrl ( MSR_IA32_FEATURE_CONTROL , msr ) ;
/* if SGX is enabled */
if ( msr & ( 1 < < 18 ) )
return ;
}
skl_cstates [ 5 ] . disabled = 1 ; /* C8-SKL */
skl_cstates [ 6 ] . disabled = 1 ; /* C9-SKL */
}
/*
* intel_idle_state_table_update ( )
*
* Update the default state_table for this CPU - id
*/
static void intel_idle_state_table_update ( void )
{
switch ( boot_cpu_data . x86_model ) {
case 0x3e : /* IVT */
ivt_idle_state_table_update ( ) ;
break ;
case 0x5e : /* SKL-H */
sklh_idle_state_table_update ( ) ;
break ;
}
return ;
}
/*
@ -1063,6 +1119,14 @@ static int __init intel_idle_cpuidle_driver_init(void)
if ( num_substates = = 0 )
continue ;
/* if state marked as disabled, skip it */
if ( cpuidle_state_table [ cstate ] . disabled ! = 0 ) {
pr_debug ( PREFIX " state %s is disabled " ,
cpuidle_state_table [ cstate ] . name ) ;
continue ;
}
if ( ( ( mwait_cstate + 1 ) > 2 ) & &
! boot_cpu_has ( X86_FEATURE_NONSTOP_TSC ) )
mark_tsc_unstable ( " TSC halts in idle "