Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
Linus Torvalds [Mon, 15 Mar 2010 03:29:21 +0000 (20:29 -0700)]
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (34 commits)
  ACPI: processor: push file static MADT pointer into internal map_madt_entry()
  ACPI: processor: refactor internal map_lsapic_id()
  ACPI: processor: refactor internal map_x2apic_id()
  ACPI: processor: refactor internal map_lapic_id()
  ACPI: processor: driver doesn't need to evaluate _PDC
  ACPI: processor: remove early _PDC optin quirks
  ACPI: processor: add internal processor_physically_present()
  ACPI: processor: move acpi_get_cpuid into processor_core.c
  ACPI: processor: export acpi_get_cpuid()
  ACPI: processor: mv processor_pdc.c processor_core.c
  ACPI: processor: mv processor_core.c processor_driver.c
  ACPI: plan to delete "acpi=ht" boot option
  ACPI: remove "acpi=ht" DMI blacklist
  PNPACPI: add bus number support
  PNPACPI: add window support
  resource: add window support
  resource: add bus number support
  resource: expand IORESOURCE_TYPE_BITS to make room for bus resource type
  acpiphp: Execute ACPI _REG method for hotadded devices
  ACPI video: Be more liberal in validating _BQC behaviour
  ...

31 files changed:
Documentation/feature-removal-schedule.txt
Documentation/kernel-parameters.txt
arch/ia64/kernel/acpi.c
arch/x86/kernel/acpi/boot.c
drivers/acpi/Makefile
drivers/acpi/acpica/exmutex.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/acpi/ec.c
drivers/acpi/internal.h
drivers/acpi/processor_core.c
drivers/acpi/processor_driver.c [new file with mode: 0644]
drivers/acpi/processor_pdc.c [deleted file]
drivers/acpi/processor_throttling.c
drivers/acpi/sbs.c
drivers/acpi/sleep.c
drivers/acpi/thermal.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/platform/x86/sony-laptop.c
drivers/pnp/base.h
drivers/pnp/interface.c
drivers/pnp/pnpacpi/rsparser.c
drivers/pnp/resource.c
drivers/pnp/support.c
drivers/power/power_supply_sysfs.c
include/acpi/processor.h
include/linux/ioport.h
include/linux/power_supply.h
lib/vsprintf.c

index a5cc0db..ed511af 100644 (file)
@@ -582,3 +582,10 @@ Why:       The paravirt mmu host support is slower than non-paravirt mmu, both
 Who:   Avi Kivity <avi@redhat.com>
 
 ----------------------------
+
+What:  "acpi=ht" boot option
+When:  2.6.35
+Why:   Useful in 2003, implementation is a hack.
+       Generally invoked by accident today.
+       Seen as doing more harm than good.
+Who:   Len Brown <len.brown@intel.com>
index 3bc48b0..e4cbca5 100644 (file)
@@ -200,10 +200,6 @@ and is between 256 and 4096 characters. It is defined in the file
                        acpi_display_output=video
                        See above.
 
-       acpi_early_pdc_eval     [HW,ACPI] Evaluate processor _PDC methods
-                               early. Needed on some platforms to properly
-                               initialize the EC.
-
        acpi_irq_balance [HW,ACPI]
                        ACPI will balance active IRQs
                        default in APIC mode
index a7ca07f..f1c9f70 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/efi.h>
 #include <linux/mmzone.h>
 #include <linux/nodemask.h>
+#include <acpi/processor.h>
 #include <asm/io.h>
 #include <asm/iosapic.h>
 #include <asm/machvec.h>
@@ -907,6 +908,8 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu)
        cpu_set(cpu, cpu_present_map);
        ia64_cpu_to_sapicid[cpu] = physid;
 
+       acpi_processor_set_pdc(handle);
+
        *pcpu = cpu;
        return (0);
 }
index a54d714..0061ea2 100644 (file)
@@ -490,6 +490,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
  *  ACPI based hotplug support for CPU
  */
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
+#include <acpi/processor.h>
 
 static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 {
@@ -567,6 +568,8 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
                goto free_new_map;
        }
 
+       acpi_processor_set_pdc(handle);
+
        cpu = cpumask_first(new_map);
        acpi_map_cpu2node(handle, cpu, physid);
 
@@ -1293,23 +1296,6 @@ static int __init dmi_disable_acpi(const struct dmi_system_id *d)
 }
 
 /*
- * Limit ACPI to CPU enumeration for HT
- */
-static int __init force_acpi_ht(const struct dmi_system_id *d)
-{
-       if (!acpi_force) {
-               printk(KERN_NOTICE "%s detected: force use of acpi=ht\n",
-                      d->ident);
-               disable_acpi();
-               acpi_ht = 1;
-       } else {
-               printk(KERN_NOTICE
-                      "Warning: acpi=force overrules DMI blacklist: acpi=ht\n");
-       }
-       return 0;
-}
-
-/*
  * Force ignoring BIOS IRQ0 pin2 override
  */
 static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
@@ -1345,82 +1331,6 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
         },
 
        /*
-        * Boxes that need acpi=ht
-        */
-       {
-        .callback = force_acpi_ht,
-        .ident = "FSC Primergy T850",
-        .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "HP VISUALIZE NT Workstation",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "Compaq Workstation W8000",
-        .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "ASUS CUR-DLS",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-                    DMI_MATCH(DMI_BOARD_NAME, "CUR-DLS"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "ABIT i440BX-W83977",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
-                    DMI_MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "IBM Bladecenter",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
-                    DMI_MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "IBM eServer xSeries 360",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
-                    DMI_MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "IBM eserver xSeries 330",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
-                    DMI_MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "IBM eserver xSeries 440",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
-                    },
-        },
-
-       /*
         * Boxes that need ACPI PCI IRQ routing disabled
         */
        {
@@ -1652,8 +1562,10 @@ static int __init parse_acpi(char *arg)
        }
        /* Limit ACPI just to boot-time to enable HT */
        else if (strcmp(arg, "ht") == 0) {
-               if (!acpi_force)
+               if (!acpi_force) {
+                       printk(KERN_WARNING "acpi=ht will be removed in Linux-2.6.35\n");
                        disable_acpi();
+               }
                acpi_ht = 1;
        }
        /* acpi=rsdt use RSDT instead of XSDT */
index 66cc3f3..a8d8998 100644 (file)
@@ -32,7 +32,7 @@ acpi-$(CONFIG_ACPI_SLEEP)     += proc.o
 #
 acpi-y                         += bus.o glue.o
 acpi-y                         += scan.o
-acpi-y                         += processor_pdc.o
+acpi-y                         += processor_core.o
 acpi-y                         += ec.o
 acpi-$(CONFIG_ACPI_DOCK)       += dock.o
 acpi-y                         += pci_root.o pci_link.o pci_irq.o pci_bind.o
@@ -61,7 +61,7 @@ obj-$(CONFIG_ACPI_SBS)                += sbs.o
 obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o
 
 # processor has its own "processor." module_param namespace
-processor-y                    := processor_core.o processor_throttling.o
+processor-y                    := processor_driver.o processor_throttling.o
 processor-y                    += processor_idle.o processor_thermal.o
 processor-$(CONFIG_CPU_FREQ)   += processor_perflib.o
 
index cc8a102..7116bc8 100644 (file)
@@ -375,8 +375,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
                return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
        }
 
