bus.c revision b913100d7304ea9596d8d85ab5f3ae04bd2b0ddb
1/* 2 * acpi_bus.c - ACPI Bus Driver ($Revision: 80 $) 3 * 4 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 5 * 6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or (at 11 * your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License along 19 * with this program; if not, write to the Free Software Foundation, Inc., 20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 21 * 22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 */ 24 25#include <linux/module.h> 26#include <linux/init.h> 27#include <linux/ioport.h> 28#include <linux/list.h> 29#include <linux/sched.h> 30#include <linux/pm.h> 31#include <linux/device.h> 32#include <linux/proc_fs.h> 33#ifdef CONFIG_X86 34#include <asm/mpspec.h> 35#endif 36#include <acpi/acpi_bus.h> 37#include <acpi/acpi_drivers.h> 38 39 40#define _COMPONENT ACPI_BUS_COMPONENT 41ACPI_MODULE_NAME ("acpi_bus") 42 43#ifdef CONFIG_X86 44extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger); 45#endif 46 47FADT_DESCRIPTOR acpi_fadt; 48EXPORT_SYMBOL(acpi_fadt); 49 50struct acpi_device *acpi_root; 51struct proc_dir_entry *acpi_root_dir; 52EXPORT_SYMBOL(acpi_root_dir); 53 54#define STRUCT_TO_INT(s) (*((int*)&s)) 55 56/* -------------------------------------------------------------------------- 57 Device Management 58 -------------------------------------------------------------------------- */ 59 60int 61acpi_bus_get_device ( 62 acpi_handle handle, 63 struct acpi_device **device) 64{ 65 acpi_status status = AE_OK; 66 67 ACPI_FUNCTION_TRACE("acpi_bus_get_device"); 68 69 if (!device) 70 return_VALUE(-EINVAL); 71 72 /* TBD: Support fixed-feature devices */ 73 74 status = acpi_get_data(handle, acpi_bus_data_handler, (void**) device); 75 if (ACPI_FAILURE(status) || !*device) { 76 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "No context for object [%p]\n", 77 handle)); 78 return_VALUE(-ENODEV); 79 } 80 81 return_VALUE(0); 82} 83EXPORT_SYMBOL(acpi_bus_get_device); 84 85int 86acpi_bus_get_status ( 87 struct acpi_device *device) 88{ 89 acpi_status status = AE_OK; 90 unsigned long sta = 0; 91 92 ACPI_FUNCTION_TRACE("acpi_bus_get_status"); 93 94 if (!device) 95 return_VALUE(-EINVAL); 96 97 /* 98 * Evaluate _STA if present. 99 */ 100 if (device->flags.dynamic_status) { 101 status = acpi_evaluate_integer(device->handle, "_STA", NULL, &sta); 102 if (ACPI_FAILURE(status)) 103 return_VALUE(-ENODEV); 104 STRUCT_TO_INT(device->status) = (int) sta; 105 } 106 107 /* 108 * Otherwise we assume the status of our parent (unless we don't 109 * have one, in which case status is implied). 110 */ 111 else if (device->parent) 112 device->status = device->parent->status; 113 else 114 STRUCT_TO_INT(device->status) = 0x0F; 115 116 if (device->status.functional && !device->status.present) { 117 printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: " 118 "functional but not present; setting present\n", 119 device->pnp.bus_id, 120 (u32) STRUCT_TO_INT(device->status)); 121 device->status.present = 1; 122 } 123 124 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", 125 device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status))); 126 127 return_VALUE(0); 128} 129EXPORT_SYMBOL(acpi_bus_get_status); 130 131 132/* -------------------------------------------------------------------------- 133 Power Management 134 -------------------------------------------------------------------------- */ 135 136int 137acpi_bus_get_power ( 138 acpi_handle handle, 139 int *state) 140{ 141 int result = 0; 142 acpi_status status = 0; 143 struct acpi_device *device = NULL; 144 unsigned long psc = 0; 145 146 ACPI_FUNCTION_TRACE("acpi_bus_get_power"); 147 148 result = acpi_bus_get_device(handle, &device); 149 if (result) 150 return_VALUE(result); 151 152 *state = ACPI_STATE_UNKNOWN; 153 154 if (!device->flags.power_manageable) { 155 /* TBD: Non-recursive algorithm for walking up hierarchy */ 156 if (device->parent) 157 *state = device->parent->power.state; 158 else 159 *state = ACPI_STATE_D0; 160 } 161 else { 162 /* 163 * Get the device's power state either directly (via _PSC) or 164 * indirectly (via power resources). 165 */ 166 if (device->power.flags.explicit_get) { 167 status = acpi_evaluate_integer(device->handle, "_PSC", 168 NULL, &psc); 169 if (ACPI_FAILURE(status)) 170 return_VALUE(-ENODEV); 171 device->power.state = (int) psc; 172 } 173 else if (device->power.flags.power_resources) { 174 result = acpi_power_get_inferred_state(device); 175 if (result) 176 return_VALUE(result); 177 } 178 179 *state = device->power.state; 180 } 181 182 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", 183 device->pnp.bus_id, device->power.state)); 184 185 return_VALUE(0); 186} 187EXPORT_SYMBOL(acpi_bus_get_power); 188 189 190int 191acpi_bus_set_power ( 192 acpi_handle handle, 193 int state) 194{ 195 int result = 0; 196 acpi_status status = AE_OK; 197 struct acpi_device *device = NULL; 198 char object_name[5] = {'_','P','S','0'+state,'\0'}; 199 200 ACPI_FUNCTION_TRACE("acpi_bus_set_power"); 201 202 result = acpi_bus_get_device(handle, &device); 203 if (result) 204 return_VALUE(result); 205 206 if ((state < ACPI_STATE_D0) || (state > ACPI_STATE_D3)) 207 return_VALUE(-EINVAL); 208 209 /* Make sure this is a valid target state */ 210 211 if (!device->flags.power_manageable) { 212 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device is not power manageable\n")); 213 return_VALUE(-ENODEV); 214 } 215 /* 216 * Get device's current power state if it's unknown 217 * This means device power state isn't initialized or previous setting failed 218 */ 219 if (device->power.state == ACPI_STATE_UNKNOWN) 220 acpi_bus_get_power(device->handle, &device->power.state); 221 if (state == device->power.state) { 222 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", state)); 223 return_VALUE(0); 224 } 225 if (!device->power.states[state].flags.valid) { 226 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n", state)); 227 return_VALUE(-ENODEV); 228 } 229 if (device->parent && (state < device->parent->power.state)) { 230 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Cannot set device to a higher-powered state than parent\n")); 231 return_VALUE(-ENODEV); 232 } 233 234 /* 235 * Transition Power 236 * ---------------- 237 * On transitions to a high-powered state we first apply power (via 238 * power resources) then evalute _PSx. Conversly for transitions to 239 * a lower-powered state. 240 */ 241 if (state < device->power.state) { 242 if (device->power.flags.power_resources) { 243 result = acpi_power_transition(device, state); 244 if (result) 245 goto end; 246 } 247 if (device->power.states[state].flags.explicit_set) { 248 status = acpi_evaluate_object(device->handle, 249 object_name, NULL, NULL); 250 if (ACPI_FAILURE(status)) { 251 result = -ENODEV; 252 goto end; 253 } 254 } 255 } 256 else { 257 if (device->power.states[state].flags.explicit_set) { 258 status = acpi_evaluate_object(device->handle, 259 object_name, NULL, NULL); 260 if (ACPI_FAILURE(status)) { 261 result = -ENODEV; 262 goto end; 263 } 264 } 265 if (device->power.flags.power_resources) { 266 result = acpi_power_transition(device, state); 267 if (result) 268 goto end; 269 } 270 } 271 272end: 273 if (result) 274 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error transitioning device [%s] to D%d\n", 275 device->pnp.bus_id, state)); 276 else 277 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] transitioned to D%d\n", 278 device->pnp.bus_id, state)); 279 280 return_VALUE(result); 281} 282EXPORT_SYMBOL(acpi_bus_set_power); 283 284 285 286/* -------------------------------------------------------------------------- 287 Event Management 288 -------------------------------------------------------------------------- */ 289 290static DEFINE_SPINLOCK(acpi_bus_event_lock); 291 292LIST_HEAD(acpi_bus_event_list); 293DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); 294 295extern int event_is_open; 296 297int 298acpi_bus_generate_event ( 299 struct acpi_device *device, 300 u8 type, 301 int data) 302{ 303 struct acpi_bus_event *event = NULL; 304 unsigned long flags = 0; 305 306 ACPI_FUNCTION_TRACE("acpi_bus_generate_event"); 307 308 if (!device) 309 return_VALUE(-EINVAL); 310 311 /* drop event on the floor if no one's listening */ 312 if (!event_is_open) 313 return_VALUE(0); 314 315 event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); 316 if (!event) 317 return_VALUE(-ENOMEM); 318 319 strcpy(event->device_class, device->pnp.device_class); 320 strcpy(event->bus_id, device->pnp.bus_id); 321 event->type = type; 322 event->data = data; 323 324 spin_lock_irqsave(&acpi_bus_event_lock, flags); 325 list_add_tail(&event->node, &acpi_bus_event_list); 326 spin_unlock_irqrestore(&acpi_bus_event_lock, flags); 327 328 wake_up_interruptible(&acpi_bus_event_queue); 329 330 return_VALUE(0); 331} 332EXPORT_SYMBOL(acpi_bus_generate_event); 333 334int 335acpi_bus_receive_event ( 336 struct acpi_bus_event *event) 337{ 338 unsigned long flags = 0; 339 struct acpi_bus_event *entry = NULL; 340 341 DECLARE_WAITQUEUE(wait, current); 342 343 ACPI_FUNCTION_TRACE("acpi_bus_receive_event"); 344 345 if (!event) 346 return_VALUE(-EINVAL); 347 348 if (list_empty(&acpi_bus_event_list)) { 349 350 set_current_state(TASK_INTERRUPTIBLE); 351 add_wait_queue(&acpi_bus_event_queue, &wait); 352 353 if (list_empty(&acpi_bus_event_list)) 354 schedule(); 355 356 remove_wait_queue(&acpi_bus_event_queue, &wait); 357 set_current_state(TASK_RUNNING); 358 359 if (signal_pending(current)) 360 return_VALUE(-ERESTARTSYS); 361 } 362 363 spin_lock_irqsave(&acpi_bus_event_lock, flags); 364 entry = list_entry(acpi_bus_event_list.next, struct acpi_bus_event, node); 365 if (entry) 366 list_del(&entry->node); 367 spin_unlock_irqrestore(&acpi_bus_event_lock, flags); 368 369 if (!entry) 370 return_VALUE(-ENODEV); 371 372 memcpy(event, entry, sizeof(struct acpi_bus_event)); 373 374 kfree(entry); 375 376 return_VALUE(0); 377} 378EXPORT_SYMBOL(acpi_bus_receive_event); 379 380 381/* -------------------------------------------------------------------------- 382 Notification Handling 383 -------------------------------------------------------------------------- */ 384 385static int 386acpi_bus_check_device ( 387 struct acpi_device *device, 388 int *status_changed) 389{ 390 acpi_status status = 0; 391 struct acpi_device_status old_status; 392 393 ACPI_FUNCTION_TRACE("acpi_bus_check_device"); 394 395 if (!device) 396 return_VALUE(-EINVAL); 397 398 if (status_changed) 399 *status_changed = 0; 400 401 old_status = device->status; 402 403 /* 404 * Make sure this device's parent is present before we go about 405 * messing with the device. 406 */ 407 if (device->parent && !device->parent->status.present) { 408 device->status = device->parent->status; 409 if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) { 410 if (status_changed) 411 *status_changed = 1; 412 } 413 return_VALUE(0); 414 } 415 416 status = acpi_bus_get_status(device); 417 if (ACPI_FAILURE(status)) 418 return_VALUE(-ENODEV); 419 420 if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) 421 return_VALUE(0); 422 423 if (status_changed) 424 *status_changed = 1; 425 426 /* 427 * Device Insertion/Removal 428 */ 429 if ((device->status.present) && !(old_status.present)) { 430 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); 431 /* TBD: Handle device insertion */ 432 } 433 else if (!(device->status.present) && (old_status.present)) { 434 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); 435 /* TBD: Handle device removal */ 436 } 437 438 return_VALUE(0); 439} 440 441 442static int 443acpi_bus_check_scope ( 444 struct acpi_device *device) 445{ 446 int result = 0; 447 int status_changed = 0; 448 449 ACPI_FUNCTION_TRACE("acpi_bus_check_scope"); 450 451 if (!device) 452 return_VALUE(-EINVAL); 453 454 /* Status Change? */ 455 result = acpi_bus_check_device(device, &status_changed); 456 if (result) 457 return_VALUE(result); 458 459 if (!status_changed) 460 return_VALUE(0); 461 462 /* 463 * TBD: Enumerate child devices within this device's scope and 464 * run acpi_bus_check_device()'s on them. 465 */ 466 467 return_VALUE(0); 468} 469 470 471/** 472 * acpi_bus_notify 473 * --------------- 474 * Callback for all 'system-level' device notifications (values 0x00-0x7F). 475 */ 476static void 477acpi_bus_notify ( 478 acpi_handle handle, 479 u32 type, 480 void *data) 481{ 482 int result = 0; 483 struct acpi_device *device = NULL; 484 485 ACPI_FUNCTION_TRACE("acpi_bus_notify"); 486 487 if (acpi_bus_get_device(handle, &device)) 488 return_VOID; 489 490 switch (type) { 491 492 case ACPI_NOTIFY_BUS_CHECK: 493 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS CHECK notification for device [%s]\n", 494 device->pnp.bus_id)); 495 result = acpi_bus_check_scope(device); 496 /* 497 * TBD: We'll need to outsource certain events to non-ACPI 498 * drivers via the device manager (device.c). 499 */ 500 break; 501 502 case ACPI_NOTIFY_DEVICE_CHECK: 503 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK notification for device [%s]\n", 504 device->pnp.bus_id)); 505 result = acpi_bus_check_device(device, NULL); 506 /* 507 * TBD: We'll need to outsource certain events to non-ACPI 508 * drivers via the device manager (device.c). 509 */ 510 break; 511 512 case ACPI_NOTIFY_DEVICE_WAKE: 513 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE WAKE notification for device [%s]\n", 514 device->pnp.bus_id)); 515 /* TBD */ 516 break; 517 518 case ACPI_NOTIFY_EJECT_REQUEST: 519 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received EJECT REQUEST notification for device [%s]\n", 520 device->pnp.bus_id)); 521 /* TBD */ 522 break; 523 524 case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: 525 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received DEVICE CHECK LIGHT notification for device [%s]\n", 526 device->pnp.bus_id)); 527 /* TBD: Exactly what does 'light' mean? */ 528 break; 529 530 case ACPI_NOTIFY_FREQUENCY_MISMATCH: 531 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received FREQUENCY MISMATCH notification for device [%s]\n", 532 device->pnp.bus_id)); 533 /* TBD */ 534 break; 535 536 case ACPI_NOTIFY_BUS_MODE_MISMATCH: 537 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received BUS MODE MISMATCH notification for device [%s]\n", 538 device->pnp.bus_id)); 539 /* TBD */ 540 break; 541 542 case ACPI_NOTIFY_POWER_FAULT: 543 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received POWER FAULT notification for device [%s]\n", 544 device->pnp.bus_id)); 545 /* TBD */ 546 break; 547 548 default: 549 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Received unknown/unsupported notification [%08x]\n", 550 type)); 551 break; 552 } 553 554 return_VOID; 555} 556 557/* -------------------------------------------------------------------------- 558 Initialization/Cleanup 559 -------------------------------------------------------------------------- */ 560 561static int __init 562acpi_bus_init_irq (void) 563{ 564 acpi_status status = AE_OK; 565 union acpi_object arg = {ACPI_TYPE_INTEGER}; 566 struct acpi_object_list arg_list = {1, &arg}; 567 char *message = NULL; 568 569 ACPI_FUNCTION_TRACE("acpi_bus_init_irq"); 570 571 /* 572 * Let the system know what interrupt model we are using by 573 * evaluating the \_PIC object, if exists. 574 */ 575 576 switch (acpi_irq_model) { 577 case ACPI_IRQ_MODEL_PIC: 578 message = "PIC"; 579 break; 580 case ACPI_IRQ_MODEL_IOAPIC: 581 message = "IOAPIC"; 582 break; 583 case ACPI_IRQ_MODEL_IOSAPIC: 584 message = "IOSAPIC"; 585 break; 586 default: 587 printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n"); 588 return_VALUE(-ENODEV); 589 } 590 591 printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message); 592 593 arg.integer.value = acpi_irq_model; 594 595 status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL); 596 if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { 597 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n")); 598 return_VALUE(-ENODEV); 599 } 600 601 return_VALUE(0); 602} 603 604 605void __init 606acpi_early_init (void) 607{ 608 acpi_status status = AE_OK; 609 struct acpi_buffer buffer = {sizeof(acpi_fadt), &acpi_fadt}; 610 611 ACPI_FUNCTION_TRACE("acpi_early_init"); 612 613 if (acpi_disabled) 614 return_VOID; 615 616 /* enable workarounds, unless strict ACPI spec. compliance */ 617 if (!acpi_strict) 618 acpi_gbl_enable_interpreter_slack = TRUE; 619 620 status = acpi_initialize_subsystem(); 621 if (ACPI_FAILURE(status)) { 622 printk(KERN_ERR PREFIX "Unable to initialize the ACPI Interpreter\n"); 623 goto error0; 624 } 625 626 status = acpi_load_tables(); 627 if (ACPI_FAILURE(status)) { 628 printk(KERN_ERR PREFIX "Unable to load the System Description Tables\n"); 629 goto error0; 630 } 631 632 /* 633 * Get a separate copy of the FADT for use by other drivers. 634 */ 635 status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer); 636 if (ACPI_FAILURE(status)) { 637 printk(KERN_ERR PREFIX "Unable to get the FADT\n"); 638 goto error0; 639 } 640 641#ifdef CONFIG_X86 642 if (!acpi_ioapic) { 643 extern acpi_interrupt_flags acpi_sci_flags; 644 645 /* compatible (0) means level (3) */ 646 if (acpi_sci_flags.trigger == 0) 647 acpi_sci_flags.trigger = 3; 648 649 /* Set PIC-mode SCI trigger type */ 650 acpi_pic_sci_set_trigger(acpi_fadt.sci_int, acpi_sci_flags.trigger); 651 } else { 652 extern int acpi_sci_override_gsi; 653 /* 654 * now that acpi_fadt is initialized, 655 * update it with result from INT_SRC_OVR parsing 656 */ 657 acpi_fadt.sci_int = acpi_sci_override_gsi; 658 } 659#endif 660 661 status = acpi_enable_subsystem(~(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE)); 662 if (ACPI_FAILURE(status)) { 663 printk(KERN_ERR PREFIX "Unable to enable ACPI\n"); 664 goto error0; 665 } 666 667 return_VOID; 668 669error0: 670 disable_acpi(); 671 return_VOID; 672} 673 674static int __init 675acpi_bus_init (void) 676{ 677 int result = 0; 678 acpi_status status = AE_OK; 679 extern acpi_status acpi_os_initialize1(void); 680 681 ACPI_FUNCTION_TRACE("acpi_bus_init"); 682 683 status = acpi_os_initialize1(); 684 685 status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE); 686 if (ACPI_FAILURE(status)) { 687 printk(KERN_ERR PREFIX "Unable to start the ACPI Interpreter\n"); 688 goto error1; 689 } 690 691 if (ACPI_FAILURE(status)) { 692 printk(KERN_ERR PREFIX "Unable to initialize ACPI OS objects\n"); 693 goto error1; 694 } 695#ifdef CONFIG_ACPI_EC 696 /* 697 * ACPI 2.0 requires the EC driver to be loaded and work before 698 * the EC device is found in the namespace (i.e. before acpi_initialize_objects() 699 * is called). 700 * 701 * This is accomplished by looking for the ECDT table, and getting 702 * the EC parameters out of that. 703 */ 704 status = acpi_ec_ecdt_probe(); 705 /* Ignore result. Not having an ECDT is not fatal. */ 706#endif 707 708 status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); 709 if (ACPI_FAILURE(status)) { 710 printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); 711 goto error1; 712 } 713 714 printk(KERN_INFO PREFIX "Interpreter enabled\n"); 715 716 /* 717 * Get the system interrupt model and evaluate \_PIC. 718 */ 719 result = acpi_bus_init_irq(); 720 if (result) 721 goto error1; 722 723 /* 724 * Register the for all standard device notifications. 725 */ 726 status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL); 727 if (ACPI_FAILURE(status)) { 728 printk(KERN_ERR PREFIX "Unable to register for device notifications\n"); 729 goto error1; 730 } 731 732 /* 733 * Create the top ACPI proc directory 734 */ 735 acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL); 736 737 return_VALUE(0); 738 739 /* Mimic structured exception handling */ 740error1: 741 acpi_terminate(); 742 return_VALUE(-ENODEV); 743} 744 745decl_subsys(acpi,NULL,NULL); 746 747static int __init acpi_init (void) 748{ 749 int result = 0; 750 751 ACPI_FUNCTION_TRACE("acpi_init"); 752 753 printk(KERN_INFO PREFIX "Subsystem revision %08x\n", 754 ACPI_CA_VERSION); 755 756 if (acpi_disabled) { 757 printk(KERN_INFO PREFIX "Interpreter disabled.\n"); 758 return_VALUE(-ENODEV); 759 } 760 761 firmware_register(&acpi_subsys); 762 763 result = acpi_bus_init(); 764 765 if (!result) { 766#ifdef CONFIG_PM 767 if (!PM_IS_ACTIVE()) 768 pm_active = 1; 769 else { 770 printk(KERN_INFO PREFIX "APM is already active, exiting\n"); 771 disable_acpi(); 772 result = -ENODEV; 773 } 774#endif 775 } else 776 disable_acpi(); 777 778 return_VALUE(result); 779} 780 781subsys_initcall(acpi_init); 782