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