-       /* Must have a valid thread ID */
-
+       /* Must have a valid thread. */
        if (!walk_state->thread) {
                ACPI_ERROR((AE_INFO,
                            "Cannot release Mutex [%4.4s], null thread info",
index 58d2c91..75f39f2 100644 (file)
@@ -54,6 +54,7 @@
 #define ACPI_BATTERY_DEVICE_NAME       "Battery"
 #define ACPI_BATTERY_NOTIFY_STATUS     0x80
 #define ACPI_BATTERY_NOTIFY_INFO       0x81
+#define ACPI_BATTERY_NOTIFY_THRESHOLD   0x82
 
 #define _COMPONENT             ACPI_BATTERY_COMPONENT
 
@@ -88,10 +89,15 @@ static const struct acpi_device_id battery_device_ids[] = {
 
 MODULE_DEVICE_TABLE(acpi, battery_device_ids);
 
-/* For buggy DSDTs that report negative 16-bit values for either charging
- * or discharging current and/or report 0 as 65536 due to bad math.
- */
-#define QUIRK_SIGNED16_CURRENT 0x0001
+enum {
+       ACPI_BATTERY_ALARM_PRESENT,
+       ACPI_BATTERY_XINFO_PRESENT,
+       /* For buggy DSDTs that report negative 16-bit values for either
+        * charging or discharging current and/or report 0 as 65536
+        * due to bad math.
+        */
+       ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
+};
 
 struct acpi_battery {
        struct mutex lock;
@@ -109,6 +115,12 @@ struct acpi_battery {
        int design_voltage;
        int design_capacity_warning;
        int design_capacity_low;
+       int cycle_count;
+       int measurement_accuracy;
+       int max_sampling_time;
+       int min_sampling_time;
+       int max_averaging_interval;
+       int min_averaging_interval;
        int capacity_granularity_1;
        int capacity_granularity_2;
        int alarm;
@@ -118,8 +130,7 @@ struct acpi_battery {
        char oem_info[32];
        int state;
        int power_unit;
-       u8 alarm_present;
-       long quirks;
+       unsigned long flags;
 };
 
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
@@ -198,6 +209,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_TECHNOLOGY:
                val->intval = acpi_battery_technology(battery);
                break;
+       case POWER_SUPPLY_PROP_CYCLE_COUNT:
+               val->intval = battery->cycle_count;
+               break;
        case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
                val->intval = battery->design_voltage * 1000;
                break;
@@ -239,6 +253,7 @@ static enum power_supply_property charge_battery_props[] = {
        POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_CYCLE_COUNT,
        POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_CURRENT_NOW,
@@ -254,6 +269,7 @@ static enum power_supply_property energy_battery_props[] = {
        POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_CYCLE_COUNT,
        POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_CURRENT_NOW,
@@ -305,6 +321,28 @@ static struct acpi_offsets info_offsets[] = {
        {offsetof(struct acpi_battery, oem_info), 1},
 };
 
+static struct acpi_offsets extended_info_offsets[] = {
+       {offsetof(struct acpi_battery, power_unit), 0},
+       {offsetof(struct acpi_battery, design_capacity), 0},
+       {offsetof(struct acpi_battery, full_charge_capacity), 0},
+       {offsetof(struct acpi_battery, technology), 0},
+       {offsetof(struct acpi_battery, design_voltage), 0},
+       {offsetof(struct acpi_battery, design_capacity_warning), 0},
+       {offsetof(struct acpi_battery, design_capacity_low), 0},
+       {offsetof(struct acpi_battery, cycle_count), 0},
+       {offsetof(struct acpi_battery, measurement_accuracy), 0},
+       {offsetof(struct acpi_battery, max_sampling_time), 0},
+       {offsetof(struct acpi_battery, min_sampling_time), 0},
+       {offsetof(struct acpi_battery, max_averaging_interval), 0},
+       {offsetof(struct acpi_battery, min_averaging_interval), 0},
+       {offsetof(struct acpi_battery, capacity_granularity_1), 0},
+       {offsetof(struct acpi_battery, capacity_granularity_2), 0},
+       {offsetof(struct acpi_battery, model_number), 1},
+       {offsetof(struct acpi_battery, serial_number), 1},
+       {offsetof(struct acpi_battery, type), 1},
+       {offsetof(struct acpi_battery, oem_info), 1},
+};
+
 static int extract_package(struct acpi_battery *battery,
                           union acpi_object *package,
                           struct acpi_offsets *offsets, int num)
@@ -350,22 +388,29 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
 {
        int result = -EFAULT;
        acpi_status status = 0;
+       char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)?
+                       "_BIX" : "_BIF";
+
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
        if (!acpi_battery_present(battery))
                return 0;
        mutex_lock(&battery->lock);
-       status = acpi_evaluate_object(battery->device->handle, "_BIF",
-                                     NULL, &buffer);
+       status = acpi_evaluate_object(battery->device->handle, name,
+                                               NULL, &buffer);
        mutex_unlock(&battery->lock);
 
        if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
+               ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
                return -ENODEV;
        }
-
-       result = extract_package(battery, buffer.pointer,
-                                info_offsets, ARRAY_SIZE(info_offsets));
+       if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
+               result = extract_package(battery, buffer.pointer,
+                               extended_info_offsets,
+                               ARRAY_SIZE(extended_info_offsets));
+       else
+               result = extract_package(battery, buffer.pointer,
+                               info_offsets, ARRAY_SIZE(info_offsets));
        kfree(buffer.pointer);
        return result;
 }
@@ -399,7 +444,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
        battery->update_time = jiffies;
        kfree(buffer.pointer);
 
-       if ((battery->quirks & QUIRK_SIGNED16_CURRENT) &&
+       if (test_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags) &&
            battery->rate_now != -1)
                battery->rate_now = abs((s16)battery->rate_now);
 
@@ -412,7 +457,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery)
        union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER };
        struct acpi_object_list arg_list = { 1, &arg0 };
 
-       if (!acpi_battery_present(battery)|| !battery->alarm_present)
+       if (!acpi_battery_present(battery) ||
+           !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
                return -ENODEV;
 
        arg0.integer.value = battery->alarm;
@@ -437,10 +483,10 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery)
        /* See if alarms are supported, and if so, set default */
        status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
        if (ACPI_FAILURE(status)) {
-               battery->alarm_present = 0;
+               clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
                return 0;
        }
-       battery->alarm_present = 1;
+       set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
        if (!battery->alarm)
                battery->alarm = battery->design_capacity_warning;
        return acpi_battery_set_alarm(battery);
@@ -510,9 +556,8 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
 
 static void acpi_battery_quirks(struct acpi_battery *battery)
 {
-       battery->quirks = 0;
        if (dmi_name_in_vendors("Acer") && battery->power_unit) {
-               battery->quirks |= QUIRK_SIGNED16_CURRENT;
+               set_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags);
        }
 }
 
@@ -590,6 +635,7 @@ static int acpi_battery_print_info(struct seq_file *seq, int result)
        seq_printf(seq, "design capacity low:     %d %sh\n",
                   battery->design_capacity_low,
                   acpi_battery_units(battery));
+       seq_printf(seq, "cycle count:             %i\n", battery->cycle_count);
        seq_printf(seq, "capacity granularity 1:  %d %sh\n",
                   battery->capacity_granularity_1,
                   acpi_battery_units(battery));
@@ -841,6 +887,7 @@ static int acpi_battery_add(struct acpi_device *device)
 {
        int result = 0;
        struct acpi_battery *battery = NULL;
+       acpi_handle handle;
        if (!device)
                return -EINVAL;
        battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
@@ -851,6 +898,9 @@ static int acpi_battery_add(struct acpi_device *device)
        strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
        device->driver_data = battery;
        mutex_init(&battery->lock);
+       if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
+                       "_BIX", &handle)))
+               set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
        acpi_battery_update(battery);
 #ifdef CONFIG_ACPI_PROCFS_POWER
        result = acpi_battery_add_fs(device);
index a52126e..b70cd37 100644 (file)
@@ -190,16 +190,16 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
                 * Get the device's power state either directly (via _PSC) or
                 * indirectly (via power resources).
                 */
-               if (device->power.flags.explicit_get) {
+               if (device->power.flags.power_resources) {
+                       result = acpi_power_get_inferred_state(device);
+                       if (result)
+                               return result;
+               } else if (device->power.flags.explicit_get) {
                        status = acpi_evaluate_integer(device->handle, "_PSC",
                                                       NULL, &psc);
                        if (ACPI_FAILURE(status))
                                return -ENODEV;
                        device->power.state = (int)psc;
-               } else if (device->power.flags.power_resources) {
-                       result = acpi_power_get_inferred_state(device);
-                       if (result)
-                               return result;
                }
 
                *state = device->power.state;
index d7a6bbb..1ac28c6 100644 (file)
@@ -76,8 +76,9 @@ enum ec_command {
 enum {
        EC_FLAGS_QUERY_PENDING,         /* Query is pending */
        EC_FLAGS_GPE_STORM,             /* GPE storm detected */
-       EC_FLAGS_HANDLERS_INSTALLED     /* Handlers for GPE and
+       EC_FLAGS_HANDLERS_INSTALLED,    /* Handlers for GPE and
                                         * OpReg are installed */
+       EC_FLAGS_FROZEN,                /* Transactions are suspended */
 };
 
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
@@ -291,6 +292,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
        if (t->rdata)
                memset(t->rdata, 0, t->rlen);
        mutex_lock(&ec->lock);
+       if (test_bit(EC_FLAGS_FROZEN, &ec->flags)) {
+               status = -EINVAL;
+               goto unlock;
+       }
        if (ec->global_lock) {
                status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
                if (ACPI_FAILURE(status)) {
@@ -453,6 +458,32 @@ int ec_transaction(u8 command,
 
 EXPORT_SYMBOL(ec_transaction);
 
+void acpi_ec_suspend_transactions(void)
+{
+       struct acpi_ec *ec = first_ec;
+
+       if (!ec)
+               return;
+
+       mutex_lock(&ec->lock);
+       /* Prevent transactions from being carried out */
+       set_bit(EC_FLAGS_FROZEN, &ec->flags);
+       mutex_unlock(&ec->lock);
+}
+
+void acpi_ec_resume_transactions(void)
+{
+       struct acpi_ec *ec = first_ec;
+
+       if (!ec)
+               return;
+
+       mutex_lock(&ec->lock);
+       /* Allow transactions to be carried out again */
+       clear_bit(EC_FLAGS_FROZEN, &ec->flags);
+       mutex_unlock(&ec->lock);
+}
+
 static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
 {
        int result;
index 9c4c962..e284113 100644 (file)
@@ -49,6 +49,8 @@ void acpi_early_processor_set_pdc(void);
 int acpi_ec_init(void);
 int acpi_ec_ecdt_probe(void);
 int acpi_boot_ec_enable(void);
+void acpi_ec_suspend_transactions(void);
+void acpi_ec_resume_transactions(void);
 
 /*--------------------------------------------------------------------------
                                   Suspend/Resume
index e9b7b40..791ac7b 100644 (file)
 /*
- * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $)
+ * Copyright (C) 2005 Intel Corporation
+ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
  *
- *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
- *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
- *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
- *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- *                     - Added processor hotplug support
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or (at
- *  your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *  TBD:
- *     1. Make # power states dynamic.
- *     2. Support duty_cycle values that span bit 4.
- *     3. Optimize by having scheduler determine business instead of
- *        having us try to calculate it here.
- *     4. Need C1 timing -- must modify kernel (IRQ handler) to get this.
+ *     Alex Chiang <achiang@hp.com>
+ *     - Unified x86/ia64 implementations
+ *     Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ *     - Added _PDC for platforms with Intel CPUs
  */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
-#include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
 #include <linux/dmi.h>
-#include <linux/moduleparam.h>
-#include <linux/cpuidle.h>
 
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/cpu.h>
-#include <asm/delay.h>
-#include <asm/uaccess.h>
-#include <asm/processor.h>
-#include <asm/smp.h>
-#include <asm/acpi.h>
-
-#include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/processor.h>
 
-#define PREFIX "ACPI: "
-
-#define ACPI_PROCESSOR_CLASS           "processor"
-#define ACPI_PROCESSOR_DEVICE_NAME     "Processor"
-#define ACPI_PROCESSOR_FILE_INFO       "info"
-#define ACPI_PROCESSOR_FILE_THROTTLING "throttling"
-#define ACPI_PROCESSOR_FILE_LIMIT      "limit"
-#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
-#define ACPI_PROCESSOR_NOTIFY_POWER    0x81
-#define ACPI_PROCESSOR_NOTIFY_THROTTLING       0x82
-
-#define ACPI_PROCESSOR_LIMIT_USER      0
-#define ACPI_PROCESSOR_LIMIT_THERMAL   1
+#include "internal.h"
 
+#define PREFIX                 "ACPI: "
 #define _COMPONENT             ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_core");
 
-MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION("ACPI Processor Driver");
-MODULE_LICENSE("GPL");
-
-static int acpi_processor_add(struct acpi_device *device);
-static int acpi_processor_remove(struct acpi_device *device, int type);
-#ifdef CONFIG_ACPI_PROCFS
-static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
-#endif
-static void acpi_processor_notify(struct acpi_device *device, u32 event);
-static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
-static int acpi_processor_handle_eject(struct acpi_processor *pr);
-
-
-static const struct acpi_device_id processor_device_ids[] = {
-       {ACPI_PROCESSOR_OBJECT_HID, 0},
-       {"ACPI0007", 0},
-       {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, processor_device_ids);
-
-static struct acpi_driver acpi_processor_driver = {
-       .name = "processor",
-       .class = ACPI_PROCESSOR_CLASS,
-       .ids = processor_device_ids,
-       .ops = {
-               .add = acpi_processor_add,
-               .remove = acpi_processor_remove,
-               .suspend = acpi_processor_suspend,
-               .resume = acpi_processor_resume,
-               .notify = acpi_processor_notify,
-               },
-};
-
-#define INSTALL_NOTIFY_HANDLER         1
-#define UNINSTALL_NOTIFY_HANDLER       2
-#ifdef CONFIG_ACPI_PROCFS
-static const struct file_operations acpi_processor_info_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_processor_info_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-#endif
-
-DEFINE_PER_CPU(struct acpi_processor *, processors);
-EXPORT_PER_CPU_SYMBOL(processors);
-
-struct acpi_processor_errata errata __read_mostly;
-
-/* --------------------------------------------------------------------------
-                                Errata Handling
-   -------------------------------------------------------------------------- */
-
-static int acpi_processor_errata_piix4(struct pci_dev *dev)
+static int set_no_mwait(const struct dmi_system_id *id)
 {
-       u8 value1 = 0;
-       u8 value2 = 0;
-
-
-       if (!dev)
-               return -EINVAL;
-
-       /*
-        * Note that 'dev' references the PIIX4 ACPI Controller.
-        */
-
-       switch (dev->revision) {
-       case 0:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
-               break;
-       case 1:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n"));
-               break;
-       case 2:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n"));
-               break;
-       case 3:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n"));
-               break;
-       default:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n"));
-               break;
-       }
-
-       switch (dev->revision) {
-
-       case 0:         /* PIIX4 A-step */
-       case 1:         /* PIIX4 B-step */
-               /*
-                * See specification changes #13 ("Manual Throttle Duty Cycle")
-                * and #14 ("Enabling and Disabling Manual Throttle"), plus
-                * erratum #5 ("STPCLK# Deassertion Time") from the January
-                * 2002 PIIX4 specification update.  Applies to only older
-                * PIIX4 models.
-                */
-               errata.piix4.throttle = 1;
-
-       case 2:         /* PIIX4E */
-       case 3:         /* PIIX4M */
-               /*
-                * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA
-                * Livelock") from the January 2002 PIIX4 specification update.
-                * Applies to all PIIX4 models.
-                */
-
-               /*
-                * BM-IDE
-                * ------
-                * Find the PIIX4 IDE Controller and get the Bus Master IDE
-                * Status register address.  We'll use this later to read
-                * each IDE controller's DMA status to make sure we catch all
-                * DMA activity.
-                */
-               dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
-                                    PCI_DEVICE_ID_INTEL_82371AB,
-                                    PCI_ANY_ID, PCI_ANY_ID, NULL);
-               if (dev) {
-                       errata.piix4.bmisx = pci_resource_start(dev, 4);
-                       pci_dev_put(dev);
-               }
-
-               /*
-                * Type-F DMA
-                * ----------
-                * Find the PIIX4 ISA Controller and read the Motherboard
-                * DMA controller's status to see if Type-F (Fast) DMA mode
-                * is enabled (bit 7) on either channel.  Note that we'll
-                * disable C3 support if this is enabled, as some legacy
-                * devices won't operate well if fast DMA is disabled.
-                */
-               dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
-                                    PCI_DEVICE_ID_INTEL_82371AB_0,
-                                    PCI_ANY_ID, PCI_ANY_ID, NULL);
-               if (dev) {
-                       pci_read_config_byte(dev, 0x76, &value1);
-                       pci_read_config_byte(dev, 0x77, &value2);
-                       if ((value1 & 0x80) || (value2 & 0x80))
-                               errata.piix4.fdma = 1;
-                       pci_dev_put(dev);
-               }
-
-               break;
-       }
-
-       if (errata.piix4.bmisx)
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "Bus master activity detection (BM-IDE) erratum enabled\n"));
-       if (errata.piix4.fdma)
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "Type-F DMA livelock erratum (C3 disabled)\n"));
-
+       printk(KERN_NOTICE PREFIX "%s detected - "
+               "disabling mwait for CPU C-states\n", id->ident);
+       idle_nomwait = 1;
        return 0;
 }
 
-static int acpi_processor_errata(struct acpi_processor *pr)
-{
-       int result = 0;
-       struct pci_dev *dev = NULL;
-
-
-       if (!pr)
-               return -EINVAL;
-
-       /*
-        * PIIX4
-        */
-       dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
-                            PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID,
-                            PCI_ANY_ID, NULL);
-       if (dev) {
-               result = acpi_processor_errata_piix4(dev);
-               pci_dev_put(dev);
-       }
-
-       return result;
-}
-
-/* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ACPI_PROCFS
-static struct proc_dir_entry *acpi_processor_dir = NULL;
-
-static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_processor *pr = seq->private;
-
-
-       if (!pr)
-               goto end;
-
-       seq_printf(seq, "processor id:            %d\n"
-                  "acpi id:                 %d\n"
-                  "bus mastering control:   %s\n"
-                  "power management:        %s\n"
-                  "throttling control:      %s\n"
-                  "limit interface:         %s\n",
-                  pr->id,
-                  pr->acpi_id,
-                  pr->flags.bm_control ? "yes" : "no",
-                  pr->flags.power ? "yes" : "no",
-                  pr->flags.throttling ? "yes" : "no",
-                  pr->flags.limit ? "yes" : "no");
-
-      end:
-       return 0;
-}
-
-static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_processor_info_seq_show,
-                          PDE(inode)->data);
-}
-
-static int __cpuinit acpi_processor_add_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *entry = NULL;
-
-
-       if (!acpi_device_dir(device)) {
-               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-                                                    acpi_processor_dir);
-               if (!acpi_device_dir(device))
-                       return -ENODEV;
-       }
-
-       /* 'info' [R] */
-       entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO,
-                                S_IRUGO, acpi_device_dir(device),
-                                &acpi_processor_info_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               return -EIO;
-
-       /* 'throttling' [R/W] */
-       entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING,
-                                S_IFREG | S_IRUGO | S_IWUSR,
-                                acpi_device_dir(device),
-                                &acpi_processor_throttling_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               return -EIO;
-
-       /* 'limit' [R/W] */
-       entry = proc_create_data(ACPI_PROCESSOR_FILE_LIMIT,
-                                S_IFREG | S_IRUGO | S_IWUSR,
-                                acpi_device_dir(device),
-                                &acpi_processor_limit_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               return -EIO;
-       return 0;
-}
-static int acpi_processor_remove_fs(struct acpi_device *device)
-{
-
-       if (acpi_device_dir(device)) {
-               remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,
-                                 acpi_device_dir(device));
-               remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
-                                 acpi_device_dir(device));
-               remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
-                                 acpi_device_dir(device));
-               remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
-               acpi_device_dir(device) = NULL;
-       }
-
-       return 0;
-}
-#else
-static inline int acpi_processor_add_fs(struct acpi_device *device)
-{
-       return 0;
-}
-static inline int acpi_processor_remove_fs(struct acpi_device *device)
-{
-       return 0;
-}
-#endif
-
-/* Use the acpiid in MADT to map cpus in case of SMP */
-
-#ifndef CONFIG_SMP
-static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { return -1; }
-#else
-
-static struct acpi_table_madt *madt;
+static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
+       {
+       set_no_mwait, "IFL91 board", {
+       DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
+       DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
+       DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
+       DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
+       {
+       set_no_mwait, "Extensa 5220", {
+       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+       DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+       DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
+       {},
+};
 
+#ifdef CONFIG_SMP
 static int map_lapic_id(struct acpi_subtable_header *entry,
                 u32 acpi_id, int *apic_id)
 {
        struct acpi_madt_local_apic *lapic =
                (struct acpi_madt_local_apic *)entry;
-       if ((lapic->lapic_flags & ACPI_MADT_ENABLED) &&
-           lapic->processor_id == acpi_id) {
-               *apic_id = lapic->id;
-               return 1;
-       }
-       return 0;
+
+       if (!(lapic->lapic_flags & ACPI_MADT_ENABLED))
+               return 0;
+
+       if (lapic->processor_id != acpi_id)
+               return 0;
+
+       *apic_id = lapic->id;
+       return 1;
 }
 
 static int map_x2apic_id(struct acpi_subtable_header *entry,
@@ -385,22 +64,16 @@ static int map_x2apic_id(struct acpi_subtable_header *entry,
 {
        struct acpi_madt_local_x2apic *apic =
                (struct acpi_madt_local_x2apic *)entry;
-       u32 tmp = apic->local_apic_id;
 
-       /* Only check enabled APICs*/
        if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
                return 0;
 
-       /* Device statement declaration type */
-       if (device_declaration) {
-               if (apic->uid == acpi_id)
-                       goto found;
+       if (device_declaration && (apic->uid == acpi_id)) {
+               *apic_id = apic->local_apic_id;
+               return 1;
        }
 
        return 0;
-found:
-       *apic_id = tmp;
-       return 1;
 }
 
 static int map_lsapic_id(struct acpi_subtable_header *entry,
@@ -408,35 +81,34 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
 {
        struct acpi_madt_local_sapic *lsapic =
                (struct acpi_madt_local_sapic *)entry;
-       u32 tmp = (lsapic->id << 8) | lsapic->eid;
 
-       /* Only check enabled APICs*/
        if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))
                return 0;
 
-       /* Device statement declaration type */
        if (device_declaration) {
-               if (entry->length < 16)
-                       printk(KERN_ERR PREFIX
-                           "Invalid LSAPIC with Device type processor (SAPIC ID %#x)\n",
-                           tmp);
-               else if (lsapic->uid == acpi_id)
-                       goto found;
-       /* Processor statement declaration type */
-       } else if (lsapic->processor_id == acpi_id)
-               goto found;
+               if ((entry->length < 16) || (lsapic->uid != acpi_id))
+                       return 0;
+       } else if (lsapic->processor_id != acpi_id)
+               return 0;
 
-       return 0;
-found:
-       *apic_id = tmp;
+       *apic_id = (lsapic->id << 8) | lsapic->eid;
        return 1;
 }
 
 static int map_madt_entry(int type, u32 acpi_id)
 {
        unsigned long madt_end, entry;
+       static struct acpi_table_madt *madt;
+       static int read_madt;
        int apic_id = -1;
 
+       if (!read_madt) {
+               if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
+                                       (struct acpi_table_header **)&madt)))
+                       madt = NULL;
+               read_madt++;
+       }
+
        if (!madt)
                return apic_id;
 
@@ -496,7 +168,7 @@ exit:
        return apic_id;
 }
 
-static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id)
+int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
 {
        int i;
        int apic_id = -1;
@@ -513,630 +185,170 @@ static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id)
        }
        return -1;
 }
