diff options
Diffstat (limited to 'drivers/acpi/processor_driver.c')
| -rw-r--r-- | drivers/acpi/processor_driver.c | 62 | 
1 files changed, 48 insertions, 14 deletions
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 8ae05ce1850..41de1355edc 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -68,6 +68,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 @@ -88,7 +89,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);  |