diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpi_memhotplug.c | 34 | ||||
-rw-r--r-- | drivers/acpi/acpica/acobject.h | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/dsopcode.c | 24 | ||||
-rw-r--r-- | drivers/acpi/acpica/exfldio.c | 6 | ||||
-rw-r--r-- | drivers/acpi/acpica/exstorob.c | 12 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 25 | ||||
-rw-r--r-- | drivers/acpi/processor_core.c | 6 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 6 | ||||
-rw-r--r-- | drivers/acpi/processor_thermal.c | 6 | ||||
-rw-r--r-- | drivers/acpi/processor_throttling.c | 30 | ||||
-rw-r--r-- | drivers/acpi/system.c | 2 | ||||
-rw-r--r-- | drivers/acpi/video.c | 7 |
12 files changed, 128 insertions, 31 deletions
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 7a0f4aa4fa1..9a62224cc27 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -38,6 +38,9 @@ #define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT +#undef PREFIX +#define PREFIX "ACPI:memory_hp:" + ACPI_MODULE_NAME("acpi_memhotplug"); MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>"); MODULE_DESCRIPTION("Hotplug Mem Driver"); @@ -153,6 +156,7 @@ acpi_memory_get_device(acpi_handle handle, acpi_handle phandle; struct acpi_device *device = NULL; struct acpi_device *pdevice = NULL; + int result; if (!acpi_bus_get_device(handle, &device) && device) @@ -165,9 +169,9 @@ acpi_memory_get_device(acpi_handle handle, } /* Get the parent device */ - status = acpi_bus_get_device(phandle, &pdevice); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Cannot get acpi bus device")); + result = acpi_bus_get_device(phandle, &pdevice); + if (result) { + printk(KERN_WARNING PREFIX "Cannot get acpi bus device"); return -EINVAL; } @@ -175,9 +179,9 @@ acpi_memory_get_device(acpi_handle handle, * Now add the notified device. This creates the acpi_device * and invokes .add function */ - status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Cannot add acpi bus")); + result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); + if (result) { + printk(KERN_WARNING PREFIX "Cannot add acpi bus"); return -EINVAL; } @@ -238,7 +242,12 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) num_enabled++; continue; } - + /* + * If the memory block size is zero, please ignore it. + * Don't try to do the following memory hotplug flowchart. + */ + if (!info->length) + continue; if (node < 0) node = memory_add_physaddr_to_nid(info->start_addr); @@ -253,8 +262,15 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) mem_device->state = MEMORY_INVALID_STATE; return -EINVAL; } - - return result; + /* + * Sometimes the memory device will contain several memory blocks. + * When one memory block is hot-added to the system memory, it will + * be regarded as a success. + * Otherwise if the last memory block can't be hot-added to the system + * memory, it will be failure and the memory device can't be bound with + * driver. + */ + return 0; } static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 544dcf83492..eb6f038b03d 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -97,6 +97,7 @@ #define AOPOBJ_OBJECT_INITIALIZED 0x08 #define AOPOBJ_SETUP_COMPLETE 0x10 #define AOPOBJ_SINGLE_DATUM 0x20 +#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */ /****************************************************************************** * diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 584d766e6f1..b79978f7bc7 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -397,6 +397,30 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), extra_desc->extra.aml_length, extra_desc->extra.aml_start); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Validate the region address/length via the host OS */ + + status = acpi_os_validate_address(obj_desc->region.space_id, + obj_desc->region.address, + (acpi_size) obj_desc->region.length, + acpi_ut_get_node_name(node)); + + if (ACPI_FAILURE(status)) { + /* + * Invalid address/length. We will emit an error message and mark + * the region as invalid, so that it will cause an additional error if + * it is ever used. Then return AE_OK. + */ + ACPI_EXCEPTION((AE_INFO, status, + "During address validation of OpRegion [%4.4s]", + node->name.ascii)); + obj_desc->common.flags |= AOPOBJ_INVALID; + status = AE_OK; + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index d4075b82102..6687be167f5 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -113,6 +113,12 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, } } + /* Exit if Address/Length have been disallowed by the host OS */ + + if (rgn_desc->common.flags & AOPOBJ_INVALID) { + return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); + } + /* * Exit now for SMBus address space, it has a non-linear address space * and the request cannot be directly validated diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c index 67340cc7014..257706e7734 100644 --- a/drivers/acpi/acpica/exstorob.c +++ b/drivers/acpi/acpica/exstorob.c @@ -70,6 +70,12 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc); + /* If Source and Target are the same, just return */ + + if (source_desc == target_desc) { + return_ACPI_STATUS(AE_OK); + } + /* We know that source_desc is a buffer by now */ buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer); @@ -161,6 +167,12 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc); + /* If Source and Target are the same, just return */ + + if (source_desc == target_desc) { + return_ACPI_STATUS(AE_OK); + } + /* We know that source_desc is a string by now */ buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 71670719d61..5691f165a95 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -189,11 +189,36 @@ acpi_status __init acpi_os_initialize(void) return AE_OK; } +static void bind_to_cpu0(struct work_struct *work) +{ + set_cpus_allowed(current, cpumask_of_cpu(0)); + kfree(work); +} + +static void bind_workqueue(struct workqueue_struct *wq) +{ + struct work_struct *work; + + work = kzalloc(sizeof(struct work_struct), GFP_KERNEL); + INIT_WORK(work, bind_to_cpu0); + queue_work(wq, work); +} + acpi_status acpi_os_initialize1(void) { + /* + * On some machines, a software-initiated SMI causes corruption unless + * the SMI runs on CPU 0. An SMI can be initiated by any AML, but + * typically it's done in GPE-related methods that are run via + * workqueues, so we can avoid the known corruption cases by binding + * the workqueues to CPU 0. + */ kacpid_wq = create_singlethread_workqueue("kacpid"); + bind_workqueue(kacpid_wq); kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); + bind_workqueue(kacpi_notify_wq); kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug"); + bind_workqueue(kacpi_hotplug_wq); BUG_ON(!kacpid_wq); BUG_ON(!kacpi_notify_wq); BUG_ON(!kacpi_hotplug_wq); diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 84e0f3c0744..2cc4b303387 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -1151,6 +1151,9 @@ static int __init acpi_processor_init(void) { int result = 0; + if (acpi_disabled) + return 0; + memset(&errata, 0, sizeof(errata)); #ifdef CONFIG_SMP @@ -1197,6 +1200,9 @@ out_proc: static void __exit acpi_processor_exit(void) { + if (acpi_disabled) + return; + acpi_processor_ppc_exit(); acpi_thermal_cpufreq_exit(); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 0efa59e7e3a..66393d5c4c7 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -162,8 +162,9 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr, pr->power.timer_broadcast_on_state = state; } -static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) +static void lapic_timer_propagate_broadcast(void *arg) { + struct acpi_processor *pr = (struct acpi_processor *) arg; unsigned long reason; reason = pr->power.timer_broadcast_on_state < INT_MAX ? @@ -635,7 +636,8 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) working++; } - lapic_timer_propagate_broadcast(pr); + smp_call_function_single(pr->id, lapic_timer_propagate_broadcast, + pr, 1); return (working); } diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 39838c66603..31adda1099e 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -66,7 +66,7 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr) if (pr->limit.thermal.tx > tx) tx = pr->limit.thermal.tx; - result = acpi_processor_set_throttling(pr, tx); + result = acpi_processor_set_throttling(pr, tx, false); if (result) goto end; } @@ -421,12 +421,12 @@ processor_set_cur_state(struct thermal_cooling_device *cdev, if (state <= max_pstate) { if (pr->flags.throttling && pr->throttling.state) - result = acpi_processor_set_throttling(pr, 0); + result = acpi_processor_set_throttling(pr, 0, false); cpufreq_set_cur_state(pr->id, state); } else { cpufreq_set_cur_state(pr->id, max_pstate); result = acpi_processor_set_throttling(pr, - state - max_pstate); + state - max_pstate, false); } return result; } diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 227543789ba..ae39797aab5 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -62,7 +62,8 @@ struct throttling_tstate { #define THROTTLING_POSTCHANGE (2) static int acpi_processor_get_throttling(struct acpi_processor *pr); -int acpi_processor_set_throttling(struct acpi_processor *pr, int state); +int acpi_processor_set_throttling(struct acpi_processor *pr, + int state, bool force); static int acpi_processor_update_tsd_coord(void) { @@ -361,7 +362,7 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr) */ target_state = throttling_limit; } - return acpi_processor_set_throttling(pr, target_state); + return acpi_processor_set_throttling(pr, target_state, false); } /* @@ -839,10 +840,10 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) if (ret >= 0) { state = acpi_get_throttling_state(pr, value); if (state == -1) { - ACPI_WARNING((AE_INFO, - "Invalid throttling state, reset")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Invalid throttling state, reset\n")); state = 0; - ret = acpi_processor_set_throttling(pr, state); + ret = acpi_processor_set_throttling(pr, state, true); if (ret) return ret; } @@ -915,7 +916,7 @@ static int acpi_processor_get_fadt_info(struct acpi_processor *pr) } static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, - int state) + int state, bool force) { u32 value = 0; u32 duty_mask = 0; @@ -930,7 +931,7 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, if (!pr->flags.throttling) return -ENODEV; - if (state == pr->throttling.state) + if (!force && (state == pr->throttling.state)) return 0; if (state < pr->throttling_platform_limit) @@ -988,7 +989,7 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, } static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, - int state) + int state, bool force) { int ret; acpi_integer value; @@ -1002,7 +1003,7 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, if (!pr->flags.throttling) return -ENODEV; - if (state == pr->throttling.state) + if (!force && (state == pr->throttling.state)) return 0; if (state < pr->throttling_platform_limit) @@ -1018,7 +1019,8 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, return 0; } -int acpi_processor_set_throttling(struct acpi_processor *pr, int state) +int acpi_processor_set_throttling(struct acpi_processor *pr, + int state, bool force) { cpumask_var_t saved_mask; int ret = 0; @@ -1070,7 +1072,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) /* FIXME: use work_on_cpu() */ set_cpus_allowed_ptr(current, cpumask_of(pr->id)); ret = p_throttling->acpi_processor_set_throttling(pr, - t_state.target_state); + t_state.target_state, force); } else { /* * When the T-state coordination is SW_ALL or HW_ALL, @@ -1103,7 +1105,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) set_cpus_allowed_ptr(current, cpumask_of(i)); ret = match_pr->throttling. acpi_processor_set_throttling( - match_pr, t_state.target_state); + match_pr, t_state.target_state, force); } } /* @@ -1201,7 +1203,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabling throttling (was T%d)\n", pr->throttling.state)); - result = acpi_processor_set_throttling(pr, 0); + result = acpi_processor_set_throttling(pr, 0, false); if (result) goto end; } @@ -1307,7 +1309,7 @@ static ssize_t acpi_processor_write_throttling(struct file *file, if (strcmp(tmpbuf, charp) != 0) return -EINVAL; - result = acpi_processor_set_throttling(pr, state_val); + result = acpi_processor_set_throttling(pr, state_val, false); if (result) return result; diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 0944daec064..9c61ab2177c 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -121,7 +121,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, table_attr->attr.size = 0; table_attr->attr.read = acpi_table_show; table_attr->attr.attr.name = table_attr->name; - table_attr->attr.attr.mode = 0444; + table_attr->attr.attr.mode = 0400; return; } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 8851315ce85..60ea984c84a 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -2004,8 +2004,11 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) status = acpi_remove_notify_handler(device->dev->handle, ACPI_DEVICE_NOTIFY, acpi_video_device_notify); - sysfs_remove_link(&device->backlight->dev.kobj, "device"); - backlight_device_unregister(device->backlight); + if (device->backlight) { + sysfs_remove_link(&device->backlight->dev.kobj, "device"); + backlight_device_unregister(device->backlight); + device->backlight = NULL; + } if (device->cdev) { sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling"); |