+EXPORT_SYMBOL_GPL(acpi_get_cpuid);
 #endif
 
-/* --------------------------------------------------------------------------
-                                 Driver Interface
-   -------------------------------------------------------------------------- */
-
-static int acpi_processor_get_info(struct acpi_device *device)
+static bool processor_physically_present(acpi_handle handle)
 {
-       acpi_status status = 0;
+       int cpuid, type;
+       u32 acpi_id;
+       acpi_status status;
+       acpi_object_type acpi_type;
+       unsigned long long tmp;
        union acpi_object object = { 0 };
        struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
-       struct acpi_processor *pr;
-       int cpu_index, device_declaration = 0;
-       static int cpu0_initialized;
-
-       pr = acpi_driver_data(device);
-       if (!pr)
-               return -EINVAL;
-
-       if (num_online_cpus() > 1)
-               errata.smp = TRUE;
-
-       acpi_processor_errata(pr);
-
-       /*
-        * Check to see if we have bus mastering arbitration control.  This
-        * is required for proper C3 usage (to maintain cache coherency).
-        */
-       if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) {
-               pr->flags.bm_control = 1;
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "Bus mastering arbitration control present\n"));
-       } else
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "No bus mastering arbitration control\n"));
-
-       if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
-               /* Declared with "Processor" statement; match ProcessorID */
-               status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
-               if (ACPI_FAILURE(status)) {
-                       printk(KERN_ERR PREFIX "Evaluating processor object\n");
-                       return -ENODEV;
-               }
-
-               /*
-                * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
-                *      >>> 'acpi_get_processor_id(acpi_id, &id)' in
-                *      arch/xxx/acpi.c
-                */
-               pr->acpi_id = object.processor.proc_id;
-       } else {
-               /*
-                * Declared with "Device" statement; match _UID.
-                * Note that we don't handle string _UIDs yet.
-                */
-               unsigned long long value;
-               status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
-                                               NULL, &value);
-               if (ACPI_FAILURE(status)) {
-                       printk(KERN_ERR PREFIX
-                           "Evaluating processor _UID [%#x]\n", status);
-                       return -ENODEV;
-               }
-               device_declaration = 1;
-               pr->acpi_id = value;
-       }
-       cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id);
-
-       /* Handle UP system running SMP kernel, with no LAPIC in MADT */
-       if (!cpu0_initialized && (cpu_index == -1) &&
-           (num_online_cpus() == 1)) {
-               cpu_index = 0;
-       }
-
-       cpu0_initialized = 1;
-
-       pr->id = cpu_index;
-
-       /*
-        *  Extra Processor objects may be enumerated on MP systems with
-        *  less than the max # of CPUs. They should be ignored _iff
-        *  they are physically not present.
-        */
-       if (pr->id == -1) {
-               if (ACPI_FAILURE
-                   (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
-                       return -ENODEV;
-               }
-       }
-       /*
-        * On some boxes several processors use the same processor bus id.
-        * But they are located in different scope. For example:
-        * \_SB.SCK0.CPU0
-        * \_SB.SCK1.CPU0
-        * Rename the processor device bus id. And the new bus id will be
-        * generated as the following format:
-        * CPU+CPU ID.
-        */
-       sprintf(acpi_device_bid(device), "CPU%X", pr->id);
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
-                         pr->acpi_id));
-
-       if (!object.processor.pblk_address)
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
-       else if (object.processor.pblk_length != 6)
-               printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
-                           object.processor.pblk_length);
-       else {
-               pr->throttling.address = object.processor.pblk_address;
-               pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset;
-               pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
-
-               pr->pblk = object.processor.pblk_address;
-
-               /*
-                * We don't care about error returns - we just try to mark
-                * these reserved so that nobody else is confused into thinking
-                * that this region might be unused..
-                *
-                * (In particular, allocating the IO range for Cardbus)
-                */
-               request_region(pr->throttling.address, 6, "ACPI CPU throttle");
-       }
-
-       /*
-        * If ACPI describes a slot number for this CPU, we can use it
-        * ensure we get the right value in the "physical id" field
-        * of /proc/cpuinfo
-        */
-       status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
-       if (ACPI_SUCCESS(status))
-               arch_fix_phys_package_id(pr->id, object.integer.value);
-
-       return 0;
-}
-
-static DEFINE_PER_CPU(void *, processor_device_array);
-
-static void acpi_processor_notify(struct acpi_device *device, u32 event)
-{
-       struct acpi_processor *pr = acpi_driver_data(device);
-       int saved;
-
-       if (!pr)
-               return;
 
-       switch (event) {
-       case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
-               saved = pr->performance_platform_limit;
-               acpi_processor_ppc_has_changed(pr, 1);
-               if (saved == pr->performance_platform_limit)
-                       break;
-               acpi_bus_generate_proc_event(device, event,
-                                       pr->performance_platform_limit);
-               acpi_bus_generate_netlink_event(device->pnp.device_class,
-                                                 dev_name(&device->dev), event,
-                                                 pr->performance_platform_limit);
+       status = acpi_get_type(handle, &acpi_type);
+       if (ACPI_FAILURE(status))
+               return false;
+
+       switch (acpi_type) {
+       case ACPI_TYPE_PROCESSOR:
+               status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
+               if (ACPI_FAILURE(status))
+                       return false;
+               acpi_id = object.processor.proc_id;
                break;
-       case ACPI_PROCESSOR_NOTIFY_POWER:
-               acpi_processor_cst_has_changed(pr);
-               acpi_bus_generate_proc_event(device, event, 0);
-               acpi_bus_generate_netlink_event(device->pnp.device_class,
-                                                 dev_name(&device->dev), event, 0);
+       case ACPI_TYPE_DEVICE:
+               status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
+               if (ACPI_FAILURE(status))
+                       return false;
+               acpi_id = tmp;
                break;
-       case ACPI_PROCESSOR_NOTIFY_THROTTLING:
-               acpi_processor_tstate_has_changed(pr);
-               acpi_bus_generate_proc_event(device, event, 0);
-               acpi_bus_generate_netlink_event(device->pnp.device_class,
-                                                 dev_name(&device->dev), event, 0);
        default:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "Unsupported event [0x%x]\n", event));
-               break;
+               return false;
        }
 
-       return;
-}
+       type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
+       cpuid = acpi_get_cpuid(handle, type, acpi_id);
 
-static int acpi_cpu_soft_notify(struct notifier_block *nfb,
-               unsigned long action, void *hcpu)
-{
-       unsigned int cpu = (unsigned long)hcpu;
-       struct acpi_processor *pr = per_cpu(processors, cpu);
+       if (cpuid == -1)
+               return false;
 
-       if (action == CPU_ONLINE && pr) {
-               acpi_processor_ppc_has_changed(pr, 0);
-               acpi_processor_cst_has_changed(pr);
-               acpi_processor_tstate_has_changed(pr);
-       }
-       return NOTIFY_OK;
+       return true;
 }
 
-static struct notifier_block acpi_cpu_notifier =
+static void acpi_set_pdc_bits(u32 *buf)
 {
-           .notifier_call = acpi_cpu_soft_notify,
-};
-
-static int __cpuinit acpi_processor_add(struct acpi_device *device)
-{
-       struct acpi_processor *pr = NULL;
-       int result = 0;
-       struct sys_device *sysdev;
-
-       pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
-       if (!pr)
-               return -ENOMEM;
-
-       if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
-               kfree(pr);
-               return -ENOMEM;
-       }
-
-       pr->handle = device->handle;
-       strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
-       strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
-       device->driver_data = pr;
-
-       result = acpi_processor_get_info(device);
-       if (result) {
-               /* Processor is physically not present */
-               return 0;
-       }
-
-       BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
-
-       /*
-        * Buggy BIOS check
-        * ACPI id of processors can be reported wrongly by the BIOS.
-        * Don't trust it blindly
-        */
-       if (per_cpu(processor_device_array, pr->id) != NULL &&
-           per_cpu(processor_device_array, pr->id) != device) {
-               printk(KERN_WARNING "BIOS reported wrong ACPI id "
-                       "for the processor\n");
-               result = -ENODEV;
-               goto err_free_cpumask;
-       }
-       per_cpu(processor_device_array, pr->id) = device;
+       buf[0] = ACPI_PDC_REVISION_ID;
+       buf[1] = 1;
 
-       per_cpu(processors, pr->id) = pr;
+       /* Enable coordination with firmware's _TSD info */
+       buf[2] = ACPI_PDC_SMP_T_SWCOORD;
 
-       result = acpi_processor_add_fs(device);
-       if (result)
-               goto err_free_cpumask;
-
-       sysdev = get_cpu_sysdev(pr->id);
-       if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
-               result = -EFAULT;
-               goto err_remove_fs;
-       }
-
-       /* _PDC call should be done before doing anything else (if reqd.). */
-       acpi_processor_set_pdc(pr->handle);
-
-#ifdef CONFIG_CPU_FREQ
-       acpi_processor_ppc_has_changed(pr, 0);
-#endif
-       acpi_processor_get_throttling_info(pr);
-       acpi_processor_get_limit_info(pr);
-
-
-       acpi_processor_power_init(pr, device);
-
-       pr->cdev = thermal_cooling_device_register("Processor", device,
-                                               &processor_cooling_ops);
-       if (IS_ERR(pr->cdev)) {
-               result = PTR_ERR(pr->cdev);
-               goto err_power_exit;
-       }
-
-       dev_dbg(&device->dev, "registered as cooling_device%d\n",
-                pr->cdev->id);
-
-       result = sysfs_create_link(&device->dev.kobj,
-                                  &pr->cdev->device.kobj,
-                                  "thermal_cooling");
-       if (result) {
-               printk(KERN_ERR PREFIX "Create sysfs link\n");
-               goto err_thermal_unregister;
-       }
-       result = sysfs_create_link(&pr->cdev->device.kobj,
-                                  &device->dev.kobj,
-                                  "device");
-       if (result) {
-               printk(KERN_ERR PREFIX "Create sysfs link\n");
-               goto err_remove_sysfs;
-       }
-
-       return 0;
-
-err_remove_sysfs:
-       sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
-err_thermal_unregister:
-       thermal_cooling_device_unregister(pr->cdev);
-err_power_exit:
-       acpi_processor_power_exit(pr, device);
-err_remove_fs:
-       acpi_processor_remove_fs(device);
-err_free_cpumask:
-       free_cpumask_var(pr->throttling.shared_cpu_map);
-
-       return result;
+       /* Twiddle arch-specific bits needed for _PDC */
+       arch_acpi_set_pdc_bits(buf);
 }
 
