aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
authorAlexey Starikovskiy <astarikovskiy@suse.de>2007-10-22 06:19:09 -0400
committerLen Brown <len.brown@intel.com>2007-10-25 16:31:31 -0400
commitc35923bc558074d4f5e6f9706e4cb9811ae55775 (patch)
tree562d2a16fac0bf72b5126f9d79e6d1765038692f /drivers/acpi/power.c
parent95b937e3f52a7f5546c4bffe29886fe400bad1d1 (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/acpi/power.c')
-rw-r--r--drivers/acpi/power.c63
1 files changed, 24 insertions, 39 deletions
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
131static int acpi_power_get_state(struct acpi_power_resource *resource) 130static 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
155static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) 152static 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
187static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) 184static 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
251static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) 242static 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;
494static int acpi_power_seq_show(struct seq_file *seq, void *offset) 479static 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
592static int acpi_power_add(struct acpi_device *device) 577static 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
681static int acpi_power_resume(struct acpi_device *device) 666static 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);