]> Pileus Git - ~andy/linux/blobdiff - drivers/acpi/processor_driver.c
Merge branch 'next' of git://git.monstr.eu/linux-2.6-microblaze
[~andy/linux] / drivers / acpi / processor_driver.c
index bd4e5dca3ff7e81f4ce754cbaad3856bb4948a6a..e83311bf1ebdaaaea1adbf2de1351cca907d3465 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/moduleparam.h>
 #include <linux/cpuidle.h>
 #include <linux/slab.h>
+#include <linux/acpi.h>
 
 #include <asm/io.h>
 #include <asm/cpu.h>
@@ -282,7 +283,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
                /* 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");
+                       dev_err(&device->dev,
+                               "Failed to evaluate processor object (0x%x)\n",
+                               status);
                        return -ENODEV;
                }
 
@@ -301,8 +304,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
                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);
+                       dev_err(&device->dev,
+                               "Failed to evaluate processor _UID (0x%x)\n",
+                               status);
                        return -ENODEV;
                }
                device_declaration = 1;
@@ -345,7 +349,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
        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",
+               dev_err(&device->dev, "Invalid PBLK length [%d]\n",
                            object.processor.pblk_length);
        else {
                pr->throttling.address = object.processor.pblk_address;
@@ -430,8 +434,8 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
                 * Initialize missing things
                 */
                if (pr->flags.need_hotplug_init) {
-                       printk(KERN_INFO "Will online and init hotplugged "
-                              "CPU: %d\n", pr->id);
+                       pr_info("Will online and init hotplugged CPU: %d\n",
+                               pr->id);
                        WARN(acpi_processor_start(pr), "Failed to start CPU:"
                                " %d\n", pr->id);
                        pr->flags.need_hotplug_init = 0;
@@ -492,14 +496,16 @@ static __ref int acpi_processor_start(struct acpi_processor *pr)
                                   &pr->cdev->device.kobj,
                                   "thermal_cooling");
        if (result) {
-               printk(KERN_ERR PREFIX "Create sysfs link\n");
+               dev_err(&device->dev,
+                       "Failed to create sysfs link 'thermal_cooling'\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");
+               dev_err(&pr->cdev->device,
+                       "Failed to create sysfs link 'device'\n");
                goto err_remove_sysfs_thermal;
        }
 
@@ -561,8 +567,9 @@ static int __cpuinit acpi_processor_add(struct acpi_device *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");
+               dev_warn(&device->dev,
+                       "BIOS reported wrong ACPI id %d for the processor\n",
+                       pr->id);
                result = -ENODEV;
                goto err_free_cpumask;
        }
@@ -695,8 +702,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
 static void acpi_processor_hotplug_notify(acpi_handle handle,
                                          u32 event, void *data)
 {
-       struct acpi_processor *pr;
        struct acpi_device *device = NULL;
+       struct acpi_eject_event *ej_event = NULL;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
        int result;
 
@@ -716,7 +723,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
 
                result = acpi_processor_device_add(handle, &device);
                if (result) {
-                       printk(KERN_ERR PREFIX "Unable to add the device\n");
+                       acpi_handle_err(handle, "Unable to add the device\n");
                        break;
                }
 
@@ -728,20 +735,29 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
                                  "received ACPI_NOTIFY_EJECT_REQUEST\n"));
 
                if (acpi_bus_get_device(handle, &device)) {
-                       printk(KERN_ERR PREFIX
-                                   "Device don't exist, dropping EJECT\n");
+                       acpi_handle_err(handle,
+                               "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");
+               if (!acpi_driver_data(device)) {
+                       acpi_handle_err(handle,
+                               "Driver data is NULL, dropping EJECT\n");
                        break;
                }
 
-               /* REVISIT: update when eject is supported */
-               ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-               break;
+               ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
+               if (!ej_event) {
+                       acpi_handle_err(handle, "No memory, dropping EJECT\n");
+                       break;
+               }
+
+               ej_event->handle = handle;
+               ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+               acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+                                       (void *)ej_event);
+
+               /* eject is performed asynchronously */
+               return;
 
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -841,7 +857,7 @@ static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
         * and do it when the CPU gets online the first time
         * TBD: Cleanup above functions and try to do this more elegant.
         */
-       printk(KERN_INFO "CPU %d got hotplugged\n", pr->id);
+       pr_info("CPU %d got hotplugged\n", pr->id);
        pr->flags.need_hotplug_init = 1;
 
        return AE_OK;
@@ -852,8 +868,22 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr)
        if (cpu_online(pr->id))
                cpu_down(pr->id);
 
+       get_online_cpus();
+       /*
+        * The cpu might become online again at this point. So we check whether
+        * the cpu has been onlined or not. If the cpu became online, it means
+        * that someone wants to use the cpu. So acpi_processor_handle_eject()
+        * returns -EAGAIN.
+        */
+       if (unlikely(cpu_online(pr->id))) {
+               put_online_cpus();
+               pr_warn("Failed to remove CPU %d, because other task "
+                       "brought the CPU back online\n", pr->id);
+               return -EAGAIN;
+       }
        arch_unregister_cpu(pr->id);
        acpi_unmap_lsapic(pr->id);
+       put_online_cpus();
        return (0);
 }
 #else