-static int acpi_processor_remove(struct acpi_device *device, int type)
+static struct acpi_object_list *acpi_processor_alloc_pdc(void)
 {
-       struct acpi_processor *pr = NULL;
-
-
-       if (!device || !acpi_driver_data(device))
-               return -EINVAL;
-
-       pr = acpi_driver_data(device);
-
-       if (pr->id >= nr_cpu_ids)
-               goto free;
+       struct acpi_object_list *obj_list;
+       union acpi_object *obj;
+       u32 *buf;
 
-       if (type == ACPI_BUS_REMOVAL_EJECT) {
-               if (acpi_processor_handle_eject(pr))
-                       return -EINVAL;
+       /* allocate and initialize pdc. It will be used later. */
+       obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
+       if (!obj_list) {
+               printk(KERN_ERR "Memory allocation error\n");
+               return NULL;
        }
 
-       acpi_processor_power_exit(pr, device);
-
-       sysfs_remove_link(&device->dev.kobj, "sysdev");
-
-       acpi_processor_remove_fs(device);
-
-       if (pr->cdev) {
-               sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
-               sysfs_remove_link(&pr->cdev->device.kobj, "device");
-               thermal_cooling_device_unregister(pr->cdev);
-               pr->cdev = NULL;
+       obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+       if (!obj) {
+               printk(KERN_ERR "Memory allocation error\n");
+               kfree(obj_list);
+               return NULL;
        }
 
-       per_cpu(processors, pr->id) = NULL;
-       per_cpu(processor_device_array, pr->id) = NULL;
-
-free:
-       free_cpumask_var(pr->throttling.shared_cpu_map);
-       kfree(pr);
-
-       return 0;
-}
-
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
-/****************************************************************************
- *     Acpi processor hotplug support                                      *
- ****************************************************************************/
-
-static int is_processor_present(acpi_handle handle)
-{
-       acpi_status status;
-       unsigned long long sta = 0;
-
-
-       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-
-       if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
-               return 1;
-
-       /*
-        * _STA is mandatory for a processor that supports hot plug
-        */
-       if (status == AE_NOT_FOUND)
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                               "Processor does not support hot plug\n"));
-       else
-               ACPI_EXCEPTION((AE_INFO, status,
-                               "Processor Device is not present"));
-       return 0;
-}
-
-static
-int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
-{
-       acpi_handle phandle;
-       struct acpi_device *pdev;
-
-
-       if (acpi_get_parent(handle, &phandle)) {
-               return -ENODEV;
+       buf = kmalloc(12, GFP_KERNEL);
+       if (!buf) {
+               printk(KERN_ERR "Memory allocation error\n");
+               kfree(obj);
+               kfree(obj_list);
+               return NULL;
        }
 
-       if (acpi_bus_get_device(phandle, &pdev)) {
-               return -ENODEV;
-       }
+       acpi_set_pdc_bits(buf);
 
-       if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
-               return -ENODEV;
-       }
+       obj->type = ACPI_TYPE_BUFFER;
+       obj->buffer.length = 12;
+       obj->buffer.pointer = (u8 *) buf;
+       obj_list->count = 1;
+       obj_list->pointer = obj;
 
-       return 0;
+       return obj_list;
 }
 
-static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
-                                               u32 event, void *data)
+/*
+ * _PDC is required for a BIOS-OS handshake for most of the newer
+ * ACPI processor features.
+ */
+static int
+acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
 {
-       struct acpi_processor *pr;
-       struct acpi_device *device = NULL;
-       int result;
-
+       acpi_status status = AE_OK;
 
-       switch (event) {
-       case ACPI_NOTIFY_BUS_CHECK:
-       case ACPI_NOTIFY_DEVICE_CHECK:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-               "Processor driver received %s event\n",
-                      (event == ACPI_NOTIFY_BUS_CHECK) ?
-                      "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"));
-
-               if (!is_processor_present(handle))
-                       break;
+       if (idle_nomwait) {
+               /*
+                * If mwait is disabled for CPU C-states, the C2C3_FFH access
+                * mode will be disabled in the parameter of _PDC object.
+                * Of course C1_FFH access mode will also be disabled.
+                */
+               union acpi_object *obj;
+               u32 *buffer = NULL;
 
-               if (acpi_bus_get_device(handle, &device)) {
-                       result = acpi_processor_device_add(handle, &device);
-                       if (result)
-                               printk(KERN_ERR PREFIX
-                                           "Unable to add the device\n");
-                       break;
-               }
-               break;
-       case ACPI_NOTIFY_EJECT_REQUEST:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "received ACPI_NOTIFY_EJECT_REQUEST\n"));
+               obj = pdc_in->pointer;
+               buffer = (u32 *)(obj->buffer.pointer);
+               buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
 
-               if (acpi_bus_get_device(handle, &device)) {
-                       printk(KERN_ERR PREFIX
-                                   "Device don't exist, dropping EJECT\n");
-                       break;
-               }
-               pr = acpi_driver_data(device);
-               if (!pr) {
-                       printk(KERN_ERR PREFIX
-                                   "Driver data is NULL, dropping EJECT\n");
-                       return;
-               }
-               break;
-       default:
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "Unsupported event [0x%x]\n", event));
-               break;
        }
+       status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
 
-       return;
-}
-
-static acpi_status
-processor_walk_namespace_cb(acpi_handle handle,
-                           u32 lvl, void *context, void **rv)
-{
-       acpi_status status;
-       int *action = context;
-       acpi_object_type type = 0;
-
-       status = acpi_get_type(handle, &type);
        if (ACPI_FAILURE(status))
-               return (AE_OK);
-
-       if (type != ACPI_TYPE_PROCESSOR)
-               return (AE_OK);
-
-       switch (*action) {
-       case INSTALL_NOTIFY_HANDLER:
-               acpi_install_notify_handler(handle,
-                                           ACPI_SYSTEM_NOTIFY,
-                                           acpi_processor_hotplug_notify,
-                                           NULL);
-               break;
-       case UNINSTALL_NOTIFY_HANDLER:
-               acpi_remove_notify_handler(handle,
-                                          ACPI_SYSTEM_NOTIFY,
-                                          acpi_processor_hotplug_notify);
-               break;
-       default:
-               break;
-       }
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                   "Could not evaluate _PDC, using legacy perf. control.\n"));
 
-       return (AE_OK);
+       return status;
 }
 
-static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
+void acpi_processor_set_pdc(acpi_handle handle)
 {
+       struct acpi_object_list *obj_list;
 
-       if (!is_processor_present(handle)) {
-               return AE_ERROR;
-       }
+       if (arch_has_acpi_pdc() == false)
+               return;
 
-       if (acpi_map_lsapic(handle, p_cpu))
-               return AE_ERROR;
+       obj_list = acpi_processor_alloc_pdc();
+       if (!obj_list)
+               return;
 
-       if (arch_register_cpu(*p_cpu)) {
-               acpi_unmap_lsapic(*p_cpu);
-               return AE_ERROR;
-       }
+       acpi_processor_eval_pdc(handle, obj_list);
 
-       return AE_OK;
+       kfree(obj_list->pointer->buffer.pointer);
+       kfree(obj_list->pointer);
+       kfree(obj_list);
 }
+EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
 
-static int acpi_processor_handle_eject(struct acpi_processor *pr)
+static acpi_status
+early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
-       if (cpu_online(pr->id))
-               cpu_down(pr->id);
+       if (processor_physically_present(handle) == false)
+               return AE_OK;
 
-       arch_unregister_cpu(pr->id);
-       acpi_unmap_lsapic(pr->id);
-       return (0);
-}
-#else
-static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
-{
-       return AE_ERROR;
-}
-static int acpi_processor_handle_eject(struct acpi_processor *pr)
-{
-       return (-EINVAL);
+       acpi_processor_set_pdc(handle);
+       return AE_OK;
 }
-#endif
 
-static
-void acpi_processor_install_hotplug_notify(void)
+void __init acpi_early_processor_set_pdc(void)
 {
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
-       int action = INSTALL_NOTIFY_HANDLER;
-       acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
-                           ACPI_ROOT_OBJECT,
-                           ACPI_UINT32_MAX,
-                           processor_walk_namespace_cb, NULL, &action, NULL);
-#endif
-       register_hotcpu_notifier(&acpi_cpu_notifier);
-}
+       /*
+        * Check whether the system is DMI table. If yes, OSPM
+        * should not use mwait for CPU-states.
+        */
+       dmi_check_system(processor_idle_dmi_table);
 
-static
-void acpi_processor_uninstall_hotplug_notify(void)
-{
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
-       int action = UNINSTALL_NOTIFY_HANDLER;
-       acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
-                           ACPI_ROOT_OBJECT,
+       acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX,
-                           processor_walk_namespace_cb, NULL, &action, NULL);
-#endif
-       unregister_hotcpu_notifier(&acpi_cpu_notifier);
+                           early_init_pdc, NULL, NULL, NULL);
 }
