diff options
author | Alexey Starikovskiy <astarikovskiy@suse.de> | 2007-10-22 06:19:09 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-10-25 16:31:31 -0400 |
commit | c35923bc558074d4f5e6f9706e4cb9811ae55775 (patch) | |
tree | 562d2a16fac0bf72b5126f9d79e6d1765038692f /drivers | |
parent | 95b937e3f52a7f5546c4bffe29886fe400bad1d1 (diff) |
ACPI: power: don't cache power resource state
ACPI may change power resource state behind our back, so don't
keep our local copy, which may not be valid.
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/bus.c | 6 | ||||
-rw-r--r-- | drivers/acpi/power.c | 63 |
2 files changed, 26 insertions, 43 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index fb2cff9a2d24..fdee82d37b7d 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -198,11 +198,9 @@ int acpi_bus_set_power(acpi_handle handle, int state) | |||
198 | return -ENODEV; | 198 | return -ENODEV; |
199 | } | 199 | } |
200 | /* | 200 | /* |
201 | * Get device's current power state if it's unknown | 201 | * Get device's current power state |
202 | * This means device power state isn't initialized or previous setting failed | ||
203 | */ | 202 | */ |
204 | if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state) | 203 | acpi_bus_get_power(device->handle, &device->power.state); |
205 | acpi_bus_get_power(device->handle, &device->power.state); | ||
206 | if ((state == device->power.state) && !device->flags.force_power_state) { | 204 | if ((state == device->power.state) && !device->flags.force_power_state) { |
207 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", | 205 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", |
208 | state)); | 206 | state)); |
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 57b9a2998fd0..af1769a20c7a 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -86,7 +86,6 @@ struct acpi_power_resource { | |||
86 | acpi_bus_id name; | 86 | acpi_bus_id name; |
87 | u32 system_level; | 87 | u32 system_level; |
88 | u32 order; | 88 | u32 order; |
89 | int state; | ||
90 | struct mutex resource_lock; | 89 | struct mutex resource_lock; |
91 | struct list_head reference; | 90 | struct list_head reference; |
92 | }; | 91 | }; |
@@ -128,33 +127,31 @@ acpi_power_get_context(acpi_handle handle, | |||
128 | return 0; | 127 | return 0; |
129 | } | 128 | } |
130 | 129 | ||
131 | static int acpi_power_get_state(struct acpi_power_resource *resource) | 130 | static int acpi_power_get_state(struct acpi_power_resource *resource, int *state) |
132 | { | 131 | { |
133 | acpi_status status = AE_OK; | 132 | acpi_status status = AE_OK; |
134 | unsigned long sta = 0; | 133 | unsigned long sta = 0; |
135 | 134 | ||
136 | 135 | ||
137 | if (!resource) | 136 | if (!resource || !state) |
138 | return -EINVAL; | 137 | return -EINVAL; |
139 | 138 | ||
140 | status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta); | 139 | status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta); |
141 | if (ACPI_FAILURE(status)) | 140 | if (ACPI_FAILURE(status)) |
142 | return -ENODEV; | 141 | return -ENODEV; |
143 | 142 | ||
144 | if (sta & 0x01) | 143 | *state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON: |
145 | resource->state = ACPI_POWER_RESOURCE_STATE_ON; | 144 | ACPI_POWER_RESOURCE_STATE_OFF; |
146 | else | ||
147 | resource->state = ACPI_POWER_RESOURCE_STATE_OFF; | ||
148 | 145 | ||
149 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", | 146 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", |
150 | resource->name, resource->state ? "on" : "off")); | 147 | resource->name, state ? "on" : "off")); |
151 | 148 | ||
152 | return 0; | 149 | return 0; |
153 | } | 150 | } |
154 | 151 | ||
155 | static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | 152 | static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) |
156 | { | 153 | { |
157 | int result = 0; | 154 | int result = 0, state1; |
158 | struct acpi_power_resource *resource = NULL; | 155 | struct acpi_power_resource *resource = NULL; |
159 | u32 i = 0; | 156 | u32 i = 0; |
160 | 157 | ||
@@ -168,11 +165,11 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | |||
168 | result = acpi_power_get_context(list->handles[i], &resource); | 165 | result = acpi_power_get_context(list->handles[i], &resource); |
169 | if (result) | 166 | if (result) |
170 | return result; | 167 | return result; |
171 | result = acpi_power_get_state(resource); | 168 | result = acpi_power_get_state(resource, &state1); |
172 | if (result) | 169 | if (result) |
173 | return result; | 170 | return result; |
174 | 171 | ||
175 | *state = resource->state; | 172 | *state = state1; |
176 | 173 | ||
177 | if (*state != ACPI_POWER_RESOURCE_STATE_ON) | 174 | if (*state != ACPI_POWER_RESOURCE_STATE_ON) |
178 | break; | 175 | break; |
@@ -186,7 +183,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) | |||
186 | 183 | ||
187 | static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | 184 | static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) |
188 | { | 185 | { |
189 | int result = 0; | 186 | int result = 0, state; |
190 | int found = 0; | 187 | int found = 0; |
191 | acpi_status status = AE_OK; | 188 | acpi_status status = AE_OK; |
192 | struct acpi_power_resource *resource = NULL; | 189 | struct acpi_power_resource *resource = NULL; |
@@ -224,20 +221,14 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | |||
224 | } | 221 | } |
225 | mutex_unlock(&resource->resource_lock); | 222 | mutex_unlock(&resource->resource_lock); |
226 | 223 | ||
227 | if (resource->state == ACPI_POWER_RESOURCE_STATE_ON) { | ||
228 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n", | ||
229 | resource->name)); | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); | 224 | status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); |
234 | if (ACPI_FAILURE(status)) | 225 | if (ACPI_FAILURE(status)) |
235 | return -ENODEV; | 226 | return -ENODEV; |
236 | 227 | ||
237 | result = acpi_power_get_state(resource); | 228 | result = acpi_power_get_state(resource, &state); |
238 | if (result) | 229 | if (result) |
239 | return result; | 230 | return result; |
240 | if (resource->state != ACPI_POWER_RESOURCE_STATE_ON) | 231 | if (state != ACPI_POWER_RESOURCE_STATE_ON) |
241 | return -ENOEXEC; | 232 | return -ENOEXEC; |
242 | 233 | ||
243 | /* Update the power resource's _device_ power state */ | 234 | /* Update the power resource's _device_ power state */ |
@@ -250,7 +241,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) | |||
250 | 241 | ||
251 | static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | 242 | static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) |
252 | { | 243 | { |
253 | int result = 0; | 244 | int result = 0, state; |
254 | acpi_status status = AE_OK; | 245 | acpi_status status = AE_OK; |
255 | struct acpi_power_resource *resource = NULL; | 246 | struct acpi_power_resource *resource = NULL; |
256 | struct list_head *node, *next; | 247 | struct list_head *node, *next; |
@@ -281,20 +272,14 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | |||
281 | } | 272 | } |
282 | mutex_unlock(&resource->resource_lock); | 273 | mutex_unlock(&resource->resource_lock); |
283 | 274 | ||
284 | if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) { | ||
285 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n", | ||
286 | resource->name)); | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL); | 275 | status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL); |
291 | if (ACPI_FAILURE(status)) | 276 | if (ACPI_FAILURE(status)) |
292 | return -ENODEV; | 277 | return -ENODEV; |
293 | 278 | ||
294 | result = acpi_power_get_state(resource); | 279 | result = acpi_power_get_state(resource, &state); |
295 | if (result) | 280 | if (result) |
296 | return result; | 281 | return result; |
297 | if (resource->state != ACPI_POWER_RESOURCE_STATE_OFF) | 282 | if (state != ACPI_POWER_RESOURCE_STATE_OFF) |
298 | return -ENOEXEC; | 283 | return -ENOEXEC; |
299 | 284 | ||
300 | /* Update the power resource's _device_ power state */ | 285 | /* Update the power resource's _device_ power state */ |
@@ -494,7 +479,7 @@ static struct proc_dir_entry *acpi_power_dir; | |||
494 | static int acpi_power_seq_show(struct seq_file *seq, void *offset) | 479 | static int acpi_power_seq_show(struct seq_file *seq, void *offset) |
495 | { | 480 | { |
496 | int count = 0; | 481 | int count = 0; |
497 | int result = 0; | 482 | int result = 0, state; |
498 | struct acpi_power_resource *resource = NULL; | 483 | struct acpi_power_resource *resource = NULL; |
499 | struct list_head *node, *next; | 484 | struct list_head *node, *next; |
500 | struct acpi_power_reference *ref; | 485 | struct acpi_power_reference *ref; |
@@ -505,12 +490,12 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset) | |||
505 | if (!resource) | 490 | if (!resource) |
506 | goto end; | 491 | goto end; |
507 | 492 | ||
508 | result = acpi_power_get_state(resource); | 493 | result = acpi_power_get_state(resource, &state); |
509 | if (result) | 494 | if (result) |
510 | goto end; | 495 | goto end; |
511 | 496 | ||
512 | seq_puts(seq, "state: "); | 497 | seq_puts(seq, "state: "); |
513 | switch (resource->state) { | 498 | switch (state) { |
514 | case ACPI_POWER_RESOURCE_STATE_ON: | 499 | case ACPI_POWER_RESOURCE_STATE_ON: |
515 | seq_puts(seq, "on\n"); | 500 | seq_puts(seq, "on\n"); |
516 | break; | 501 | break; |
@@ -591,7 +576,7 @@ static int acpi_power_remove_fs(struct acpi_device *device) | |||
591 | 576 | ||
592 | static int acpi_power_add(struct acpi_device *device) | 577 | static int acpi_power_add(struct acpi_device *device) |
593 | { | 578 | { |
594 | int result = 0; | 579 | int result = 0, state; |
595 | acpi_status status = AE_OK; | 580 | acpi_status status = AE_OK; |
596 | struct acpi_power_resource *resource = NULL; | 581 | struct acpi_power_resource *resource = NULL; |
597 | union acpi_object acpi_object; | 582 | union acpi_object acpi_object; |
@@ -622,11 +607,11 @@ static int acpi_power_add(struct acpi_device *device) | |||
622 | resource->system_level = acpi_object.power_resource.system_level; | 607 | resource->system_level = acpi_object.power_resource.system_level; |
623 | resource->order = acpi_object.power_resource.resource_order; | 608 | resource->order = acpi_object.power_resource.resource_order; |
624 | 609 | ||
625 | result = acpi_power_get_state(resource); | 610 | result = acpi_power_get_state(resource, &state); |
626 | if (result) | 611 | if (result) |
627 | goto end; | 612 | goto end; |
628 | 613 | ||
629 | switch (resource->state) { | 614 | switch (state) { |
630 | case ACPI_POWER_RESOURCE_STATE_ON: | 615 | case ACPI_POWER_RESOURCE_STATE_ON: |
631 | device->power.state = ACPI_STATE_D0; | 616 | device->power.state = ACPI_STATE_D0; |
632 | break; | 617 | break; |
@@ -643,7 +628,7 @@ static int acpi_power_add(struct acpi_device *device) | |||
643 | goto end; | 628 | goto end; |
644 | 629 | ||
645 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), | 630 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), |
646 | acpi_device_bid(device), resource->state ? "on" : "off"); | 631 | acpi_device_bid(device), state ? "on" : "off"); |
647 | 632 | ||
648 | end: | 633 | end: |
649 | if (result) | 634 | if (result) |
@@ -680,7 +665,7 @@ static int acpi_power_remove(struct acpi_device *device, int type) | |||
680 | 665 | ||
681 | static int acpi_power_resume(struct acpi_device *device) | 666 | static int acpi_power_resume(struct acpi_device *device) |
682 | { | 667 | { |
683 | int result = 0; | 668 | int result = 0, state; |
684 | struct acpi_power_resource *resource = NULL; | 669 | struct acpi_power_resource *resource = NULL; |
685 | struct acpi_power_reference *ref; | 670 | struct acpi_power_reference *ref; |
686 | 671 | ||
@@ -689,12 +674,12 @@ static int acpi_power_resume(struct acpi_device *device) | |||
689 | 674 | ||
690 | resource = (struct acpi_power_resource *)acpi_driver_data(device); | 675 | resource = (struct acpi_power_resource *)acpi_driver_data(device); |
691 | 676 | ||
692 | result = acpi_power_get_state(resource); | 677 | result = acpi_power_get_state(resource, &state); |
693 | if (result) | 678 | if (result) |
694 | return result; | 679 | return result; |
695 | 680 | ||
696 | mutex_lock(&resource->resource_lock); | 681 | mutex_lock(&resource->resource_lock); |
697 | if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) && | 682 | if (state == ACPI_POWER_RESOURCE_STATE_OFF && |
698 | !list_empty(&resource->reference)) { | 683 | !list_empty(&resource->reference)) { |
699 | ref = container_of(resource->reference.next, struct acpi_power_reference, node); | 684 | ref = container_of(resource->reference.next, struct acpi_power_reference, node); |
700 | mutex_unlock(&resource->resource_lock); | 685 | mutex_unlock(&resource->resource_lock); |