cpumask: alloc zeroed cpumask for static cpumask_var_ts
[safe/jmp/linux-2.6] / drivers / acpi / processor_core.c
index 9dd0fa9..23f0fb8 100644 (file)
@@ -59,7 +59,6 @@
 #include <acpi/acpi_drivers.h>
 #include <acpi/processor.h>
 
-#define ACPI_PROCESSOR_COMPONENT       0x01000000
 #define ACPI_PROCESSOR_CLASS           "processor"
 #define ACPI_PROCESSOR_DEVICE_NAME     "Processor"
 #define ACPI_PROCESSOR_FILE_INFO       "info"
@@ -83,12 +82,13 @@ static int acpi_processor_add(struct acpi_device *device);
 static int acpi_processor_start(struct acpi_device *device);
 static int acpi_processor_remove(struct acpi_device *device, int type);
 static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
-static void acpi_processor_notify(acpi_handle handle, u32 event, void *data);
+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},
        {ACPI_PROCESSOR_HID, 0},
        {"", 0},
 };
@@ -104,6 +104,7 @@ static struct acpi_driver acpi_processor_driver = {
                .start = acpi_processor_start,
                .suspend = acpi_processor_suspend,
                .resume = acpi_processor_resume,
+               .notify = acpi_processor_notify,
                },
 };
 
@@ -118,8 +119,31 @@ static const struct file_operations acpi_processor_info_fops = {
        .release = single_release,
 };
 
-struct acpi_processor *processors[NR_CPUS];
+DEFINE_PER_CPU(struct acpi_processor *, processors);
 struct acpi_processor_errata errata __read_mostly;
+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},
+       {},
+};
 
 /* --------------------------------------------------------------------------
                                 Errata Handling
@@ -265,7 +289,20 @@ static int acpi_processor_set_pdc(struct acpi_processor *pr)
 
        if (!pdc_in)
                return status;
+       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(pr->handle, "_PDC", pdc_in, NULL);
 
        if (ACPI_FAILURE(status))
@@ -323,7 +360,6 @@ static int acpi_processor_add_fs(struct acpi_device *device)
                if (!acpi_device_dir(device))
                        return -ENODEV;
        }
-       acpi_device_dir(device)->owner = THIS_MODULE;
 
        /* 'info' [R] */
        entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO,
@@ -373,7 +409,7 @@ static int acpi_processor_remove_fs(struct acpi_device *device)
 /* Use the acpiid in MADT to map cpus in case of SMP */
 
 #ifndef CONFIG_SMP
-static int get_cpu_id(acpi_handle handle, u32 acpi_id) {return -1;}
+static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { return -1; }
 #else
 
 static struct acpi_table_madt *madt;
@@ -391,28 +427,59 @@ static int map_lapic_id(struct acpi_subtable_header *entry,
        return 0;
 }
 
+static int map_x2apic_id(struct acpi_subtable_header *entry,
+                        int device_declaration, u32 acpi_id, int *apic_id)
+{
+       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;
+       }
+
+       return 0;
+found:
+       *apic_id = tmp;
+       return 1;
+}
+
 static int map_lsapic_id(struct acpi_subtable_header *entry,
-                 u32 acpi_id, int *apic_id)
+               int device_declaration, u32 acpi_id, int *apic_id)
 {
        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) {
-               /* First check against id */
-               if (lsapic->processor_id == acpi_id) {
-                       *apic_id = (lsapic->id << 8) | lsapic->eid;
-                       return 1;
-               /* Check against optional uid */
-               } else if (entry->length >= 16 &&
-                       lsapic->uid == acpi_id) {
-                       *apic_id = lsapic->uid;
-                       return 1;
-               }
-       }
+       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;
+
        return 0;
+found:
+       *apic_id = tmp;
+       return 1;
 }
 
-static int map_madt_entry(u32 acpi_id)
+static int map_madt_entry(int type, u32 acpi_id)
 {
        unsigned long madt_end, entry;
        int apic_id = -1;
@@ -432,8 +499,11 @@ static int map_madt_entry(u32 acpi_id)
                if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
                        if (map_lapic_id(header, acpi_id, &apic_id))
                                break;
+               } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
+                       if (map_x2apic_id(header, type, acpi_id, &apic_id))
+                               break;
                } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