-
-/*
- * We keep the driver loaded even when ACPI is not running.
- * This is needed for the powernow-k8 driver, that works even without
- * ACPI, but needs symbols from this driver
- */
-
-static int __init acpi_processor_init(void)
-{
-       int result = 0;
-
-       if (acpi_disabled)
-               return 0;
-
-       memset(&errata, 0, sizeof(errata));
-
-#ifdef CONFIG_SMP
-       if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
-                               (struct acpi_table_header **)&madt)))
-               madt = NULL;
-#endif
-#ifdef CONFIG_ACPI_PROCFS
-       acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-       if (!acpi_processor_dir)
-               return -ENOMEM;
-#endif
-       result = cpuidle_register_driver(&acpi_idle_driver);
-       if (result < 0)
-               goto out_proc;
-
-       result = acpi_bus_register_driver(&acpi_processor_driver);
-       if (result < 0)
-               goto out_cpuidle;
-
-       acpi_processor_install_hotplug_notify();
-
-       acpi_thermal_cpufreq_init();
-
-       acpi_processor_ppc_init();
-
-       acpi_processor_throttling_init();
-
-       return 0;
-
-out_cpuidle:
-       cpuidle_unregister_driver(&acpi_idle_driver);
-
-out_proc:
-#ifdef CONFIG_ACPI_PROCFS
-       remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-#endif
-
-       return result;
-}
-
-static void __exit acpi_processor_exit(void)
-{
-       if (acpi_disabled)
-               return;
-
-       acpi_processor_ppc_exit();
-
-       acpi_thermal_cpufreq_exit();
-
-       acpi_processor_uninstall_hotplug_notify();
-
-       acpi_bus_unregister_driver(&acpi_processor_driver);
-
-       cpuidle_unregister_driver(&acpi_idle_driver);
-
-#ifdef CONFIG_ACPI_PROCFS
-       remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
-#endif
-
-       return;
-}
-
-module_init(acpi_processor_init);
-module_exit(acpi_processor_exit);
-
-EXPORT_SYMBOL(acpi_processor_set_thermal_limit);
-
-MODULE_ALIAS("processor");
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
new file mode 100644 (file)
index 0000000..b5658cd
--- /dev/null
@@ -0,0 +1,978 @@
+/*
+ * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $)
+ *
+ *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
+ *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
+ *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
+ *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ *                     - Added processor hotplug support
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *  TBD:
+ *     1. Make # power states dynamic.
+ *     2. Support duty_cycle values that span bit 4.
+ *     3. Optimize by having scheduler determine business instead of
+ *        having us try to calculate it here.
+ *     4. Need C1 timing -- must modify kernel (IRQ handler) to get this.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/cpufreq.h>
+#include <linux/cpu.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/dmi.h>
+#include <linux/moduleparam.h>
+#include <linux/cpuidle.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/cpu.h>
+#include <asm/delay.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/smp.h>
+#include <asm/acpi.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/processor.h>
+
+#define PREFIX "ACPI: "
+
+#define ACPI_PROCESSOR_CLASS           "processor"
+#define ACPI_PROCESSOR_DEVICE_NAME     "Processor"
+#define ACPI_PROCESSOR_FILE_INFO       "info"
+#define ACPI_PROCESSOR_FILE_THROTTLING "throttling"
+#define ACPI_PROCESSOR_FILE_LIMIT      "limit"
+#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
+#define ACPI_PROCESSOR_NOTIFY_POWER    0x81
+#define ACPI_PROCESSOR_NOTIFY_THROTTLING       0x82
+
+#define ACPI_PROCESSOR_LIMIT_USER      0
+#define ACPI_PROCESSOR_LIMIT_THERMAL   1
+
+#define _COMPONENT             ACPI_PROCESSOR_COMPONENT
+ACPI_MODULE_NAME("processor_driver");
+
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Processor Driver");
+MODULE_LICENSE("GPL");
+
+static int acpi_processor_add(struct acpi_device *device);
+static int acpi_processor_remove(struct acpi_device *device, int type);
+#ifdef CONFIG_ACPI_PROCFS
+static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
+#endif
+static void acpi_processor_notify(struct acpi_device *device, u32 event);
+static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
+static int acpi_processor_handle_eject(struct acpi_processor *pr);
+
+
+static const struct acpi_device_id processor_device_ids[] = {
+       {ACPI_PROCESSOR_OBJECT_HID, 0},
+       {"ACPI0007", 0},
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, processor_device_ids);
+
+static struct acpi_driver acpi_processor_driver = {
+       .name = "processor",
+       .class = ACPI_PROCESSOR_CLASS,
+       .ids = processor_device_ids,
+       .ops = {
+               .add = acpi_processor_add,
+               .remove = acpi_processor_remove,
+               .suspend = acpi_processor_suspend,
+               .resume = acpi_processor_resume,
+               .notify = acpi_processor_notify,
+               },
+};
+
+#define INSTALL_NOTIFY_HANDLER         1
+#define UNINSTALL_NOTIFY_HANDLER       2
+#ifdef CONFIG_ACPI_PROCFS
+static const struct file_operations acpi_processor_info_fops = {
+       .owner = THIS_MODULE,
+       .open = acpi_processor_info_open_fs,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+#endif
+
+DEFINE_PER_CPU(struct acpi_processor *, processors);
+EXPORT_PER_CPU_SYMBOL(processors);
+
+struct acpi_processor_errata errata __read_mostly;
+
+/* --------------------------------------------------------------------------
+                                Errata Handling
+   -------------------------------------------------------------------------- */
+
+static int acpi_processor_errata_piix4(struct pci_dev *dev)
+{
+       u8 value1 = 0;
+       u8 value2 = 0;
+
+
+       if (!dev)
+               return -EINVAL;
+
+       /*
+        * Note that 'dev' references the PIIX4 ACPI Controller.
+        */
+
+       switch (dev->revision) {
+       case 0:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
+               break;
+       case 1:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n"));
+               break;
+       case 2:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n"));
+               break;
+       case 3:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n"));
+               break;
+       default:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n"));
+               break;
+       }
+
+       switch (dev->revision) {
+
+       case 0:         /* PIIX4 A-step */
+       case 1:         /* PIIX4 B-step */
+               /*
+                * See specification changes #13 ("Manual Throttle Duty Cycle")
+                * and #14 ("Enabling and Disabling Manual Throttle"), plus
+                * erratum #5 ("STPCLK# Deassertion Time") from the January
+                * 2002 PIIX4 specification update.  Applies to only older
+                * PIIX4 models.
+                */
+               errata.piix4.throttle = 1;
+
+       case 2:         /* PIIX4E */
+       case 3:         /* PIIX4M */
+               /*
+                * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA
+                * Livelock") from the January 2002 PIIX4 specification update.
+                * Applies to all PIIX4 models.
+                */
+
+               /*
+                * BM-IDE
+                * ------
+                * Find the PIIX4 IDE Controller and get the Bus Master IDE
+                * Status register address.  We'll use this later to read
+                * each IDE controller's DMA status to make sure we catch all
+                * DMA activity.
+                */
+               dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+                                    PCI_DEVICE_ID_INTEL_82371AB,
+                                    PCI_ANY_ID, PCI_ANY_ID, NULL);
+               if (dev) {
+                       errata.piix4.bmisx = pci_resource_start(dev, 4);
+                       pci_dev_put(dev);
+               }
+
+               /*
+                * Type-F DMA
+                * ----------
+                * Find the PIIX4 ISA Controller and read the Motherboard
+                * DMA controller's status to see if Type-F (Fast) DMA mode
+                * is enabled (bit 7) on either channel.  Note that we'll
+                * disable C3 support if this is enabled, as some legacy
+                * devices won't operate well if fast DMA is disabled.
+                */
+               dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+                                    PCI_DEVICE_ID_INTEL_82371AB_0,
+                                    PCI_ANY_ID, PCI_ANY_ID, NULL);
+               if (dev) {
+                       pci_read_config_byte(dev, 0x76, &value1);
+                       pci_read_config_byte(dev, 0x77, &value2);
+                       if ((value1 & 0x80) || (value2 & 0x80))
+                               errata.piix4.fdma = 1;
+                       pci_dev_put(dev);
+               }
+
+               break;
+       }
+
+       if (errata.piix4.bmisx)
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Bus master activity detection (BM-IDE) erratum enabled\n"));
+       if (errata.piix4.fdma)
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Type-F DMA livelock erratum (C3 disabled)\n"));
+
+       return 0;
+}
+
+static int acpi_processor_errata(struct acpi_processor *pr)
+{
+       int result = 0;
+       struct pci_dev *dev = NULL;
+
+
+       if (!pr)
+               return -EINVAL;
+
+       /*
+        * PIIX4
+        */
+       dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+                            PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID,
+                            PCI_ANY_ID, NULL);
+       if (dev) {
+               result = acpi_processor_errata_piix4(dev);
+               pci_dev_put(dev);
+       }
+
+       return result;
+}
+
+/* --------------------------------------------------------------------------
+                              FS Interface (/proc)
+   -------------------------------------------------------------------------- */
+
+#ifdef CONFIG_ACPI_PROCFS
+static struct proc_dir_entry *acpi_processor_dir = NULL;
+
+static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
+{
+       struct acpi_processor *pr = seq->private;
+
+
+       if (!pr)
+               goto end;
+
+       seq_printf(seq, "processor id:            %d\n"
+                  "acpi id:                 %d\n"
+                  "bus mastering control:   %s\n"
+                  "power management:        %s\n"
+                  "throttling control:      %s\n"
+                  "limit interface:         %s\n",
+                  pr->id,
+                  pr->acpi_id,
+                  pr->flags.bm_control ? "yes" : "no",
+                  pr->flags.power ? "yes" : "no",
+                  pr->flags.throttling ? "yes" : "no",
+                  pr->flags.limit ? "yes" : "no");
+
+      end:
+       return 0;
+}
+
+static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_processor_info_seq_show,
+                          PDE(inode)->data);
+}
+
+static int __cpuinit acpi_processor_add_fs(struct acpi_device *device)
+{
+       struct proc_dir_entry *entry = NULL;
+
+
+       if (!acpi_device_dir(device)) {
+               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
+                                                    acpi_processor_dir);
+               if (!acpi_device_dir(device))
+                       return -ENODEV;
+       }
+
+       /* 'info' [R] */
+       entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO,
+                                S_IRUGO, acpi_device_dir(device),
+                                &acpi_processor_info_fops,
+                                acpi_driver_data(device));
+       if (!entry)
+               return -EIO;
+
+       /* 'throttling' [R/W] */
+       entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING,
+                                S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_processor_throttling_fops,
+                                acpi_driver_data(device));
+       if (!entry)
+               return -EIO;
+
+       /* 'limit' [R/W] */
+       entry = proc_create_data(ACPI_PROCESSOR_FILE_LIMIT,
+                                S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_processor_limit_fops,
+                                acpi_driver_data(device));
+       if (!entry)
+               return -EIO;
+       return 0;
+}
+static int acpi_processor_remove_fs(struct acpi_device *device)
+{
+
+       if (acpi_device_dir(device)) {
+               remove_proc_entry(ACPI_PROCESSOR_FILE_INFO,
+                                 acpi_device_dir(device));
+               remove_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
+                                 acpi_device_dir(device));
+               remove_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
+                                 acpi_device_dir(device));
+               remove_proc_entry(acpi_device_bid(device), acpi_processor_dir);
+               acpi_device_dir(device) = NULL;
+       }
+
+       return 0;
+}
+#else
+static inline int acpi_processor_add_fs(struct acpi_device *device)
+{
+       return 0;
+}
+static inline int acpi_processor_remove_fs(struct acpi_device *device)
+{
+       return 0;
+}
+#endif
+
+/* --------------------------------------------------------------------------
+                                 Driver Interface
+   -------------------------------------------------------------------------- */
+
+static int acpi_processor_get_info(struct acpi_device *device)
+{
+       acpi_status status = 0;
+       union acpi_object object = { 0 };
+       struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
+       struct acpi_processor *pr;
+       int cpu_index, device_declaration = 0;
+       static int cpu0_initialized;
+
+       pr = acpi_driver_data(device);
+       if (!pr)
+               return -EINVAL;
+
+       if (num_online_cpus() > 1)
+               errata.smp = TRUE;
+
+       acpi_processor_errata(pr);
+
+       /*
+        * Check to see if we have bus mastering arbitration control.  This
+        * is required for proper C3 usage (to maintain cache coherency).
+        */
+       if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) {
+               pr->flags.bm_control = 1;
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Bus mastering arbitration control present\n"));
+       } else
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "No bus mastering arbitration control\n"));
+
+       if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
+               /* Declared with "Processor" statement; match ProcessorID */
+               status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
+               if (ACPI_FAILURE(status)) {
+                       printk(KERN_ERR PREFIX "Evaluating processor object\n");
+                       return -ENODEV;
+               }
+
+               /*
+                * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
+                *      >>> 'acpi_get_processor_id(acpi_id, &id)' in
+                *      arch/xxx/acpi.c
+                */
+               pr->acpi_id = object.processor.proc_id;
+       } else {
+               /*
+                * Declared with "Device" statement; match _UID.
+                * Note that we don't handle string _UIDs yet.
+                */
+               unsigned long long value;
+               status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
+                                               NULL, &value);
+               if (ACPI_FAILURE(status)) {
+                       printk(KERN_ERR PREFIX
+                           "Evaluating processor _UID [%#x]\n", status);
+                       return -ENODEV;
+               }
+               device_declaration = 1;
+               pr->acpi_id = value;
+       }
+       cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id);
+
+       /* Handle UP system running SMP kernel, with no LAPIC in MADT */
+       if (!cpu0_initialized && (cpu_index == -1) &&
+           (num_online_cpus() == 1)) {
+               cpu_index = 0;
+       }
+
+       cpu0_initialized = 1;
+
+       pr->id = cpu_index;
+
+       /*
+        *  Extra Processor objects may be enumerated on MP systems with
+        *  less than the max # of CPUs. They should be ignored _iff
+        *  they are physically not present.
+        */
+       if (pr->id == -1) {
+               if (ACPI_FAILURE
+                   (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
+                       return -ENODEV;
+               }
+       }
+       /*
+        * On some boxes several processors use the same processor bus id.
+        * But they are located in different scope. For example:
+        * \_SB.SCK0.CPU0
+        * \_SB.SCK1.CPU0
+        * Rename the processor device bus id. And the new bus id will be
+        * generated as the following format:
+        * CPU+CPU ID.
+        */
+       sprintf(acpi_device_bid(device), "CPU%X", pr->id);
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
+                         pr->acpi_id));
+
+       if (!object.processor.pblk_address)
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
+       else if (object.processor.pblk_length != 6)
+               printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
+                           object.processor.pblk_length);
+       else {
+               pr->throttling.address = object.processor.pblk_address;
+               pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset;
+               pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
+
+               pr->pblk = object.processor.pblk_address;
+
+               /*
+                * We don't care about error returns - we just try to mark
+                * these reserved so that nobody else is confused into thinking
+                * that this region might be unused..
+                *
+                * (In particular, allocating the IO range for Cardbus)
+                */
+               request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+       }
+
+       /*
+        * If ACPI describes a slot number for this CPU, we can use it
+        * ensure we get the right value in the "physical id" field
+        * of /proc/cpuinfo
+        */
+       status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+       if (ACPI_SUCCESS(status))
+               arch_fix_phys_package_id(pr->id, object.integer.value);
+
+       return 0;
+}
+
+static DEFINE_PER_CPU(void *, processor_device_array);
+
+static void acpi_processor_notify(struct acpi_device *device, u32 event)
+{
+       struct acpi_processor *pr = acpi_driver_data(device);
+       int saved;
+
+       if (!pr)
+               return;
+
+       switch (event) {
+       case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
+               saved = pr->performance_platform_limit;
+               acpi_processor_ppc_has_changed(pr, 1);
+               if (saved == pr->performance_platform_limit)
+                       break;
+               acpi_bus_generate_proc_event(device, event,
+                                       pr->performance_platform_limit);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 dev_name(&device->dev), event,
+                                                 pr->performance_platform_limit);
+               break;
+       case ACPI_PROCESSOR_NOTIFY_POWER:
+               acpi_processor_cst_has_changed(pr);
+               acpi_bus_generate_proc_event(device, event, 0);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 dev_name(&device->dev), event, 0);
+               break;
+       case ACPI_PROCESSOR_NOTIFY_THROTTLING:
+               acpi_processor_tstate_has_changed(pr);
+               acpi_bus_generate_proc_event(device, event, 0);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 dev_name(&device->dev), event, 0);
+       default:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Unsupported event [0x%x]\n", event));
+               break;
+       }
+
+       return;
+}
+
+static int acpi_cpu_soft_notify(struct notifier_block *nfb,
+               unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+       struct acpi_processor *pr = per_cpu(processors, cpu);
+
+       if (action == CPU_ONLINE && pr) {
+               acpi_processor_ppc_has_changed(pr, 0);
+               acpi_processor_cst_has_changed(pr);
+               acpi_processor_tstate_has_changed(pr);
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block acpi_cpu_notifier =
+{
+           .notifier_call = acpi_cpu_soft_notify,
+};
+
+static int __cpuinit acpi_processor_add(struct acpi_device *device)
+{
+       struct acpi_processor *pr = NULL;
+       int result = 0;
+       struct sys_device *sysdev;
+
+       pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
+       if (!pr)
+               return -ENOMEM;
+
+       if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
+               kfree(pr);
+               return -ENOMEM;
+       }
+
+       pr->handle = device->handle;
+       strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
+       strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
+       device->driver_data = pr;
+
+       result = acpi_processor_get_info(device);
+       if (result) {
+               /* Processor is physically not present */
+               return 0;
+       }
+
+       BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
+
+       /*
+        * Buggy BIOS check
+        * ACPI id of processors can be reported wrongly by the BIOS.
+        * Don't trust it blindly
+        */
+       if (per_cpu(processor_device_array, pr->id) != NULL &&
+           per_cpu(processor_device_array, pr->id) != device) {
+               printk(KERN_WARNING "BIOS reported wrong ACPI id "
+                       "for the processor\n");
+               result = -ENODEV;
+               goto err_free_cpumask;
+       }
+       per_cpu(processor_device_array, pr->id) = device;
+
+       per_cpu(processors, pr->id) = pr;
+
+       result = acpi_processor_add_fs(device);
+       if (result)
+               goto err_free_cpumask;
+
+       sysdev = get_cpu_sysdev(pr->id);
+       if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
+               result = -EFAULT;
+               goto err_remove_fs;
+       }
+
+#ifdef CONFIG_CPU_FREQ
+       acpi_processor_ppc_has_changed(pr, 0);
+#endif
+       acpi_processor_get_throttling_info(pr);
+       acpi_processor_get_limit_info(pr);
+
+
+       acpi_processor_power_init(pr, device);
+
+       pr->cdev = thermal_cooling_device_register("Processor", device,
+                                               &processor_cooling_ops);
+       if (IS_ERR(pr->cdev)) {
+               result = PTR_ERR(pr->cdev);
+               goto err_power_exit;
+       }
+
+       dev_dbg(&device->dev, "registered as cooling_device%d\n",
+                pr->cdev->id);
+
+       result = sysfs_create_link(&device->dev.kobj,
+                                  &pr->cdev->device.kobj,
+                                  "thermal_cooling");
+       if (result) {
+               printk(KERN_ERR PREFIX "Create sysfs link\n");
+               goto err_thermal_unregister;
+       }
+       result = sysfs_create_link(&pr->cdev->device.kobj,
+                                  &device->dev.kobj,
+                                  "device");
+       if (result) {
+               printk(KERN_ERR PREFIX "Create sysfs link\n");
+               goto err_remove_sysfs;
+       }
+
+       return 0;
+
+err_remove_sysfs:
+       sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+err_thermal_unregister:
+       thermal_cooling_device_unregister(pr->cdev);
+err_power_exit:
+       acpi_processor_power_exit(pr, device);
+err_remove_fs:
+       acpi_processor_remove_fs(device);
+err_free_cpumask:
+       free_cpumask_var(pr->throttling.shared_cpu_map);
+
+       return result;
+}
+
+static int acpi_processor_remove(struct acpi_device *device, int type)
+{
+       struct acpi_processor *pr = NULL;
+
+
+       if (!device || !acpi_driver_data(device))
+               return -EINVAL;
+
+       pr = acpi_driver_data(device);
+
+       if (pr->id >= nr_cpu_ids)
+               goto free;
+
+       if (type == ACPI_BUS_REMOVAL_EJECT) {
+               if (acpi_processor_handle_eject(pr))
+                       return -EINVAL;
+       }
+
+       acpi_processor_power_exit(pr, device);
+
+       sysfs_remove_link(&device->dev.kobj, "sysdev");
+
+       acpi_processor_remove_fs(device);
+
+       if (pr->cdev) {
+               sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+               sysfs_remove_link(&pr->cdev->device.kobj, "device");
+               thermal_cooling_device_unregister(pr->cdev);
+               pr->cdev = NULL;
+       }
+
+       per_cpu(processors, pr->id) = NULL;
+       per_cpu(processor_device_array, pr->id) = NULL;
+
+free:
+       free_cpumask_var(pr->throttling.shared_cpu_map);
+       kfree(pr);
+
+       return 0;
+}
+
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+/****************************************************************************
+ *     Acpi processor hotplug support                                      *
+ ****************************************************************************/
+
+static int is_processor_present(acpi_handle handle)
+{
+       acpi_status status;
+       unsigned long long sta = 0;
+
+
+       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+
+       if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
+               return 1;
+
+       /*
+        * _STA is mandatory for a processor that supports hot plug
+        */
+       if (status == AE_NOT_FOUND)
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                               "Processor does not support hot plug\n"));
+       else
+               ACPI_EXCEPTION((AE_INFO, status,
+                               "Processor Device is not present"));
+       return 0;
+}
+
+static
+int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
+{
+       acpi_handle phandle;
+       struct acpi_device *pdev;
+
+
+       if (acpi_get_parent(handle, &phandle)) {
+               return -ENODEV;
+       }
+
+       if (acpi_bus_get_device(phandle, &pdev)) {
+               return -ENODEV;
+       }
+
+       if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
+                                               u32 event, void *data)
+{
+       struct acpi_processor *pr;
+       struct acpi_device *device = NULL;
+       int result;
+
+
+       switch (event) {
+       case ACPI_NOTIFY_BUS_CHECK:
+       case ACPI_NOTIFY_DEVICE_CHECK:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+               "Processor driver received %s event\n",
+                      (event == ACPI_NOTIFY_BUS_CHECK) ?
+                      "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"));
+
+               if (!is_processor_present(handle))
+                       break;
+
+               if (acpi_bus_get_device(handle, &device)) {
+                       result = acpi_processor_device_add(handle, &device);
+                       if (result)
+                               printk(KERN_ERR PREFIX
+                                           "Unable to add the device\n");
+                       break;
+               }
+               break;
+       case ACPI_NOTIFY_EJECT_REQUEST:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "received ACPI_NOTIFY_EJECT_REQUEST\n"));
+
+               if (acpi_bus_get_device(handle, &device)) {
+                       printk(KERN_ERR PREFIX
+                                   "Device don't exist, dropping EJECT\n");
+                       break;
+               }
+               pr = acpi_driver_data(device);
+               if (!pr) {
+                       printk(KERN_ERR PREFIX
+                                   "Driver data is NULL, dropping EJECT\n");
+                       return;
+               }
+               break;
+       default:
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Unsupported event [0x%x]\n", event));
+               break;
+       }
+
+       return;
+}
+
+static acpi_status
+processor_walk_namespace_cb(acpi_handle handle,
+                           u32 lvl, void *context, void **rv)
+{
+       acpi_status status;
+       int *action = context;
+       acpi_object_type type = 0;
+
+       status = acpi_get_type(handle, &type);
+       if (ACPI_FAILURE(status))
+               return (AE_OK);
+
+       if (type != ACPI_TYPE_PROCESSOR)
+               return (AE_OK);
+
+       switch (*action) {
+       case INSTALL_NOTIFY_HANDLER:
+               acpi_install_notify_handler(handle,
+                                           ACPI_SYSTEM_NOTIFY,
+                                           acpi_processor_hotplug_notify,
+                                           NULL);
+               break;
+       case UNINSTALL_NOTIFY_HANDLER:
+               acpi_remove_notify_handler(handle,
+                                          ACPI_SYSTEM_NOTIFY,
+                                          acpi_processor_hotplug_notify);
+               break;
+       default:
+               break;
+       }
+
+       return (AE_OK);
+}
+
+static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
+{
+
+       if (!is_processor_present(handle)) {
+               return AE_ERROR;
+       }
+
+       if (acpi_map_lsapic(handle, p_cpu))
+               return AE_ERROR;
+
+       if (arch_register_cpu(*p_cpu)) {
+               acpi_unmap_lsapic(*p_cpu);
+               return AE_ERROR;
+       }
+
+       return AE_OK;
+}
+
+static int acpi_processor_handle_eject(struct acpi_processor *pr)
+{
+       if (cpu_online(pr->id))
+               cpu_down(pr->id);
+
+       arch_unregister_cpu(pr->id);
+       acpi_unmap_lsapic(pr->id);
+       return (0);
+}
+#else
+static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
+{
+       return AE_ERROR;
+}
+static int acpi_processor_handle_eject(struct acpi_processor *pr)
+{
+       return (-EINVAL);
+}
+#endif
+
+static
+void acpi_processor_install_hotplug_notify(void)
+{
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+       int action = INSTALL_NOTIFY_HANDLER;
+       acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
+                           ACPI_ROOT_OBJECT,
+                           ACPI_UINT32_MAX,
+                           processor_walk_namespace_cb, NULL, &action, NULL);
+#endif
+       register_hotcpu_notifier(&acpi_cpu_notifier);
+}
+
+static
+void acpi_processor_uninstall_hotplug_notify(void)
+{
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+       int action = UNINSTALL_NOTIFY_HANDLER;
+       acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
+                           ACPI_ROOT_OBJECT,
+                           ACPI_UINT32_MAX,
+                           processor_walk_namespace_cb, NULL, &action, NULL);
+#endif
+       unregister_hotcpu_notifier(&acpi_cpu_notifier);
+}
+
+/*
+ * We keep the driver loaded even when ACPI is not running.
+ * This is needed for the powernow-k8 driver, that works even without
+ * ACPI, but needs symbols from this driver
+ */
+
+static int __init acpi_processor_init(void)
+{
+       int result = 0;
+
+       if (acpi_disabled)
+               return 0;
+
+       memset(&errata, 0, sizeof(errata));
+
+#ifdef CONFIG_ACPI_PROCFS
+       acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+       if (!acpi_processor_dir)
+               return -ENOMEM;
+#endif
+       result = cpuidle_register_driver(&acpi_idle_driver);
+       if (result < 0)
+               goto out_proc;
+
+       result = acpi_bus_register_driver(&acpi_processor_driver);
+       if (result < 0)
+               goto out_cpuidle;
+
+       acpi_processor_install_hotplug_notify();
+
+       acpi_thermal_cpufreq_init();
+
+       acpi_processor_ppc_init();
+
+       acpi_processor_throttling_init();
+
+       return 0;
+
+out_cpuidle:
+       cpuidle_unregister_driver(&acpi_idle_driver);
+
+out_proc:
+#ifdef CONFIG_ACPI_PROCFS
+       remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+#endif
+
+       return result;
+}
+
+static void __exit acpi_processor_exit(void)
+{
+       if (acpi_disabled)
+               return;
+
+       acpi_processor_ppc_exit();
+
+       acpi_thermal_cpufreq_exit();
+
+       acpi_processor_uninstall_hotplug_notify();
+
+       acpi_bus_unregister_driver(&acpi_processor_driver);
+
+       cpuidle_unregister_driver(&acpi_idle_driver);
+
+#ifdef CONFIG_ACPI_PROCFS
+       remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+#endif
+
+       return;
+}
+
+module_init(acpi_processor_init);
+module_exit(acpi_processor_exit);
+
+EXPORT_SYMBOL(acpi_processor_set_thermal_limit);
+
+MODULE_ALIAS("processor");
diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c
deleted file mode 100644 (file)
index e306ba9..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2005 Intel Corporation
- * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
- *
- *     Alex Chiang <achiang@hp.com>
- *     - Unified x86/ia64 implementations
- *     Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- *     - Added _PDC for platforms with Intel CPUs
- */
-#include <linux/dmi.h>
-
-#include <acpi/acpi_drivers.h>
-#include <acpi/processor.h>
-
-#include "internal.h"
-
-#define PREFIX                 "ACPI: "
-#define _COMPONENT             ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("processor_pdc");
-
-static int set_no_mwait(const struct dmi_system_id *id)
-{
-       printk(KERN_NOTICE PREFIX "%s detected - "
-               "disabling mwait for CPU C-states\n", id->ident);
-       idle_nomwait = 1;
-       return 0;
-}
-
-static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
-       {
-       set_no_mwait, "IFL91 board", {
-       DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
-       DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
-       DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
-       DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
-       {
-       set_no_mwait, "Extensa 5220", {
-       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-       DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
-       DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
-       {},
-};
-
-static void acpi_set_pdc_bits(u32 *buf)
-{
-       buf[0] = ACPI_PDC_REVISION_ID;
-       buf[1] = 1;
-
-       /* Enable coordination with firmware's _TSD info */
-       buf[2] = ACPI_PDC_SMP_T_SWCOORD;
-
-       /* Twiddle arch-specific bits needed for _PDC */
-       arch_acpi_set_pdc_bits(buf);
-}
-
-static struct acpi_object_list *acpi_processor_alloc_pdc(void)
-{
-       struct acpi_object_list *obj_list;
-       union acpi_object *obj;
-       u32 *buf;
-
-       /* allocate and initialize pdc. It will be used later. */
-       obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
-       if (!obj_list) {
-               printk(KERN_ERR "Memory allocation error\n");
-               return NULL;
-       }
-
-       obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-       if (!obj) {
-               printk(KERN_ERR "Memory allocation error\n");
-               kfree(obj_list);
-               return NULL;
-       }
-
-       buf = kmalloc(12, GFP_KERNEL);
-       if (!buf) {
-               printk(KERN_ERR "Memory allocation error\n");
-               kfree(obj);
-               kfree(obj_list);
-               return NULL;
-       }
-
-       acpi_set_pdc_bits(buf);
-
-       obj->type = ACPI_TYPE_BUFFER;
-       obj->buffer.length = 12;
-       obj->buffer.pointer = (u8 *) buf;
-       obj_list->count = 1;
-       obj_list->pointer = obj;
-
-       return obj_list;
-}
-
-/*
- * _PDC is required for a BIOS-OS handshake for most of the newer
- * ACPI processor features.
- */
-static int
-acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
-{
-       acpi_status status = AE_OK;
-
-       if (idle_nomwait) {
-               /*
-                * If mwait is disabled for CPU C-states, the C2C3_FFH access
-                * mode will be disabled in the parameter of _PDC object.
-                * Of course C1_FFH access mode will also be disabled.
-                */
-               union acpi_object *obj;
-               u32 *buffer = NULL;
-
-               obj = pdc_in->pointer;
-               buffer = (u32 *)(obj->buffer.pointer);
-               buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
-
-       }
-       status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
-
-       if (ACPI_FAILURE(status))
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                   "Could not evaluate _PDC, using legacy perf. control.\n"));
-
-       return status;
-}
-
-static int early_pdc_done;
-
-void acpi_processor_set_pdc(acpi_handle handle)
-{
-       struct acpi_object_list *obj_list;
-
-       if (arch_has_acpi_pdc() == false)
-               return;
-
-       if (early_pdc_done)
-               return;
-
-       obj_list = acpi_processor_alloc_pdc();
-       if (!obj_list)
-               return;
-
-       acpi_processor_eval_pdc(handle, obj_list);
-
-       kfree(obj_list->pointer->buffer.pointer);
-       kfree(obj_list->pointer);
-       kfree(obj_list);
-}
-EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
-
-static int early_pdc_optin;
-static int set_early_pdc_optin(const struct dmi_system_id *id)
-{
-       early_pdc_optin = 1;
-       return 0;
-}
-
-static int param_early_pdc_optin(char *s)
-{
-       early_pdc_optin = 1;
-       return 1;
-}
-__setup("acpi_early_pdc_eval", param_early_pdc_optin);
-
-static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = {
-       {
-       set_early_pdc_optin, "HP Envy", {
-       DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
-       DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL},
-       {
-       set_early_pdc_optin, "HP Pavilion dv6", {
-       DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
-       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL},
-       {
-       set_early_pdc_optin, "HP Pavilion dv7", {
-       DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
-       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL},
-       {},
-};
-
-static acpi_status
-early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       acpi_processor_set_pdc(handle);
-       return AE_OK;
-}
-
-void __init acpi_early_processor_set_pdc(void)
-{
-       /*
-        * Check whether the system is DMI table. If yes, OSPM
-        * should not use mwait for CPU-states.
-        */
-       dmi_check_system(processor_idle_dmi_table);
-
-       /*
-        * Allow systems to opt-in to early _PDC evaluation.
-        */
-       dmi_check_system(early_pdc_optin_table);
-       if (!early_pdc_optin)
-               return;
-
-       acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
-                           ACPI_UINT32_MAX,
-                           early_init_pdc, NULL, NULL, NULL);
-
-       early_pdc_done = 1;
-}
index 7ded754..29c6f57 100644 (file)
@@ -1133,9 +1133,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
        int result = 0;
        struct acpi_processor_throttling *pthrottling;
 
-       if (!pr)
-               return -EINVAL;
-
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n",
                          pr->throttling.address,
index b16ddbf..89ad111 100644 (file)
@@ -217,6 +217,9 @@ static int acpi_sbs_battery_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_TECHNOLOGY:
                val->intval = acpi_battery_technology(battery);
                break;
+       case POWER_SUPPLY_PROP_CYCLE_COUNT:
+               val->intval = battery->cycle_count;
+               break;
        case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
                val->intval = battery->design_voltage *
                        acpi_battery_vscale(battery) * 1000;
@@ -276,6 +279,7 @@ static enum power_supply_property sbs_charge_battery_props[] = {
        POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_CYCLE_COUNT,
        POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_CURRENT_NOW,
@@ -560,6 +564,7 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
                   battery->design_voltage * acpi_battery_vscale(battery));
        seq_printf(seq, "design capacity warning: unknown\n");
        seq_printf(seq, "design capacity low:     unknown\n");
+       seq_printf(seq, "cycle count:             %i\n", battery->cycle_count);
        seq_printf(seq, "capacity granularity 1:  unknown\n");
        seq_printf(seq, "capacity granularity 2:  unknown\n");
        seq_printf(seq, "model number:            %s\n", battery->device_name);
index 3bde594..f74834a 100644 (file)
@@ -552,8 +552,17 @@ static void acpi_hibernation_leave(void)
        hibernate_nvs_restore();
 }
 
-static void acpi_pm_enable_gpes(void)
+static int acpi_pm_pre_restore(void)
 {
+       acpi_disable_all_gpes();
+       acpi_os_wait_events_complete(NULL);
+       acpi_ec_suspend_transactions();
+       return 0;
+}
+
+static void acpi_pm_restore_cleanup(void)
+{
+       acpi_ec_resume_transactions();
        acpi_enable_all_runtime_gpes();
 }
 
@@ -565,8 +574,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
        .prepare = acpi_pm_prepare,
        .enter = acpi_hibernation_enter,
        .leave = acpi_hibernation_leave,
-       .pre_restore = acpi_pm_disable_gpes,
-       .restore_cleanup = acpi_pm_enable_gpes,
+       .pre_restore = acpi_pm_pre_restore,
+       .restore_cleanup = acpi_pm_restore_cleanup,
 };
 
 /**
@@ -618,8 +627,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = {
        .prepare = acpi_pm_disable_gpes,
        .enter = acpi_hibernation_enter,
        .leave = acpi_hibernation_leave,
-       .pre_restore = acpi_pm_disable_gpes,
-       .restore_cleanup = acpi_pm_enable_gpes,
+       .pre_restore = acpi_pm_pre_restore,
+       .restore_cleanup = acpi_pm_restore_cleanup,
        .recover = acpi_pm_finish,
 };
 #endif /* CONFIG_HIBERNATION */
