Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
[~shefty/rdma-dev.git] / drivers / acpi / processor_driver.c
index d4d9cb7e016a0b2d5ea5663f039ae905f77ce92c..0734086537b89732ba805158389b904e94ae7ecf 100644 (file)
@@ -67,6 +67,7 @@
 #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
 #define ACPI_PROCESSOR_NOTIFY_POWER    0x81
 #define ACPI_PROCESSOR_NOTIFY_THROTTLING       0x82
+#define ACPI_PROCESSOR_DEVICE_HID      "ACPI0007"
 
 #define ACPI_PROCESSOR_LIMIT_USER      0
 #define ACPI_PROCESSOR_LIMIT_THERMAL   1
@@ -87,7 +88,7 @@ static int acpi_processor_start(struct acpi_processor *pr);
 
 static const struct acpi_device_id processor_device_ids[] = {
        {ACPI_PROCESSOR_OBJECT_HID, 0},
-       {"ACPI0007", 0},
+       {ACPI_PROCESSOR_DEVICE_HID, 0},
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, processor_device_ids);
@@ -535,8 +536,8 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
                return -ENOMEM;
 
        if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
-               kfree(pr);
-               return -ENOMEM;
+               result = -ENOMEM;
+               goto err_free_pr;
        }
 
        pr->handle = device->handle;
@@ -576,7 +577,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
        dev = get_cpu_device(pr->id);
        if (sysfs_create_link(&device->dev.kobj, &dev->kobj, "sysdev")) {
                result = -EFAULT;
-               goto err_free_cpumask;
+               goto err_clear_processor;
        }
 
        /*
@@ -594,9 +595,15 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
 
 err_remove_sysfs:
        sysfs_remove_link(&device->dev.kobj, "sysdev");
+err_clear_processor:
+       /*
+        * processor_device_array is not cleared to allow checks for buggy BIOS
+        */ 
+       per_cpu(processors, pr->id) = NULL;
 err_free_cpumask:
        free_cpumask_var(pr->throttling.shared_cpu_map);
-
+err_free_pr:
+       kfree(pr);
        return result;
 }
 
@@ -741,20 +748,46 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
        return;
 }
 
+static acpi_status is_processor_device(acpi_handle handle)
+{
+       struct acpi_device_info *info;
+       char *hid;
+       acpi_status status;
+
+       status = acpi_get_object_info(handle, &info);
+       if (ACPI_FAILURE(status))
+               return status;
+
+       if (info->type == ACPI_TYPE_PROCESSOR) {
+               kfree(info);
+               return AE_OK;   /* found a processor object */
+       }
+
+       if (!(info->valid & ACPI_VALID_HID)) {
+               kfree(info);
+               return AE_ERROR;
+       }
+
+       hid = info->hardware_id.string;
+       if ((hid == NULL) || strcmp(hid, ACPI_PROCESSOR_DEVICE_HID)) {
+               kfree(info);
+               return AE_ERROR;
+       }
+
+       kfree(info);
+       return AE_OK;   /* found a processor device object */
+}
+
 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);
+       status = is_processor_device(handle);
        if (ACPI_FAILURE(status))
-               return (AE_OK);
-
-       if (type != ACPI_TYPE_PROCESSOR)
-               return (AE_OK);
+               return AE_OK;   /* not a processor; continue to walk */
 
        switch (*action) {
        case INSTALL_NOTIFY_HANDLER:
@@ -772,7 +805,8 @@ processor_walk_namespace_cb(acpi_handle handle,
                break;
        }
 
-       return (AE_OK);
+       /* found a processor; skip walking underneath */
+       return AE_CTRL_DEPTH;
 }
 
 static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
@@ -830,7 +864,7 @@ void acpi_processor_install_hotplug_notify(void)
 {
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
        int action = INSTALL_NOTIFY_HANDLER;
-       acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
+       acpi_walk_namespace(ACPI_TYPE_ANY,
                            ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX,
                            processor_walk_namespace_cb, NULL, &action, NULL);
@@ -843,7 +877,7 @@ void acpi_processor_uninstall_hotplug_notify(void)
 {
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
        int action = UNINSTALL_NOTIFY_HANDLER;
-       acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
+       acpi_walk_namespace(ACPI_TYPE_ANY,
                            ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX,
                            processor_walk_namespace_cb, NULL, &action, NULL);