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