index 9073ada..5d38935 100644 (file)
@@ -368,7 +368,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
        int valid = 0;
        int i;
 
-       /* Critical Shutdown (required) */
+       /* Critical Shutdown */
        if (flag & ACPI_TRIPS_CRITICAL) {
                status = acpi_evaluate_integer(tz->device->handle,
                                "_CRT", NULL, &tmp);
@@ -379,17 +379,19 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                 * Below zero (Celsius) values clearly aren't right for sure..
                 * ... so lets discard those as invalid.
                 */
-               if (ACPI_FAILURE(status) ||
-                               tz->trips.critical.temperature <= 2732) {
+               if (ACPI_FAILURE(status)) {
+                       tz->trips.critical.flags.valid = 0;
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                         "No critical threshold\n"));
+               } else if (tmp <= 2732) {
+                       printk(KERN_WARNING FW_BUG "Invalid critical threshold "
+                              "(%llu)\n", tmp);
                        tz->trips.critical.flags.valid = 0;
-                       ACPI_EXCEPTION((AE_INFO, status,
-                                       "No or invalid critical threshold"));
-                       return -ENODEV;
                } else {
                        tz->trips.critical.flags.valid = 1;
                        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                       "Found critical threshold [%lu]\n",
-                                       tz->trips.critical.temperature));
+                                         "Found critical threshold [%lu]\n",
+                                         tz->trips.critical.temperature));
                }
                if (tz->trips.critical.flags.valid == 1) {
                        if (crt == -1) {
@@ -575,7 +577,23 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
 
 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
 {
-       return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
+       int i, valid, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
+
+       if (ret)
+               return ret;
+
+       valid = tz->trips.critical.flags.valid |
+               tz->trips.hot.flags.valid |
+               tz->trips.passive.flags.valid;
+
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
+               valid |= tz->trips.active[i].flags.valid;
+
+       if (!valid) {
+               printk(KERN_WARNING FW_BUG "No valid trip found\n");
+               return -ENODEV;
+       }
+       return 0;
 }
 
 static void acpi_thermal_check(void *data)
index 11882db..c9a49f4 100644 (file)
@@ -289,51 +289,6 @@ acpi_evaluate_integer(acpi_handle handle,
 
 EXPORT_SYMBOL(acpi_evaluate_integer);
 
-#if 0
-acpi_status
-acpi_evaluate_string(acpi_handle handle,
-                    acpi_string pathname,
-                    acpi_object_list * arguments, acpi_string * data)
-{
-       acpi_status status = AE_OK;
-       acpi_object *element = NULL;
-       acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
-
-       if (!data)
-               return AE_BAD_PARAMETER;
-
-       status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
-       if (ACPI_FAILURE(status)) {
-               acpi_util_eval_error(handle, pathname, status);
-               return status;
-       }
-
-       element = (acpi_object *) buffer.pointer;
-
-       if ((element->type != ACPI_TYPE_STRING)
-           || (element->type != ACPI_TYPE_BUFFER)
-           || !element->string.length) {
-               acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
-               return AE_BAD_DATA;
-       }
-
-       *data = kzalloc(element->string.length + 1, GFP_KERNEL);
-       if (!data) {
-               printk(KERN_ERR PREFIX "Memory allocation\n");
-               return -ENOMEM;
-       }
-
-       memcpy(*data, element->string.pointer, element->string.length);
-
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data));
-
-       kfree(buffer.pointer);
-
-       return AE_OK;
-}
-#endif
-
 acpi_status
 acpi_evaluate_reference(acpi_handle handle,
                        acpi_string pathname,
index 6e9b491..2ff2b6a 100644 (file)
@@ -327,7 +327,7 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
                        int level);
 static int acpi_video_device_lcd_get_level_current(
                        struct acpi_video_device *device,
-                       unsigned long long *level);
+                       unsigned long long *level, int init);
 static int acpi_video_get_next_level(struct acpi_video_device *device,
                                     u32 level_current, u32 event);
 static int acpi_video_switch_brightness(struct acpi_video_device *device,
@@ -345,7 +345,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
        struct acpi_video_device *vd =
                (struct acpi_video_device *)bl_get_data(bd);
 
-       if (acpi_video_device_lcd_get_level_current(vd, &cur_level))
+       if (acpi_video_device_lcd_get_level_current(vd, &cur_level, 0))
                return -EINVAL;
        for (i = 2; i < vd->brightness->count; i++) {
                if (vd->brightness->levels[i] == cur_level)
@@ -414,7 +414,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig
        unsigned long long level;
        int offset;
 
-       if (acpi_video_device_lcd_get_level_current(video, &level))
+       if (acpi_video_device_lcd_get_level_current(video, &level, 0))
                return -EINVAL;
        for (offset = 2; offset < video->brightness->count; offset++)
                if (level == video->brightness->levels[offset]) {
@@ -609,7 +609,7 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
 
 static int
 acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
-                                       unsigned long long *level)
+                                       unsigned long long *level, int init)
 {
        acpi_status status = AE_OK;
        int i;
@@ -633,10 +633,16 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
                                        device->brightness->curr = *level;
                                        return 0;
                        }
-                       /* BQC returned an invalid level. Stop using it.  */
-                       ACPI_WARNING((AE_INFO, "%s returned an invalid level",
-                                               buf));
-                       device->cap._BQC = device->cap._BCQ = 0;
+                       if (!init) {
+                               /*
+                                * BQC returned an invalid level.
+                                * Stop using it.
+                                */
+                               ACPI_WARNING((AE_INFO,
+                                             "%s returned an invalid level",
+                                             buf));
+                               device->cap._BQC = device->cap._BCQ = 0;
+                       }
                } else {
                        /* Fixme:
                         * should we return an error or ignore this failure?
@@ -892,7 +898,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
        if (!device->cap._BQC)
                goto set_level;
 
-       result = acpi_video_device_lcd_get_level_current(device, &level_old);
+       result = acpi_video_device_lcd_get_level_current(device, &level_old, 1);
        if (result)
                goto out_free_levels;
 
@@ -903,7 +909,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
        if (result)
                goto out_free_levels;
 
-       result = acpi_video_device_lcd_get_level_current(device, &level);
+       result = acpi_video_device_lcd_get_level_current(device, &level, 0);
        if (result)
                goto out_free_levels;
 
@@ -1996,7 +2002,7 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
                goto out;
 
        result = acpi_video_device_lcd_get_level_current(device,
-                                                        &level_current);
+                                                        &level_current, 0);
        if (result)
                goto out;
 
index cb2fd01..b5dad9f 100644 (file)
@@ -749,6 +749,24 @@ static int acpiphp_bus_trim(acpi_handle handle)
        return retval;
 }
 
+static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
+{
+       struct acpiphp_func *func;
+       union acpi_object params[2];
+       struct acpi_object_list arg_list;
+
+       list_for_each_entry(func, &slot->funcs, sibling) {
+               arg_list.count = 2;
+               arg_list.pointer = params;
+               params[0].type = ACPI_TYPE_INTEGER;
+               params[0].integer.value = ACPI_ADR_SPACE_PCI_CONFIG;
+               params[1].type = ACPI_TYPE_INTEGER;
+               params[1].integer.value = 1;
+               /* _REG is optional, we don't care about if there is failure */
+               acpi_evaluate_object(func->handle, "_REG", &arg_list, NULL);
+       }
+}
+
 /**
  * enable_device - enable, configure a slot
  * @slot: slot to be enabled
@@ -805,6 +823,7 @@ static int __ref enable_device(struct acpiphp_slot *slot)
        pci_bus_assign_resources(bus);
        acpiphp_sanitize_bus(bus);
        acpiphp_set_hpp_values(bus);
+       acpiphp_set_acpi_region(slot);
        pci_enable_bridges(bus);
        pci_bus_add_devices(bus);
 
index 3f71a60..5a3d851 100644 (file)
@@ -145,7 +145,7 @@ struct sony_laptop_input_s {
        struct input_dev        *key_dev;
        struct kfifo            fifo;
        spinlock_t              fifo_lock;
-       struct workqueue_struct *wq;
+       struct timer_list       release_key_timer;
 };
 
 static struct sony_laptop_input_s sony_laptop_input = {
@@ -299,20 +299,26 @@ static int sony_laptop_input_keycode_map[] = {
 };
 
 /* release buttons after a short delay if pressed */
