@ -182,41 +182,66 @@ EXPORT_SYMBOL(acpi_bus_get_private_data);
Power Management
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static const char * state_string ( int state )
{
switch ( state ) {
case ACPI_STATE_D0 :
return " D0 " ;
case ACPI_STATE_D1 :
return " D1 " ;
case ACPI_STATE_D2 :
return " D2 " ;
case ACPI_STATE_D3_HOT :
return " D3hot " ;
case ACPI_STATE_D3_COLD :
return " D3 " ;
default :
return " (unknown) " ;
}
}
static int __acpi_bus_get_power ( struct acpi_device * device , int * state )
{
int result = 0 ;
acpi_status status = 0 ;
unsigned long long psc = 0 ;
int result = ACPI_STATE_UNKNOWN ;
if ( ! device | | ! state )
return - EINVAL ;
* state = ACPI_STATE_UNKNOWN ;
if ( device - > flags . power_manageable ) {
/*
* Get the device ' s power state either directly ( via _PSC ) or
* indirectly ( via power resources ) .
*/
if ( device - > power . flags . power_resources ) {
result = acpi_power_get_inferred_state ( device , state ) ;
if ( result )
return result ;
} else if ( device - > power . flags . explicit_get ) {
status = acpi_evaluate_integer ( device - > handle , " _PSC " ,
NULL , & psc ) ;
if ( ACPI_FAILURE ( status ) )
return - ENODEV ;
* state = ( int ) psc ;
}
} else {
if ( ! device - > flags . power_manageable ) {
/* TBD: Non-recursive algorithm for walking up hierarchy. */
* state = device - > parent ?
device - > parent - > power . state : ACPI_STATE_D0 ;
goto out ;
}
/*
* Get the device ' s power state either directly ( via _PSC ) or
* indirectly ( via power resources ) .
*/
if ( device - > power . flags . explicit_get ) {
unsigned long long psc ;
acpi_status status = acpi_evaluate_integer ( device - > handle ,
" _PSC " , NULL , & psc ) ;
if ( ACPI_FAILURE ( status ) )
return - ENODEV ;
result = psc ;
}
/* The test below covers ACPI_STATE_UNKNOWN too. */
if ( result < = ACPI_STATE_D2 ) {
; /* Do nothing. */
} else if ( device - > power . flags . power_resources ) {
int error = acpi_power_get_inferred_state ( device , & result ) ;
if ( error )
return error ;
} else if ( result = = ACPI_STATE_D3_HOT ) {
result = ACPI_STATE_D3 ;
}
* state = result ;
ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO , " Device [%s] power state is D%d \n " ,
device - > pnp . bus_id , * state ) ) ;
out :
ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO , " Device [%s] power state is %s \n " ,
device - > pnp . bus_id , state_string ( * state ) ) ) ;
return 0 ;
}
@ -234,13 +259,14 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state)
/* Make sure this is a valid target state */
if ( state = = device - > power . state ) {
ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO , " Device is already at D%d \n " ,
state ) ) ;
ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO , " Device is already at %s \n " ,
state_string ( state ) ) ) ;
return 0 ;
}
if ( ! device - > power . states [ state ] . flags . valid ) {
printk ( KERN_WARNING PREFIX " Device does not support D%d \n " , state ) ;
printk ( KERN_WARNING PREFIX " Device does not support %s \n " ,
state_string ( state ) ) ;
return - ENODEV ;
}
if ( device - > parent & & ( state < device - > parent - > power . state ) ) {
@ -294,13 +320,13 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state)
end :
if ( result )
printk ( KERN_WARNING PREFIX
" Device [%s] failed to transition to D%d \n " ,
device - > pnp . bus_id , state ) ;
" Device [%s] failed to transition to %s \n " ,
device - > pnp . bus_id , state_string ( state ) ) ;
else {
device - > power . state = state ;
ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO ,
" Device [%s] transitioned to D%d \n " ,
device - > pnp . bus_id , state ) ) ;
" Device [%s] transitioned to %s \n " ,
device - > pnp . bus_id , state_string ( state ) ) ) ;
}
return result ;