aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r--drivers/acpi/power.c125
1 files changed, 55 insertions, 70 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index efc4bb751286..224f729f700e 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -98,22 +98,21 @@ acpi_power_get_context(acpi_handle handle,
98 int result = 0; 98 int result = 0;
99 struct acpi_device *device = NULL; 99 struct acpi_device *device = NULL;
100 100
101 ACPI_FUNCTION_TRACE("acpi_power_get_context");
102 101
103 if (!resource) 102 if (!resource)
104 return_VALUE(-ENODEV); 103 return -ENODEV;
105 104
106 result = acpi_bus_get_device(handle, &device); 105 result = acpi_bus_get_device(handle, &device);
107 if (result) { 106 if (result) {
108 printk(KERN_WARNING PREFIX "Getting context [%p]\n", handle); 107 printk(KERN_WARNING PREFIX "Getting context [%p]\n", handle);
109 return_VALUE(result); 108 return result;
110 } 109 }
111 110
112 *resource = (struct acpi_power_resource *)acpi_driver_data(device); 111 *resource = (struct acpi_power_resource *)acpi_driver_data(device);
113 if (!resource) 112 if (!resource)
114 return_VALUE(-ENODEV); 113 return -ENODEV;
115 114
116 return_VALUE(0); 115 return 0;
117} 116}
118 117
119static int acpi_power_get_state(struct acpi_power_resource *resource) 118static int acpi_power_get_state(struct acpi_power_resource *resource)
@@ -121,14 +120,13 @@ static int acpi_power_get_state(struct acpi_power_resource *resource)
121 acpi_status status = AE_OK; 120 acpi_status status = AE_OK;
122 unsigned long sta = 0; 121 unsigned long sta = 0;
123 122
124 ACPI_FUNCTION_TRACE("acpi_power_get_state");
125 123
126 if (!resource) 124 if (!resource)
127 return_VALUE(-EINVAL); 125 return -EINVAL;
128 126
129 status = acpi_evaluate_integer(resource->handle, "_STA", NULL, &sta); 127 status = acpi_evaluate_integer(resource->handle, "_STA", NULL, &sta);
130 if (ACPI_FAILURE(status)) 128 if (ACPI_FAILURE(status))
131 return_VALUE(-ENODEV); 129 return -ENODEV;
132 130
133 if (sta & 0x01) 131 if (sta & 0x01)
134 resource->state = ACPI_POWER_RESOURCE_STATE_ON; 132 resource->state = ACPI_POWER_RESOURCE_STATE_ON;
@@ -138,7 +136,7 @@ static int acpi_power_get_state(struct acpi_power_resource *resource)
138 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", 136 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
139 resource->name, resource->state ? "on" : "off")); 137 resource->name, resource->state ? "on" : "off"));
140 138
141 return_VALUE(0); 139 return 0;
142} 140}
143 141
144static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) 142static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
@@ -147,20 +145,19 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
147 struct acpi_power_resource *resource = NULL; 145 struct acpi_power_resource *resource = NULL;
148 u32 i = 0; 146 u32 i = 0;
149 147
150 ACPI_FUNCTION_TRACE("acpi_power_get_list_state");
151 148
152 if (!list || !state) 149 if (!list || !state)
153 return_VALUE(-EINVAL); 150 return -EINVAL;
154 151
155 /* The state of the list is 'on' IFF all resources are 'on'. */ 152 /* The state of the list is 'on' IFF all resources are 'on'. */
156 153
157 for (i = 0; i < list->count; i++) { 154 for (i = 0; i < list->count; i++) {
158 result = acpi_power_get_context(list->handles[i], &resource); 155 result = acpi_power_get_context(list->handles[i], &resource);
159 if (result) 156 if (result)
160 return_VALUE(result); 157 return result;
161 result = acpi_power_get_state(resource); 158 result = acpi_power_get_state(resource);
162 if (result) 159 if (result)
163 return_VALUE(result); 160 return result;
164 161
165 *state = resource->state; 162 *state = resource->state;
166 163
@@ -171,7 +168,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
171 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n", 168 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource list is %s\n",
172 *state ? "on" : "off")); 169 *state ? "on" : "off"));
173 170
174 return_VALUE(result); 171 return result;
175} 172}
176 173
177static int acpi_power_on(acpi_handle handle) 174static int acpi_power_on(acpi_handle handle)
@@ -181,11 +178,10 @@ static int acpi_power_on(acpi_handle handle)
181 struct acpi_device *device = NULL; 178 struct acpi_device *device = NULL;
182 struct acpi_power_resource *resource = NULL; 179 struct acpi_power_resource *resource = NULL;
183 180
184 ACPI_FUNCTION_TRACE("acpi_power_on");
185 181
186 result = acpi_power_get_context(handle, &resource); 182 result = acpi_power_get_context(handle, &resource);
187 if (result) 183 if (result)
188 return_VALUE(result); 184 return result;
189 185
190 resource->references++; 186 resource->references++;
191 187
@@ -193,29 +189,29 @@ static int acpi_power_on(acpi_handle handle)
193 || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) { 189 || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) {
194 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n", 190 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n",
195 resource->name)); 191 resource->name));
196 return_VALUE(0); 192 return 0;
197 } 193 }
198 194
199 status = acpi_evaluate_object(resource->handle, "_ON", NULL, NULL); 195 status = acpi_evaluate_object(resource->handle, "_ON", NULL, NULL);
200 if (ACPI_FAILURE(status)) 196 if (ACPI_FAILURE(status))
201 return_VALUE(-ENODEV); 197 return -ENODEV;
202 198
203 result = acpi_power_get_state(resource); 199 result = acpi_power_get_state(resource);
204 if (result) 200 if (result)
205 return_VALUE(result); 201 return result;
206 if (resource->state != ACPI_POWER_RESOURCE_STATE_ON) 202 if (resource->state != ACPI_POWER_RESOURCE_STATE_ON)
207 return_VALUE(-ENOEXEC); 203 return -ENOEXEC;
208 204
209 /* Update the power resource's _device_ power state */ 205 /* Update the power resource's _device_ power state */
210 result = acpi_bus_get_device(resource->handle, &device); 206 result = acpi_bus_get_device(resource->handle, &device);
211 if (result) 207 if (result)
212 return_VALUE(result); 208 return result;
213 device->power.state = ACPI_STATE_D0; 209 device->power.state = ACPI_STATE_D0;
214 210
215 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n", 211 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
216 resource->name)); 212 resource->name));
217 213
218 return_VALUE(0); 214 return 0;
219} 215}
220 216
221static int acpi_power_off_device(acpi_handle handle) 217static int acpi_power_off_device(acpi_handle handle)
@@ -225,11 +221,10 @@ static int acpi_power_off_device(acpi_handle handle)
225 struct acpi_device *device = NULL; 221 struct acpi_device *device = NULL;
226 struct acpi_power_resource *resource = NULL; 222 struct acpi_power_resource *resource = NULL;
227 223
228 ACPI_FUNCTION_TRACE("acpi_power_off_device");
229 224
230 result = acpi_power_get_context(handle, &resource); 225 result = acpi_power_get_context(handle, &resource);
231 if (result) 226 if (result)
232 return_VALUE(result); 227 return result;
233 228
234 if (resource->references) 229 if (resource->references)
235 resource->references--; 230 resource->references--;
@@ -238,35 +233,35 @@ static int acpi_power_off_device(acpi_handle handle)
238 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 233 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
239 "Resource [%s] is still in use, dereferencing\n", 234 "Resource [%s] is still in use, dereferencing\n",
240 device->pnp.bus_id)); 235 device->pnp.bus_id));
241 return_VALUE(0); 236 return 0;
242 } 237 }
243 238
244 if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) { 239 if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
245 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n", 240 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
246 device->pnp.bus_id)); 241 device->pnp.bus_id));
247 return_VALUE(0); 242 return 0;
248 } 243 }
249 244
250 status = acpi_evaluate_object(resource->handle, "_OFF", NULL, NULL); 245 status = acpi_evaluate_object(resource->handle, "_OFF", NULL, NULL);
251 if (ACPI_FAILURE(status)) 246 if (ACPI_FAILURE(status))
252 return_VALUE(-ENODEV); 247 return -ENODEV;
253 248
254 result = acpi_power_get_state(resource); 249 result = acpi_power_get_state(resource);
255 if (result) 250 if (result)
256 return_VALUE(result); 251 return result;
257 if (resource->state != ACPI_POWER_RESOURCE_STATE_OFF) 252 if (resource->state != ACPI_POWER_RESOURCE_STATE_OFF)
258 return_VALUE(-ENOEXEC); 253 return -ENOEXEC;
259 254
260 /* Update the power resource's _device_ power state */ 255 /* Update the power resource's _device_ power state */
261 result = acpi_bus_get_device(resource->handle, &device); 256 result = acpi_bus_get_device(resource->handle, &device);
262 if (result) 257 if (result)
263 return_VALUE(result); 258 return result;
264 device->power.state = ACPI_STATE_D3; 259 device->power.state = ACPI_STATE_D3;
265 260
266 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n", 261 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
267 resource->name)); 262 resource->name));
268 263
269 return_VALUE(0); 264 return 0;
270} 265}
271 266
272/* 267/*
@@ -282,9 +277,8 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev)
282 int i; 277 int i;
283 int ret = 0; 278 int ret = 0;
284 279
285 ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_power");
286 if (!dev || !dev->wakeup.flags.valid) 280 if (!dev || !dev->wakeup.flags.valid)
287 return_VALUE(-1); 281 return -1;
288 282
289 arg.integer.value = 1; 283 arg.integer.value = 1;
290 /* Open power resource */ 284 /* Open power resource */
@@ -293,7 +287,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev)
293 if (ret) { 287 if (ret) {
294 printk(KERN_ERR PREFIX "Transition power state\n"); 288 printk(KERN_ERR PREFIX "Transition power state\n");
295 dev->wakeup.flags.valid = 0; 289 dev->wakeup.flags.valid = 0;
296 return_VALUE(-1); 290 return -1;
297 } 291 }
298 } 292 }
299 293
@@ -305,7 +299,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev)
305 ret = -1; 299 ret = -1;
306 } 300 }
307 301
308 return_VALUE(ret); 302 return ret;
309} 303}
310 304
311/* 305/*
@@ -321,10 +315,9 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
321 int i; 315 int i;
322 int ret = 0; 316 int ret = 0;
323 317
324 ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device_power");
325 318
326 if (!dev || !dev->wakeup.flags.valid) 319 if (!dev || !dev->wakeup.flags.valid)
327 return_VALUE(-1); 320 return -1;
328 321
329 arg.integer.value = 0; 322 arg.integer.value = 0;
330 /* Execute PSW */ 323 /* Execute PSW */
@@ -332,7 +325,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
332 if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { 325 if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
333 printk(KERN_ERR PREFIX "Evaluate _PSW\n"); 326 printk(KERN_ERR PREFIX "Evaluate _PSW\n");
334 dev->wakeup.flags.valid = 0; 327 dev->wakeup.flags.valid = 0;
335 return_VALUE(-1); 328 return -1;
336 } 329 }
337 330
338 /* Close power resource */ 331 /* Close power resource */
@@ -341,11 +334,11 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
341 if (ret) { 334 if (ret) {
342 printk(KERN_ERR PREFIX "Transition power state\n"); 335 printk(KERN_ERR PREFIX "Transition power state\n");
343 dev->wakeup.flags.valid = 0; 336 dev->wakeup.flags.valid = 0;
344 return_VALUE(-1); 337 return -1;
345 } 338 }
346 } 339 }
347 340
348 return_VALUE(ret); 341 return ret;
349} 342}
350 343
351/* -------------------------------------------------------------------------- 344/* --------------------------------------------------------------------------
@@ -359,10 +352,9 @@ int acpi_power_get_inferred_state(struct acpi_device *device)
359 int list_state = 0; 352 int list_state = 0;
360 int i = 0; 353 int i = 0;
361 354
362 ACPI_FUNCTION_TRACE("acpi_power_get_inferred_state");
363 355
364 if (!device) 356 if (!device)
365 return_VALUE(-EINVAL); 357 return -EINVAL;
366 358
367 device->power.state = ACPI_STATE_UNKNOWN; 359 device->power.state = ACPI_STATE_UNKNOWN;
368 360
@@ -377,17 +369,17 @@ int acpi_power_get_inferred_state(struct acpi_device *device)
377 369
378 result = acpi_power_get_list_state(list, &list_state); 370 result = acpi_power_get_list_state(list, &list_state);
379 if (result) 371 if (result)
380 return_VALUE(result); 372 return result;
381 373
382 if (list_state == ACPI_POWER_RESOURCE_STATE_ON) { 374 if (list_state == ACPI_POWER_RESOURCE_STATE_ON) {
383 device->power.state = i; 375 device->power.state = i;
384 return_VALUE(0); 376 return 0;
385 } 377 }
386 } 378 }
387 379
388 device->power.state = ACPI_STATE_D3; 380 device->power.state = ACPI_STATE_D3;
389 381
390 return_VALUE(0); 382 return 0;
391} 383}
392 384
393int acpi_power_transition(struct acpi_device *device, int state) 385int acpi_power_transition(struct acpi_device *device, int state)
@@ -397,14 +389,13 @@ int acpi_power_transition(struct acpi_device *device, int state)
397 struct acpi_handle_list *tl = NULL; /* Target Resources */ 389 struct acpi_handle_list *tl = NULL; /* Target Resources */
398 int i = 0; 390 int i = 0;
399 391
400 ACPI_FUNCTION_TRACE("acpi_power_transition");
401 392
402 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) 393 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
403 return_VALUE(-EINVAL); 394 return -EINVAL;
404 395
405 if ((device->power.state < ACPI_STATE_D0) 396 if ((device->power.state < ACPI_STATE_D0)
406 || (device->power.state > ACPI_STATE_D3)) 397 || (device->power.state > ACPI_STATE_D3))
407 return_VALUE(-ENODEV); 398 return -ENODEV;
408 399
409 cl = &device->power.states[device->power.state].resources; 400 cl = &device->power.states[device->power.state].resources;
410 tl = &device->power.states[state].resources; 401 tl = &device->power.states[state].resources;
@@ -444,7 +435,7 @@ int acpi_power_transition(struct acpi_device *device, int state)
444 printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n", 435 printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n",
445 device->pnp.bus_id, state); 436 device->pnp.bus_id, state);
446 437
447 return_VALUE(result); 438 return result;
448} 439}
449 440
450/* -------------------------------------------------------------------------- 441/* --------------------------------------------------------------------------
@@ -457,7 +448,6 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
457{ 448{
458 struct acpi_power_resource *resource = NULL; 449 struct acpi_power_resource *resource = NULL;
459 450
460 ACPI_FUNCTION_TRACE("acpi_power_seq_show");
461 451
462 resource = (struct acpi_power_resource *)seq->private; 452 resource = (struct acpi_power_resource *)seq->private;
463 453
@@ -484,7 +474,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
484 resource->order, resource->references); 474 resource->order, resource->references);
485 475
486 end: 476 end:
487 return_VALUE(0); 477 return 0;
488} 478}
489 479
490static int acpi_power_open_fs(struct inode *inode, struct file *file) 480static int acpi_power_open_fs(struct inode *inode, struct file *file)
@@ -496,34 +486,32 @@ static int acpi_power_add_fs(struct acpi_device *device)
496{ 486{
497 struct proc_dir_entry *entry = NULL; 487 struct proc_dir_entry *entry = NULL;
498 488
499 ACPI_FUNCTION_TRACE("acpi_power_add_fs");
500 489
501 if (!device) 490 if (!device)
502 return_VALUE(-EINVAL); 491 return -EINVAL;
503 492
504 if (!acpi_device_dir(device)) { 493 if (!acpi_device_dir(device)) {
505 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 494 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
506 acpi_power_dir); 495 acpi_power_dir);
507 if (!acpi_device_dir(device)) 496 if (!acpi_device_dir(device))
508 return_VALUE(-ENODEV); 497 return -ENODEV;
509 } 498 }
510 499
511 /* 'status' [R] */ 500 /* 'status' [R] */
512 entry = create_proc_entry(ACPI_POWER_FILE_STATUS, 501 entry = create_proc_entry(ACPI_POWER_FILE_STATUS,
513 S_IRUGO, acpi_device_dir(device)); 502 S_IRUGO, acpi_device_dir(device));
514 if (!entry) 503 if (!entry)
515 return_VALUE(-EIO); 504 return -EIO;
516 else { 505 else {
517 entry->proc_fops = &acpi_power_fops; 506 entry->proc_fops = &acpi_power_fops;
518 entry->data = acpi_driver_data(device); 507 entry->data = acpi_driver_data(device);
519 } 508 }
520 509
521 return_VALUE(0); 510 return 0;
522} 511}
523 512
524static int acpi_power_remove_fs(struct acpi_device *device) 513static int acpi_power_remove_fs(struct acpi_device *device)
525{ 514{
526 ACPI_FUNCTION_TRACE("acpi_power_remove_fs");
527 515
528 if (acpi_device_dir(device)) { 516 if (acpi_device_dir(device)) {
529 remove_proc_entry(ACPI_POWER_FILE_STATUS, 517 remove_proc_entry(ACPI_POWER_FILE_STATUS,
@@ -532,7 +520,7 @@ static int acpi_power_remove_fs(struct acpi_device *device)
532 acpi_device_dir(device) = NULL; 520 acpi_device_dir(device) = NULL;
533 } 521 }
534 522
535 return_VALUE(0); 523 return 0;
536} 524}
537 525
538/* -------------------------------------------------------------------------- 526/* --------------------------------------------------------------------------
@@ -547,14 +535,13 @@ static int acpi_power_add(struct acpi_device *device)
547 union acpi_object acpi_object; 535 union acpi_object acpi_object;
548 struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object }; 536 struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
549 537
550 ACPI_FUNCTION_TRACE("acpi_power_add");
551 538
552 if (!device) 539 if (!device)
553 return_VALUE(-EINVAL); 540 return -EINVAL;
554 541
555 resource = kmalloc(sizeof(struct acpi_power_resource), GFP_KERNEL); 542 resource = kmalloc(sizeof(struct acpi_power_resource), GFP_KERNEL);
556 if (!resource) 543 if (!resource)
557 return_VALUE(-ENOMEM); 544 return -ENOMEM;
558 memset(resource, 0, sizeof(struct acpi_power_resource)); 545 memset(resource, 0, sizeof(struct acpi_power_resource));
559 546
560 resource->handle = device->handle; 547 resource->handle = device->handle;
@@ -599,17 +586,16 @@ static int acpi_power_add(struct acpi_device *device)
599 if (result) 586 if (result)
600 kfree(resource); 587 kfree(resource);
601 588
602 return_VALUE(result); 589 return result;
603} 590}
604 591
605static int acpi_power_remove(struct acpi_device *device, int type) 592static int acpi_power_remove(struct acpi_device *device, int type)
606{ 593{
607 struct acpi_power_resource *resource = NULL; 594 struct acpi_power_resource *resource = NULL;
608 595
609 ACPI_FUNCTION_TRACE("acpi_power_remove");
610 596
611 if (!device || !acpi_driver_data(device)) 597 if (!device || !acpi_driver_data(device))
612 return_VALUE(-EINVAL); 598 return -EINVAL;
613 599
614 resource = (struct acpi_power_resource *)acpi_driver_data(device); 600 resource = (struct acpi_power_resource *)acpi_driver_data(device);
615 601
@@ -617,31 +603,30 @@ static int acpi_power_remove(struct acpi_device *device, int type)
617 603
618 kfree(resource); 604 kfree(resource);
619 605
620 return_VALUE(0); 606 return 0;
621} 607}
622 608
623static int __init acpi_power_init(void) 609static int __init acpi_power_init(void)
624{ 610{
625 int result = 0; 611 int result = 0;
626 612
627 ACPI_FUNCTION_TRACE("acpi_power_init");
628 613
629 if (acpi_disabled) 614 if (acpi_disabled)
630 return_VALUE(0); 615 return 0;
631 616
632 INIT_LIST_HEAD(&acpi_power_resource_list); 617 INIT_LIST_HEAD(&acpi_power_resource_list);
633 618
634 acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir); 619 acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir);
635 if (!acpi_power_dir) 620 if (!acpi_power_dir)
636 return_VALUE(-ENODEV); 621 return -ENODEV;
637 622
638 result = acpi_bus_register_driver(&acpi_power_driver); 623 result = acpi_bus_register_driver(&acpi_power_driver);
639 if (result < 0) { 624 if (result < 0) {
640 remove_proc_entry(ACPI_POWER_CLASS, acpi_root_dir); 625 remove_proc_entry(ACPI_POWER_CLASS, acpi_root_dir);
641 return_VALUE(-ENODEV); 626 return -ENODEV;
642 } 627 }
643 628
644 return_VALUE(0); 629 return 0;
645} 630}
646 631
647subsys_initcall(acpi_power_init); 632subsys_initcall(acpi_power_init);