-static void do_sony_laptop_release_key(struct work_struct *work)
+static void do_sony_laptop_release_key(unsigned long unused)
 {
        struct sony_laptop_keypress kp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags);
 
-       while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp,
-                       sizeof(kp), &sony_laptop_input.fifo_lock)
-                       == sizeof(kp)) {
-               msleep(10);
+       if (kfifo_out(&sony_laptop_input.fifo,
+                     (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
                input_report_key(kp.dev, kp.key, 0);
                input_sync(kp.dev);
        }
+
+       /* If there is something in the fifo schedule next release. */
+       if (kfifo_len(&sony_laptop_input.fifo) != 0)
+               mod_timer(&sony_laptop_input.release_key_timer,
+                         jiffies + msecs_to_jiffies(10));
+
+       spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags);
 }
-static DECLARE_WORK(sony_laptop_release_key_work,
-               do_sony_laptop_release_key);
 
 /* forward event to the input subsystem */
 static void sony_laptop_report_input_event(u8 event)
@@ -366,13 +372,13 @@ static void sony_laptop_report_input_event(u8 event)
                /* we emit the scancode so we can always remap the key */
                input_event(kp.dev, EV_MSC, MSC_SCAN, event);
                input_sync(kp.dev);
-               kfifo_in_locked(&sony_laptop_input.fifo,
-                         (unsigned char *)&kp, sizeof(kp),
-                         &sony_laptop_input.fifo_lock);
 
-               if (!work_pending(&sony_laptop_release_key_work))
-                       queue_work(sony_laptop_input.wq,
-                                       &sony_laptop_release_key_work);
+               /* schedule key release */
+               kfifo_in_locked(&sony_laptop_input.fifo,
+                               (unsigned char *)&kp, sizeof(kp),
+                               &sony_laptop_input.fifo_lock);
+               mod_timer(&sony_laptop_input.release_key_timer,
+                         jiffies + msecs_to_jiffies(10));
        } else
                dprintk("unknown input event %.2x\n", event);
 }
@@ -390,27 +396,21 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
 
        /* kfifo */
        spin_lock_init(&sony_laptop_input.fifo_lock);
-       error =
-        kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
+       error = kfifo_alloc(&sony_laptop_input.fifo,
+                           SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
        if (error) {
                printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
                goto err_dec_users;
        }
 
-       /* init workqueue */
-       sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop");
-       if (!sony_laptop_input.wq) {
-               printk(KERN_ERR DRV_PFX
-                               "Unable to create workqueue.\n");
-               error = -ENXIO;
-               goto err_free_kfifo;
-       }
+       setup_timer(&sony_laptop_input.release_key_timer,
+                   do_sony_laptop_release_key, 0);
 
        /* input keys */
        key_dev = input_allocate_device();
        if (!key_dev) {
                error = -ENOMEM;
-               goto err_destroy_wq;
+               goto err_free_kfifo;
        }
 
        key_dev->name = "Sony Vaio Keys";
@@ -419,18 +419,15 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
        key_dev->dev.parent = &acpi_device->dev;
 
        /* Initialize the Input Drivers: special keys */
-       set_bit(EV_KEY, key_dev->evbit);
-       set_bit(EV_MSC, key_dev->evbit);
-       set_bit(MSC_SCAN, key_dev->mscbit);
+       input_set_capability(key_dev, EV_MSC, MSC_SCAN);
+
+       __set_bit(EV_KEY, key_dev->evbit);
        key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]);
        key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map);
        key_dev->keycode = &sony_laptop_input_keycode_map;
-       for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) {
-               if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) {
-                       set_bit(sony_laptop_input_keycode_map[i],
-                               key_dev->keybit);
-               }
-       }
+       for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++)
+               __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit);
+       __clear_bit(KEY_RESERVED, key_dev->keybit);
 
        error = input_register_device(key_dev);
        if (error)
@@ -450,9 +447,8 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
        jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
        key_dev->dev.parent = &acpi_device->dev;
 
-       jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
-       jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE);
-       jog_dev->relbit[0] = BIT_MASK(REL_WHEEL);
+       input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
+       input_set_capability(jog_dev, EV_REL, REL_WHEEL);
 
        error = input_register_device(jog_dev);
        if (error)
