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