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