-                       if (map_lsapic_id(header, acpi_id, &apic_id))
+                       if (map_lsapic_id(header, type, acpi_id, &apic_id))
                                break;
                }
                entry += header->length;
@@ -441,7 +511,7 @@ static int map_madt_entry(u32 acpi_id)
        return apic_id;
 }
 
-static int map_mat_entry(acpi_handle handle, u32 acpi_id)
+static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *obj;
@@ -464,7 +534,7 @@ static int map_mat_entry(acpi_handle handle, u32 acpi_id)
        if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
                map_lapic_id(header, acpi_id, &apic_id);
        } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
-               map_lsapic_id(header, acpi_id, &apic_id);
+               map_lsapic_id(header, type, acpi_id, &apic_id);
        }
 
 exit:
@@ -473,14 +543,14 @@ exit:
        return apic_id;
 }
 
-static int get_cpu_id(acpi_handle handle, u32 acpi_id)
+static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id)
 {
        int i;
        int apic_id = -1;
 
-       apic_id = map_mat_entry(handle, acpi_id);
+       apic_id = map_mat_entry(handle, type, acpi_id);
        if (apic_id == -1)
-               apic_id = map_madt_entry(acpi_id);
+               apic_id = map_madt_entry(type, acpi_id);
        if (apic_id == -1)
                return apic_id;
 
@@ -496,15 +566,16 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id)
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
-static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
+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 };
-       int cpu_index;
+       struct acpi_processor *pr;
+       int cpu_index, device_declaration = 0;
        static int cpu0_initialized;
 
-
+       pr = acpi_driver_data(device);
        if (!pr)
                return -EINVAL;
 
@@ -525,22 +596,23 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "No bus mastering arbitration control\n"));
 
-       /* Check if it is a Device with HID and UID */
-       if (has_uid) {
-               unsigned long value;
+       if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) {
+               /*
+                * 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\n");
+                       printk(KERN_ERR PREFIX
+                           "Evaluating processor _UID [%#x]\n", status);
                        return -ENODEV;
                }
+               device_declaration = 1;
                pr->acpi_id = value;
        } else {
-               /*
-               * Evalute the processor object.  Note that it is common on SMP to
-               * have the first (boot) processor with a valid PBLK address while
-               * all others have a NULL address.
-               */
+               /* 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");
@@ -548,12 +620,13 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
                }
 
                /*
-               * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
-               *      >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
-               */
+                * 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;
        }
-       cpu_index = get_cpu_id(pr->handle, pr->acpi_id);
+       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) &&
@@ -614,18 +687,17 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
        return 0;
 }
 
-static void *processor_device_array[NR_CPUS];
+static DEFINE_PER_CPU(void *, processor_device_array);
 
 static int __cpuinit acpi_processor_start(struct acpi_device *device)
 {
        int result = 0;
-       acpi_status status = AE_OK;
        struct acpi_processor *pr;
-
+       struct sys_device *sysdev;
 
        pr = acpi_driver_data(device);
 
-       result = acpi_processor_get_info(pr, device->flags.unique_id);
+       result = acpi_processor_get_info(device);
        if (result) {
                /* Processor is physically not present */
                return 0;
@@ -638,22 +710,23 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
         * ACPI id of processors can be reported wrongly by the BIOS.
         * Don't trust it blindly
         */
-       if (processor_device_array[pr->id] != NULL &&
-           processor_device_array[pr->id] != device) {
+       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");
                return -ENODEV;
        }
-       processor_device_array[pr->id] = device;
+       per_cpu(processor_device_array, pr->id) = device;
 
-       processors[pr->id] = pr;
+       per_cpu(processors, pr->id) = pr;
 
        result = acpi_processor_add_fs(device);
        if (result)
                goto end;
 
-       status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
-                                            acpi_processor_notify, pr);
+       sysdev = get_cpu_sysdev(pr->id);
+       if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev"))
+               return -EFAULT;
 
        /* _PDC call should be done before doing anything else (if reqd.). */
        arch_acpi_processor_init_pdc(pr);
@@ -674,9 +747,8 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
                goto end;
        }
 
