summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/processor_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/processor_driver.c')
-rw-r--r--drivers/acpi/processor_driver.c75
1 files changed, 53 insertions, 22 deletions
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index e78c2a52ea46..e83311bf1ebd 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -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;
@@ -409,6 +413,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event)
acpi_bus_generate_proc_event(device, event, 0);
acpi_bus_generate_netlink_event(device->pnp.device_class,
dev_name(&device->dev), event, 0);
+ break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Unsupported event [0x%x]\n", event));
@@ -429,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;
@@ -491,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;
}
@@ -560,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;
}
@@ -694,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;
@@ -715,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;
}
@@ -727,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,
@@ -840,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;
@@ -851,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
OpenPOWER on IntegriCloud