@@ -52,7 +52,7 @@ struct acpi_power_resource {
52
52
u32 system_level ;
53
53
u32 order ;
54
54
unsigned int ref_count ;
55
- unsigned int users ;
55
+ u8 state ;
56
56
bool wakeup_enabled ;
57
57
struct mutex resource_lock ;
58
58
struct list_head dependents ;
@@ -173,53 +173,61 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
173
173
err = acpi_power_resources_list_add (rhandle , list );
174
174
if (err )
175
175
break ;
176
-
177
- to_power_resource (rdev )-> users ++ ;
178
176
}
179
177
if (err )
180
178
acpi_power_resources_list_free (list );
181
179
182
180
return err ;
183
181
}
184
182
185
- static int acpi_power_get_state (acpi_handle handle , int * state )
183
+ static int __get_state (acpi_handle handle , u8 * state )
186
184
{
187
185
acpi_status status = AE_OK ;
188
186
unsigned long long sta = 0 ;
189
-
190
- if (!handle || !state )
191
- return - EINVAL ;
187
+ u8 cur_state ;
192
188
193
189
status = acpi_evaluate_integer (handle , "_STA" , NULL , & sta );
194
190
if (ACPI_FAILURE (status ))
195
191
return - ENODEV ;
196
192
197
- * state = (sta & 0x01 )?ACPI_POWER_RESOURCE_STATE_ON :
198
- ACPI_POWER_RESOURCE_STATE_OFF ;
193
+ cur_state = sta & ACPI_POWER_RESOURCE_STATE_ON ;
199
194
200
195
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 ;
202
206
207
+ ret = __get_state (resource -> device .handle , & resource -> state );
208
+ if (ret )
209
+ return ret ;
210
+ }
211
+
212
+ * state = resource -> state ;
203
213
return 0 ;
204
214
}
205
215
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 )
207
217
{
208
218
struct acpi_power_resource_entry * entry ;
209
- int cur_state ;
219
+ u8 cur_state = ACPI_POWER_RESOURCE_STATE_OFF ;
210
220
211
221
if (!list || !state )
212
222
return - EINVAL ;
213
223
214
224
/* The state of the list is 'on' IFF all resources are 'on'. */
215
- cur_state = 0 ;
216
225
list_for_each_entry (entry , list , node ) {
217
226
struct acpi_power_resource * resource = entry -> resource ;
218
- acpi_handle handle = resource -> device .handle ;
219
227
int result ;
220
228
221
229
mutex_lock (& resource -> resource_lock );
222
- result = acpi_power_get_state (handle , & cur_state );
230
+ result = acpi_power_get_state (resource , & cur_state );
223
231
mutex_unlock (& resource -> resource_lock );
224
232
if (result )
225
233
return result ;
@@ -352,8 +360,12 @@ static int __acpi_power_on(struct acpi_power_resource *resource)
352
360
acpi_status status = AE_OK ;
353
361
354
362
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 ;
356
365
return - ENODEV ;
366
+ }
367
+
368
+ resource -> state = ACPI_POWER_RESOURCE_STATE_ON ;
357
369
358
370
pr_debug ("Power resource [%s] turned on\n" , resource -> name );
359
371
@@ -405,8 +417,12 @@ static int __acpi_power_off(struct acpi_power_resource *resource)
405
417
406
418
status = acpi_evaluate_object (resource -> device .handle , "_OFF" ,
407
419
NULL , NULL );
408
- if (ACPI_FAILURE (status ))
420
+ if (ACPI_FAILURE (status )) {
421
+ resource -> state = ACPI_POWER_RESOURCE_STATE_UNKNOWN ;
409
422
return - ENODEV ;
423
+ }
424
+
425
+ resource -> state = ACPI_POWER_RESOURCE_STATE_OFF ;
410
426
411
427
pr_debug ("Power resource [%s] turned off\n" , resource -> name );
412
428
@@ -590,13 +606,12 @@ int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
590
606
591
607
list_for_each_entry (entry , list , node ) {
592
608
struct acpi_power_resource * resource = entry -> resource ;
593
- acpi_handle handle = resource -> device .handle ;
594
609
int result ;
595
- int state ;
610
+ u8 state ;
596
611
597
612
mutex_lock (& resource -> resource_lock );
598
613
599
- result = acpi_power_get_state (handle , & state );
614
+ result = acpi_power_get_state (resource , & state );
600
615
if (result ) {
601
616
mutex_unlock (& resource -> resource_lock );
602
617
return result ;
@@ -789,8 +804,8 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
789
804
790
805
int acpi_power_get_inferred_state (struct acpi_device * device , int * state )
791
806
{
807
+ u8 list_state = ACPI_POWER_RESOURCE_STATE_OFF ;
792
808
int result = 0 ;
793
- int list_state = 0 ;
794
809
int i = 0 ;
795
810
796
811
if (!device || !state )
@@ -919,7 +934,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
919
934
union acpi_object acpi_object ;
920
935
struct acpi_buffer buffer = { sizeof (acpi_object ), & acpi_object };
921
936
acpi_status status ;
922
- int state , result = - ENODEV ;
937
+ int result ;
923
938
924
939
acpi_bus_get_device (handle , & device );
925
940
if (device )
@@ -946,13 +961,9 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
946
961
947
962
resource -> system_level = acpi_object .power_resource .system_level ;
948
963
resource -> order = acpi_object .power_resource .resource_order ;
964
+ resource -> state = ACPI_POWER_RESOURCE_STATE_UNKNOWN ;
949
965
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 ));
956
967
957
968
device -> flags .match_driver = true;
958
969
result = acpi_device_add (device , acpi_release_power_resource );
@@ -979,19 +990,21 @@ void acpi_resume_power_resources(void)
979
990
mutex_lock (& power_resource_list_lock );
980
991
981
992
list_for_each_entry (resource , & acpi_power_resource_list , list_node ) {
982
- int result , state ;
993
+ int result ;
994
+ u8 state ;
983
995
984
996
mutex_lock (& resource -> resource_lock );
985
997
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 );
987
1000
if (result ) {
988
1001
mutex_unlock (& resource -> resource_lock );
989
1002
continue ;
990
1003
}
991
1004
992
1005
if (state == ACPI_POWER_RESOURCE_STATE_OFF
993
1006
&& resource -> ref_count ) {
994
- dev_info (& resource -> device .dev , "Turning ON\n" );
1007
+ dev_dbg (& resource -> device .dev , "Turning ON\n" );
995
1008
__acpi_power_on (resource );
996
1009
}
997
1010
@@ -1002,38 +1015,10 @@ void acpi_resume_power_resources(void)
1002
1015
}
1003
1016
#endif
1004
1017
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
-
1026
1018
/**
1027
1019
* 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".
1035
1020
*/
1036
- void acpi_turn_off_unused_power_resources (bool init )
1021
+ void acpi_turn_off_unused_power_resources (void )
1037
1022
{
1038
1023
struct acpi_power_resource * resource ;
1039
1024
@@ -1042,7 +1027,16 @@ void acpi_turn_off_unused_power_resources(bool init)
1042
1027
list_for_each_entry_reverse (resource , & acpi_power_resource_list , list_node ) {
1043
1028
mutex_lock (& resource -> resource_lock );
1044
1029
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
+ }
1046
1040
1047
1041
mutex_unlock (& resource -> resource_lock );
1048
1042
}
0 commit comments