@@ -473,9 +469,6 @@ err_unregister_keydev:
 err_free_keydev:
        input_free_device(key_dev);
 
-err_destroy_wq:
-       destroy_workqueue(sony_laptop_input.wq);
-
 err_free_kfifo:
        kfifo_free(&sony_laptop_input.fifo);
 
@@ -486,12 +479,23 @@ err_dec_users:
 
 static void sony_laptop_remove_input(void)
 {
-       /* cleanup only after the last user has gone */
+       struct sony_laptop_keypress kp = { NULL };
+
+       /* Cleanup only after the last user has gone */
        if (!atomic_dec_and_test(&sony_laptop_input.users))
                return;
 
-       /* flush workqueue first */
-       flush_workqueue(sony_laptop_input.wq);
+       del_timer_sync(&sony_laptop_input.release_key_timer);
+
+       /*
+        * Generate key-up events for remaining keys. Note that we don't
+        * need locking since nobody is adding new events to the kfifo.
+        */
+       while (kfifo_out(&sony_laptop_input.fifo,
+                        (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
+               input_report_key(kp.dev, kp.key, 0);
+               input_sync(kp.dev);
+       }
 
        /* destroy input devs */
        input_unregister_device(sony_laptop_input.key_dev);
@@ -502,7 +506,6 @@ static void sony_laptop_remove_input(void)
                sony_laptop_input.jog_dev = NULL;
        }
 
-       destroy_workqueue(sony_laptop_input.wq);
        kfifo_free(&sony_laptop_input.fifo);
 }
 
index 0b8d140..0bab84e 100644 (file)
@@ -166,6 +166,9 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
 struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
                                          resource_size_t start,
                                          resource_size_t end, int flags);
+struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,
+                                         resource_size_t start,
+                                         resource_size_t end);
 
 extern int pnp_debug;
 
index 68b0c04..cfaf5b7 100644 (file)
@@ -278,9 +278,12 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
                switch (pnp_resource_type(res)) {
                case IORESOURCE_IO:
                case IORESOURCE_MEM:
-                       pnp_printf(buffer, " %#llx-%#llx\n",
+               case IORESOURCE_BUS:
+                       pnp_printf(buffer, " %#llx-%#llx%s\n",
                                   (unsigned long long) res->start,
-                                  (unsigned long long) res->end);
+                                  (unsigned long long) res->end,
+                                  res->flags & IORESOURCE_WINDOW ?
+                                       " window" : "");
                        break;
                case IORESOURCE_IRQ:
                case IORESOURCE_DMA:
index 5702b2c..54514aa 100644 (file)
@@ -177,7 +177,8 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
 }
 
 static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
-                                              u64 len, int io_decode)
+                                              u64 len, int io_decode,
+                                              int window)
 {
        int flags = 0;
        u64 end = start + len - 1;
@@ -186,6 +187,8 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
                flags |= IORESOURCE_IO_16BIT_ADDR;
        if (len == 0 || end >= 0x10003)
                flags |= IORESOURCE_DISABLED;
+       if (window)
+               flags |= IORESOURCE_WINDOW;
 
        pnp_add_io_resource(dev, start, end, flags);
 }
@@ -247,7 +250,7 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
 
 static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
                                                u64 start, u64 len,
-                                               int write_protect)
+                                               int write_protect, int window)
 {
        int flags = 0;
        u64 end = start + len - 1;
@@ -256,15 +259,26 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
                flags |= IORESOURCE_DISABLED;
        if (write_protect == ACPI_READ_WRITE_MEMORY)
                flags |= IORESOURCE_MEM_WRITEABLE;
+       if (window)
+               flags |= IORESOURCE_WINDOW;
 
        pnp_add_mem_resource(dev, start, end, flags);
 }
 
+static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
+                                               u64 start, u64 len)
+{
+       u64 end = start + len - 1;
+
+       pnp_add_bus_resource(dev, start, end);
+}
+
 static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
                                                  struct acpi_resource *res)
 {
        struct acpi_resource_address64 addr, *p = &addr;
        acpi_status status;
+       int window;
 
        status = acpi_resource_to_address64(res, p);
        if (!ACPI_SUCCESS(status)) {
@@ -273,37 +287,42 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
                return;
        }
 
-       if (p->producer_consumer == ACPI_PRODUCER)
-               return;
+       window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
 
        if (p->resource_type == ACPI_MEMORY_RANGE)
                pnpacpi_parse_allocated_memresource(dev,
                        p->minimum, p->address_length,
-                       p->info.mem.write_protect);
+                       p->info.mem.write_protect, window);
        else if (p->resource_type == ACPI_IO_RANGE)
                pnpacpi_parse_allocated_ioresource(dev,
                        p->minimum, p->address_length,
                        p->granularity == 0xfff ? ACPI_DECODE_10 :
-                               ACPI_DECODE_16);
+                               ACPI_DECODE_16, window);
+       else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
+               pnpacpi_parse_allocated_busresource(dev, p->minimum,
+                                                   p->address_length);
 }
 
 static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
                                                      struct acpi_resource *res)
 {
        struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
+       int window;
 
-       if (p->producer_consumer == ACPI_PRODUCER)
-               return;
+       window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
 
        if (p->resource_type == ACPI_MEMORY_RANGE)
                pnpacpi_parse_allocated_memresource(dev,
                        p->minimum, p->address_length,
-                       p->info.mem.write_protect);
+                       p->info.mem.write_protect, window);
        else if (p->resource_type == ACPI_IO_RANGE)
                pnpacpi_parse_allocated_ioresource(dev,
                        p->minimum, p->address_length,
                        p->granularity == 0xfff ? ACPI_DECODE_10 :
-                               ACPI_DECODE_16);
+                               ACPI_DECODE_16, window);
+       else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
+               pnpacpi_parse_allocated_busresource(dev, p->minimum,
+                                                   p->address_length);
 }
 
 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
@@ -368,7 +387,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
                pnpacpi_parse_allocated_ioresource(dev,
                        io->minimum,
                        io->address_length,
-                       io->io_decode);
+                       io->io_decode, 0);
                break;
 
        case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -380,7 +399,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
                pnpacpi_parse_allocated_ioresource(dev,
                        fixed_io->address,
                        fixed_io->address_length,
-                       ACPI_DECODE_10);
+                       ACPI_DECODE_10, 0);
                break;
 
        case ACPI_RESOURCE_TYPE_VENDOR:
@@ -396,21 +415,21 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
                pnpacpi_parse_allocated_memresource(dev,
                        memory24->minimum,
                        memory24->address_length,
-                       memory24->write_protect);
+                       memory24->write_protect, 0);
                break;
        case ACPI_RESOURCE_TYPE_MEMORY32:
                memory32 = &res->data.memory32;
                pnpacpi_parse_allocated_memresource(dev,
                        memory32->minimum,
                        memory32->address_length,
-                       memory32->write_protect);
+                       memory32->write_protect, 0);
                break;
        case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
                fixed_memory32 = &res->data.fixed_memory32;
                pnpacpi_parse_allocated_memresource(dev,
                        fixed_memory32->address,
                        fixed_memory32->address_length,
-                       fixed_memory32->write_protect);
+                       fixed_memory32->write_protect, 0);
                break;
        case ACPI_RESOURCE_TYPE_ADDRESS16:
        case ACPI_RESOURCE_TYPE_ADDRESS32:
index 64d0596..5b277db 100644 (file)
@@ -470,7 +470,8 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
 unsigned long pnp_resource_type(struct resource *res)
 {
        return res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
-                            IORESOURCE_IRQ | IORESOURCE_DMA);
+                            IORESOURCE_IRQ | IORESOURCE_DMA |
+                            IORESOURCE_BUS);
 }
 
 struct resource *pnp_get_resource(struct pnp_dev *dev,
@@ -590,6 +591,30 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
        return pnp_res;
 }
 
+struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,
+                                         resource_size_t start,
+                                         resource_size_t end)
+{
+       struct pnp_resource *pnp_res;
+       struct resource *res;
+
+       pnp_res = pnp_new_resource(dev);
+       if (!pnp_res) {
+               dev_err(&dev->dev, "can't add resource for BUS %#llx-%#llx\n",
+                       (unsigned long long) start,
+                       (unsigned long long) end);
+               return NULL;
+       }
+
+       res = &pnp_res->res;
+       res->flags = IORESOURCE_BUS;
+       res->start = start;
+       res->end = end;
+
+       pnp_dbg(&dev->dev, "  add %pr\n", res);
+       return pnp_res;
+}
+
 /*
  * Determine whether the specified resource is a possible configuration
  * for this device.
index 9585c1c..f5beb24 100644 (file)
@@ -69,8 +69,10 @@ char *pnp_resource_type_name(struct resource *res)
                return "irq";
        case IORESOURCE_DMA:
                return "dma";
+       case IORESOURCE_BUS:
+               return "bus";
        }
-       return NULL;
+       return "unknown";
 }
 
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc)
index c790e0c..ff05e61 100644 (file)
@@ -99,6 +99,7 @@ static struct device_attribute power_supply_attrs[] = {
        POWER_SUPPLY_ATTR(present),
        POWER_SUPPLY_ATTR(online),
        POWER_SUPPLY_ATTR(technology),
+       POWER_SUPPLY_ATTR(cycle_count),
        POWER_SUPPLY_ATTR(voltage_max),
        POWER_SUPPLY_ATTR(voltage_min),
        POWER_SUPPLY_ATTR(voltage_max_design),
index 1172c27..86825dd 100644 (file)
@@ -320,8 +320,16 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
 
 #endif                         /* CONFIG_CPU_FREQ */
 
-/* in processor_pdc.c */
+/* in processor_core.c */
 void acpi_processor_set_pdc(acpi_handle handle);
+#ifdef CONFIG_SMP
+int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
+#else
+static inline int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
+{
+       return -1;
+}
+#endif
 
 /* in processor_throttling.c */
 int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
index dda9841..71ab79d 100644 (file)
@@ -34,22 +34,24 @@ struct resource_list {
  */
 #define IORESOURCE_BITS                0x000000ff      /* Bus-specific bits */
 
-#define IORESOURCE_TYPE_BITS   0x00000f00      /* Resource type */
+#define IORESOURCE_TYPE_BITS   0x00001f00      /* Resource type */
 #define IORESOURCE_IO          0x00000100
 #define IORESOURCE_MEM         0x00000200
 #define IORESOURCE_IRQ         0x00000400
 #define IORESOURCE_DMA         0x00000800
+#define IORESOURCE_BUS         0x00001000
 
-#define IORESOURCE_PREFETCH    0x00001000      /* No side effects */
-#define IORESOURCE_READONLY    0x00002000
-#define IORESOURCE_CACHEABLE   0x00004000
-#define IORESOURCE_RANGELENGTH 0x00008000
-#define IORESOURCE_SHADOWABLE  0x00010000
+#define IORESOURCE_PREFETCH    0x00002000      /* No side effects */
+#define IORESOURCE_READONLY    0x00004000
+#define IORESOURCE_CACHEABLE   0x00008000
+#define IORESOURCE_RANGELENGTH 0x00010000
+#define IORESOURCE_SHADOWABLE  0x00020000
 
-#define IORESOURCE_SIZEALIGN   0x00020000      /* size indicates alignment */
-#define IORESOURCE_STARTALIGN  0x00040000      /* start field is alignment */
+#define IORESOURCE_SIZEALIGN   0x00040000      /* size indicates alignment */
+#define IORESOURCE_STARTALIGN  0x00080000      /* start field is alignment */
 
 #define IORESOURCE_MEM_64      0x00100000
+#define IORESOURCE_WINDOW      0x00200000      /* forwarded by bridge */
 
 #define IORESOURCE_EXCLUSIVE   0x08000000      /* Userland may not map this resource */
 #define IORESOURCE_DISABLED    0x10000000
index b5d096d..ebd2b8f 100644 (file)
@@ -82,6 +82,7 @@ enum power_supply_property {
        POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_ONLINE,
        POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_CYCLE_COUNT,
        POWER_SUPPLY_PROP_VOLTAGE_MAX,
        POWER_SUPPLY_PROP_VOLTAGE_MIN,
        POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
index 0d461c7..24112e5 100644 (file)
@@ -609,6 +609,12 @@ static char *resource_string(char *buf, char *end, struct resource *res,
                .precision = -1,
                .flags = SPECIAL | SMALL | ZEROPAD,
        };
+       static const struct printf_spec bus_spec = {
+               .base = 16,
+               .field_width = 2,
+               .precision = -1,
+               .flags = SMALL | ZEROPAD,
+       };
        static const struct printf_spec dec_spec = {
                .base = 10,
                .precision = -1,
@@ -629,7 +635,7 @@ static char *resource_string(char *buf, char *end, struct resource *res,
         * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */
 #define RSRC_BUF_SIZE          ((2 * sizeof(resource_size_t)) + 4)
 #define FLAG_BUF_SIZE          (2 * sizeof(res->flags))
-#define DECODED_BUF_SIZE       sizeof("[mem - 64bit pref disabled]")
+#define DECODED_BUF_SIZE       sizeof("[mem - 64bit pref window disabled]")
 #define RAW_BUF_SIZE           sizeof("[mem - flags 0x]")
        char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
                     2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
@@ -651,6 +657,9 @@ static char *resource_string(char *buf, char *end, struct resource *res,
        } else if (res->flags & IORESOURCE_DMA) {
                p = string(p, pend, "dma ", str_spec);
                specp = &dec_spec;
+       } else if (res->flags & IORESOURCE_BUS) {
+               p = string(p, pend, "bus ", str_spec);
+               specp = &bus_spec;
        } else {
                p = string(p, pend, "??? ", str_spec);
                specp = &mem_spec;
@@ -666,6 +675,8 @@ static char *resource_string(char *buf, char *end, struct resource *res,
                        p = string(p, pend, " 64bit", str_spec);
                if (res->flags & IORESOURCE_PREFETCH)
                        p = string(p, pend, " pref", str_spec);
+               if (res->flags & IORESOURCE_WINDOW)
+                       p = string(p, pend, " window", str_spec);
                if (res->flags & IORESOURCE_DISABLED)
                        p = string(p, pend, " disabled", str_spec);
        } else {