@@ -52,7 +52,7 @@ struct acpi_power_resource {
5252 u32 system_level ;
5353 u32 order ;
5454 unsigned int ref_count ;
55- unsigned int users ;
55+ u8 state ;
5656 bool wakeup_enabled ;
5757 struct mutex resource_lock ;
5858 struct list_head dependents ;
@@ -173,53 +173,61 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
173173 err = acpi_power_resources_list_add (rhandle , list );
174174 if (err )
175175 break ;
176-
177- to_power_resource (rdev )-> users ++ ;
178176 }
179177 if (err )
180178 acpi_power_resources_list_free (list );
181179
182180 return err ;
183181}
184182
185- static int acpi_power_get_state (acpi_handle handle , int * state )
183+ static int __get_state (acpi_handle handle , u8 * state )
186184{
187185 acpi_status status = AE_OK ;
188186 unsigned long long sta = 0 ;
189-
190- if (!handle || !state )
191- return - EINVAL ;
187+ u8 cur_state ;
192188
193189 status = acpi_evaluate_integer (handle , "_STA" , NULL , & sta );
194190 if (ACPI_FAILURE (status ))
195191 return - ENODEV ;
196192
197- * state = (sta & 0x01 )?ACPI_POWER_RESOURCE_STATE_ON :
198- ACPI_POWER_RESOURCE_STATE_OFF ;
193+ cur_state = sta & ACPI_POWER_RESOURCE_STATE_ON ;
199194
200195 acpi_handle_debug (handle , "Power resource is %s\n" ,
201- * state ? "on" : "off" );
196+ cur_state ? "on" : "off" );
197+
198+ * state = cur_state ;
199+ return 0 ;
200+ }
201+
202+ static int acpi_power_get_state (struct acpi_power_resource * resource , u8 * state )
203+ {
204+ if (resource -> state == ACPI_POWER_RESOURCE_STATE_UNKNOWN ) {
205+ int ret ;
202206
207+ ret = __get_state (resource -> device .handle , & resource -> state );
208+ if (ret )
209+ return ret ;
210+ }
211+
212+ * state = resource -> state ;
203213 return 0 ;
204214}
205215
206- static int acpi_power_get_list_state (struct list_head * list , int * state )
216+ static int acpi_power_get_list_state (struct list_head * list , u8 * state )
207217{
208218 struct acpi_power_resource_entry * entry ;
209- int cur_state ;
219+ u8 cur_state = ACPI_POWER_RESOURCE_STATE_OFF ;
210220
211221 if (!list || !state )
212222 return - EINVAL ;
213223
214224 /* The state of the list is 'on' IFF all resources are 'on'. */
215- cur_state = 0 ;
216225 list_for_each_entry (entry , list , node ) {
217226 struct acpi_power_resource * resource = entry -> resource ;
218- acpi_handle handle = resource -> device .handle ;
219227 int result ;
220228
221229 mutex_lock (& resource -> resource_lock );
222- result = acpi_power_get_state (handle , & cur_state );
230+ result = acpi_power_get_state (resource , & cur_state );
223231 mutex_unlock (& resource -> resource_lock );
224232 if (result )
225233 return result ;
@@ -352,8 +360,12 @@ static int __acpi_power_on(struct acpi_power_resource *resource)
352360 acpi_status status = AE_OK ;
353361
354362 status = acpi_evaluate_object (resource -> device .handle , "_ON" , NULL , NULL );
355- if (ACPI_FAILURE (status ))
363+ if (ACPI_FAILURE (status )) {
364+ resource -> state = ACPI_POWER_RESOURCE_STATE_UNKNOWN ;
356365 return - ENODEV ;
366+ }
367+
368+ resource -> state = ACPI_POWER_RESOURCE_STATE_ON ;
357369
358370 pr_debug ("Power resource [%s] turned on\n" , resource -> name );
359371
@@ -405,8 +417,12 @@ static int __acpi_power_off(struct acpi_power_resource *resource)
405417
406418 status = acpi_evaluate_object (resource -> device .handle , "_OFF" ,
407419 NULL , NULL );
408- if (ACPI_FAILURE (status ))
420+ if (ACPI_FAILURE (status )) {
421+ resource -> state = ACPI_POWER_RESOURCE_STATE_UNKNOWN ;
409422 return - ENODEV ;
423+ }
424+
425+ resource -> state = ACPI_POWER_RESOURCE_STATE_OFF ;
410426
411427 pr_debug ("Power resource [%s] turned off\n" , resource -> name );
412428
@@ -590,13 +606,12 @@ int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
590606
591607 list_for_each_entry (entry , list , node ) {
592608 struct acpi_power_resource * resource = entry -> resource ;
593- acpi_handle handle = resource -> device .handle ;
594609 int result ;
595- int state ;
610+ u8 state ;
596611
597612 mutex_lock (& resource -> resource_lock );
598613
599- result = acpi_power_get_state (handle , & state );
614+ result = acpi_power_get_state (resource , & state );
600615 if (result ) {
601616 mutex_unlock (& resource -> resource_lock );
602617 return result ;
@@ -789,8 +804,8 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
789804
790805int acpi_power_get_inferred_state (struct acpi_device * device , int * state )
791806{
807+ u8 list_state = ACPI_POWER_RESOURCE_STATE_OFF ;
792808 int result = 0 ;
793- int list_state = 0 ;
794809 int i = 0 ;
795810
796811 if (!device || !state )
@@ -919,7 +934,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
919934 union acpi_object acpi_object ;
920935 struct acpi_buffer buffer = { sizeof (acpi_object ), & acpi_object };
921936 acpi_status status ;
922- int state , result = - ENODEV ;
937+ int result ;
923938
924939 acpi_bus_get_device (handle , & device );
925940 if (device )
@@ -946,13 +961,9 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
946961
947962 resource -> system_level = acpi_object .power_resource .system_level ;
948963 resource -> order = acpi_object .power_resource .resource_order ;
964+ resource -> state = ACPI_POWER_RESOURCE_STATE_UNKNOWN ;
949965
950- result = acpi_power_get_state (handle , & state );
951- if (result )
952- goto err ;
953-
954- pr_info ("%s [%s] (%s)\n" , acpi_device_name (device ),
955- acpi_device_bid (device ), state ? "on" : "off" );
966+ pr_info ("%s [%s]\n" , acpi_device_name (device ), acpi_device_bid (device ));
956967
957968 device -> flags .match_driver = true;
958969 result = acpi_device_add (device , acpi_release_power_resource );
@@ -979,19 +990,21 @@ void acpi_resume_power_resources(void)
979990 mutex_lock (& power_resource_list_lock );
980991
981992 list_for_each_entry (resource , & acpi_power_resource_list , list_node ) {
982- int result , state ;
993+ int result ;
994+ u8 state ;
983995
984996 mutex_lock (& resource -> resource_lock );
985997
986- result = acpi_power_get_state (resource -> device .handle , & state );
998+ resource -> state = ACPI_POWER_RESOURCE_STATE_UNKNOWN ;
999+ result = acpi_power_get_state (resource , & state );
9871000 if (result ) {
9881001 mutex_unlock (& resource -> resource_lock );
9891002 continue ;
9901003 }
9911004
9921005 if (state == ACPI_POWER_RESOURCE_STATE_OFF
9931006 && resource -> ref_count ) {
994- dev_info (& resource -> device .dev , "Turning ON\n" );
1007+ dev_dbg (& resource -> device .dev , "Turning ON\n" );
9951008 __acpi_power_on (resource );
9961009 }
9971010
@@ -1002,38 +1015,10 @@ void acpi_resume_power_resources(void)
10021015}
10031016#endif
10041017
1005- static void acpi_power_turn_off_if_unused (struct acpi_power_resource * resource ,
1006- bool init )
1007- {
1008- if (resource -> ref_count > 0 )
1009- return ;
1010-
1011- if (init ) {
1012- if (resource -> users > 0 )
1013- return ;
1014- } else {
1015- int result , state ;
1016-
1017- result = acpi_power_get_state (resource -> device .handle , & state );
1018- if (result || state == ACPI_POWER_RESOURCE_STATE_OFF )
1019- return ;
1020- }
1021-
1022- dev_info (& resource -> device .dev , "Turning OFF\n" );
1023- __acpi_power_off (resource );
1024- }
1025-
10261018/**
10271019 * acpi_turn_off_unused_power_resources - Turn off power resources not in use.
1028- * @init: Control switch.
1029- *
1030- * If @ainit is set, unconditionally turn off all of the ACPI power resources
1031- * without any users.
1032- *
1033- * Otherwise, turn off all ACPI power resources without active references (that
1034- * is, the ones that should be "off" at the moment) that are "on".
10351020 */
1036- void acpi_turn_off_unused_power_resources (bool init )
1021+ void acpi_turn_off_unused_power_resources (void )
10371022{
10381023 struct acpi_power_resource * resource ;
10391024
@@ -1042,7 +1027,16 @@ void acpi_turn_off_unused_power_resources(bool init)
10421027 list_for_each_entry_reverse (resource , & acpi_power_resource_list , list_node ) {
10431028 mutex_lock (& resource -> resource_lock );
10441029
1045- acpi_power_turn_off_if_unused (resource , init );
1030+ /*
1031+ * Turn off power resources in an unknown state too, because the
1032+ * platform firmware on some system expects the OS to turn off
1033+ * power resources without any users unconditionally.
1034+ */
1035+ if (!resource -> ref_count &&
1036+ resource -> state != ACPI_POWER_RESOURCE_STATE_OFF ) {
1037+ dev_dbg (& resource -> device .dev , "Turning OFF\n" );
1038+ __acpi_power_off (resource );
1039+ }
10461040
10471041 mutex_unlock (& resource -> resource_lock );
10481042 }
0 commit comments