-       printk(KERN_INFO PREFIX
-               "%s is registered as cooling_device%d\n",
-               device->dev.bus_id, pr->cdev->id);
+       dev_info(&device->dev, "registered as cooling_device%d\n",
+                pr->cdev->id);
 
        result = sysfs_create_link(&device->dev.kobj,
                                   &pr->cdev->device.kobj,
@@ -701,18 +773,14 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
        return result;
 }
 
-static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
+static void acpi_processor_notify(struct acpi_device *device, u32 event)
 {
-       struct acpi_processor *pr = data;
-       struct acpi_device *device = NULL;
+       struct acpi_processor *pr = acpi_driver_data(device);
        int saved;
 
        if (!pr)
                return;
 
-       if (acpi_bus_get_device(pr->handle, &device))
-               return;
-
        switch (event) {
        case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
                saved = pr->performance_platform_limit;
@@ -722,20 +790,20 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
                acpi_bus_generate_proc_event(device, event,
                                        pr->performance_platform_limit);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
-                                                 device->dev.bus_id, event,
+                                                 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,
-                                                 device->dev.bus_id, event, 0);
+                                                 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,
-                                                 device->dev.bus_id, event, 0);
+                                                 dev_name(&device->dev), event, 0);
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
@@ -749,7 +817,7 @@ 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 = processors[cpu];
+       struct acpi_processor *pr = per_cpu(processors, cpu);
 
        if (action == CPU_ONLINE && pr) {
                acpi_processor_ppc_has_changed(pr);
@@ -776,17 +844,21 @@ static int acpi_processor_add(struct acpi_device *device)
        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);
-       acpi_driver_data(device) = pr;
+       device->driver_data = pr;
 
        return 0;
 }
 
 static int acpi_processor_remove(struct acpi_device *device, int type)
 {
-       acpi_status status = AE_OK;
        struct acpi_processor *pr = NULL;
 
 
@@ -795,10 +867,8 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
 
        pr = acpi_driver_data(device);
 
-       if (pr->id >= nr_cpu_ids) {
-               kfree(pr);
-               return 0;
-       }
+       if (pr->id >= nr_cpu_ids)
+               goto free;
 
        if (type == ACPI_BUS_REMOVAL_EJECT) {
                if (acpi_processor_handle_eject(pr))
@@ -807,8 +877,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
 
        acpi_processor_power_exit(pr, device);
 
-       status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY,
-                                           acpi_processor_notify);
+       sysfs_remove_link(&device->dev.kobj, "sysdev");
 
        acpi_processor_remove_fs(device);
 
@@ -819,8 +888,11 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
                pr->cdev = NULL;
        }
 
-       processors[pr->id] = NULL;
-       processor_device_array[pr->id] = 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;
@@ -834,7 +906,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
 static int is_processor_present(acpi_handle handle)
 {
        acpi_status status;
-       unsigned long sta = 0;
+       unsigned long long sta = 0;
 
 
        status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
@@ -1014,9 +1086,9 @@ static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
 
 static int acpi_processor_handle_eject(struct acpi_processor *pr)
 {
-       if (cpu_online(pr->id)) {
-               return (-EINVAL);
-       }
+       if (cpu_online(pr->id))
+               cpu_down(pr->id);
+
        arch_unregister_cpu(pr->id);
        acpi_unmap_lsapic(pr->id);
        return (0);
@@ -1068,8 +1140,6 @@ static int __init acpi_processor_init(void)
 {
        int result = 0;
 
-
-       memset(&processors, 0, sizeof(processors));
        memset(&errata, 0, sizeof(errata));
 
 #ifdef CONFIG_SMP
@@ -1081,8 +1151,12 @@ static int __init acpi_processor_init(void)
        acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
        if (!acpi_processor_dir)
                return -ENOMEM;
-       acpi_processor_dir->owner = THIS_MODULE;
 
+       /*
+        * Check whether the system is DMI table. If yes, OSPM
+        * should not use mwait for CPU-states.
+        */
+       dmi_check_system(processor_idle_dmi_table);
        result = cpuidle_register_driver(&acpi_idle_driver);
        if (result < 0)
                goto out_proc;