From 5f46c2f25cfbb5faca7550738ac42c4d1491ddc8 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Mon, 19 Oct 2009 15:14:24 -0600 Subject: ACPI: dock: convert sysfs attributes to an attribute_group As suggested by Dmitry Torokhov, convert the individual sysfs attributes into an attribute group. This change eliminates quite a bit of copy/paste code in the error handling paths. Signed-off-by: Alex Chiang Reviewed-by: Dmitry Torokhov Acked-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 81 ++++++++++++++++------------------------------------- 1 file changed, 24 insertions(+), 57 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 7338b6a3e049..4f2aa98e2cee 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -936,6 +936,19 @@ static ssize_t show_dock_type(struct device *dev, } static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL); +static struct attribute *dock_attributes[] = { + &dev_attr_docked.attr, + &dev_attr_flags.attr, + &dev_attr_undock.attr, + &dev_attr_uid.attr, + &dev_attr_type.attr, + NULL +}; + +static struct attribute_group dock_attribute_group = { + .attrs = dock_attributes +}; + /** * dock_add - add a new dock station * @handle: the dock station handle @@ -969,9 +982,8 @@ static int dock_add(acpi_handle handle) dock_station_count, NULL, 0); dock_device = dock_station->dock_device; if (IS_ERR(dock_device)) { - kfree(dock_station); - dock_station = NULL; - return PTR_ERR(dock_device); + ret = PTR_ERR(dock_device); + goto out; } platform_device_add_data(dock_device, &dock_station, sizeof(struct dock_station *)); @@ -986,47 +998,9 @@ static int dock_add(acpi_handle handle) if (is_battery(handle)) dock_station->flags |= DOCK_IS_BAT; - ret = device_create_file(&dock_device->dev, &dev_attr_docked); - if (ret) { - printk(KERN_ERR "Error %d adding sysfs file\n", ret); - platform_device_unregister(dock_device); - kfree(dock_station); - dock_station = NULL; - return ret; - } - ret = device_create_file(&dock_device->dev, &dev_attr_undock); - if (ret) { - printk(KERN_ERR "Error %d adding sysfs file\n", ret); - device_remove_file(&dock_device->dev, &dev_attr_docked); - platform_device_unregister(dock_device); - kfree(dock_station); - dock_station = NULL; - return ret; - } - ret = device_create_file(&dock_device->dev, &dev_attr_uid); - if (ret) { - printk(KERN_ERR "Error %d adding sysfs file\n", ret); - device_remove_file(&dock_device->dev, &dev_attr_docked); - device_remove_file(&dock_device->dev, &dev_attr_undock); - platform_device_unregister(dock_device); - kfree(dock_station); - dock_station = NULL; - return ret; - } - ret = device_create_file(&dock_device->dev, &dev_attr_flags); - if (ret) { - printk(KERN_ERR "Error %d adding sysfs file\n", ret); - device_remove_file(&dock_device->dev, &dev_attr_docked); - device_remove_file(&dock_device->dev, &dev_attr_undock); - device_remove_file(&dock_device->dev, &dev_attr_uid); - platform_device_unregister(dock_device); - kfree(dock_station); - dock_station = NULL; - return ret; - } - ret = device_create_file(&dock_device->dev, &dev_attr_type); + ret = sysfs_create_group(&dock_device->dev.kobj, &dock_attribute_group); if (ret) - printk(KERN_ERR"Error %d adding sysfs file\n", ret); + goto err_unregister; /* Find dependent devices */ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, @@ -1036,10 +1010,8 @@ static int dock_add(acpi_handle handle) /* add the dock station as a device dependent on itself */ dd = alloc_dock_dependent_device(handle); if (!dd) { - kfree(dock_station); - dock_station = NULL; ret = -ENOMEM; - goto dock_add_err_unregister; + goto err_rmgroup; } add_dock_dependent_device(dock_station, dd); @@ -1047,15 +1019,14 @@ static int dock_add(acpi_handle handle) list_add(&dock_station->sibling, &dock_stations); return 0; -dock_add_err_unregister: - device_remove_file(&dock_device->dev, &dev_attr_type); - device_remove_file(&dock_device->dev, &dev_attr_docked); - device_remove_file(&dock_device->dev, &dev_attr_undock); - device_remove_file(&dock_device->dev, &dev_attr_uid); - device_remove_file(&dock_device->dev, &dev_attr_flags); +err_rmgroup: + sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group); +err_unregister: platform_device_unregister(dock_device); +out: kfree(dock_station); dock_station = NULL; + printk(KERN_ERR "%s encountered error %d\n", __func__, ret); return ret; } @@ -1076,11 +1047,7 @@ static int dock_remove(struct dock_station *dock_station) kfree(dd); /* cleanup sysfs */ - device_remove_file(&dock_device->dev, &dev_attr_type); - device_remove_file(&dock_device->dev, &dev_attr_docked); - device_remove_file(&dock_device->dev, &dev_attr_undock); - device_remove_file(&dock_device->dev, &dev_attr_uid); - device_remove_file(&dock_device->dev, &dev_attr_flags); + sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group); platform_device_unregister(dock_device); /* free dock station memory */ -- cgit v1.2.3 From 7fb2616e249184e217f9818a7662596165710ea4 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Mon, 26 Oct 2009 08:39:01 +0100 Subject: acpi: thermal: display forced passive trip points in proc Users can force a passive trip point for a thermal zone that does not have _PSV defined in ACPI by setting the passive attribute in sysfs. It's useful to display such trip points in /proc/acpi/thermal_zone. .../TZ1/cooling_mode: .../TZ1/polling_frequency:polling frequency: 10 seconds .../TZ1/state:state: ok .../TZ1/temperature:temperature: 53 C .../TZ1/trip_points:critical (S5): 110 C .../TZ1/trip_points:passive (forced): 95 C And if not set (passive is 0): .../TZ1/trip_points:passive (forced): Signed-off-by: Frans Pop Acked-by: Zhang Rui Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/thermal.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 65f67815902a..9073ada88835 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1052,6 +1052,13 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) acpi_device_bid(device)); } seq_puts(seq, "\n"); + } else { + seq_printf(seq, "passive (forced):"); + if (tz->thermal_zone->forced_passive) + seq_printf(seq, " %i C\n", + tz->thermal_zone->forced_passive / 1000); + else + seq_printf(seq, "\n"); } for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { -- cgit v1.2.3 From d81c45e1c9369855901420f79114852eba2ea16a Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 16 Oct 2009 09:20:41 +0800 Subject: ACPI: Notify the _PPC evaluation status to the platform According to the ACPI spec(section 8.4.4.3) OSPM should convey the _PPC evaluations status to the platform if there exists the _OST object. The _OST contains two arguments: The first is the PERFORMANCE notificatin event. The second is the status of _PPC object. OSPM will convey the _PPC evaluation status to the platform. Of course when the module parameter of "ignore_ppc" is added, OSPM won't evaluate the _PPC object. But it will call the _OST object. At the same time the _OST object will be evaluated only when the PERFORMANCE notification event is received. Signed-off-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 6 ++--- drivers/acpi/processor_perflib.c | 50 +++++++++++++++++++++++++++++++++++++--- include/acpi/processor.h | 5 ++-- 3 files changed, 53 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index c567b46dfa0f..773d7e76f301 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -722,7 +722,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event) switch (event) { case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: saved = pr->performance_platform_limit; - acpi_processor_ppc_has_changed(pr); + acpi_processor_ppc_has_changed(pr, 1); if (saved == pr->performance_platform_limit) break; acpi_bus_generate_proc_event(device, event, @@ -758,7 +758,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, struct acpi_processor *pr = per_cpu(processors, cpu); if (action == CPU_ONLINE && pr) { - acpi_processor_ppc_has_changed(pr); + acpi_processor_ppc_has_changed(pr, 0); acpi_processor_cst_has_changed(pr); acpi_processor_tstate_has_changed(pr); } @@ -830,7 +830,7 @@ static int acpi_processor_add(struct acpi_device *device) arch_acpi_processor_cleanup_pdc(pr); #ifdef CONFIG_CPU_FREQ - acpi_processor_ppc_has_changed(pr); + acpi_processor_ppc_has_changed(pr, 0); #endif acpi_processor_get_throttling_info(pr); acpi_processor_get_limit_info(pr); diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 8ba0ed0b9ddb..fc1f49bbbeef 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -152,15 +152,59 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) return 0; } -int acpi_processor_ppc_has_changed(struct acpi_processor *pr) +#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 +/* + * acpi_processor_ppc_ost: Notify firmware the _PPC evaluation status + * @handle: ACPI processor handle + * @status: the status code of _PPC evaluation + * 0: success. OSPM is now using the performance state specificed. + * 1: failure. OSPM has not changed the number of P-states in use + */ +static void acpi_processor_ppc_ost(acpi_handle handle, int status) +{ + union acpi_object params[2] = { + {.type = ACPI_TYPE_INTEGER,}, + {.type = ACPI_TYPE_INTEGER,}, + }; + struct acpi_object_list arg_list = {2, params}; + acpi_handle temp; + + params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE; + params[1].integer.value = status; + + /* when there is no _OST , skip it */ + if (ACPI_FAILURE(acpi_get_handle(handle, "_OST", &temp))) + return; + + acpi_evaluate_object(handle, "_OST", &arg_list, NULL); + return; +} + +int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag) { int ret; - if (ignore_ppc) + if (ignore_ppc) { + /* + * Only when it is notification event, the _OST object + * will be evaluated. Otherwise it is skipped. + */ + if (event_flag) + acpi_processor_ppc_ost(pr->handle, 1); return 0; + } ret = acpi_processor_get_platform_limit(pr); - + /* + * Only when it is notification event, the _OST object + * will be evaluated. Otherwise it is skipped. + */ + if (event_flag) { + if (ret < 0) + acpi_processor_ppc_ost(pr->handle, 1); + else + acpi_processor_ppc_ost(pr->handle, 0); + } if (ret < 0) return (ret); else diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 740ac3ad8fd0..a920237f7c62 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -294,7 +294,7 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx #ifdef CONFIG_CPU_FREQ void acpi_processor_ppc_init(void); void acpi_processor_ppc_exit(void); -int acpi_processor_ppc_has_changed(struct acpi_processor *pr); +int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag); #else static inline void acpi_processor_ppc_init(void) { @@ -304,7 +304,8 @@ static inline void acpi_processor_ppc_exit(void) { return; } -static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) +static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr, + int event_flag) { static unsigned int printout = 1; if (printout) { -- cgit v1.2.3 From 876fba43cc810e3c37ce26995933f9547b83cb0e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 11 Nov 2009 15:22:15 +0100 Subject: ACPI: add const to acpi_check_resource_conflict() acpi_check_resource_conflict() doesn't change the resource it operates on, so the res parameter can be marked const. Signed-off-by: Jean Delvare Signed-off-by: Len Brown --- drivers/acpi/osl.c | 2 +- include/linux/acpi.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 7c1c59ea9ec6..02e8464e480f 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1118,7 +1118,7 @@ __setup("acpi_enforce_resources=", acpi_enforce_resources_setup); /* Check for resource conflicts between ACPI OperationRegions and native * drivers */ -int acpi_check_resource_conflict(struct resource *res) +int acpi_check_resource_conflict(const struct resource *res) { struct acpi_res_list *res_list_elem; int ioport; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index dfcd920c3e54..c920d2def4d3 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -240,7 +240,7 @@ extern int pnpacpi_disabled; #define PXM_INVAL (-1) #define NID_INVAL (-1) -int acpi_check_resource_conflict(struct resource *res); +int acpi_check_resource_conflict(const struct resource *res); int acpi_check_region(resource_size_t start, resource_size_t n, const char *name); -- cgit v1.2.3 From a1a541d86f50a9957beeedb122a035870d602647 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 2 Dec 2009 13:31:00 +0800 Subject: ACPI: support customizing ACPI control methods at runtime Introduce a new debugfs I/F (/sys/kernel/debug/acpi/custom_method) for ACPI, which can be used to customize the ACPI control methods at runtime. We can use this to debug the AML code level bugs instead of overriding the whole DSDT table, without rebuilding/rebooting kernel any more. Detailed description about how to use this debugfs I/F is stated in Documentation/acpi/method-customizing.txt Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- Documentation/acpi/method-customizing.txt | 66 ++++++++++++++++++++++++ drivers/acpi/debug.c | 83 ++++++++++++++++++++++++++++++- 2 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 Documentation/acpi/method-customizing.txt (limited to 'drivers/acpi') diff --git a/Documentation/acpi/method-customizing.txt b/Documentation/acpi/method-customizing.txt new file mode 100644 index 000000000000..e628cd23ca80 --- /dev/null +++ b/Documentation/acpi/method-customizing.txt @@ -0,0 +1,66 @@ +Linux ACPI Custom Control Method How To +======================================= + +Written by Zhang Rui + + +Linux supports customizing ACPI control methods at runtime. + +Users can use this to +1. override an existing method which may not work correctly, + or just for debugging purposes. +2. insert a completely new method in order to create a missing + method such as _OFF, _ON, _STA, _INI, etc. +For these cases, it is far simpler to dynamically install a single +control method rather than override the entire DSDT, because kernel +rebuild/reboot is not needed and test result can be got in minutes. + +Note: Only ACPI METHOD can be overridden, any other object types like + "Device", "OperationRegion", are not recognized. +Note: The same ACPI control method can be overridden for many times, + and it's always the latest one that used by Linux/kernel. + +1. override an existing method + a) get the ACPI table via ACPI sysfs I/F. e.g. to get the DSDT, + just run "cat /sys/firmware/acpi/tables/DSDT > /tmp/dsdt.dat" + b) disassemble the table by running "iasl -d dsdt.dat". + c) rewrite the ASL code of the method and save it in a new file, + d) package the new file (psr.asl) to an ACPI table format. + Here is an example of a customized \_SB._AC._PSR method, + + DefinitionBlock ("", "SSDT", 1, "", "", 0x20080715) + { + External (ACON) + + Method (\_SB_.AC._PSR, 0, NotSerialized) + { + Store ("In AC _PSR", Debug) + Return (ACON) + } + } + Note that the full pathname of the method in ACPI namespace + should be used. + And remember to use "External" to declare external objects. + e) assemble the file to generate the AML code of the method. + e.g. "iasl psr.asl" (psr.aml is generated as a result) + f) mount debugfs by "mount -t debugfs none /sys/kernel/debug" + g) override the old method via the debugfs by running + "cat /tmp/psr.aml > /sys/kernel/debug/acpi/custom_method" + +2. insert a new method + This is easier than overriding an existing method. + We just need to create the ASL code of the method we want to + insert and then follow the step c) ~ g) in section 1. + +3. undo your changes + The "undo" operation is not supported for a new inserted method + right now, i.e. we can not remove a method currently. + For an overrided method, in order to undo your changes, please + save a copy of the method original ASL code in step c) section 1, + and redo step c) ~ g) to override the method with the original one. + + +Note: We can use a kernel with multiple custom ACPI method running, + But each individual write to debugfs can implement a SINGLE + method override. i.e. if we want to insert/override multiple + ACPI methods, we need to redo step c) ~ g) for multiple times. diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 8a690c3b8e23..0bedd1554f2f 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -195,6 +196,79 @@ static int param_get_trace_state(char *buffer, struct kernel_param *kp) module_param_call(trace_state, param_set_trace_state, param_get_trace_state, NULL, 0644); +/* -------------------------------------------------------------------------- + DebugFS Interface + -------------------------------------------------------------------------- */ + +static ssize_t cm_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + static char *buf; + static int uncopied_bytes; + struct acpi_table_header table; + acpi_status status; + + if (!(*ppos)) { + /* parse the table header to get the table length */ + if (count <= sizeof(struct acpi_table_header)) + return -EINVAL; + if (copy_from_user(&table, user_buf, + sizeof(struct acpi_table_header))) + return -EFAULT; + uncopied_bytes = table.length; + buf = kzalloc(uncopied_bytes, GFP_KERNEL); + if (!buf) + return -ENOMEM; + } + + if (uncopied_bytes < count) { + kfree(buf); + return -EINVAL; + } + + if (copy_from_user(buf + (*ppos), user_buf, count)) { + kfree(buf); + return -EFAULT; + } + + uncopied_bytes -= count; + *ppos += count; + + if (!uncopied_bytes) { + status = acpi_install_method(buf); + kfree(buf); + if (ACPI_FAILURE(status)) + return -EINVAL; + } + + return count; +} + +static const struct file_operations cm_fops = { + .write = cm_write, +}; + +static int acpi_debugfs_init(void) +{ + struct dentry *acpi_dir, *cm_dentry; + + acpi_dir = debugfs_create_dir("acpi", NULL); + if (!acpi_dir) + goto err; + + cm_dentry = debugfs_create_file("custom_method", S_IWUGO, + acpi_dir, NULL, &cm_fops); + if (!cm_dentry) + goto err; + + return 0; + +err: + if (acpi_dir) + debugfs_remove(acpi_dir); + return -EINVAL; +} + /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -286,7 +360,7 @@ static const struct file_operations acpi_system_debug_proc_fops = { }; #endif -int __init acpi_debug_init(void) +int __init acpi_procfs_init(void) { #ifdef CONFIG_ACPI_PROCFS struct proc_dir_entry *entry; @@ -321,3 +395,10 @@ int __init acpi_debug_init(void) return 0; #endif } + +int __init acpi_debug_init(void) +{ + acpi_debugfs_init(); + acpi_procfs_init(); + return 0; +} -- cgit v1.2.3 From 583061c59ffea1ea14f6dca735ab0f99238a7a92 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Fri, 11 Dec 2009 14:36:47 +0800 Subject: ACPICA: Fix possible memory leak for module-level code execution An object can be leaked for each block of executed module-level code if the interpreter slack mode is enabled. The change deletes any implicitly returned object in this case. Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/acpica/nseval.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index f771e978c403..65e0d1a260ea 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -415,6 +415,12 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n", method_obj->method.aml_start)); + /* Delete a possible implicit return value (in slack mode) */ + + if (info->return_object) { + acpi_ut_remove_reference(info->return_object); + } + /* Detach the temporary method object */ acpi_ns_detach_object(parent_node); -- cgit v1.2.3 From f2cb12510836da63cf459dca452fc0770da155f1 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 14:38:08 +0800 Subject: ACPICA: Fix two Scope type error messages Both messages incorrectly used the internal Path string instead of the node name. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/dswload.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 10fc78517843..1bab934e99f8 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -212,18 +212,19 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, case ACPI_TYPE_BUFFER: /* - * These types we will allow, but we will change the type. This - * enables some existing code of the form: + * These types we will allow, but we will change the type. + * This enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } * - * Note: silently change the type here. On the second pass, we will report - * a warning + * Note: silently change the type here. On the second pass, + * we will report a warning */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", - path, + "Type override - [%4.4s] had invalid type (%s) " + "for Scope operator, changed to type ANY\n", + acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type))); node->type = ACPI_TYPE_ANY; @@ -235,8 +236,10 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, /* All other types are an error */ ACPI_ERROR((AE_INFO, - "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)", - acpi_ut_get_type_name(node->type), path)); + "Invalid type (%s) for target of " + "Scope operator [%4.4s] (Cannot override)", + acpi_ut_get_type_name(node->type), + acpi_ut_get_node_name(node))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } -- cgit v1.2.3 From ebdca3edd5ac61e37f2f5e7c11006c1a68d3cc7e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 14:40:17 +0800 Subject: ACPICA: Fix two additional Scope override error messages These messages were using the internal path for the message instead of using the node name. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/dswload.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 1bab934e99f8..9cc2289f872e 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -700,15 +700,16 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, case ACPI_TYPE_BUFFER: /* - * These types we will allow, but we will change the type. This - * enables some existing code of the form: + * These types we will allow, but we will change the type. + * This enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } */ ACPI_WARNING((AE_INFO, - "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)", - buffer_ptr, + "Type override - [%4.4s] had invalid type (%s) " + "for Scope operator, changed to type ANY\n", + acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type))); node->type = ACPI_TYPE_ANY; @@ -720,9 +721,10 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, /* All other types are an error */ ACPI_ERROR((AE_INFO, - "Invalid type (%s) for target of Scope operator [%4.4s]", + "Invalid type (%s) for target of " + "Scope operator [%4.4s] (Cannot override)", acpi_ut_get_type_name(node->type), - buffer_ptr)); + acpi_ut_get_node_name(node))); return (AE_AML_OPERAND_TYPE); } -- cgit v1.2.3 From 34c39c755347c1ca3d06284bad2273c6a9c3108a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 14:53:11 +0800 Subject: ACPICA: Add repair for bad _FDE/_GTM buffers The expected return value for both names is a Buffer of 5 DWORDS. This repair fixes two possible problems (both seen in the field): A package of integers is returned, or a buffer of BYTEs is returned. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/nspredef.c | 14 ++-- drivers/acpi/acpica/nsrepair2.c | 149 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 152 insertions(+), 11 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index b05f42903c86..1782c3d85ba2 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -222,23 +222,21 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, status = acpi_ns_check_object_type(data, return_object_ptr, predefined->info.expected_btypes, ACPI_NOT_PACKAGE_ELEMENT); - if (ACPI_FAILURE(status)) { - goto check_validation_status; - } + if (ACPI_SUCCESS(status)) { - /* For returned Package objects, check the type of all sub-objects */ + /* For returned Package objects, check the type of all sub-objects */ - if (return_object->common.type == ACPI_TYPE_PACKAGE) { - status = acpi_ns_check_package(data, return_object_ptr); + if (return_object->common.type == ACPI_TYPE_PACKAGE) { + status = acpi_ns_check_package(data, return_object_ptr); + } } /* * Perform additional, more complicated repairs on a per-name - * basis. + * basis. Do this regardless of the status from above. */ status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); -check_validation_status: /* * If the object validation failed or if we successfully repaired one * or more objects, mark the parent node to suppress further warning diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index d07b68613818..6c35b57a7fd0 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -73,6 +73,10 @@ static acpi_status acpi_ns_repair_ALR(struct acpi_predefined_data *data, union acpi_operand_object **return_object_ptr); +static acpi_status +acpi_ns_repair_FDE(struct acpi_predefined_data *data, + union acpi_operand_object **return_object_ptr); + static acpi_status acpi_ns_repair_PSS(struct acpi_predefined_data *data, union acpi_operand_object **return_object_ptr); @@ -104,17 +108,27 @@ acpi_ns_sort_list(union acpi_operand_object **elements, * This table contains the names of the predefined methods for which we can * perform more complex repairs. * - * _ALR: Sort the list ascending by ambient_illuminance if necessary - * _PSS: Sort the list descending by Power if necessary - * _TSS: Sort the list descending by Power if necessary + * As necessary: + * + * _ALR: Sort the list ascending by ambient_illuminance + * _FDE: Convert a Package or Buffer of BYTEs to a Buffer of DWORDs + * _GTM: Convert a Package or Buffer of BYTEs to a Buffer of DWORDs + * _PSS: Sort the list descending by Power + * _TSS: Sort the list descending by Power */ static const struct acpi_repair_info acpi_ns_repairable_names[] = { {"_ALR", acpi_ns_repair_ALR}, + {"_FDE", acpi_ns_repair_FDE}, + {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ {"_PSS", acpi_ns_repair_PSS}, {"_TSS", acpi_ns_repair_TSS}, {{0, 0, 0, 0}, NULL} /* Table terminator */ }; +#define ACPI_FDE_FIELD_COUNT 5 +#define ACPI_FDE_BYTE_BUFFER_SIZE 5 +#define ACPI_FDE_DWORD_BUFFER_SIZE (ACPI_FDE_FIELD_COUNT * sizeof (u32)) + /****************************************************************************** * * FUNCTION: acpi_ns_complex_repairs @@ -213,6 +227,135 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data, return (status); } +/****************************************************************************** + * + * FUNCTION: acpi_ns_repair_FDE + * + * PARAMETERS: Data - Pointer to validation data structure + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return + * value is a Buffer of 5 DWORDs. This function repairs two + * possible problems: + * 1) The return value is a Buffer of BYTEs, not DWORDs + * 2) The return value is a Package of Integer objects + * + *****************************************************************************/ + +static acpi_status +acpi_ns_repair_FDE(struct acpi_predefined_data *data, + union acpi_operand_object **return_object_ptr) +{ + union acpi_operand_object *return_object = *return_object_ptr; + union acpi_operand_object **elements; + union acpi_operand_object *buffer_object; + u8 *byte_buffer; + u32 *dword_buffer; + u32 count; + u32 i; + + switch (return_object->common.type) { + case ACPI_TYPE_BUFFER: + + /* This is the expected type. Length should be (at least) 5 DWORDs */ + + if (return_object->buffer.length >= ACPI_FDE_DWORD_BUFFER_SIZE) { + return (AE_OK); + } + + /* We can only repair if we have exactly 5 BYTEs */ + + if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) { + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, + data->node_flags, + "Incorrect return buffer length %u, expected %u", + return_object->buffer.length, + ACPI_FDE_DWORD_BUFFER_SIZE)); + + return (AE_AML_OPERAND_TYPE); + } + + /* Create the new (larger) buffer object */ + + buffer_object = + acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE); + if (!buffer_object) { + return (AE_NO_MEMORY); + } + + /* Expand each byte to a DWORD */ + + byte_buffer = return_object->buffer.pointer; + dword_buffer = + ACPI_CAST_PTR(u32, buffer_object->buffer.pointer); + + for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) { + *dword_buffer = (u32) *byte_buffer; + dword_buffer++; + byte_buffer++; + } + + ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Expanded Byte Buffer to expected DWord Buffer")); + break; + + case ACPI_TYPE_PACKAGE: + + /* All elements of the Package must be integers */ + + elements = return_object->package.elements; + count = + ACPI_MIN(ACPI_FDE_FIELD_COUNT, + return_object->package.count); + + for (i = 0; i < count; i++) { + if ((!*elements) || + ((*elements)->common.type != ACPI_TYPE_INTEGER)) { + return (AE_AML_OPERAND_TYPE); + } + elements++; + } + + /* Create the new buffer object to replace the Package */ + + buffer_object = + acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE); + if (!buffer_object) { + return (AE_NO_MEMORY); + } + + /* Copy the package elements (integers) to the buffer */ + + elements = return_object->package.elements; + dword_buffer = + ACPI_CAST_PTR(u32, buffer_object->buffer.pointer); + + for (i = 0; i < count; i++) { + *dword_buffer = (u32) (*elements)->integer.value; + dword_buffer++; + elements++; + } + + ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Converted Package to expected Buffer")); + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + /* Delete the original return object, return the new buffer object */ + + acpi_ut_remove_reference(return_object); + *return_object_ptr = buffer_object; + + data->flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + /****************************************************************************** * * FUNCTION: acpi_ns_repair_TSS -- cgit v1.2.3 From f24b664dc44a4ab4df61db2258cea298eeb43a8e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 14:57:00 +0800 Subject: ACPICA: Update internal namespace node/handle interfaces This change deletes the unnecessary acpi_ns_convert_entry_to_handle interface and renames the acpi_ns_map_handle_to_node interface to acpi_ns_validate_handle. ACPICA BZ 798. http://www.acpica.org/bugzilla/show_bug.cgi?id=798 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acnamesp.h | 4 +-- drivers/acpi/acpica/evregion.c | 4 +-- drivers/acpi/acpica/evxface.c | 4 +-- drivers/acpi/acpica/evxfevnt.c | 4 +-- drivers/acpi/acpica/evxfregn.c | 4 +-- drivers/acpi/acpica/nsdump.c | 2 +- drivers/acpi/acpica/nsnames.c | 2 +- drivers/acpi/acpica/nsutils.c | 57 ++++++++---------------------------------- drivers/acpi/acpica/nsxfeval.c | 10 ++++---- drivers/acpi/acpica/nsxfname.c | 10 ++++---- drivers/acpi/acpica/nsxfobj.c | 14 +++++------ drivers/acpi/acpica/rsxface.c | 2 +- 12 files changed, 40 insertions(+), 77 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index ab83919dda61..14cef45bd6c4 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -354,9 +354,7 @@ acpi_ns_externalize_name(u32 internal_name_length, const char *internal_name, u32 * converted_name_length, char **converted_name); -struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle); - -acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node); +struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle); void acpi_ns_terminate(void); diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 0bc807c33a56..5336d911fbf0 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -718,7 +718,7 @@ acpi_ev_install_handler(acpi_handle obj_handle, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(obj_handle); + node = acpi_ns_validate_handle(obj_handle); if (!node) { return (AE_BAD_PARAMETER); } @@ -1087,7 +1087,7 @@ acpi_ev_reg_run(acpi_handle obj_handle, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(obj_handle); + node = acpi_ns_validate_handle(obj_handle); if (!node) { return (AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 10b8543dd466..2fe0809d4eb2 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -259,7 +259,7 @@ acpi_install_notify_handler(acpi_handle device, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(device); + node = acpi_ns_validate_handle(device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -425,7 +425,7 @@ acpi_remove_notify_handler(acpi_handle device, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(device); + node = acpi_ns_validate_handle(device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 4721f58fe42c..eed7a38d25f2 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -610,7 +610,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, return (status); } - node = acpi_ns_map_handle_to_node(gpe_device); + node = acpi_ns_validate_handle(gpe_device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -698,7 +698,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) return (status); } - node = acpi_ns_map_handle_to_node(gpe_device); + node = acpi_ns_validate_handle(gpe_device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 7c3d2d356ffb..c98aa7c2d67c 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -89,7 +89,7 @@ acpi_install_address_space_handler(acpi_handle device, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(device); + node = acpi_ns_validate_handle(device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -155,7 +155,7 @@ acpi_remove_address_space_handler(acpi_handle device, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(device); + node = acpi_ns_validate_handle(device); if (!node || ((node->type != ACPI_TYPE_DEVICE) && (node->type != ACPI_TYPE_PROCESSOR) && diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 2deb986861ca..e37836e27e29 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -180,7 +180,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, return (AE_OK); } - this_node = acpi_ns_map_handle_to_node(obj_handle); + this_node = acpi_ns_validate_handle(obj_handle); if (!this_node) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n", obj_handle)); diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index af8e6bcee07e..8f9a4875ce26 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -232,7 +232,7 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle, ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle); - node = acpi_ns_map_handle_to_node(target_handle); + node = acpi_ns_validate_handle(target_handle); if (!node) { return_ACPI_STATUS(AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index ea55ab4f9849..47d91e668a1b 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -671,24 +671,25 @@ acpi_ns_externalize_name(u32 internal_name_length, /******************************************************************************* * - * FUNCTION: acpi_ns_map_handle_to_node + * FUNCTION: acpi_ns_validate_handle * - * PARAMETERS: Handle - Handle to be converted to an Node + * PARAMETERS: Handle - Handle to be validated and typecast to a + * namespace node. * - * RETURN: A Name table entry pointer + * RETURN: A pointer to a namespace node * - * DESCRIPTION: Convert a namespace handle to a real Node + * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special + * cases for the root node. * - * Note: Real integer handles would allow for more verification + * NOTE: Real integer handles would allow for more verification * and keep all pointers within this subsystem - however this introduces - * more (and perhaps unnecessary) overhead. - * - * The current implemenation is basically a placeholder until such time comes - * that it is needed. + * more overhead and has not been necessary to this point. Drivers + * holding handles are typically notified before a node becomes invalid + * due to a table unload. * ******************************************************************************/ -struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) +struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle) { ACPI_FUNCTION_ENTRY(); @@ -708,42 +709,6 @@ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); } -/******************************************************************************* - * - * FUNCTION: acpi_ns_convert_entry_to_handle - * - * PARAMETERS: Node - Node to be converted to a Handle - * - * RETURN: A user handle - * - * DESCRIPTION: Convert a real Node to a namespace handle - * - ******************************************************************************/ - -acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node) -{ - - /* - * Simple implementation for now; - */ - return ((acpi_handle) node); - -/* Example future implementation --------------------- - - if (!Node) - { - return (NULL); - } - - if (Node == acpi_gbl_root_node) - { - return (ACPI_ROOT_OBJECT); - } - - return ((acpi_handle) Node); -------------------------------------------------------*/ -} - /******************************************************************************* * * FUNCTION: acpi_ns_terminate diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index f2bd1da77001..f0c0892bc7e5 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -190,7 +190,7 @@ acpi_evaluate_object(acpi_handle handle, /* Convert and validate the device handle */ - info->prefix_node = acpi_ns_map_handle_to_node(handle); + info->prefix_node = acpi_ns_validate_handle(handle); if (!info->prefix_node) { status = AE_BAD_PARAMETER; goto cleanup; @@ -552,7 +552,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, return (status); } - node = acpi_ns_map_handle_to_node(obj_handle); + node = acpi_ns_validate_handle(obj_handle); status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return (status); @@ -729,7 +729,7 @@ acpi_attach_data(acpi_handle obj_handle, /* Convert and validate the handle */ - node = acpi_ns_map_handle_to_node(obj_handle); + node = acpi_ns_validate_handle(obj_handle); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -775,7 +775,7 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) /* Convert and validate the handle */ - node = acpi_ns_map_handle_to_node(obj_handle); + node = acpi_ns_validate_handle(obj_handle); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -822,7 +822,7 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) /* Convert and validate the handle */ - node = acpi_ns_map_handle_to_node(obj_handle); + node = acpi_ns_validate_handle(obj_handle); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index ddc84af6336e..e611dd961b20 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -93,7 +93,7 @@ acpi_get_handle(acpi_handle parent, /* Convert a parent handle to a prefix node */ if (parent) { - prefix_node = acpi_ns_map_handle_to_node(parent); + prefix_node = acpi_ns_validate_handle(parent); if (!prefix_node) { return (AE_BAD_PARAMETER); } @@ -114,7 +114,7 @@ acpi_get_handle(acpi_handle parent, if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) { *ret_handle = - acpi_ns_convert_entry_to_handle(acpi_gbl_root_node); + ACPI_CAST_PTR(acpi_handle, acpi_gbl_root_node); return (AE_OK); } } else if (!prefix_node) { @@ -129,7 +129,7 @@ acpi_get_handle(acpi_handle parent, status = acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node); if (ACPI_SUCCESS(status)) { - *ret_handle = acpi_ns_convert_entry_to_handle(node); + *ret_handle = ACPI_CAST_PTR(acpi_handle, node); } return (status); @@ -186,7 +186,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) return (status); } - node = acpi_ns_map_handle_to_node(handle); + node = acpi_ns_validate_handle(handle); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -291,7 +291,7 @@ acpi_get_object_info(acpi_handle handle, goto cleanup; } - node = acpi_ns_map_handle_to_node(handle); + node = acpi_ns_validate_handle(handle); if (!node) { (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index 4071bad4458e..0cc6ba01a495 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -79,7 +79,7 @@ acpi_status acpi_get_id(acpi_handle handle, acpi_owner_id * ret_id) /* Convert and validate the handle */ - node = acpi_ns_map_handle_to_node(handle); + node = acpi_ns_validate_handle(handle); if (!node) { (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); @@ -132,7 +132,7 @@ acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type) /* Convert and validate the handle */ - node = acpi_ns_map_handle_to_node(handle); + node = acpi_ns_validate_handle(handle); if (!node) { (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); @@ -182,7 +182,7 @@ acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle) /* Convert and validate the handle */ - node = acpi_ns_map_handle_to_node(handle); + node = acpi_ns_validate_handle(handle); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -191,7 +191,7 @@ acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle) /* Get the parent entry */ parent_node = acpi_ns_get_parent_node(node); - *ret_handle = acpi_ns_convert_entry_to_handle(parent_node); + *ret_handle = ACPI_CAST_PTR(acpi_handle, parent_node); /* Return exception if parent is null */ @@ -251,7 +251,7 @@ acpi_get_next_object(acpi_object_type type, /* Start search at the beginning of the specified scope */ - parent_node = acpi_ns_map_handle_to_node(parent); + parent_node = acpi_ns_validate_handle(parent); if (!parent_node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -260,7 +260,7 @@ acpi_get_next_object(acpi_object_type type, /* Non-null handle, ignore the parent */ /* Convert and validate the handle */ - child_node = acpi_ns_map_handle_to_node(child); + child_node = acpi_ns_validate_handle(child); if (!child_node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -276,7 +276,7 @@ acpi_get_next_object(acpi_object_type type, } if (ret_handle) { - *ret_handle = acpi_ns_convert_entry_to_handle(node); + *ret_handle = ACPI_CAST_PTR(acpi_handle, node); } unlock_and_exit: diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index 395212bcd19b..f27feb4772f6 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -104,7 +104,7 @@ acpi_rs_validate_parameters(acpi_handle device_handle, return_ACPI_STATUS(AE_BAD_PARAMETER); } - node = acpi_ns_map_handle_to_node(device_handle); + node = acpi_ns_validate_handle(device_handle); if (!node) { return_ACPI_STATUS(AE_BAD_PARAMETER); } -- cgit v1.2.3 From 47e11d54d2a516461d89cbb3f2fb87084056af72 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 15:01:12 +0800 Subject: ACPICA: Add more conversions to predefined name repair module This change enhances the automatic repairs/conversions for predefined name return values to make Integers, Strings, and Buffers fully interchangeable. Also, a Buffer can be converted to a Package of Integers if necessary. The nsrepair.c module was completely restructured. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/nsrepair.c | 403 +++++++++++++++++++++++++++++++++-------- 1 file changed, 327 insertions(+), 76 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index d563f1a564a7..10629fa55d83 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -45,11 +45,50 @@ #include "accommon.h" #include "acnamesp.h" #include "acinterp.h" -#include "acpredef.h" #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsrepair") +/******************************************************************************* + * + * This module attempts to repair or convert objects returned by the + * predefined methods to an object type that is expected, as per the ACPI + * specification. The need for this code is dictated by the many machines that + * return incorrect types for the standard predefined methods. Performing these + * conversions here, in one place, eliminates the need for individual ACPI + * device drivers to do the same. Note: Most of these conversions are different + * than the internal object conversion routines used for implicit object + * conversion. + * + * The following conversions can be performed as necessary: + * + * Integer -> String + * Integer -> Buffer + * String -> Integer + * String -> Buffer + * Buffer -> Integer + * Buffer -> String + * Buffer -> Package of Integers + * Package -> Package of one Package + * + ******************************************************************************/ +/* Local prototypes */ +static acpi_status +acpi_ns_convert_to_integer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +static acpi_status +acpi_ns_convert_to_string(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +static acpi_status +acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +static acpi_status +acpi_ns_convert_to_package(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + /******************************************************************************* * * FUNCTION: acpi_ns_repair_object @@ -68,6 +107,7 @@ ACPI_MODULE_NAME("nsrepair") * not expected. * ******************************************************************************/ + acpi_status acpi_ns_repair_object(struct acpi_predefined_data *data, u32 expected_btypes, @@ -76,32 +116,205 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, { union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object *new_object; - acpi_size length; acpi_status status; /* * At this point, we know that the type of the returned object was not * one of the expected types for this predefined name. Attempt to - * repair the object. Only a limited number of repairs are possible. + * repair the object by converting it to one of the expected object + * types for this predefined name. + */ + if (expected_btypes & ACPI_RTYPE_INTEGER) { + status = acpi_ns_convert_to_integer(return_object, &new_object); + if (ACPI_SUCCESS(status)) { + goto object_repaired; + } + } + if (expected_btypes & ACPI_RTYPE_STRING) { + status = acpi_ns_convert_to_string(return_object, &new_object); + if (ACPI_SUCCESS(status)) { + goto object_repaired; + } + } + if (expected_btypes & ACPI_RTYPE_BUFFER) { + status = acpi_ns_convert_to_buffer(return_object, &new_object); + if (ACPI_SUCCESS(status)) { + goto object_repaired; + } + } + if (expected_btypes & ACPI_RTYPE_PACKAGE) { + status = acpi_ns_convert_to_package(return_object, &new_object); + if (ACPI_SUCCESS(status)) { + goto object_repaired; + } + } + + /* We cannot repair this object */ + + return (AE_AML_OPERAND_TYPE); + + object_repaired: + + /* Object was successfully repaired */ + + /* + * If the original object is a package element, we need to: + * 1. Set the reference count of the new object to match the + * reference count of the old object. + * 2. Decrement the reference count of the original object. */ - switch (return_object->common.type) { + if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { + new_object->common.reference_count = + return_object->common.reference_count; + + if (return_object->common.reference_count > 1) { + return_object->common.reference_count--; + } + + ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Converted %s to expected %s at index %u", + acpi_ut_get_object_type_name + (return_object), + acpi_ut_get_object_type_name(new_object), + package_index)); + } else { + ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Converted %s to expected %s", + acpi_ut_get_object_type_name + (return_object), + acpi_ut_get_object_type_name + (new_object))); + } + + /* Delete old object, install the new return object */ + + acpi_ut_remove_reference(return_object); + *return_object_ptr = new_object; + data->flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_integer + * + * PARAMETERS: original_object - Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_convert_to_integer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object) +{ + union acpi_operand_object *new_object; + acpi_status status; + u64 value = 0; + u32 i; + + switch (original_object->common.type) { + case ACPI_TYPE_STRING: + + /* String-to-Integer conversion */ + + status = acpi_ut_strtoul64(original_object->string.pointer, + ACPI_ANY_BASE, &value); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + case ACPI_TYPE_BUFFER: - /* Does the method/object legally return a string? */ + /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ - if (!(expected_btypes & ACPI_RTYPE_STRING)) { + if (original_object->buffer.length > 8) { return (AE_AML_OPERAND_TYPE); } + /* Extract each buffer byte to create the integer */ + + for (i = 0; i < original_object->buffer.length; i++) { + value |= + ((u64) original_object->buffer. + pointer[i] << (i * 8)); + } + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + new_object = acpi_ut_create_integer_object(value); + if (!new_object) { + return (AE_NO_MEMORY); + } + + *return_object = new_object; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_string + * + * PARAMETERS: original_object - Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_convert_to_string(union acpi_operand_object *original_object, + union acpi_operand_object **return_object) +{ + union acpi_operand_object *new_object; + acpi_size length; + acpi_status status; + + switch (original_object->common.type) { + case ACPI_TYPE_INTEGER: + /* + * Integer-to-String conversion. Commonly, convert + * an integer of value 0 to a NULL string. The last element of + * _BIF and _BIX packages occasionally need this fix. + */ + if (original_object->integer.value == 0) { + + /* Allocate a new NULL string object */ + + new_object = acpi_ut_create_string_object(0); + if (!new_object) { + return (AE_NO_MEMORY); + } + } else { + status = + acpi_ex_convert_to_string(original_object, + &new_object, + ACPI_IMPLICIT_CONVERT_HEX); + if (ACPI_FAILURE(status)) { + return (status); + } + } + break; + + case ACPI_TYPE_BUFFER: /* - * Have a Buffer, expected a String, convert. Use a to_string + * Buffer-to-String conversion. Use a to_string * conversion, no transform performed on the buffer data. The best * example of this is the _BIF method, where the string data from * the battery is often (incorrectly) returned as buffer object(s). */ length = 0; - while ((length < return_object->buffer.length) && - (return_object->buffer.pointer[length])) { + while ((length < original_object->buffer.length) && + (original_object->buffer.pointer[length])) { length++; } @@ -117,94 +330,132 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, * terminated at Length+1. */ ACPI_MEMCPY(new_object->string.pointer, - return_object->buffer.pointer, length); + original_object->buffer.pointer, length); break; - case ACPI_TYPE_INTEGER: + default: + return (AE_AML_OPERAND_TYPE); + } - /* 1) Does the method/object legally return a buffer? */ + *return_object = new_object; + return (AE_OK); +} - if (expected_btypes & ACPI_RTYPE_BUFFER) { - /* - * Convert the Integer to a packed-byte buffer. _MAT needs - * this sometimes, if a read has been performed on a Field - * object that is less than or equal to the global integer - * size (32 or 64 bits). - */ - status = - acpi_ex_convert_to_buffer(return_object, - &new_object); - if (ACPI_FAILURE(status)) { - return (status); - } - } +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_buffer + * + * PARAMETERS: original_object - Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/String object to a Buffer. + * + ******************************************************************************/ - /* 2) Does the method/object legally return a string? */ +static acpi_status +acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object) +{ + union acpi_operand_object *new_object; + acpi_status status; - else if (expected_btypes & ACPI_RTYPE_STRING) { - /* - * The only supported Integer-to-String conversion is to convert - * an integer of value 0 to a NULL string. The last element of - * _BIF and _BIX packages occasionally need this fix. - */ - if (return_object->integer.value != 0) { - return (AE_AML_OPERAND_TYPE); - } + switch (original_object->common.type) { + case ACPI_TYPE_INTEGER: + /* + * Integer-to-Buffer conversion. + * Convert the Integer to a packed-byte buffer. _MAT and other + * objects need this sometimes, if a read has been performed on a + * Field object that is less than or equal to the global integer + * size (32 or 64 bits). + */ + status = + acpi_ex_convert_to_buffer(original_object, &new_object); + if (ACPI_FAILURE(status)) { + return (status); + } + break; - /* Allocate a new NULL string object */ + case ACPI_TYPE_STRING: - new_object = acpi_ut_create_string_object(0); - if (!new_object) { - return (AE_NO_MEMORY); - } - } else { - return (AE_AML_OPERAND_TYPE); + /* String-to-Buffer conversion. Simple data copy */ + + new_object = + acpi_ut_create_buffer_object(original_object->string. + length); + if (!new_object) { + return (AE_NO_MEMORY); } + + ACPI_MEMCPY(new_object->buffer.pointer, + original_object->string.pointer, + original_object->string.length); break; default: - - /* We cannot repair this object */ - return (AE_AML_OPERAND_TYPE); } - /* Object was successfully repaired */ + *return_object = new_object; + return (AE_OK); +} - /* - * If the original object is a package element, we need to: - * 1. Set the reference count of the new object to match the - * reference count of the old object. - * 2. Decrement the reference count of the original object. - */ - if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { - new_object->common.reference_count = - return_object->common.reference_count; +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_package + * + * PARAMETERS: original_object - Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of + * the buffer is converted to a single integer package element. + * + ******************************************************************************/ - if (return_object->common.reference_count > 1) { - return_object->common.reference_count--; +static acpi_status +acpi_ns_convert_to_package(union acpi_operand_object *original_object, + union acpi_operand_object **return_object) +{ + union acpi_operand_object *new_object; + union acpi_operand_object **elements; + u32 length; + u8 *buffer; + + switch (original_object->common.type) { + case ACPI_TYPE_BUFFER: + + /* Buffer-to-Package conversion */ + + length = original_object->buffer.length; + new_object = acpi_ut_create_package_object(length); + if (!new_object) { + return (AE_NO_MEMORY); } - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Converted %s to expected %s at index %u", - acpi_ut_get_object_type_name - (return_object), - acpi_ut_get_object_type_name(new_object), - package_index)); - } else { - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Converted %s to expected %s", - acpi_ut_get_object_type_name - (return_object), - acpi_ut_get_object_type_name - (new_object))); - } + /* Convert each buffer byte to an integer package element */ - /* Delete old object, install the new return object */ + elements = new_object->package.elements; + buffer = original_object->buffer.pointer; - acpi_ut_remove_reference(return_object); - *return_object_ptr = new_object; - data->flags |= ACPI_OBJECT_REPAIRED; + while (length--) { + *elements = acpi_ut_create_integer_object(*buffer); + if (!*elements) { + acpi_ut_remove_reference(new_object); + return (AE_NO_MEMORY); + } + elements++; + buffer++; + } + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + *return_object = new_object; return (AE_OK); } -- cgit v1.2.3 From 90434c1c7c61ce7dd349f17f003b8813421aeadc Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 15:02:15 +0800 Subject: ACPICA: Update function headers, no functional change Fixed a few errors with the headers in utcopy.c Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/utcopy.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 0f0c64bf8ac9..f857c5efb79f 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -323,11 +323,11 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type, * RETURN: Status * * DESCRIPTION: This function is called to place a package object in a user - * buffer. A package object by definition contains other objects. + * buffer. A package object by definition contains other objects. * * The buffer is assumed to have sufficient space for the object. - * The caller must have verified the buffer length needed using the - * acpi_ut_get_object_size function before calling this function. + * The caller must have verified the buffer length needed using + * the acpi_ut_get_object_size function before calling this function. * ******************************************************************************/ @@ -382,12 +382,12 @@ acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, * FUNCTION: acpi_ut_copy_iobject_to_eobject * * PARAMETERS: internal_object - The internal object to be converted - * buffer_ptr - Where the object is returned + * ret_buffer - Where the object is returned * * RETURN: Status * - * DESCRIPTION: This function is called to build an API object to be returned to - * the caller. + * DESCRIPTION: This function is called to build an API object to be returned + * to the caller. * ******************************************************************************/ @@ -626,7 +626,7 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, * PARAMETERS: external_object - The external object to be converted * internal_object - Where the internal object is returned * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: Converts an external object to an internal object. * @@ -665,7 +665,7 @@ acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object, * * RETURN: Status * - * DESCRIPTION: Simple copy of one internal object to another. Reference count + * DESCRIPTION: Simple copy of one internal object to another. Reference count * of the destination object is preserved. * ******************************************************************************/ @@ -897,10 +897,11 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, * * FUNCTION: acpi_ut_copy_ipackage_to_ipackage * - * PARAMETERS: *source_obj - Pointer to the source package object - * *dest_obj - Where the internal object is returned + * PARAMETERS: source_obj - Pointer to the source package object + * dest_obj - Where the internal object is returned + * walk_state - Current Walk state descriptor * - * RETURN: Status - the status of the call + * RETURN: Status * * DESCRIPTION: This function is called to copy an internal package object * into another internal package object. @@ -953,9 +954,9 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, * * FUNCTION: acpi_ut_copy_iobject_to_iobject * - * PARAMETERS: walk_state - Current walk state - * source_desc - The internal object to be copied + * PARAMETERS: source_desc - The internal object to be copied * dest_desc - Where the copied object is returned + * walk_state - Current walk state * * RETURN: Status * -- cgit v1.2.3 From d97659112044c0c77b93c6199eee7ee884eb3cca Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 15:16:38 +0800 Subject: ACPICA: Fix mutex errors when running _REG methods Fixes a problem where mutex errors can occur when running a _REG method that is in the same scope as a method-defined operation region or an operation region under a module-level IF block. This is rare, so the problem has not been seen before. ACPICA BZ 826. http://www.acpica.org/bugzilla/show_bug.cgi?id=826 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/dswload.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 9cc2289f872e..b40513dd6a6a 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -1052,9 +1052,22 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) } /* - * If we are executing a method, initialize the region + * The op_region is not fully parsed at this time. The only valid + * argument is the space_id. (We must save the address of the + * AML of the address and length operands) + * + * If we have a valid region, initialize it. The namespace is + * unlocked at this point. + * + * Need to unlock interpreter if it is locked (if we are running + * a control method), in order to allow _REG methods to be run + * during acpi_ev_initialize_region. */ if (walk_state->method_node) { + /* + * Executing a method: initialize the region and unlock + * the interpreter + */ status = acpi_ex_create_region(op->named.data, op->named.length, @@ -1063,21 +1076,17 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { return (status); } - } - /* - * The op_region is not fully parsed at this time. Only valid - * argument is the space_id. (We must save the address of the - * AML of the address and length operands) - */ + acpi_ex_exit_interpreter(); + } - /* - * If we have a valid region, initialize it - * Namespace is NOT locked at this point. - */ status = acpi_ev_initialize_region (acpi_ns_get_attached_object(node), FALSE); + if (walk_state->method_node) { + acpi_ex_enter_interpreter(); + } + if (ACPI_FAILURE(status)) { /* * If AE_NOT_EXIST is returned, it is not fatal -- cgit v1.2.3 From ea7c5ec148044776d5e134e52a3e1aca8d662dbe Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 15:18:52 +0800 Subject: ACPICA: Move Package-to-Buffer repair code into common ToBuffer function Move code specific to _FDE and _GTM into the generic repair code. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/nspredef.c | 11 +++++++---- drivers/acpi/acpica/nsrepair.c | 43 +++++++++++++++++++++++++++++++++++++++-- drivers/acpi/acpica/nsrepair2.c | 43 ----------------------------------------- 3 files changed, 48 insertions(+), 49 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 1782c3d85ba2..c6297f57fea8 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -215,6 +215,8 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, data->node_flags = node->flags; data->pathname = pathname; + /* TBD: For variable-length Packages, remove NULL elements here */ + /* * Check that the type of the return object is what is expected for * this predefined name @@ -223,10 +225,11 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, predefined->info.expected_btypes, ACPI_NOT_PACKAGE_ELEMENT); if (ACPI_SUCCESS(status)) { - - /* For returned Package objects, check the type of all sub-objects */ - - if (return_object->common.type == ACPI_TYPE_PACKAGE) { + /* + * For returned Package objects, check the type of all sub-objects. + * Note: Package may have been created by call above. + */ + if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { status = acpi_ns_check_package(data, return_object_ptr); } } diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 10629fa55d83..062a016d4554 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -350,7 +350,7 @@ acpi_ns_convert_to_string(union acpi_operand_object *original_object, * * RETURN: Status. AE_OK if conversion was successful. * - * DESCRIPTION: Attempt to convert a Integer/String object to a Buffer. + * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. * ******************************************************************************/ @@ -360,6 +360,10 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, { union acpi_operand_object *new_object; acpi_status status; + union acpi_operand_object **elements; + u32 *dword_buffer; + u32 count; + u32 i; switch (original_object->common.type) { case ACPI_TYPE_INTEGER: @@ -393,6 +397,40 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, original_object->string.length); break; + case ACPI_TYPE_PACKAGE: + + /* All elements of the Package must be integers */ + + elements = original_object->package.elements; + count = original_object->package.count; + + for (i = 0; i < count; i++) { + if ((!*elements) || + ((*elements)->common.type != ACPI_TYPE_INTEGER)) { + return (AE_AML_OPERAND_TYPE); + } + elements++; + } + + /* Create the new buffer object to replace the Package */ + + new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count)); + if (!new_object) { + return (AE_NO_MEMORY); + } + + /* Copy the package elements (integers) to the buffer as DWORDs */ + + elements = original_object->package.elements; + dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer); + + for (i = 0; i < count; i++) { + *dword_buffer = (u32) (*elements)->integer.value; + dword_buffer++; + elements++; + } + break; + default: return (AE_AML_OPERAND_TYPE); } @@ -441,7 +479,8 @@ acpi_ns_convert_to_package(union acpi_operand_object *original_object, buffer = original_object->buffer.pointer; while (length--) { - *elements = acpi_ut_create_integer_object(*buffer); + *elements = + acpi_ut_create_integer_object((u64) *buffer); if (!*elements) { acpi_ut_remove_reference(new_object); return (AE_NO_MEMORY); diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 6c35b57a7fd0..846df7047a81 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -250,11 +250,9 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; - union acpi_operand_object **elements; union acpi_operand_object *buffer_object; u8 *byte_buffer; u32 *dword_buffer; - u32 count; u32 i; switch (return_object->common.type) { @@ -302,47 +300,6 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, "Expanded Byte Buffer to expected DWord Buffer")); break; - case ACPI_TYPE_PACKAGE: - - /* All elements of the Package must be integers */ - - elements = return_object->package.elements; - count = - ACPI_MIN(ACPI_FDE_FIELD_COUNT, - return_object->package.count); - - for (i = 0; i < count; i++) { - if ((!*elements) || - ((*elements)->common.type != ACPI_TYPE_INTEGER)) { - return (AE_AML_OPERAND_TYPE); - } - elements++; - } - - /* Create the new buffer object to replace the Package */ - - buffer_object = - acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE); - if (!buffer_object) { - return (AE_NO_MEMORY); - } - - /* Copy the package elements (integers) to the buffer */ - - elements = return_object->package.elements; - dword_buffer = - ACPI_CAST_PTR(u32, buffer_object->buffer.pointer); - - for (i = 0; i < count; i++) { - *dword_buffer = (u32) (*elements)->integer.value; - dword_buffer++; - elements++; - } - - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Converted Package to expected Buffer")); - break; - default: return (AE_AML_OPERAND_TYPE); } -- cgit v1.2.3 From 3a58176e4fa47d8232e04131b023f3f2ecd7084b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 15:23:22 +0800 Subject: ACPICA: Remove messages if predefined repair(s) are successful Repair mechanism was considered too wordy. Now, messages are only unconditionally emitted if the return object cannot be repaired. Existing messages for successful repairs were converted to ACPI_DEBUG_PRINT messages for now. ACPICA BZ 827. http://www.acpica.org/bugzilla/show_bug.cgi?id=827 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/nspredef.c | 10 +++++----- drivers/acpi/acpica/nsrepair.c | 32 ++++++++++++++++++-------------- drivers/acpi/acpica/nsrepair2.c | 21 +++++++++++++-------- include/acpi/acoutput.h | 8 +++++--- 4 files changed, 41 insertions(+), 30 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index c6297f57fea8..e352467413f5 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -462,11 +462,11 @@ acpi_ns_check_package(struct acpi_predefined_data *data, if (count < expected_count) { goto package_too_small; } else if (count > expected_count) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, - "Return Package is larger than needed - " - "found %u, expected %u", count, - expected_count)); + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Return Package is larger than needed - " + "found %u, expected %u\n", + data->pathname, count, + expected_count)); } /* Validate all elements of the returned package */ diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 062a016d4554..907f60c9c9e5 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -118,6 +118,8 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, union acpi_operand_object *new_object; acpi_status status; + ACPI_FUNCTION_NAME(ns_repair_object); + /* * At this point, we know that the type of the returned object was not * one of the expected types for this predefined name. Attempt to @@ -171,19 +173,18 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, return_object->common.reference_count--; } - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Converted %s to expected %s at index %u", - acpi_ut_get_object_type_name - (return_object), - acpi_ut_get_object_type_name(new_object), - package_index)); + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Converted %s to expected %s at index %u\n", + data->pathname, + acpi_ut_get_object_type_name(return_object), + acpi_ut_get_object_type_name(new_object), + package_index)); } else { - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Converted %s to expected %s", - acpi_ut_get_object_type_name - (return_object), - acpi_ut_get_object_type_name - (new_object))); + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Converted %s to expected %s\n", + data->pathname, + acpi_ut_get_object_type_name(return_object), + acpi_ut_get_object_type_name(new_object))); } /* Delete old object, install the new return object */ @@ -528,6 +529,8 @@ acpi_ns_repair_package_list(struct acpi_predefined_data *data, { union acpi_operand_object *pkg_obj_desc; + ACPI_FUNCTION_NAME(ns_repair_package_list); + /* * Create the new outer package and populate it. The new package will * have a single element, the lone subpackage. @@ -544,8 +547,9 @@ acpi_ns_repair_package_list(struct acpi_predefined_data *data, *obj_desc_ptr = pkg_obj_desc; data->flags |= ACPI_OBJECT_REPAIRED; - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Repaired Incorrectly formed Package")); + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Repaired incorrectly formed Package\n", + data->pathname)); return (AE_OK); } diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 846df7047a81..199333880c8d 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -255,6 +255,8 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, u32 *dword_buffer; u32 i; + ACPI_FUNCTION_NAME(ns_repair_FDE); + switch (return_object->common.type) { case ACPI_TYPE_BUFFER: @@ -296,8 +298,9 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, byte_buffer++; } - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Expanded Byte Buffer to expected DWord Buffer")); + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s Expanded Byte Buffer to expected DWord Buffer\n", + data->pathname)); break; default: @@ -445,6 +448,8 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, u32 previous_value; acpi_status status; + ACPI_FUNCTION_NAME(ns_check_sorted_list); + /* The top-level object must be a package */ if (return_object->common.type != ACPI_TYPE_PACKAGE) { @@ -460,8 +465,9 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, */ status = acpi_ns_remove_null_elements(return_object); if (status == AE_NULL_ENTRY) { - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "NULL elements removed from package")); + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: NULL elements removed from package\n", + data->pathname)); /* Exit if package is now zero length */ @@ -522,10 +528,9 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, data->flags |= ACPI_OBJECT_REPAIRED; - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, - "Repaired unsorted list - now sorted by %s", - sort_key_name)); + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Repaired unsorted list - now sorted by %s\n", + data->pathname, sort_key_name)); return (AE_OK); } diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h index 5c823d5ab783..d814da4b5365 100644 --- a/include/acpi/acoutput.h +++ b/include/acpi/acoutput.h @@ -85,7 +85,8 @@ #define ACPI_LV_INIT 0x00000001 #define ACPI_LV_DEBUG_OBJECT 0x00000002 #define ACPI_LV_INFO 0x00000004 -#define ACPI_LV_ALL_EXCEPTIONS 0x00000007 +#define ACPI_LV_REPAIR 0x00000008 +#define ACPI_LV_ALL_EXCEPTIONS 0x0000000F /* Trace verbosity level 1 [Standard Trace Level] */ @@ -143,6 +144,7 @@ #define ACPI_DB_INIT ACPI_DEBUG_LEVEL (ACPI_LV_INIT) #define ACPI_DB_DEBUG_OBJECT ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT) #define ACPI_DB_INFO ACPI_DEBUG_LEVEL (ACPI_LV_INFO) +#define ACPI_DB_REPAIR ACPI_DEBUG_LEVEL (ACPI_LV_REPAIR) #define ACPI_DB_ALL_EXCEPTIONS ACPI_DEBUG_LEVEL (ACPI_LV_ALL_EXCEPTIONS) /* Trace level -- also used in the global "DebugLevel" */ @@ -174,8 +176,8 @@ /* Defaults for debug_level, debug and normal */ -#define ACPI_DEBUG_DEFAULT (ACPI_LV_INFO) -#define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT) +#define ACPI_DEBUG_DEFAULT (ACPI_LV_INFO | ACPI_LV_REPAIR) +#define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT | ACPI_LV_REPAIR) #define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL) #if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES) -- cgit v1.2.3 From 43420bbb892268b5fc42cb80c3bc31dedbad3ac9 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 15:24:27 +0800 Subject: ACPICA: Update function headers and comments, no functional change Update comments for repair of _FDE and _GTM methods. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/nsrepair.c | 5 +++++ drivers/acpi/acpica/nsrepair2.c | 11 +++++------ 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 907f60c9c9e5..4fd1bdb056b2 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -399,6 +399,11 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, break; case ACPI_TYPE_PACKAGE: + /* + * This case is often seen for predefined names that must return a + * Buffer object with multiple DWORD integers within. For example, + * _FDE and _GTM. The Package can be converted to a Buffer. + */ /* All elements of the Package must be integers */ diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 199333880c8d..e7373eb6cfa5 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -111,8 +111,8 @@ acpi_ns_sort_list(union acpi_operand_object **elements, * As necessary: * * _ALR: Sort the list ascending by ambient_illuminance - * _FDE: Convert a Package or Buffer of BYTEs to a Buffer of DWORDs - * _GTM: Convert a Package or Buffer of BYTEs to a Buffer of DWORDs + * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs + * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs * _PSS: Sort the list descending by Power * _TSS: Sort the list descending by Power */ @@ -238,10 +238,9 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data, * RETURN: Status. AE_OK if object is OK or was repaired successfully * * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return - * value is a Buffer of 5 DWORDs. This function repairs two - * possible problems: - * 1) The return value is a Buffer of BYTEs, not DWORDs - * 2) The return value is a Package of Integer objects + * value is a Buffer of 5 DWORDs. This function repairs a common + * problem where the return value is a Buffer of BYTEs, not + * DWORDs. * *****************************************************************************/ -- cgit v1.2.3 From 465da9eb75665203a826f961de74a817b870850a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 15:26:13 +0800 Subject: ACPICA: Conditionally perform complex per-predefined-name repairs Only attempt the "complex" repairs (package sorting, buffer expansion) if the previous "generic" validation and repair was successful. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/nspredef.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index e352467413f5..239fa2f731ca 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -215,31 +215,42 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, data->node_flags = node->flags; data->pathname = pathname; - /* TBD: For variable-length Packages, remove NULL elements here */ - /* - * Check that the type of the return object is what is expected for - * this predefined name + * Check that the type of the main return object is what is expected + * for this predefined name */ status = acpi_ns_check_object_type(data, return_object_ptr, predefined->info.expected_btypes, ACPI_NOT_PACKAGE_ELEMENT); - if (ACPI_SUCCESS(status)) { - /* - * For returned Package objects, check the type of all sub-objects. - * Note: Package may have been created by call above. - */ - if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { - status = acpi_ns_check_package(data, return_object_ptr); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* + * For returned Package objects, check the type of all sub-objects. + * Note: Package may have been newly created by call above. + */ + if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { + + /* TBD: For variable-length Packages, remove NULL elements here */ + + status = acpi_ns_check_package(data, return_object_ptr); + if (ACPI_FAILURE(status)) { + goto exit; } } /* - * Perform additional, more complicated repairs on a per-name - * basis. Do this regardless of the status from above. + * The return object was OK, or it was successfully repaired above. + * Now make some additional checks such as verifying that package + * objects are sorted correctly (if required) or buffer objects have + * the correct data width (bytes vs. dwords). These repairs are + * performed on a per-name basis, i.e., the code is specific to + * particular predefined names. */ status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); +exit: /* * If the object validation failed or if we successfully repaired one * or more objects, mark the parent node to suppress further warning -- cgit v1.2.3 From e31c32cfe52e98344dad28853c3331879f72c4b0 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Fri, 11 Dec 2009 15:28:27 +0800 Subject: ACPICA: Module-level code: enable _REG execution in same scope This change enables the execution of _REG methods that appear in the same scope as the module-level code, in resonse to an operation region declaration within the module-level code. Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/acpica/acobject.h | 6 +++++- drivers/acpi/acpica/dsmethod.c | 2 +- drivers/acpi/acpica/evrgnini.c | 15 +++++++++++++++ drivers/acpi/acpica/nsaccess.c | 2 +- drivers/acpi/acpica/nseval.c | 12 ++++++++++++ drivers/acpi/acpica/psxface.c | 3 ++- 6 files changed, 36 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index b39d682a2140..64062b1be3ee 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -180,7 +180,11 @@ struct acpi_object_method { u8 sync_level; union acpi_operand_object *mutex; u8 *aml_start; - ACPI_INTERNAL_METHOD implementation; + union { + ACPI_INTERNAL_METHOD implementation; + union acpi_operand_object *handler; + } extra; + u32 aml_length; u8 thread_count; acpi_owner_id owner_id; diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index 567a4899a018..e786f9fd767f 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -414,7 +414,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, /* Invoke an internal method if necessary */ if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { - status = obj_desc->method.implementation(next_walk_state); + status = obj_desc->method.extra.implementation(next_walk_state); if (status == AE_OK) { status = AE_CTRL_TERMINATE; } diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index cf29c4953028..ff168052a332 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -575,6 +575,21 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, handler_obj = obj_desc->thermal_zone.handler; break; + case ACPI_TYPE_METHOD: + /* + * If we are executing module level code, the original + * Node's object was replaced by this Method object and we + * saved the handler in the method object. + * + * See acpi_ns_exec_module_code + */ + if (obj_desc->method. + flags & AOPOBJ_MODULE_LEVEL) { + handler_obj = + obj_desc->method.extra.handler; + } + break; + default: /* Ignore other objects */ break; diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 9c3cdbe2d82a..d622ba770000 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -165,7 +165,7 @@ acpi_status acpi_ns_root_initialize(void) obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY; - obj_desc->method.implementation = + obj_desc->method.extra.implementation = acpi_ut_osi_implementation; #endif break; diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 65e0d1a260ea..af9fe9103734 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -381,6 +381,18 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, method_obj->method.next_object); type = acpi_ns_get_type(parent_node); + /* + * Get the region handler and save it in the method object. We may need + * this if an operation region declaration causes a _REG method to be run. + * + * We can't do this in acpi_ps_link_module_code because + * acpi_gbl_root_node->Object is NULL at PASS1. + */ + if ((type == ACPI_TYPE_DEVICE) && parent_node->object) { + method_obj->method.extra.handler = + parent_node->object->device.handler; + } + /* Must clear next_object (acpi_ns_attach_object needs the field) */ method_obj->method.next_object = NULL; diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index 12934ad6da8e..d0c1b91eb8ca 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c @@ -287,7 +287,8 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) /* Invoke an internal method if necessary */ if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { - status = info->obj_desc->method.implementation(walk_state); + status = + info->obj_desc->method.extra.implementation(walk_state); info->return_object = walk_state->return_desc; /* Cleanup states */ -- cgit v1.2.3 From d4085a3ffee8828f7f1bae7fa3cf5e58f59ba627 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 11 Dec 2009 15:29:44 +0800 Subject: ACPICA: Predefined name repair: automatically remove null package elements This change will automatically remove embedded and trailing NULL package elements from returned package objects that are defined to containe a variable number of sub-packages. The driver is then presented with a package with no null elements to deal with. ACPICA BZ 819. http://www.acpica.org/bugzilla/show_bug.cgi?id=819 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acnamesp.h | 5 +++ drivers/acpi/acpica/nspredef.c | 59 ++++++++---------------------- drivers/acpi/acpica/nsrepair2.c | 79 ++++++++++++++++++++++++----------------- 3 files changed, 65 insertions(+), 78 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 14cef45bd6c4..61edb156e8d0 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -296,6 +296,11 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data, acpi_status validate_status, union acpi_operand_object **return_object_ptr); +void +acpi_ns_remove_null_elements(struct acpi_predefined_data *data, + u8 package_type, + union acpi_operand_object *obj_desc); + /* * nssearch - Namespace searching and entry */ diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 239fa2f731ca..d34fa59548f7 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -231,9 +231,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, * Note: Package may have been newly created by call above. */ if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { - - /* TBD: For variable-length Packages, remove NULL elements here */ - status = acpi_ns_check_package(data, return_object_ptr); if (ACPI_FAILURE(status)) { goto exit; @@ -439,6 +436,13 @@ acpi_ns_check_package(struct acpi_predefined_data *data, data->pathname, package->ret_info.type, return_object->package.count)); + /* + * For variable-length Packages, we can safely remove all embedded + * and trailing NULL package elements + */ + acpi_ns_remove_null_elements(data, package->ret_info.type, + return_object); + /* Extract package count and elements array */ elements = return_object->package.elements; @@ -692,53 +696,18 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, union acpi_operand_object *sub_package; union acpi_operand_object **sub_elements; acpi_status status; - u8 non_trailing_null = FALSE; u32 expected_count; u32 i; u32 j; - /* Validate each sub-Package in the parent Package */ - + /* + * Validate each sub-Package in the parent Package + * + * NOTE: assumes list of sub-packages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to acpi_ns_remove_null_elements. + */ for (i = 0; i < count; i++) { - /* - * Handling for NULL package elements. For now, we will simply allow - * a parent package with trailing NULL elements. This can happen if - * the package was defined to be longer than the initializer list. - * This is legal as per the ACPI specification. It is often used - * to allow for dynamic initialization of a Package. - * - * A future enhancement may be to simply truncate the package to - * remove the trailing NULL elements. - */ - if (!(*elements)) { - if (!non_trailing_null) { - - /* Ensure the remaining elements are all NULL */ - - for (j = 1; j < (count - i + 1); j++) { - if (elements[j]) { - non_trailing_null = TRUE; - } - } - - if (!non_trailing_null) { - - /* Ignore the trailing NULL elements */ - - return (AE_OK); - } - } - - /* There are trailing non-null elements, issue warning */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, - "Found NULL element at package index %u", - i)); - elements++; - continue; - } - sub_package = *elements; sub_elements = sub_package->package.elements; diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index e7373eb6cfa5..f13691c1cca5 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -45,6 +45,7 @@ #include #include "accommon.h" #include "acnamesp.h" +#include "acpredef.h" #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsrepair2") @@ -92,9 +93,6 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, u32 sort_index, u8 sort_direction, char *sort_key_name); -static acpi_status -acpi_ns_remove_null_elements(union acpi_operand_object *package); - static acpi_status acpi_ns_sort_list(union acpi_operand_object **elements, u32 count, u32 index, u8 sort_direction); @@ -456,25 +454,10 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, } /* - * Detect any NULL package elements and remove them from the - * package. - * - * TBD: We may want to do this for all predefined names that - * return a variable-length package of packages. + * NOTE: assumes list of sub-packages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to acpi_ns_remove_null_elements. */ - status = acpi_ns_remove_null_elements(return_object); - if (status == AE_NULL_ENTRY) { - ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, - "%s: NULL elements removed from package\n", - data->pathname)); - - /* Exit if package is now zero length */ - - if (!return_object->package.count) { - return (AE_NULL_ENTRY); - } - } - outer_elements = return_object->package.elements; outer_element_count = return_object->package.count; if (!outer_element_count) { @@ -544,36 +527,63 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_remove_null_elements * - * PARAMETERS: obj_desc - A Package object + * PARAMETERS: Data - Pointer to validation data structure + * package_type - An acpi_return_package_types value + * obj_desc - A Package object * - * RETURN: Status. AE_NULL_ENTRY means that one or more elements were - * removed. + * RETURN: None. * - * DESCRIPTION: Remove all NULL package elements and update the package count. + * DESCRIPTION: Remove all NULL package elements from packages that contain + * a variable number of sub-packages. * *****************************************************************************/ -static acpi_status -acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc) +void +acpi_ns_remove_null_elements(struct acpi_predefined_data *data, + u8 package_type, + union acpi_operand_object *obj_desc) { union acpi_operand_object **source; union acpi_operand_object **dest; - acpi_status status = AE_OK; u32 count; u32 new_count; u32 i; + ACPI_FUNCTION_NAME(ns_remove_null_elements); + + /* + * PTYPE1 packages contain no subpackages. + * PTYPE2 packages contain a variable number of sub-packages. We can + * safely remove all NULL elements from the PTYPE2 packages. + */ + switch (package_type) { + case ACPI_PTYPE1_FIXED: + case ACPI_PTYPE1_VAR: + case ACPI_PTYPE1_OPTION: + return; + + case ACPI_PTYPE2: + case ACPI_PTYPE2_COUNT: + case ACPI_PTYPE2_PKG_COUNT: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_REV_FIXED: + break; + + default: + return; + } + count = obj_desc->package.count; new_count = count; source = obj_desc->package.elements; dest = source; - /* Examine all elements of the package object */ + /* Examine all elements of the package object, remove nulls */ for (i = 0; i < count; i++) { if (!*source) { - status = AE_NULL_ENTRY; new_count--; } else { *dest = *source; @@ -582,15 +592,18 @@ acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc) source++; } - if (status == AE_NULL_ENTRY) { + /* Update parent package if any null elements were removed */ + + if (new_count < count) { + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Found and removed %u NULL elements\n", + data->pathname, (count - new_count))); /* NULL terminate list and update the package count */ *dest = NULL; obj_desc->package.count = new_count; } - - return (status); } /****************************************************************************** -- cgit v1.2.3 From fbc3be2af3e8beb581a20c2a0cfda5692f5a1c08 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 11 Dec 2009 15:31:40 +0800 Subject: ACPICA: Move check for valid Thread ID structure This change moves the check for a valid Thread ID structure up a few lines to insure that the check is made before the structure is actually used. Signed-off-by: Dan Carpenter Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/exmutex.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index 2f0114202b05..3c456bd575d0 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -375,6 +375,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } + /* Must have a valid thread ID */ + + if (!walk_state->thread) { + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], null thread info", + acpi_ut_get_node_name(obj_desc->mutex.node))); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + /* * The Mutex is owned, but this thread must be the owner. * Special case for Global Lock, any thread can release @@ -392,15 +401,6 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_NOT_OWNER); } - /* Must have a valid thread ID */ - - if (!walk_state->thread) { - ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], null thread info", - acpi_ut_get_node_name(obj_desc->mutex.node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - /* * The sync level of the mutex must be equal to the current sync level. In * other words, the current level means that at least one mutex at that -- cgit v1.2.3 From 4bab30a041a2f27807b0b2a7fd36c8c8695c90c8 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 14 Dec 2009 11:24:18 +0800 Subject: ACPI: add kernel tainting after overriding an ACPI control method Add kernel tainting after overriding an ACPI control method successfully. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/debug.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 0bedd1554f2f..cc421b7ae166 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -239,6 +239,7 @@ static ssize_t cm_write(struct file *file, const char __user *user_buf, kfree(buf); if (ACPI_FAILURE(status)) return -EINVAL; + add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); } return count; -- cgit v1.2.3 From 13c41157096f05d5037a99152b4cf9d68ef00ef7 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Mon, 14 Dec 2009 13:38:30 -0800 Subject: ACPI: Remove repeated registered as cooling_device messages This message shows up for each cpu. Print as debug messages. [ 12.893967] processor ACPI0007:00: registered as cooling_device0 [ 12.907838] processor ACPI0007:01: registered as cooling_device1 Signed-off-by: Mike Travis Cc: Ingo Molnar Cc: linux-acpi@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Len Brown --- drivers/acpi/fan.c | 2 +- drivers/acpi/processor_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index f419849a0d3f..acf2ab249842 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -267,7 +267,7 @@ static int acpi_fan_add(struct acpi_device *device) goto end; } - dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id); + dev_dbg(&device->dev, "registered as cooling_device%d\n", cdev->id); device->driver_data = cdev; result = sysfs_create_link(&device->dev.kobj, diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index ec742a4e5635..ecb2c5122040 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -845,7 +845,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) goto err_power_exit; } - dev_info(&device->dev, "registered as cooling_device%d\n", + dev_dbg(&device->dev, "registered as cooling_device%d\n", pr->cdev->id); result = sysfs_create_link(&device->dev.kobj, -- cgit v1.2.3 From 2345baf4a8a0ac2e7e83f932048bb2d8ec1287e7 Mon Sep 17 00:00:00 2001 From: "Justin P. Mattock" Date: Sun, 13 Dec 2009 14:42:36 -0800 Subject: battery: fix typo in comment Signed-off-by: Justin P. Mattock Signed-off-by: Len Brown --- drivers/acpi/battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 3f4602b8f287..cada73ffdfa7 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -831,7 +831,7 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event) dev_name(&device->dev), event, acpi_battery_present(battery)); #ifdef CONFIG_ACPI_SYSFS_POWER - /* acpi_batter_update could remove power_supply object */ + /* acpi_battery_update could remove power_supply object */ if (battery->bat.dev) kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); #endif -- cgit v1.2.3 From 13c199c0d0cf78b27592991129fb8cbcfc5164de Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 15 Dec 2009 22:01:57 +0800 Subject: ACPI: Use the return result of ACPI lid notifier chain correctly On some laptops it will return NOTIFY_OK(non-zero) when calling the ACPI LID notifier. Then it is used as the result of ACPI LID resume function, which will complain the following warning message in course of suspend/resume: >PM: Device PNP0C0D:00 failed to resume: error 1 This patch is to eliminate the above warning message. http://bugzilla.kernel.org/show_bug.cgi?id=14782 Signed-off-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/button.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 0c9c6a9a002c..8a95e8329df7 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -282,6 +282,13 @@ static int acpi_lid_send_state(struct acpi_device *device) if (ret == NOTIFY_DONE) ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); + if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { + /* + * It is also regarded as success if the notifier_chain + * returns NOTIFY_OK or NOTIFY_DONE. + */ + ret = 0; + } return ret; } -- cgit v1.2.3 From b552a8c56db8a74ceffdcbb9269664009a81d536 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 17 Nov 2009 14:27:32 -0800 Subject: ACPI: remove NID_INVAL NUMA_NO_NODE has been exported globally and thus it can replace NID_INVAL in the acpi code. Also removes the unused acpi_unmap_pxm_to_node() function. [akpm@linux-foundation.org: coding-style fixes] Cc: Cyrill Gorcunov Cc: Lee Schermerhorn Reviewed-by: Christoph Lameter Signed-off-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/numa.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 202dd0c976a3..90f1884e8a51 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #define PREFIX "ACPI: " @@ -40,14 +41,14 @@ static nodemask_t nodes_found_map = NODE_MASK_NONE; /* maps to convert between proximity domain and logical node ID */ static int pxm_to_node_map[MAX_PXM_DOMAINS] - = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; + = { [0 ... MAX_PXM_DOMAINS - 1] = NUMA_NO_NODE }; static int node_to_pxm_map[MAX_NUMNODES] - = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; + = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; int pxm_to_node(int pxm) { if (pxm < 0) - return NID_INVAL; + return NUMA_NO_NODE; return pxm_to_node_map[pxm]; } @@ -68,9 +69,9 @@ int acpi_map_pxm_to_node(int pxm) { int node = pxm_to_node_map[pxm]; - if (node < 0){ + if (node < 0) { if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) - return NID_INVAL; + return NUMA_NO_NODE; node = first_unset_node(nodes_found_map); __acpi_map_pxm_to_node(pxm, node); node_set(node, nodes_found_map); @@ -79,16 +80,6 @@ int acpi_map_pxm_to_node(int pxm) return node; } -#if 0 -void __cpuinit acpi_unmap_pxm_to_node(int node) -{ - int pxm = node_to_pxm_map[node]; - pxm_to_node_map[pxm] = NID_INVAL; - node_to_pxm_map[node] = PXM_INVAL; - node_clear(node, nodes_found_map); -} -#endif /* 0 */ - static void __init acpi_table_print_srat_entry(struct acpi_subtable_header *header) { -- cgit v1.2.3 From bf2abdd79ac81c52957bf0d0d5430cec5433cfb7 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Tue, 17 Nov 2009 14:27:33 -0800 Subject: acpi: thermal: display forced passive trip points in proc Users can force a passive trip point for a thermal zone that does not have _PSV defined in ACPI by setting the passive attribute in sysfs. It's useful to display such trip points in /proc/acpi/thermal_zone. .../TZ1/cooling_mode: .../TZ1/polling_frequency:polling frequency: 10 seconds .../TZ1/state:state: ok .../TZ1/temperature:temperature: 53 C .../TZ1/trip_points:critical (S5): 110 C .../TZ1/trip_points:passive (forced): 95 C And if not set (passive is 0): .../TZ1/trip_points:passive (forced): Signed-off-by: Frans Pop Acked-by: Zhang Rui Cc: Matthew Garrett Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/thermal.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 65f67815902a..9073ada88835 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1052,6 +1052,13 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) acpi_device_bid(device)); } seq_puts(seq, "\n"); + } else { + seq_printf(seq, "passive (forced):"); + if (tz->thermal_zone->forced_passive) + seq_printf(seq, " %i C\n", + tz->thermal_zone->forced_passive / 1000); + else + seq_printf(seq, "\n"); } for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { -- cgit v1.2.3 From f69cfdd24ac40ab7bbd00d6ad85e003da755e3a0 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Mon, 19 Oct 2009 15:14:29 -0600 Subject: ACPI: dock: combine add|alloc_dock_dependent_device (v2) There's no real need to have a separate allocation step when adding a dock dependent device. Combining the two functions is both logical and helps with legibility. Signed-off-by: Alex Chiang Acked-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 55 ++++++++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 36 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 4f2aa98e2cee..ee9829b47e20 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -93,40 +93,30 @@ struct dock_dependent_device { * Dock Dependent device functions * *****************************************************************************/ /** - * alloc_dock_dependent_device - allocate and init a dependent device - * @handle: the acpi_handle of the dependent device + * add_dock_dependent_device - associate a device with the dock station + * @ds: The dock station + * @handle: handle of the dependent device * - * Allocate memory for a dependent device structure for a device referenced - * by the acpi handle + * Add the dependent device to the dock's dependent device list. */ -static struct dock_dependent_device * -alloc_dock_dependent_device(acpi_handle handle) +static int +add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) { struct dock_dependent_device *dd; dd = kzalloc(sizeof(*dd), GFP_KERNEL); - if (dd) { - dd->handle = handle; - INIT_LIST_HEAD(&dd->list); - INIT_LIST_HEAD(&dd->hotplug_list); - } - return dd; -} + if (!dd) + return -ENOMEM; + + dd->handle = handle; + INIT_LIST_HEAD(&dd->list); + INIT_LIST_HEAD(&dd->hotplug_list); -/** - * add_dock_dependent_device - associate a device with the dock station - * @ds: The dock station - * @dd: The dependent device - * - * Add the dependent device to the dock's dependent device list. - */ -static void -add_dock_dependent_device(struct dock_station *ds, - struct dock_dependent_device *dd) -{ spin_lock(&ds->dd_lock); list_add_tail(&dd->list, &ds->dependent_devices); spin_unlock(&ds->dd_lock); + + return 0; } /** @@ -826,7 +816,6 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv) acpi_status status; acpi_handle tmp, parent; struct dock_station *ds = context; - struct dock_dependent_device *dd; status = acpi_bus_get_ejd(handle, &tmp); if (ACPI_FAILURE(status)) { @@ -840,11 +829,9 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv) goto fdd_out; } - if (tmp == ds->handle) { - dd = alloc_dock_dependent_device(handle); - if (dd) - add_dock_dependent_device(ds, dd); - } + if (tmp == ds->handle) + add_dock_dependent_device(ds, handle); + fdd_out: return AE_OK; } @@ -959,7 +946,6 @@ static struct attribute_group dock_attribute_group = { static int dock_add(acpi_handle handle) { int ret; - struct dock_dependent_device *dd; struct dock_station *dock_station; struct platform_device *dock_device; @@ -1008,12 +994,9 @@ static int dock_add(acpi_handle handle) NULL); /* add the dock station as a device dependent on itself */ - dd = alloc_dock_dependent_device(handle); - if (!dd) { - ret = -ENOMEM; + ret = add_dock_dependent_device(dock_station, handle); + if (ret) goto err_rmgroup; - } - add_dock_dependent_device(dock_station, dd); dock_station_count++; list_add(&dock_station->sibling, &dock_stations); -- cgit v1.2.3 From c6f1905ea91bf56a921c6eb574488869c8c3eeff Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Mon, 19 Oct 2009 15:14:35 -0600 Subject: ACPI: dock: remove global 'dock_device_name' We only use it in one spot, so it probably gets optimized out, but there's still no need to use a global variable for this. Signed-off-by: Alex Chiang Acked-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index ee9829b47e20..0a1221854a25 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -50,7 +50,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to " " before undocking"); static struct atomic_notifier_head dock_notifier_list; -static char dock_device_name[] = "dock"; static const struct acpi_device_id dock_device_ids[] = { {"LNXDOCK", 0}, @@ -964,7 +963,7 @@ static int dock_add(acpi_handle handle) /* initialize platform device stuff */ dock_station->dock_device = - platform_device_register_simple(dock_device_name, + platform_device_register_simple("dock", dock_station_count, NULL, 0); dock_device = dock_station->dock_device; if (IS_ERR(dock_device)) { -- cgit v1.2.3 From 9751cb721ef650729e981c7b39abb7676cd646e1 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Mon, 19 Oct 2009 15:14:40 -0600 Subject: ACPI: dock: dock_add - hoist up platform_device_register_simple() Move the call to platform_device_register_simple so that we do it before allocating and initializing our struct dock_station. Signed-off-by: Alex Chiang Acked-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 0a1221854a25..3bd89823402a 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -948,11 +948,18 @@ static int dock_add(acpi_handle handle) struct dock_station *dock_station; struct platform_device *dock_device; + dock_device = + platform_device_register_simple("dock", + dock_station_count, NULL, 0); + if (IS_ERR(dock_device)) + return PTR_ERR(dock_device); + /* allocate & initialize the dock_station private data */ dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL); if (!dock_station) return -ENOMEM; dock_station->handle = handle; + dock_station->dock_device = dock_device; dock_station->last_dock_time = jiffies - HZ; INIT_LIST_HEAD(&dock_station->dependent_devices); INIT_LIST_HEAD(&dock_station->hotplug_devices); @@ -961,15 +968,6 @@ static int dock_add(acpi_handle handle) mutex_init(&dock_station->hp_lock); ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); - /* initialize platform device stuff */ - dock_station->dock_device = - platform_device_register_simple("dock", - dock_station_count, NULL, 0); - dock_device = dock_station->dock_device; - if (IS_ERR(dock_device)) { - ret = PTR_ERR(dock_device); - goto out; - } platform_device_add_data(dock_device, &dock_station, sizeof(struct dock_station *)); -- cgit v1.2.3 From fe06fba292af5ed5c1c6ad9af3a9ef68da7a5088 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Mon, 19 Oct 2009 15:14:45 -0600 Subject: ACPI: dock: add struct dock_station * directly to platform device data Instead of adding a (struct dock_station **) to our dock device's platform data, we can add the (struct dock_station *) directly. This change saves us some ugly casting and improves readability. The cost of making this change is an extra 290 bytes of stack usage, but this is an infrequently called code-path and unlikely to cause the kernel to blow up. Signed-off-by: Alex Chiang Acked-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 3bd89823402a..cfcd8eeb3b2a 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -843,8 +843,7 @@ static ssize_t show_docked(struct device *dev, { struct acpi_device *tmp; - struct dock_station *dock_station = *((struct dock_station **) - dev->platform_data); + struct dock_station *dock_station = dev->platform_data; if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp))) return snprintf(buf, PAGE_SIZE, "1\n"); @@ -858,8 +857,7 @@ static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf) { - struct dock_station *dock_station = *((struct dock_station **) - dev->platform_data); + struct dock_station *dock_station = dev->platform_data; return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); } @@ -872,8 +870,7 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int ret; - struct dock_station *dock_station = *((struct dock_station **) - dev->platform_data); + struct dock_station *dock_station = dev->platform_data; if (!count) return -EINVAL; @@ -891,8 +888,7 @@ static ssize_t show_dock_uid(struct device *dev, struct device_attribute *attr, char *buf) { unsigned long long lbuf; - struct dock_station *dock_station = *((struct dock_station **) - dev->platform_data); + struct dock_station *dock_station = dev->platform_data; acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf); if (ACPI_FAILURE(status)) @@ -905,8 +901,7 @@ static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); static ssize_t show_dock_type(struct device *dev, struct device_attribute *attr, char *buf) { - struct dock_station *dock_station = *((struct dock_station **) - dev->platform_data); + struct dock_station *dock_station = dev->platform_data; char *type; if (dock_station->flags & DOCK_IS_DOCK) @@ -944,20 +939,18 @@ static struct attribute_group dock_attribute_group = { */ static int dock_add(acpi_handle handle) { - int ret; - struct dock_station *dock_station; + int ret, id; + struct dock_station ds, *dock_station; struct platform_device *dock_device; + id = dock_station_count; dock_device = - platform_device_register_simple("dock", - dock_station_count, NULL, 0); + platform_device_register_data(NULL, "dock", + id, &ds, sizeof(ds)); if (IS_ERR(dock_device)) return PTR_ERR(dock_device); - /* allocate & initialize the dock_station private data */ - dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL); - if (!dock_station) - return -ENOMEM; + dock_station = dock_device->dev.platform_data; dock_station->handle = handle; dock_station->dock_device = dock_device; dock_station->last_dock_time = jiffies - HZ; @@ -968,9 +961,6 @@ static int dock_add(acpi_handle handle) mutex_init(&dock_station->hp_lock); ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); - platform_device_add_data(dock_device, &dock_station, - sizeof(struct dock_station *)); - /* we want the dock device to send uevents */ dev_set_uevent_suppress(&dock_device->dev, 0); @@ -1003,9 +993,6 @@ err_rmgroup: sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group); err_unregister: platform_device_unregister(dock_device); -out: - kfree(dock_station); - dock_station = NULL; printk(KERN_ERR "%s encountered error %d\n", __func__, ret); return ret; } @@ -1026,13 +1013,12 @@ static int dock_remove(struct dock_station *dock_station) list) kfree(dd); + list_del(&dock_station->sibling); + /* cleanup sysfs */ sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group); platform_device_unregister(dock_device); - /* free dock station memory */ - kfree(dock_station); - dock_station = NULL; return 0; } -- cgit v1.2.3 From 747479a3fb42849fe73b9b1f7545d751bde7d632 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Mon, 19 Oct 2009 15:14:50 -0600 Subject: ACPI: dock: minor whitespace and style cleanups Removed some stray whitespaces Added whitespace when needed for legibility Removed unneeded curly braces Removed useless void casts Removed unnecessary local variable initialization Renamed variables to help out with 80-column fixes Signed-off-by: Alex Chiang Acked-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/dock.c | 103 +++++++++++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 58 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index cfcd8eeb3b2a..d4c3d82bef3f 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -238,6 +238,7 @@ static int is_battery(acpi_handle handle) static int is_ejectable_bay(acpi_handle handle) { acpi_handle phandle; + if (!is_ejectable(handle)) return 0; if (is_battery(handle) || is_ata(handle)) @@ -264,14 +265,13 @@ int is_dock_device(acpi_handle handle) if (is_dock(handle)) return 1; - list_for_each_entry(dock_station, &dock_stations, sibling) { + + list_for_each_entry(dock_station, &dock_stations, sibling) if (find_dock_dependent_device(dock_station, handle)) return 1; - } return 0; } - EXPORT_SYMBOL_GPL(is_dock_device); /** @@ -294,8 +294,6 @@ static int dock_present(struct dock_station *ds) return 0; } - - /** * dock_create_acpi_device - add new devices to acpi * @handle - handle of the device to add @@ -309,7 +307,7 @@ static int dock_present(struct dock_station *ds) */ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) { - struct acpi_device *device = NULL; + struct acpi_device *device; struct acpi_device *parent_device; acpi_handle parent; int ret; @@ -326,8 +324,7 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) ret = acpi_bus_add(&device, parent_device, handle, ACPI_BUS_TYPE_DEVICE); if (ret) { - pr_debug("error adding bus, %x\n", - -ret); + pr_debug("error adding bus, %x\n", -ret); return NULL; } } @@ -353,7 +350,6 @@ static void dock_remove_acpi_device(acpi_handle handle) } } - /** * hotplug_dock_devices - insert or remove devices on the dock station * @ds: the dock station @@ -373,10 +369,9 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) /* * First call driver specific hotplug functions */ - list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) { + list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) if (dd->ops && dd->ops->handler) dd->ops->handler(dd->handle, event, dd->context); - } /* * Now make sure that an acpi_device is created for each @@ -415,6 +410,7 @@ static void dock_event(struct dock_station *ds, u32 event, int num) list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) if (dd->ops && dd->ops->uevent) dd->ops->uevent(dd->handle, event, dd->context); + if (num != DOCK_EVENT) kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); } @@ -445,8 +441,8 @@ static void eject_dock(struct dock_station *ds) arg.type = ACPI_TYPE_INTEGER; arg.integer.value = 1; - if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0", - &arg_list, NULL))) + status = acpi_evaluate_object(ds->handle, "_EJ0", &arg_list, NULL); + if (ACPI_FAILURE(status)) pr_debug("Failed to evaluate _EJ0!\n"); } @@ -566,7 +562,6 @@ int register_dock_notifier(struct notifier_block *nb) return atomic_notifier_chain_register(&dock_notifier_list, nb); } - EXPORT_SYMBOL_GPL(register_dock_notifier); /** @@ -580,7 +575,6 @@ void unregister_dock_notifier(struct notifier_block *nb) atomic_notifier_chain_unregister(&dock_notifier_list, nb); } - EXPORT_SYMBOL_GPL(unregister_dock_notifier); /** @@ -625,7 +619,6 @@ register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops, return ret; } - EXPORT_SYMBOL_GPL(register_hotplug_dock_device); /** @@ -646,7 +639,6 @@ void unregister_hotplug_dock_device(acpi_handle handle) dock_del_hotplug_device(dock_station, dd); } } - EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); /** @@ -761,7 +753,7 @@ struct dock_data { static void acpi_dock_deferred_cb(void *context) { - struct dock_data *data = (struct dock_data *)context; + struct dock_data *data = context; dock_notify(data->handle, data->event, data->ds); kfree(data); @@ -771,23 +763,22 @@ static int acpi_dock_notifier_call(struct notifier_block *this, unsigned long event, void *data) { struct dock_station *dock_station; - acpi_handle handle = (acpi_handle)data; + acpi_handle handle = data; if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK && event != ACPI_NOTIFY_EJECT_REQUEST) return 0; list_for_each_entry(dock_station, &dock_stations, sibling) { if (dock_station->handle == handle) { - struct dock_data *dock_data; + struct dock_data *dd; - dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL); - if (!dock_data) + dd = kmalloc(sizeof(*dd), GFP_KERNEL); + if (!dd) return 0; - dock_data->handle = handle; - dock_data->event = event; - dock_data->ds = dock_station; - acpi_os_hotplug_execute(acpi_dock_deferred_cb, - dock_data); + dd->handle = handle; + dd->event = event; + dd->ds = dock_station; + acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); return 0 ; } } @@ -941,28 +932,28 @@ static int dock_add(acpi_handle handle) { int ret, id; struct dock_station ds, *dock_station; - struct platform_device *dock_device; + struct platform_device *dd; id = dock_station_count; - dock_device = - platform_device_register_data(NULL, "dock", - id, &ds, sizeof(ds)); - if (IS_ERR(dock_device)) - return PTR_ERR(dock_device); + dd = platform_device_register_data(NULL, "dock", id, &ds, sizeof(ds)); + if (IS_ERR(dd)) + return PTR_ERR(dd); + + dock_station = dd->dev.platform_data; - dock_station = dock_device->dev.platform_data; dock_station->handle = handle; - dock_station->dock_device = dock_device; + dock_station->dock_device = dd; dock_station->last_dock_time = jiffies - HZ; - INIT_LIST_HEAD(&dock_station->dependent_devices); - INIT_LIST_HEAD(&dock_station->hotplug_devices); - INIT_LIST_HEAD(&dock_station->sibling); - spin_lock_init(&dock_station->dd_lock); + mutex_init(&dock_station->hp_lock); + spin_lock_init(&dock_station->dd_lock); + INIT_LIST_HEAD(&dock_station->sibling); + INIT_LIST_HEAD(&dock_station->hotplug_devices); ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); + INIT_LIST_HEAD(&dock_station->dependent_devices); /* we want the dock device to send uevents */ - dev_set_uevent_suppress(&dock_device->dev, 0); + dev_set_uevent_suppress(&dd->dev, 0); if (is_dock(handle)) dock_station->flags |= DOCK_IS_DOCK; @@ -971,14 +962,13 @@ static int dock_add(acpi_handle handle) if (is_battery(handle)) dock_station->flags |= DOCK_IS_BAT; - ret = sysfs_create_group(&dock_device->dev.kobj, &dock_attribute_group); + ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group); if (ret) goto err_unregister; /* Find dependent devices */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_dock_devices, dock_station, - NULL); + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + find_dock_devices, dock_station, NULL); /* add the dock station as a device dependent on itself */ ret = add_dock_dependent_device(dock_station, handle); @@ -990,9 +980,9 @@ static int dock_add(acpi_handle handle) return 0; err_rmgroup: - sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group); + sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group); err_unregister: - platform_device_unregister(dock_device); + platform_device_unregister(dd); printk(KERN_ERR "%s encountered error %d\n", __func__, ret); return ret; } @@ -1000,20 +990,19 @@ err_unregister: /** * dock_remove - free up resources related to the dock station */ -static int dock_remove(struct dock_station *dock_station) +static int dock_remove(struct dock_station *ds) { struct dock_dependent_device *dd, *tmp; - struct platform_device *dock_device = dock_station->dock_device; + struct platform_device *dock_device = ds->dock_device; if (!dock_station_count) return 0; /* remove dependent devices */ - list_for_each_entry_safe(dd, tmp, &dock_station->dependent_devices, - list) - kfree(dd); + list_for_each_entry_safe(dd, tmp, &ds->dependent_devices, list) + kfree(dd); - list_del(&dock_station->sibling); + list_del(&ds->sibling); /* cleanup sysfs */ sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group); @@ -1036,11 +1025,10 @@ find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status = AE_OK; - if (is_dock(handle)) { - if (dock_add(handle) >= 0) { + if (is_dock(handle)) + if (dock_add(handle) >= 0) status = AE_CTRL_TERMINATE; - } - } + return status; } @@ -1078,8 +1066,7 @@ static int __init dock_init(void) static void __exit dock_exit(void) { - struct dock_station *dock_station; - struct dock_station *tmp; + struct dock_station *tmp, *dock_station; unregister_acpi_bus_notifier(&dock_acpi_notifier); list_for_each_entry_safe(dock_station, tmp, &dock_stations, sibling) -- cgit v1.2.3 From f67538f81e6b8da9175c82807d649fbdb0055844 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 13 Nov 2009 19:55:30 -0800 Subject: acpi_pad: squish warning drivers/acpi/acpi_pad.c: In function 'power_saving_thread': drivers/acpi/acpi_pad.c:103: warning: 'preferred_cpu' may be used uninitialized in this function Cc: Shaohua Li Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/acpi_pad.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 0d2cdb86158b..97991ac6f5fc 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -100,7 +100,8 @@ static void round_robin_cpu(unsigned int tsk_index) struct cpumask *pad_busy_cpus = to_cpumask(pad_busy_cpus_bits); cpumask_var_t tmp; int cpu; - unsigned long min_weight = -1, preferred_cpu; + unsigned long min_weight = -1; + unsigned long uninitialized_var(preferred_cpu); if (!alloc_cpumask_var(&tmp, GFP_KERNEL)) return; -- cgit v1.2.3 From 918aae42aa9b611a3663b16ae849fdedc67c2292 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Mon, 14 Dec 2009 17:10:06 +0900 Subject: ACPI: fix for lapic_timer_propagate_broadcast() I got following warning on ia64 box: In function 'acpi_processor_power_verify': 642: warning: passing argument 2 of 'smp_call_function_single' from incompatible pointer type This smp_call_function_single() was introduced by a commit f833bab87fca5c3ce13778421b1365845843b976: > @@ -162,8 +162,9 @@ > 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 @@ > working++; > } > > - lapic_timer_propagate_broadcast(pr); > + smp_call_function_single(pr->id, lapic_timer_propagate_broadcast, > + pr, 1); > > return (working); > } The problem is that the lapic_timer_propagate_broadcast() has 2 versions: One is real code that modified in the above commit, and the other is NOP code that used when !ARCH_APICTIMER_STOPS_ON_C3: static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { } So I got warning because of !ARCH_APICTIMER_STOPS_ON_C3. We really want to do nothing here on !ARCH_APICTIMER_STOPS_ON_C3, so modify lapic_timer_propagate_broadcast() of real version to use smp_call_function_single() in it. Signed-off-by: Hidetoshi Seto Acked-by: Suresh Siddha Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index bbd066e7f854..d1676b1754d9 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -164,7 +164,7 @@ 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(void *arg) +static void __lapic_timer_propagate_broadcast(void *arg) { struct acpi_processor *pr = (struct acpi_processor *) arg; unsigned long reason; @@ -175,6 +175,12 @@ static void lapic_timer_propagate_broadcast(void *arg) clockevents_notify(reason, &pr->id); } +static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) +{ + smp_call_function_single(pr->id, __lapic_timer_propagate_broadcast, + (void *)pr, 1); +} + /* Power(C) State timer broadcast control */ static void lapic_timer_state_broadcast(struct acpi_processor *pr, struct acpi_processor_cx *cx, @@ -638,8 +644,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) working++; } - smp_call_function_single(pr->id, lapic_timer_propagate_broadcast, - pr, 1); + lapic_timer_propagate_broadcast(pr); return (working); } -- cgit v1.2.3 From 70023de88c58a81a730ab4d13c51a30e537ec76e Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 29 Oct 2009 11:04:28 +0800 Subject: ACPI: Add a generic API for _OSC -v2 v2->v1: .improve debug info as suggedted by Bjorn,Kenji .API is using uuid string as suggested by Alexey Add an API to execute _OSC. A lot of devices can have this method, so add a generic API. Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/bus.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 9 ++++ 2 files changed, 131 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 741191524353..12240be58f27 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -344,6 +344,128 @@ bool acpi_bus_can_wakeup(acpi_handle handle) EXPORT_SYMBOL(acpi_bus_can_wakeup); +static void acpi_print_osc_error(acpi_handle handle, + struct acpi_osc_context *context, char *error) +{ + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER}; + int i; + + if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) + printk(KERN_DEBUG "%s\n", error); + else { + printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error); + kfree(buffer.pointer); + } + printk(KERN_DEBUG"_OSC request data:"); + for (i = 0; i < context->cap.length; i += sizeof(u32)) + printk("%x ", *((u32 *)(context->cap.pointer + i))); + printk("\n"); +} + +static u8 hex_val(unsigned char c) +{ + return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10; +} + +static acpi_status acpi_str_to_uuid(char *str, u8 *uuid) +{ + int i; + static int opc_map_to_uuid[16] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21, + 24, 26, 28, 30, 32, 34}; + + if (strlen(str) != 36) + return AE_BAD_PARAMETER; + for (i = 0; i < 36; i++) { + if (i == 8 || i == 13 || i == 18 || i == 23) { + if (str[i] != '-') + return AE_BAD_PARAMETER; + } else if (!isxdigit(str[i])) + return AE_BAD_PARAMETER; + } + for (i = 0; i < 16; i++) { + uuid[i] = hex_val(str[opc_map_to_uuid[i]]) << 4; + uuid[i] |= hex_val(str[opc_map_to_uuid[i] + 1]); + } + return AE_OK; +} + +acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) +{ + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[4]; + union acpi_object *out_obj; + u8 uuid[16]; + u32 errors; + + if (!context) + return AE_ERROR; + if (ACPI_FAILURE(acpi_str_to_uuid(context->uuid_str, uuid))) + return AE_ERROR; + context->ret.length = ACPI_ALLOCATE_BUFFER; + context->ret.pointer = NULL; + + /* Setting up input parameters */ + input.count = 4; + input.pointer = in_params; + in_params[0].type = ACPI_TYPE_BUFFER; + in_params[0].buffer.length = 16; + in_params[0].buffer.pointer = uuid; + in_params[1].type = ACPI_TYPE_INTEGER; + in_params[1].integer.value = context->rev; + in_params[2].type = ACPI_TYPE_INTEGER; + in_params[2].integer.value = context->cap.length/sizeof(u32); + in_params[3].type = ACPI_TYPE_BUFFER; + in_params[3].buffer.length = context->cap.length; + in_params[3].buffer.pointer = context->cap.pointer; + + status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret); + if (ACPI_FAILURE(status)) + return status; + + /* return buffer should have the same length as cap buffer */ + if (context->ret.length != context->cap.length) + return AE_NULL_OBJECT; + + out_obj = context->ret.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { + acpi_print_osc_error(handle, context, + "_OSC evaluation returned wrong type"); + status = AE_TYPE; + goto out_kfree; + } + /* Need to ignore the bit0 in result code */ + errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); + if (errors) { + if (errors & OSC_REQUEST_ERROR) + acpi_print_osc_error(handle, context, + "_OSC request failed"); + if (errors & OSC_INVALID_UUID_ERROR) + acpi_print_osc_error(handle, context, + "_OSC invalid UUID"); + if (errors & OSC_INVALID_REVISION_ERROR) + acpi_print_osc_error(handle, context, + "_OSC invalid revision"); + if (errors & OSC_CAPABILITIES_MASK_ERROR) { + if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE] + & OSC_QUERY_ENABLE) + goto out_success; + status = AE_SUPPORT; + goto out_kfree; + } + status = AE_ERROR; + goto out_kfree; + } +out_success: + return AE_OK; + +out_kfree: + kfree(context->ret.pointer); + context->ret.pointer = NULL; + return status; +} +EXPORT_SYMBOL(acpi_run_osc); + /* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index dfcd920c3e54..3247e09db20d 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -253,6 +253,13 @@ void __init acpi_old_suspend_ordering(void); void __init acpi_s4_no_nvs(void); #endif /* CONFIG_PM_SLEEP */ +struct acpi_osc_context { + char *uuid_str; /* uuid string */ + int rev; + struct acpi_buffer cap; /* arg2/arg3 */ + struct acpi_buffer ret; /* free by caller if success */ +}; + #define OSC_QUERY_TYPE 0 #define OSC_SUPPORT_TYPE 1 #define OSC_CONTROL_TYPE 2 @@ -265,6 +272,8 @@ void __init acpi_s4_no_nvs(void); #define OSC_INVALID_REVISION_ERROR 8 #define OSC_CAPABILITIES_MASK_ERROR 16 +acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); + /* _OSC DW1 Definition (OS Support Fields) */ #define OSC_EXT_PCI_CONFIG_SUPPORT 1 #define OSC_ACTIVE_STATE_PWR_SUPPORT 2 -- cgit v1.2.3 From 3a9622dc4659af44a8098a233f65c51e495ff0a5 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 29 Oct 2009 11:04:50 +0800 Subject: ACPI: cleanup pci_root _OSC code. Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/pci_root.c | 76 +++++++++---------------------------------------- include/linux/acpi.h | 5 ++-- 2 files changed, 17 insertions(+), 64 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 1af808171d46..101cce3681d1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -202,72 +202,24 @@ static void acpi_pci_bridge_scan(struct acpi_device *device) } } -static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, - 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; +static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; static acpi_status acpi_pci_run_osc(acpi_handle handle, const u32 *capbuf, u32 *retval) { + struct acpi_osc_context context = { + .uuid_str = pci_osc_uuid_str, + .rev = 1, + .cap.length = 12, + .cap.pointer = (void *)capbuf, + }; acpi_status status; - struct acpi_object_list input; - union acpi_object in_params[4]; - struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *out_obj; - u32 errors; - - /* Setting up input parameters */ - input.count = 4; - input.pointer = in_params; - in_params[0].type = ACPI_TYPE_BUFFER; - in_params[0].buffer.length = 16; - in_params[0].buffer.pointer = OSC_UUID; - in_params[1].type = ACPI_TYPE_INTEGER; - in_params[1].integer.value = 1; - in_params[2].type = ACPI_TYPE_INTEGER; - in_params[2].integer.value = 3; - in_params[3].type = ACPI_TYPE_BUFFER; - in_params[3].buffer.length = 12; - in_params[3].buffer.pointer = (u8 *)capbuf; - - status = acpi_evaluate_object(handle, "_OSC", &input, &output); - if (ACPI_FAILURE(status)) - return status; - if (!output.length) - return AE_NULL_OBJECT; - - out_obj = output.pointer; - if (out_obj->type != ACPI_TYPE_BUFFER) { - printk(KERN_DEBUG "_OSC evaluation returned wrong type\n"); - status = AE_TYPE; - goto out_kfree; - } - /* Need to ignore the bit0 in result code */ - errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); - if (errors) { - if (errors & OSC_REQUEST_ERROR) - printk(KERN_DEBUG "_OSC request failed\n"); - if (errors & OSC_INVALID_UUID_ERROR) - printk(KERN_DEBUG "_OSC invalid UUID\n"); - if (errors & OSC_INVALID_REVISION_ERROR) - printk(KERN_DEBUG "_OSC invalid revision\n"); - if (errors & OSC_CAPABILITIES_MASK_ERROR) { - if (capbuf[OSC_QUERY_TYPE] & OSC_QUERY_ENABLE) - goto out_success; - printk(KERN_DEBUG - "Firmware did not grant requested _OSC control\n"); - status = AE_SUPPORT; - goto out_kfree; - } - status = AE_ERROR; - goto out_kfree; + status = acpi_run_osc(handle, &context); + if (ACPI_SUCCESS(status)) { + *retval = *((u32 *)(context.ret.pointer + 8)); + kfree(context.ret.pointer); } -out_success: - *retval = *((u32 *)(out_obj->buffer.pointer + 8)); - status = AE_OK; - -out_kfree: - kfree(output.pointer); return status; } @@ -277,10 +229,10 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags) u32 support_set, result, capbuf[3]; /* do _OSC query for all possible controls */ - support_set = root->osc_support_set | (flags & OSC_SUPPORT_MASKS); + support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS); capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_TYPE] = support_set; - capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; + capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; status = acpi_pci_run_osc(root->device->handle, capbuf, &result); if (ACPI_SUCCESS(status)) { @@ -427,7 +379,7 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) if (ACPI_FAILURE(status)) return status; - control_req = (flags & OSC_CONTROL_MASKS); + control_req = (flags & OSC_PCI_CONTROL_MASKS); if (!control_req) return AE_TYPE; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 3247e09db20d..535beecc37cf 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -263,7 +263,6 @@ struct acpi_osc_context { #define OSC_QUERY_TYPE 0 #define OSC_SUPPORT_TYPE 1 #define OSC_CONTROL_TYPE 2 -#define OSC_SUPPORT_MASKS 0x1f /* _OSC DW0 Definition */ #define OSC_QUERY_ENABLE 1 @@ -274,12 +273,14 @@ struct acpi_osc_context { acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); +/* PCI defined _OSC bits */ /* _OSC DW1 Definition (OS Support Fields) */ #define OSC_EXT_PCI_CONFIG_SUPPORT 1 #define OSC_ACTIVE_STATE_PWR_SUPPORT 2 #define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 4 #define OSC_PCI_SEGMENT_GROUPS_SUPPORT 8 #define OSC_MSI_SUPPORT 16 +#define OSC_PCI_SUPPORT_MASKS 0x1f /* _OSC DW1 Definition (OS Control Fields) */ #define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 1 @@ -288,7 +289,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_PCI_EXPRESS_AER_CONTROL 8 #define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 16 -#define OSC_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \ +#define OSC_PCI_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \ OSC_SHPC_NATIVE_HP_CONTROL | \ OSC_PCI_EXPRESS_PME_CONTROL | \ OSC_PCI_EXPRESS_AER_CONTROL | \ -- cgit v1.2.3 From 3563ff964fdc36358cef0330936fdac28e65142a Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 29 Oct 2009 11:05:05 +0800 Subject: ACPI: Add platform-wide _OSC support. Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/bus.c | 26 ++++++++++++++++++++++++++ include/linux/acpi.h | 7 +++++++ 2 files changed, 33 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 12240be58f27..65f7e335f122 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -466,6 +466,30 @@ out_kfree: } EXPORT_SYMBOL(acpi_run_osc); +static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48"; +static void acpi_bus_osc_support(void) +{ + u32 capbuf[2]; + struct acpi_osc_context context = { + .uuid_str = sb_uuid_str, + .rev = 1, + .cap.length = 8, + .cap.pointer = capbuf, + }; + acpi_handle handle; + + capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; + capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ +#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR + capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; +#endif + if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) + return; + if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) + kfree(context.ret.pointer); + /* do we need to check the returned cap? Sounds no */ +} + /* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ @@ -856,6 +880,8 @@ static int __init acpi_bus_init(void) status = acpi_ec_ecdt_probe(); /* Ignore result. Not having an ECDT is not fatal. */ + acpi_bus_osc_support(); + status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 535beecc37cf..e11090d462d2 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -273,6 +273,13 @@ struct acpi_osc_context { acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); +/* platform-wide _OSC bits */ +#define OSC_SB_PAD_SUPPORT 1 +#define OSC_SB_PPC_OST_SUPPORT 2 +#define OSC_SB_PR3_SUPPORT 4 +#define OSC_SB_CPUHP_OST_SUPPORT 8 +#define OSC_SB_APEI_SUPPORT 16 + /* PCI defined _OSC bits */ /* _OSC DW1 Definition (OS Support Fields) */ #define OSC_EXT_PCI_CONFIG_SUPPORT 1 -- cgit v1.2.3 From bf8b4542f92c4d8222941b1cab055fa350ab2fb4 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Mon, 26 Oct 2009 17:44:18 +0100 Subject: ACPI processor: Fix section mismatch for processor_add() Due to the merge of processor_start() (declared with __cpuinit) into processor_add(), a section mismatch warning appears: WARNING: drivers/built-in.o(.text+0x4d59d): Section mismatch in reference from the function acpi_processor_add() to the function .cpuinit.text:acpi_processor_power_init() ... This patch fixes the warning by declaring processor_add() as __cpuinit and also declares acpi_processor_add_fs() as __cpuinit as it is only used in acpi_processor_add(). Signed-off-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index ecb2c5122040..709b590c2fb6 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -353,7 +353,7 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file) PDE(inode)->data); } -static int acpi_processor_add_fs(struct acpi_device *device) +static int __cpuinit acpi_processor_add_fs(struct acpi_device *device) { struct proc_dir_entry *entry = NULL; -- cgit v1.2.3 From 81074e90f5c150ca70ab8dfcc77860cbe76f364d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 21 Dec 2009 16:13:15 +0800 Subject: ACPI: disable _OSI(Windows 2009) on Asus K50IJ Fix a win7 compability issue on Asus K50IJ. Here is the _BCM method of this laptop: Method (_BCM, 1, NotSerialized) { If (LGreaterEqual (OSFG, OSVT)) { If (LNotEqual (OSFG, OSW7)) { Store (One, BCMD) Store (GCBL (Arg0), Local0) Subtract (0x0F, Local0, LBTN) ^^^SBRG.EC0.STBR () ... } Else { DBGR (0x0B, Zero, Zero, Arg0) Store (Arg0, LBTN) ^^^SBRG.EC0.STBR () ... } } } LBTN is used to store the index of the brightness level in the _BCL. GCBL is a method that convert the percentage value to the index value. If _OSI(Windows 2009) is not disabled, LBTN is stored a percentage value which is surely beyond the end of _BCL package. http://bugzilla.kernel.org/show_bug.cgi?id=14753 Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/blacklist.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 23e5a0519af5..2815df66f6f7 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -185,6 +185,12 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) acpi_osi_setup("!Windows 2006"); return 0; } +static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) +{ + printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); + acpi_osi_setup("!Windows 2009"); + return 0; +} static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { { @@ -211,6 +217,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"), }, }, + { + .callback = dmi_disable_osi_win7, + .ident = "ASUS K50IJ", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. -- cgit v1.2.3 From 55b313f249e11b815fd0be51869f166aaf368f44 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Tue, 22 Dec 2009 02:42:52 -0500 Subject: ACPI: EC: Fix MSI DMI detection MSI strings should be ORed, not ANDed. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14446 cc: stable@kernel.org Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index baef28c1e630..7511029a1e0b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -916,6 +916,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id) /* MSI EC needs special treatment, enable it */ static int ec_flag_msi(const struct dmi_system_id *id) { + printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n"); EC_FLAGS_MSI = 1; EC_FLAGS_VALIDATE_ECDT = 1; return 0; @@ -928,8 +929,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL}, { ec_flag_msi, "MSI hardware", { - DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star"), - DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star") }, NULL}, + DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star")}, NULL}, + { + ec_flag_msi, "MSI hardware", { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star")}, NULL}, + { + ec_flag_msi, "MSI hardware", { + DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL}, { ec_validate_ecdt, "ASUS hardware", { DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL}, -- cgit v1.2.3 From 78f1699659963fff97975df44db6d5dbe7218e55 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:09 -0700 Subject: ACPI: processor: call _PDC early We discovered that at least one machine (HP Envy), methods in the DSDT attempt to call external methods defined in a dynamically loaded SSDT. Unfortunately, the DSDT methods we are trying to call are part of the EC initialization, which happens very early, and the the dynamic SSDT is only loaded when a processor _PDC method runs much later. This results in namespace lookup errors for the (as of yet) undefined methods. Since Windows doesn't have any issues with this machine, we take it as a hint that they must be evaluating _PDC much earlier than we are. Thus, the proper thing for Linux to do should be to match the Windows implementation more closely. Provide a mechanism to call _PDC before we enable the EC. Doing so loads the dynamic tables, and allows the EC to be enabled correctly. The ACPI processor driver will still evaluate _PDC in its .add() method to cover the hotplug case. Resolves: http://bugzilla.kernel.org/show_bug.cgi?id=14824 Cc: ming.m.lin@intel.com Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/Makefile | 1 + drivers/acpi/bus.c | 2 + drivers/acpi/internal.h | 1 + drivers/acpi/processor_core.c | 69 --------------------------- drivers/acpi/processor_pdc.c | 108 ++++++++++++++++++++++++++++++++++++++++++ include/acpi/processor.h | 3 ++ 6 files changed, 115 insertions(+), 69 deletions(-) create mode 100644 drivers/acpi/processor_pdc.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index c7b10b4298e9..66cc3f36a954 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -32,6 +32,7 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o # acpi-y += bus.o glue.o acpi-y += scan.o +acpi-y += processor_pdc.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 65f7e335f122..0bdf24a6fd01 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -888,6 +888,8 @@ static int __init acpi_bus_init(void) goto error1; } + acpi_early_processor_set_pdc(); + /* * Maybe EC region is required at bus_scan/acpi_get_devices. So it * is necessary to enable it as early as possible. diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 074cf8682d52..cb28e0502acc 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -43,6 +43,7 @@ int acpi_power_transition(struct acpi_device *device, int state); extern int acpi_power_nocheck; int acpi_wakeup_device_init(void); +void acpi_early_processor_set_pdc(void); /* -------------------------------------------------------------------------- Embedded Controller diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 41731236f9a1..a19a4ff962ea 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -124,29 +124,6 @@ static const struct file_operations acpi_processor_info_fops = { DEFINE_PER_CPU(struct acpi_processor *, processors); struct acpi_processor_errata errata __read_mostly; -static int set_no_mwait(const struct dmi_system_id *id) -{ - printk(KERN_NOTICE PREFIX "%s detected - " - "disabling mwait for CPU C-states\n", id->ident); - idle_nomwait = 1; - return 0; -} - -static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { - { - set_no_mwait, "IFL91 board", { - DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), - DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"), - DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL}, - { - set_no_mwait, "Extensa 5220", { - DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), - DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, - {}, -}; /* -------------------------------------------------------------------------- Errata Handling @@ -276,45 +253,6 @@ static int acpi_processor_errata(struct acpi_processor *pr) return result; } -/* -------------------------------------------------------------------------- - Common ACPI processor functions - -------------------------------------------------------------------------- */ - -/* - * _PDC is required for a BIOS-OS handshake for most of the newer - * ACPI processor features. - */ -static int acpi_processor_set_pdc(struct acpi_processor *pr) -{ - struct acpi_object_list *pdc_in = pr->pdc; - acpi_status status = AE_OK; - - - if (!pdc_in) - return status; - if (idle_nomwait) { - /* - * If mwait is disabled for CPU C-states, the C2C3_FFH access - * mode will be disabled in the parameter of _PDC object. - * Of course C1_FFH access mode will also be disabled. - */ - union acpi_object *obj; - u32 *buffer = NULL; - - obj = pdc_in->pointer; - buffer = (u32 *)(obj->buffer.pointer); - buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); - - } - status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); - - if (ACPI_FAILURE(status)) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Could not evaluate _PDC, using legacy perf. control...\n")); - - return status; -} - /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -825,9 +763,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) } /* _PDC call should be done before doing anything else (if reqd.). */ - arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); - arch_acpi_processor_cleanup_pdc(pr); #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); @@ -1145,11 +1081,6 @@ static int __init acpi_processor_init(void) if (!acpi_processor_dir) return -ENOMEM; #endif - /* - * Check whether the system is DMI table. If yes, OSPM - * should not use mwait for CPU-states. - */ - dmi_check_system(processor_idle_dmi_table); result = cpuidle_register_driver(&acpi_idle_driver); if (result < 0) goto out_proc; diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c new file mode 100644 index 000000000000..b416c32dda04 --- /dev/null +++ b/drivers/acpi/processor_pdc.c @@ -0,0 +1,108 @@ +#include + +#include +#include + +#include "internal.h" + +#define PREFIX "ACPI: " +#define _COMPONENT ACPI_PROCESSOR_COMPONENT +ACPI_MODULE_NAME("processor_pdc"); + +static int set_no_mwait(const struct dmi_system_id *id) +{ + printk(KERN_NOTICE PREFIX "%s detected - " + "disabling mwait for CPU C-states\n", id->ident); + idle_nomwait = 1; + return 0; +} + +static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { + { + set_no_mwait, "IFL91 board", { + DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), + DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"), + DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL}, + { + set_no_mwait, "Extensa 5220", { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), + DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, + {}, +}; + +/* + * _PDC is required for a BIOS-OS handshake for most of the newer + * ACPI processor features. + */ +static int acpi_processor_eval_pdc(struct acpi_processor *pr) +{ + struct acpi_object_list *pdc_in = pr->pdc; + acpi_status status = AE_OK; + + if (!pdc_in) + return status; + if (idle_nomwait) { + /* + * If mwait is disabled for CPU C-states, the C2C3_FFH access + * mode will be disabled in the parameter of _PDC object. + * Of course C1_FFH access mode will also be disabled. + */ + union acpi_object *obj; + u32 *buffer = NULL; + + obj = pdc_in->pointer; + buffer = (u32 *)(obj->buffer.pointer); + buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); + + } + status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); + + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Could not evaluate _PDC, using legacy perf. control.\n")); + + return status; +} + +void acpi_processor_set_pdc(struct acpi_processor *pr) +{ + arch_acpi_processor_init_pdc(pr); + acpi_processor_eval_pdc(pr); + arch_acpi_processor_cleanup_pdc(pr); +} +EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); + +static acpi_status +early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + struct acpi_processor pr; + + pr.handle = handle; + + /* x86 implementation looks at pr.id to determine some + * CPU capabilites. We can just hard code to 0 since we're + * assuming the CPUs in the system are homogenous and all + * have the same capabilities. + */ + pr.id = 0; + + acpi_processor_set_pdc(&pr); + + return AE_OK; +} + +void acpi_early_processor_set_pdc(void) +{ + /* + * Check whether the system is DMI table. If yes, OSPM + * should not use mwait for CPU-states. + */ + dmi_check_system(processor_idle_dmi_table); + + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + early_init_pdc, NULL, NULL, NULL); +} diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 29245c6b5c0e..a1b748a7a766 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -325,6 +325,9 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) #endif /* CONFIG_CPU_FREQ */ +/* in processor_pdc.c */ +void acpi_processor_set_pdc(struct acpi_processor *pr); + /* in processor_throttling.c */ int acpi_processor_tstate_has_changed(struct acpi_processor *pr); int acpi_processor_get_throttling_info(struct acpi_processor *pr); -- cgit v1.2.3 From 1d9cb470a755409ce97c3376174b1e234bd20371 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:14 -0700 Subject: ACPI: processor: introduce arch_has_acpi_pdc arch dependent helper function that tells us if we should attempt to evaluate _PDC on this machine or not. The x86 implementation assumes that the CPUs in the machine must be homogeneous, and that you cannot mix CPUs of different vendors. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- arch/ia64/include/asm/acpi.h | 2 ++ arch/x86/include/asm/acpi.h | 7 +++++++ arch/x86/kernel/acpi/processor.c | 4 +--- drivers/acpi/processor_pdc.c | 3 +++ 4 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index 91df9686a0da..3b7888294648 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -132,6 +132,8 @@ extern int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS]; extern int __initdata nid_to_pxm_map[MAX_NUMNODES]; #endif +static inline bool arch_has_acpi_pdc(void) { return true; } + #define acpi_unlazy_tlb(x) #ifdef CONFIG_ACPI_NUMA diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 60d2b2db0bc5..d787e6e92bd1 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -142,6 +142,13 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate) return max_cstate; } +static inline bool arch_has_acpi_pdc(void) +{ + struct cpuinfo_x86 *c = &cpu_data(0); + return (c->x86_vendor == X86_VENDOR_INTEL || + c->x86_vendor == X86_VENDOR_CENTAUR); +} + #else /* !CONFIG_ACPI */ #define acpi_lapic 0 diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index d85d1b2432ba..bcb6efe08c5d 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -79,9 +79,7 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr) struct cpuinfo_x86 *c = &cpu_data(pr->id); pr->pdc = NULL; - if (c->x86_vendor == X86_VENDOR_INTEL || - c->x86_vendor == X86_VENDOR_CENTAUR) - init_intel_pdc(pr, c); + init_intel_pdc(pr, c); return; } diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index b416c32dda04..931e735e9e37 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -69,6 +69,9 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) void acpi_processor_set_pdc(struct acpi_processor *pr) { + if (arch_has_acpi_pdc() == false) + return; + arch_acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); arch_acpi_processor_cleanup_pdc(pr); -- cgit v1.2.3 From 407cd87c54e76c266245e8faef8dd4a84b7254fe Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:19 -0700 Subject: ACPI: processor: unify arch_acpi_processor_init_pdc The x86 and ia64 implementations of arch_acpi_processor_init_pdc() are almost exactly the same. The only difference is in what bits they set in obj_list buffer. Combine the boilerplate memory management code, and leave the arch-specific bit twiddling in separate implementations. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- arch/ia64/kernel/acpi-processor.c | 34 +---------------------------- arch/x86/kernel/acpi/processor.c | 34 +---------------------------- drivers/acpi/processor_pdc.c | 45 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 67 deletions(-) (limited to 'drivers/acpi') diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c index dbda7bde6112..ab72d46f52c6 100644 --- a/arch/ia64/kernel/acpi-processor.c +++ b/arch/ia64/kernel/acpi-processor.c @@ -16,31 +16,7 @@ static void init_intel_pdc(struct acpi_processor *pr) { - struct acpi_object_list *obj_list; - union acpi_object *obj; - u32 *buf; - - /* allocate and initialize pdc. It will be used later. */ - obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); - if (!obj_list) { - printk(KERN_ERR "Memory allocation error\n"); - return; - } - - obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!obj) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj_list); - return; - } - - buf = kmalloc(12, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj); - kfree(obj_list); - return; - } + u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; @@ -52,20 +28,12 @@ static void init_intel_pdc(struct acpi_processor *pr) */ buf[2] |= ACPI_PDC_SMP_T_SWCOORD; - obj->type = ACPI_TYPE_BUFFER; - obj->buffer.length = 12; - obj->buffer.pointer = (u8 *) buf; - obj_list->count = 1; - obj_list->pointer = obj; - pr->pdc = obj_list; - return; } /* Initialize _PDC data based on the CPU vendor */ void arch_acpi_processor_init_pdc(struct acpi_processor *pr) { - pr->pdc = NULL; init_intel_pdc(pr); return; } diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index bcb6efe08c5d..967860b43f2a 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -14,31 +14,7 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) { - struct acpi_object_list *obj_list; - union acpi_object *obj; - u32 *buf; - - /* allocate and initialize pdc. It will be used later. */ - obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); - if (!obj_list) { - printk(KERN_ERR "Memory allocation error\n"); - return; - } - - obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!obj) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj_list); - return; - } - - buf = kmalloc(12, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj); - kfree(obj_list); - return; - } + u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; @@ -62,13 +38,6 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) if (!cpu_has(c, X86_FEATURE_MWAIT)) buf[2] &= ~(ACPI_PDC_C_C2C3_FFH); - obj->type = ACPI_TYPE_BUFFER; - obj->buffer.length = 12; - obj->buffer.pointer = (u8 *) buf; - obj_list->count = 1; - obj_list->pointer = obj; - pr->pdc = obj_list; - return; } @@ -78,7 +47,6 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr) { struct cpuinfo_x86 *c = &cpu_data(pr->id); - pr->pdc = NULL; init_intel_pdc(pr, c); return; diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 931e735e9e37..87946b6da765 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -33,6 +33,49 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { {}, }; +static void acpi_processor_init_pdc(struct acpi_processor *pr) +{ + struct acpi_object_list *obj_list; + union acpi_object *obj; + u32 *buf; + + pr->pdc = NULL; + + /* allocate and initialize pdc. It will be used later. */ + obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); + if (!obj_list) { + printk(KERN_ERR "Memory allocation error\n"); + return; + } + + obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + if (!obj) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj_list); + return; + } + + buf = kmalloc(12, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj); + kfree(obj_list); + return; + } + + obj->type = ACPI_TYPE_BUFFER; + obj->buffer.length = 12; + obj->buffer.pointer = (u8 *) buf; + obj_list->count = 1; + obj_list->pointer = obj; + pr->pdc = obj_list; + + /* Now let the arch do the bit-twiddling to buf[] */ + arch_acpi_processor_init_pdc(pr); + + return; +} + /* * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. @@ -72,7 +115,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (arch_has_acpi_pdc() == false) return; - arch_acpi_processor_init_pdc(pr); + acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); arch_acpi_processor_cleanup_pdc(pr); } -- cgit v1.2.3 From 08ea48a326d8030ef5b7fb02292faf5a53c95e0a Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:24 -0700 Subject: ACPI: processor: factor out common _PDC settings Both x86 and ia64 initialize _PDC with mostly common bit settings. Factor out the common settings and leave the arch-specific ones alone. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- arch/ia64/kernel/acpi-processor.c | 10 +--------- arch/x86/kernel/acpi/processor.c | 10 +--------- drivers/acpi/processor_pdc.c | 11 +++++++++++ 3 files changed, 13 insertions(+), 18 deletions(-) (limited to 'drivers/acpi') diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c index ab72d46f52c6..ebe23f58bd6e 100644 --- a/arch/ia64/kernel/acpi-processor.c +++ b/arch/ia64/kernel/acpi-processor.c @@ -18,15 +18,7 @@ static void init_intel_pdc(struct acpi_processor *pr) { u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - buf[2] = ACPI_PDC_EST_CAPABILITY_SMP; - /* - * The default of PDC_SMP_T_SWCOORD bit is set for IA64 cpu so - * that OSPM is capable of native ACPI throttling software - * coordination using BIOS supplied _TSD info. - */ - buf[2] |= ACPI_PDC_SMP_T_SWCOORD; + buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; return; } diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index 967860b43f2a..d722ca8cb4c7 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -16,16 +16,8 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) { u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - buf[2] = ACPI_PDC_C_CAPABILITY_SMP; + buf[2] |= ACPI_PDC_C_CAPABILITY_SMP; - /* - * The default of PDC_SMP_T_SWCOORD bit is set for intel x86 cpu so - * that OSPM is capable of native ACPI throttling software - * coordination using BIOS supplied _TSD info. - */ - buf[2] |= ACPI_PDC_SMP_T_SWCOORD; if (cpu_has(c, X86_FEATURE_EST)) buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP; diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 87946b6da765..ccda7c95d073 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -33,6 +33,15 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { {}, }; +static void acpi_set_pdc_bits(u32 *buf) +{ + buf[0] = ACPI_PDC_REVISION_ID; + buf[1] = 1; + + /* Enable coordination with firmware's _TSD info */ + buf[2] = ACPI_PDC_SMP_T_SWCOORD; +} + static void acpi_processor_init_pdc(struct acpi_processor *pr) { struct acpi_object_list *obj_list; @@ -63,6 +72,8 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) return; } + acpi_set_pdc_bits(buf); + obj->type = ACPI_TYPE_BUFFER; obj->buffer.length = 12; obj->buffer.pointer = (u8 *) buf; -- cgit v1.2.3 From 6c5807d7bc7d051fce00863ffb98d36325501eb2 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:29 -0700 Subject: ACPI: processor: finish unifying arch_acpi_processor_init_pdc() The only thing arch-specific about calling _PDC is what bits get set in the input obj_list buffer. There's no need for several levels of indirection to twiddle those bits. Additionally, since we're just messing around with a buffer, we can simplify the interface; no need to pass around the entire struct acpi_processor * just to get at the buffer. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- arch/ia64/include/asm/acpi.h | 4 ++++ arch/ia64/kernel/acpi-processor.c | 18 ------------------ arch/x86/include/asm/acpi.h | 19 +++++++++++++++++++ arch/x86/kernel/acpi/processor.c | 34 ---------------------------------- drivers/acpi/processor_pdc.c | 6 +++--- include/acpi/processor.h | 1 - 6 files changed, 26 insertions(+), 56 deletions(-) (limited to 'drivers/acpi') diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index 3b7888294648..7ae58892ba8d 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -133,6 +133,10 @@ extern int __initdata nid_to_pxm_map[MAX_NUMNODES]; #endif static inline bool arch_has_acpi_pdc(void) { return true; } +static inline void arch_acpi_set_pdc_bits(u32 *buf) +{ + buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; +} #define acpi_unlazy_tlb(x) diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c index ebe23f58bd6e..7ba5accebf66 100644 --- a/arch/ia64/kernel/acpi-processor.c +++ b/arch/ia64/kernel/acpi-processor.c @@ -14,24 +14,6 @@ #include #include -static void init_intel_pdc(struct acpi_processor *pr) -{ - u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; - - buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; - - return; -} - -/* Initialize _PDC data based on the CPU vendor */ -void arch_acpi_processor_init_pdc(struct acpi_processor *pr) -{ - init_intel_pdc(pr); - return; -} - -EXPORT_SYMBOL(arch_acpi_processor_init_pdc); - void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr) { if (pr->pdc) { diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index d787e6e92bd1..56f462cf22d2 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -149,6 +149,25 @@ static inline bool arch_has_acpi_pdc(void) c->x86_vendor == X86_VENDOR_CENTAUR); } +static inline void arch_acpi_set_pdc_bits(u32 *buf) +{ + struct cpuinfo_x86 *c = &cpu_data(0); + + buf[2] |= ACPI_PDC_C_CAPABILITY_SMP; + + if (cpu_has(c, X86_FEATURE_EST)) + buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP; + + if (cpu_has(c, X86_FEATURE_ACPI)) + buf[2] |= ACPI_PDC_T_FFH; + + /* + * If mwait/monitor is unsupported, C2/C3_FFH will be disabled + */ + if (!cpu_has(c, X86_FEATURE_MWAIT)) + buf[2] &= ~(ACPI_PDC_C_C2C3_FFH); +} + #else /* !CONFIG_ACPI */ #define acpi_lapic 0 diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index d722ca8cb4c7..0f57307f8224 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -12,40 +12,6 @@ #include #include -static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) -{ - u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; - - buf[2] |= ACPI_PDC_C_CAPABILITY_SMP; - - if (cpu_has(c, X86_FEATURE_EST)) - buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP; - - if (cpu_has(c, X86_FEATURE_ACPI)) - buf[2] |= ACPI_PDC_T_FFH; - - /* - * If mwait/monitor is unsupported, C2/C3_FFH will be disabled - */ - if (!cpu_has(c, X86_FEATURE_MWAIT)) - buf[2] &= ~(ACPI_PDC_C_C2C3_FFH); - - return; -} - - -/* Initialize _PDC data based on the CPU vendor */ -void arch_acpi_processor_init_pdc(struct acpi_processor *pr) -{ - struct cpuinfo_x86 *c = &cpu_data(pr->id); - - init_intel_pdc(pr, c); - - return; -} - -EXPORT_SYMBOL(arch_acpi_processor_init_pdc); - void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr) { if (pr->pdc) { diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index ccda7c95d073..48df08ebcec4 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -40,6 +40,9 @@ static void acpi_set_pdc_bits(u32 *buf) /* Enable coordination with firmware's _TSD info */ buf[2] = ACPI_PDC_SMP_T_SWCOORD; + + /* Twiddle arch-specific bits needed for _PDC */ + arch_acpi_set_pdc_bits(buf); } static void acpi_processor_init_pdc(struct acpi_processor *pr) @@ -81,9 +84,6 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) obj_list->pointer = obj; pr->pdc = obj_list; - /* Now let the arch do the bit-twiddling to buf[] */ - arch_acpi_processor_init_pdc(pr); - return; } diff --git a/include/acpi/processor.h b/include/acpi/processor.h index a1b748a7a766..50edd734aec6 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -257,7 +257,6 @@ int acpi_processor_notify_smm(struct module *calling_module); DECLARE_PER_CPU(struct acpi_processor *, processors); extern struct acpi_processor_errata errata; -void arch_acpi_processor_init_pdc(struct acpi_processor *pr); void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr); #ifdef ARCH_HAS_POWER_INIT -- cgit v1.2.3 From 47817254b8637b56730aec26eed2c337d3938bb5 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:34 -0700 Subject: ACPI: processor: unify arch_acpi_processor_cleanup_pdc The x86 and ia64 implementations of the function in $subject are exactly the same. Also, since the arch-specific implementations of setting _PDC have been completely hollowed out, remove the empty shells. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- arch/ia64/kernel/Makefile | 4 ---- arch/ia64/kernel/acpi-processor.c | 27 --------------------------- arch/x86/kernel/acpi/Makefile | 2 +- arch/x86/kernel/acpi/processor.c | 25 ------------------------- drivers/acpi/processor_pdc.c | 21 ++++++++++++++++++++- include/acpi/processor.h | 2 -- 6 files changed, 21 insertions(+), 60 deletions(-) delete mode 100644 arch/ia64/kernel/acpi-processor.c delete mode 100644 arch/x86/kernel/acpi/processor.c (limited to 'drivers/acpi') diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 2a75e937ae8d..e1236349c99f 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -18,10 +18,6 @@ obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o -ifneq ($(CONFIG_ACPI_PROCESSOR),) -obj-y += acpi-processor.o -endif - obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c deleted file mode 100644 index 7ba5accebf66..000000000000 --- a/arch/ia64/kernel/acpi-processor.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * arch/ia64/kernel/acpi-processor.c - * - * Copyright (C) 2005 Intel Corporation - * Venkatesh Pallipadi - * - Added _PDC for platforms with Intel CPUs - */ - -#include -#include -#include -#include - -#include -#include - -void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr) -{ - if (pr->pdc) { - kfree(pr->pdc->pointer->buffer.pointer); - kfree(pr->pdc->pointer); - kfree(pr->pdc); - pr->pdc = NULL; - } -} - -EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc); diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile index fd5ca97a2ad5..6f35260bb3ef 100644 --- a/arch/x86/kernel/acpi/Makefile +++ b/arch/x86/kernel/acpi/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_ACPI) += boot.o obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_rm.o wakeup_$(BITS).o ifneq ($(CONFIG_ACPI_PROCESSOR),) -obj-y += cstate.o processor.o +obj-y += cstate.o endif $(obj)/wakeup_rm.o: $(obj)/realmode/wakeup.bin diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c deleted file mode 100644 index 0f57307f8224..000000000000 --- a/arch/x86/kernel/acpi/processor.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2005 Intel Corporation - * Venkatesh Pallipadi - * - Added _PDC for platforms with Intel CPUs - */ - -#include -#include -#include -#include - -#include -#include - -void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr) -{ - if (pr->pdc) { - kfree(pr->pdc->pointer->buffer.pointer); - kfree(pr->pdc->pointer); - kfree(pr->pdc); - pr->pdc = NULL; - } -} - -EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc); diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 48df08ebcec4..e786e2ce1882 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -1,3 +1,12 @@ +/* + * Copyright (C) 2005 Intel Corporation + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. + * + * Alex Chiang + * - Unified x86/ia64 implementations + * Venkatesh Pallipadi + * - Added _PDC for platforms with Intel CPUs + */ #include #include @@ -121,6 +130,16 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) return status; } +static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) +{ + if (pr->pdc) { + kfree(pr->pdc->pointer->buffer.pointer); + kfree(pr->pdc->pointer); + kfree(pr->pdc); + pr->pdc = NULL; + } +} + void acpi_processor_set_pdc(struct acpi_processor *pr) { if (arch_has_acpi_pdc() == false) @@ -128,7 +147,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); - arch_acpi_processor_cleanup_pdc(pr); + acpi_processor_cleanup_pdc(pr); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 50edd734aec6..0873cd57510c 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -257,8 +257,6 @@ int acpi_processor_notify_smm(struct module *calling_module); DECLARE_PER_CPU(struct acpi_processor *, processors); extern struct acpi_processor_errata errata; -void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr); - #ifdef ARCH_HAS_POWER_INIT void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, unsigned int cpu); -- cgit v1.2.3 From 3b407aef573b82139c3bc4dcaad2731fad56c054 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:39 -0700 Subject: ACPI: processor: introduce acpi_processor_alloc_pdc() acpi_processor_init_pdc() isn't really doing anything interesting with the struct acpi_processor * parameter. Its real job is to allocate the buffer for the _PDC bits. So rename the function to acpi_processor_alloc_pdc(), and just return the struct acpi_object_list * it's supposed to allocate. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index e786e2ce1882..23d2828157e0 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -54,26 +54,24 @@ static void acpi_set_pdc_bits(u32 *buf) arch_acpi_set_pdc_bits(buf); } -static void acpi_processor_init_pdc(struct acpi_processor *pr) +static struct acpi_object_list *acpi_processor_alloc_pdc(void) { struct acpi_object_list *obj_list; union acpi_object *obj; u32 *buf; - pr->pdc = NULL; - /* allocate and initialize pdc. It will be used later. */ obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); if (!obj_list) { printk(KERN_ERR "Memory allocation error\n"); - return; + return NULL; } obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); if (!obj) { printk(KERN_ERR "Memory allocation error\n"); kfree(obj_list); - return; + return NULL; } buf = kmalloc(12, GFP_KERNEL); @@ -81,7 +79,7 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) printk(KERN_ERR "Memory allocation error\n"); kfree(obj); kfree(obj_list); - return; + return NULL; } acpi_set_pdc_bits(buf); @@ -91,9 +89,8 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) obj->buffer.pointer = (u8 *) buf; obj_list->count = 1; obj_list->pointer = obj; - pr->pdc = obj_list; - return; + return obj_list; } /* @@ -142,10 +139,17 @@ static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) void acpi_processor_set_pdc(struct acpi_processor *pr) { + struct acpi_object_list *obj_list; + if (arch_has_acpi_pdc() == false) return; - acpi_processor_init_pdc(pr); + obj_list = acpi_processor_alloc_pdc(); + if (!obj_list) + return; + + pr->pdc = obj_list; + acpi_processor_eval_pdc(pr); acpi_processor_cleanup_pdc(pr); } -- cgit v1.2.3 From fa118564ed66f785f957d8230745b62e9244700d Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:45 -0700 Subject: ACPI: processor: change acpi_processor_eval_pdc interface acpi_processor_eval_pdc() really only needs a handle and an acpi_object_list * to do its work. No need to pass in a struct acpi_processor *, so let's be more specific about what we want. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 23d2828157e0..974de4eb2982 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -97,13 +97,11 @@ static struct acpi_object_list *acpi_processor_alloc_pdc(void) * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. */ -static int acpi_processor_eval_pdc(struct acpi_processor *pr) +static int +acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { - struct acpi_object_list *pdc_in = pr->pdc; acpi_status status = AE_OK; - if (!pdc_in) - return status; if (idle_nomwait) { /* * If mwait is disabled for CPU C-states, the C2C3_FFH access @@ -118,7 +116,7 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); } - status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); + status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); if (ACPI_FAILURE(status)) ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -148,9 +146,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (!obj_list) return; - pr->pdc = obj_list; - - acpi_processor_eval_pdc(pr); + acpi_processor_eval_pdc(pr->handle, obj_list); acpi_processor_cleanup_pdc(pr); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -- cgit v1.2.3 From b9c2db783456bcbce31e2482214cd337528db295 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:23:11 -0700 Subject: ACPI: processor: open code acpi_processor_cleanup_pdc We have the acpi_object_list * right there in acpi_processor_set_pdc() so it doesn't seem necessary for an entire helper function just to free it. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 974de4eb2982..deeba22c932c 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -125,16 +125,6 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) -{ - if (pr->pdc) { - kfree(pr->pdc->pointer->buffer.pointer); - kfree(pr->pdc->pointer); - kfree(pr->pdc); - pr->pdc = NULL; - } -} - void acpi_processor_set_pdc(struct acpi_processor *pr) { struct acpi_object_list *obj_list; @@ -147,7 +137,10 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) return; acpi_processor_eval_pdc(pr->handle, obj_list); - acpi_processor_cleanup_pdc(pr); + + kfree(obj_list->pointer->buffer.pointer); + kfree(obj_list->pointer); + kfree(obj_list); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -- cgit v1.2.3 From 43bab25ced218385f7e6a076c2459ea008cfd2e1 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:23:16 -0700 Subject: ACPI: processor: change acpi_processor_set_pdc() interface When calling _PDC, we really only need the handle to the processor to call the method; we don't look at any other parts of the struct acpi_processor * given to us. In the early path, when we walk the namespace, we are given the handle directly, so just pass it through to acpi_processor_set_pdc() without stuffing it into a wasteful struct acpi_processor allocated on the stack each time This saves 2834 bytes of stack. Update the interface accordingly. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 2 +- drivers/acpi/processor_pdc.c | 18 +++--------------- include/acpi/processor.h | 2 +- 3 files changed, 5 insertions(+), 17 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index a19a4ff962ea..9863c98c81ba 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -763,7 +763,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) } /* _PDC call should be done before doing anything else (if reqd.). */ - acpi_processor_set_pdc(pr); + acpi_processor_set_pdc(pr->handle); #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index deeba22c932c..30e4dc0cdf30 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -125,7 +125,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -void acpi_processor_set_pdc(struct acpi_processor *pr) +void acpi_processor_set_pdc(acpi_handle handle) { struct acpi_object_list *obj_list; @@ -136,7 +136,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (!obj_list) return; - acpi_processor_eval_pdc(pr->handle, obj_list); + acpi_processor_eval_pdc(handle, obj_list); kfree(obj_list->pointer->buffer.pointer); kfree(obj_list->pointer); @@ -147,19 +147,7 @@ EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); static acpi_status early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) { - struct acpi_processor pr; - - pr.handle = handle; - - /* x86 implementation looks at pr.id to determine some - * CPU capabilites. We can just hard code to 0 since we're - * assuming the CPUs in the system are homogenous and all - * have the same capabilities. - */ - pr.id = 0; - - acpi_processor_set_pdc(&pr); - + acpi_processor_set_pdc(handle); return AE_OK; } diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 0873cd57510c..7cc433d69932 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -323,7 +323,7 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) #endif /* CONFIG_CPU_FREQ */ /* in processor_pdc.c */ -void acpi_processor_set_pdc(struct acpi_processor *pr); +void acpi_processor_set_pdc(acpi_handle handle); /* in processor_throttling.c */ int acpi_processor_tstate_has_changed(struct acpi_processor *pr); -- cgit v1.2.3 From 9dc130fccb874f2959ef313d7922d306dc6d4f75 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 23 Dec 2009 17:04:11 +0800 Subject: ACPI: fix OSC regression that caused aer and pciehp not to load Executing _OSC returns a buffer, which has an acpi object in it. Don't directly returns the buffer, instead, we return the acpi object's buffer. This fixes a regression since caller of acpi_run_osc expects an acpi object's buffer returned. Tested-by: Yinghai Lu Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/bus.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 65f7e335f122..0c1ad3105da1 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -397,6 +397,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) union acpi_object *out_obj; u8 uuid[16]; u32 errors; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; if (!context) return AE_ERROR; @@ -419,16 +420,16 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) in_params[3].buffer.length = context->cap.length; in_params[3].buffer.pointer = context->cap.pointer; - status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret); + status = acpi_evaluate_object(handle, "_OSC", &input, &output); if (ACPI_FAILURE(status)) return status; - /* return buffer should have the same length as cap buffer */ - if (context->ret.length != context->cap.length) + if (!output.length) return AE_NULL_OBJECT; - out_obj = context->ret.pointer; - if (out_obj->type != ACPI_TYPE_BUFFER) { + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER + || out_obj->buffer.length != context->cap.length) { acpi_print_osc_error(handle, context, "_OSC evaluation returned wrong type"); status = AE_TYPE; @@ -457,11 +458,20 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) goto out_kfree; } out_success: - return AE_OK; + context->ret.length = out_obj->buffer.length; + context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL); + if (!context->ret.pointer) { + status = AE_NO_MEMORY; + goto out_kfree; + } + memcpy(context->ret.pointer, out_obj->buffer.pointer, + context->ret.length); + status = AE_OK; out_kfree: - kfree(context->ret.pointer); - context->ret.pointer = NULL; + kfree(output.pointer); + if (status != AE_OK) + context->ret.pointer = NULL; return status; } EXPORT_SYMBOL(acpi_run_osc); -- cgit v1.2.3 From a62e8f1978f49e52f87a711ff6711b323d4b12ff Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Thu, 24 Dec 2009 11:34:16 +0300 Subject: ACPI: EC: Accelerate query execution Split EC query handling into acknowledge and execution phase. This allows much smaller pending query lattency and lowers chances of EC going "wild" and losing events. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14858 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 122 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 45 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index fd1801bdee66..9cc38857c33b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -201,14 +201,13 @@ unlock: spin_unlock_irqrestore(&ec->curr_lock, flags); } -static void acpi_ec_gpe_query(void *ec_cxt); +static int acpi_ec_sync_query(struct acpi_ec *ec); -static int ec_check_sci(struct acpi_ec *ec, u8 state) +static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) { if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) - return acpi_os_execute(OSL_EC_BURST_HANDLER, - acpi_ec_gpe_query, ec); + return acpi_ec_sync_query(ec); } return 0; } @@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, { unsigned long tmp; int ret = 0; - pr_debug(PREFIX "transaction start\n"); - /* disable GPE during transaction if storm is detected */ - if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { - acpi_disable_gpe(NULL, ec->gpe); - } if (EC_FLAGS_MSI) udelay(ACPI_EC_MSI_UDELAY); /* start transaction */ @@ -269,16 +263,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, spin_lock_irqsave(&ec->curr_lock, tmp); ec->curr = NULL; spin_unlock_irqrestore(&ec->curr_lock, tmp); - if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { - /* check if we received SCI during transaction */ - ec_check_sci(ec, acpi_ec_read_status(ec)); - /* it is safe to enable GPE outside of transaction */ - acpi_enable_gpe(NULL, ec->gpe); - } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { - pr_info(PREFIX "GPE storm detected, " - "transactions will use polling mode\n"); - set_bit(EC_FLAGS_GPE_STORM, &ec->flags); - } return ret; } @@ -321,7 +305,24 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) status = -ETIME; goto end; } + pr_debug(PREFIX "transaction start\n"); + /* disable GPE during transaction if storm is detected */ + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + acpi_disable_gpe(NULL, ec->gpe); + } + status = acpi_ec_transaction_unlocked(ec, t); + + /* check if we received SCI during transaction */ + ec_check_sci_sync(ec, acpi_ec_read_status(ec)); + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + /* it is safe to enable GPE outside of transaction */ + acpi_enable_gpe(NULL, ec->gpe); + } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { + pr_info(PREFIX "GPE storm detected, " + "transactions will use polling mode\n"); + set_bit(EC_FLAGS_GPE_STORM, &ec->flags); + } end: if (ec->global_lock) acpi_release_global_lock(glk); @@ -443,7 +444,7 @@ int ec_transaction(u8 command, EXPORT_SYMBOL(ec_transaction); -static int acpi_ec_query(struct acpi_ec *ec, u8 * data) +static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) { int result; u8 d; @@ -452,20 +453,16 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) .wlen = 0, .rlen = 1}; if (!ec || !data) return -EINVAL; - /* * Query the EC to find out which _Qxx method we need to evaluate. * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ - - result = acpi_ec_transaction(ec, &t); + result = acpi_ec_transaction_unlocked(ec, &t); if (result) return result; - if (!d) return -ENODATA; - *data = d; return 0; } @@ -509,43 +506,78 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); -static void acpi_ec_gpe_query(void *ec_cxt) +static void acpi_ec_run(void *cxt) { - struct acpi_ec *ec = ec_cxt; - u8 value = 0; - struct acpi_ec_query_handler *handler, copy; - - if (!ec || acpi_ec_query(ec, &value)) + struct acpi_ec_query_handler *handler = cxt; + if (!handler) return; - mutex_lock(&ec->lock); + pr_debug(PREFIX "start query execution\n"); + if (handler->func) + handler->func(handler->data); + else if (handler->handle) + acpi_evaluate_object(handler->handle, NULL, NULL, NULL); + pr_debug(PREFIX "stop query execution\n"); + kfree(handler); +} + +static int acpi_ec_sync_query(struct acpi_ec *ec) +{ + u8 value = 0; + int status; + struct acpi_ec_query_handler *handler, *copy; + if ((status = acpi_ec_query_unlocked(ec, &value))) + return status; list_for_each_entry(handler, &ec->list, node) { if (value == handler->query_bit) { /* have custom handler for this bit */ - memcpy(©, handler, sizeof(copy)); - mutex_unlock(&ec->lock); - if (copy.func) { - copy.func(copy.data); - } else if (copy.handle) { - acpi_evaluate_object(copy.handle, NULL, NULL, NULL); - } - return; + copy = kmalloc(sizeof(*handler), GFP_KERNEL); + if (!copy) + return -ENOMEM; + memcpy(copy, handler, sizeof(*copy)); + pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); + return acpi_os_execute(OSL_GPE_HANDLER, + acpi_ec_run, copy); } } + return 0; +} + +static void acpi_ec_gpe_query(void *ec_cxt) +{ + struct acpi_ec *ec = ec_cxt; + if (!ec) + return; + mutex_lock(&ec->lock); + acpi_ec_sync_query(ec); mutex_unlock(&ec->lock); } +static void acpi_ec_gpe_query(void *ec_cxt); + +static int ec_check_sci(struct acpi_ec *ec, u8 state) +{ + if (state & ACPI_EC_FLAG_SCI) { + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { + pr_debug(PREFIX "push gpe query to the queue\n"); + return acpi_os_execute(OSL_NOTIFY_HANDLER, + acpi_ec_gpe_query, ec); + } + } + return 0; +} + static u32 acpi_ec_gpe_handler(void *data) { struct acpi_ec *ec = data; - u8 status; pr_debug(PREFIX "~~~> interrupt\n"); - status = acpi_ec_read_status(ec); - advance_transaction(ec, status); - if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) + advance_transaction(ec, acpi_ec_read_status(ec)); + if (ec_transaction_done(ec) && + (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { wake_up(&ec->wait); - ec_check_sci(ec, status); + ec_check_sci(ec, acpi_ec_read_status(ec)); + } return ACPI_INTERRUPT_HANDLED; } -- cgit v1.2.3 From 28c32e99bdf5ab838e7179c1aaca5a35a07f2a2b Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 13 Jul 2009 10:33:24 +0800 Subject: ACPI video: no warning message if "acpi_backlight=vendor" is used AML code always sends notifications to ACPI video device, even if we disable the ACPI backlight control by using boot option "acpi_backlight=vendor". In this case we should not print any warning message. http://bugzilla.kernel.org/show_bug.cgi?id=13671#c14 Sigend-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 05dff631591c..3b063a6ac52e 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1979,6 +1979,10 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) unsigned long long level_current, level_next; int result = -EINVAL; + /* no warning message if acpi_backlight=vendor is used */ + if (!acpi_video_backlight_support()) + return 0; + if (!device->brightness) goto out; -- cgit v1.2.3 From e01ce79b7f6ebc5b57128ee058811aa8f9059319 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 29 Jul 2009 08:53:29 +0800 Subject: ACPI video: correct error-handling code backlight_device_register may return an ERR_PTR value rather than a valid pointer. Problem found by Julia Lawall, properly fixed by Zhang Rui. Signed-off-by: Zhang Rui Acked-by: Julia Lawall Signed-off-by: Len Brown --- drivers/acpi/video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 05dff631591c..3f685db1a76d 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -999,8 +999,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) sprintf(name, "acpi_video%d", count++); device->backlight = backlight_device_register(name, NULL, device, &acpi_backlight_ops); - device->backlight->props.max_brightness = device->brightness->count-3; kfree(name); + if (IS_ERR(device->backlight)) + return; + device->backlight->props.max_brightness = device->brightness->count-3; result = sysfs_create_link(&device->backlight->dev.kobj, &device->dev->dev.kobj, "device"); -- cgit v1.2.3 From d7f0eea9e431e1b8b0742a74db1a9490730b2a25 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 30 Dec 2009 15:36:42 +0800 Subject: ACPI: introduce kernel parameter acpi_sleep=sci_force_enable Introduce kernel parameter acpi_sleep=sci_force_enable some laptop requires SCI_EN being set directly on resume, or else they hung somewhere in the resume code path. We already have a blacklist for these laptops but we still need this option, especially when debugging some suspend/resume problems, in case there are systems that need this workaround and are not yet in the blacklist. Signed-off-by: Zhang Rui Acked-by: Rafael J. Wysocki Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 5 ++++- arch/x86/kernel/acpi/sleep.c | 2 ++ drivers/acpi/sleep.c | 29 +++++++++++++++++------------ include/linux/acpi.h | 1 + 4 files changed, 24 insertions(+), 13 deletions(-) (limited to 'drivers/acpi') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 5ba4d9dff113..736d45602886 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -240,7 +240,7 @@ and is between 256 and 4096 characters. It is defined in the file acpi_sleep= [HW,ACPI] Sleep options Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, - old_ordering, s4_nonvs } + old_ordering, s4_nonvs, sci_force_enable } See Documentation/power/video.txt for information on s3_bios and s3_mode. s3_beep is for debugging; it makes the PC's speaker beep @@ -253,6 +253,9 @@ and is between 256 and 4096 characters. It is defined in the file of _PTS is used by default). s4_nonvs prevents the kernel from saving/restoring the ACPI NVS memory during hibernation. + sci_force_enable causes the kernel to set SCI_EN directly + on resume from S1/S3 (which is against the ACPI spec, + but some broken systems don't work without it). acpi_use_timer_override [HW,ACPI] Use timer override. For some broken Nvidia NF5 boards diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 82e508677b91..f9961034e557 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -162,6 +162,8 @@ static int __init acpi_sleep_setup(char *str) #endif if (strncmp(str, "old_ordering", 12) == 0) acpi_old_suspend_ordering(); + if (strncmp(str, "sci_force_enable", 16) == 0) + acpi_set_sci_en_on_resume(); str = strchr(str, ','); if (str != NULL) str += strspn(str, ", \t"); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 5f2c379ab7bf..79d33d908b5a 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -80,6 +80,23 @@ static int acpi_sleep_prepare(u32 acpi_state) #ifdef CONFIG_ACPI_SLEEP static u32 acpi_target_sleep_state = ACPI_STATE_S0; +/* + * According to the ACPI specification the BIOS should make sure that ACPI is + * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, + * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI + * on such systems during resume. Unfortunately that doesn't help in + * particularly pathological cases in which SCI_EN has to be set directly on + * resume, although the specification states very clearly that this flag is + * owned by the hardware. The set_sci_en_on_resume variable will be set in such + * cases. + */ +static bool set_sci_en_on_resume; + +void __init acpi_set_sci_en_on_resume(void) +{ + set_sci_en_on_resume = true; +} + /* * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the * user to request that behavior by using the 'acpi_old_suspend_ordering' @@ -170,18 +187,6 @@ static void acpi_pm_end(void) #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND -/* - * According to the ACPI specification the BIOS should make sure that ACPI is - * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, - * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI - * on such systems during resume. Unfortunately that doesn't help in - * particularly pathological cases in which SCI_EN has to be set directly on - * resume, although the specification states very clearly that this flag is - * owned by the hardware. The set_sci_en_on_resume variable will be set in such - * cases. - */ -static bool set_sci_en_on_resume; - extern void do_suspend_lowlevel(void); static u32 acpi_suspend_states[] = { diff --git a/include/linux/acpi.h b/include/linux/acpi.h index ce945d4845fc..36924255c0d5 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -251,6 +251,7 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n, void __init acpi_no_s4_hw_signature(void); void __init acpi_old_suspend_ordering(void); void __init acpi_s4_no_nvs(void); +void __init acpi_set_sci_en_on_resume(void); #endif /* CONFIG_PM_SLEEP */ struct acpi_osc_context { -- cgit v1.2.3 From 3b8cb427e9281790f36e847e46cb1d005a50cec0 Mon Sep 17 00:00:00 2001 From: Chen Gong Date: Mon, 14 Dec 2009 09:42:28 +0800 Subject: acpi_pad: fix error checks There are some fixes listed below: 1. When met a bogus BIOS, the return value of cpu number maybe is a negative value so that acpi_pad_pur get an unexpected result. 2. the return value of function acpi_pad_idle_cpus is useless. 3. enhance the process of create_power_saving_task/destroy_power_saving_task 4. Add more error checks when evaluating _PUR object. 5. one typo fix Signed-off-by: Chen Gong Acked-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/acpi_pad.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 0d2cdb86158b..a7bd49f0f01f 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -207,7 +207,7 @@ static int power_saving_thread(void *data) * the mechanism only works when all CPUs have RT task running, * as if one CPU hasn't RT task, RT task from other CPUs will * borrow CPU time from this CPU and cause RT task use > 95% - * CPU time. To make 'avoid staration' work, takes a nap here. + * CPU time. To make 'avoid starvation' work, takes a nap here. */ if (do_sleep) schedule_timeout_killable(HZ * idle_pct / 100); @@ -221,14 +221,18 @@ static struct task_struct *ps_tsks[NR_CPUS]; static unsigned int ps_tsk_num; static int create_power_saving_task(void) { + int rc = -ENOMEM; + ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, (void *)(unsigned long)ps_tsk_num, "power_saving/%d", ps_tsk_num); - if (ps_tsks[ps_tsk_num]) { + rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0; + if (!rc) ps_tsk_num++; - return 0; - } - return -EINVAL; + else + ps_tsks[ps_tsk_num] = NULL; + + return rc; } static void destroy_power_saving_task(void) @@ -236,6 +240,7 @@ static void destroy_power_saving_task(void) if (ps_tsk_num > 0) { ps_tsk_num--; kthread_stop(ps_tsks[ps_tsk_num]); + ps_tsks[ps_tsk_num] = NULL; } } @@ -252,7 +257,7 @@ static void set_power_saving_task_num(unsigned int num) } } -static int acpi_pad_idle_cpus(unsigned int num_cpus) +static void acpi_pad_idle_cpus(unsigned int num_cpus) { get_online_cpus(); @@ -260,7 +265,6 @@ static int acpi_pad_idle_cpus(unsigned int num_cpus) set_power_saving_task_num(num_cpus); put_online_cpus(); - return 0; } static uint32_t acpi_pad_idle_cpus_num(void) @@ -368,19 +372,21 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device) static int acpi_pad_pur(acpi_handle handle, int *num_cpus) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_status status; union acpi_object *package; int rev, num, ret = -EINVAL; - status = acpi_evaluate_object(handle, "_PUR", NULL, &buffer); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer))) + return -EINVAL; + + if (!buffer.length || !buffer.pointer) return -EINVAL; + package = buffer.pointer; if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2) goto out; rev = package->package.elements[0].integer.value; num = package->package.elements[1].integer.value; - if (rev != 1) + if (rev != 1 || num < 0) goto out; *num_cpus = num; ret = 0; @@ -409,7 +415,7 @@ static void acpi_pad_ost(acpi_handle handle, int stat, static void acpi_pad_handle_notify(acpi_handle handle) { - int num_cpus, ret; + int num_cpus; uint32_t idle_cpus; mutex_lock(&isolated_cpus_lock); @@ -417,12 +423,9 @@ static void acpi_pad_handle_notify(acpi_handle handle) mutex_unlock(&isolated_cpus_lock); return; } - ret = acpi_pad_idle_cpus(num_cpus); + acpi_pad_idle_cpus(num_cpus); idle_cpus = acpi_pad_idle_cpus_num(); - if (!ret) - acpi_pad_ost(handle, 0, idle_cpus); - else - acpi_pad_ost(handle, 1, 0); + acpi_pad_ost(handle, 0, idle_cpus); mutex_unlock(&isolated_cpus_lock); } -- cgit v1.2.3 From c504f8cb68eb0d6cde53ba043daff8cb34586493 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 30 Dec 2009 15:59:23 +0800 Subject: ACPI video: Prune dupe video devices, unless "video.allow_duplicates" Some buggy BIOS exports multiple ACPI video bus devices for the same VGA controller, and multiple backlight control methods as well. This messes up the ACPI video backlight control. http://bugzilla.kernel.org/show_bug.cgi?id=13577 With this patch applied, only the FIRST ACPI video bus device under a PCI device node is bind to ACPI video driver by default. If the first ACPI video bus device doesn't work well, we can use video.allow_duplicates=1 to go back to the old behavior. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 05dff631591c..45e6a29c8177 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -78,6 +78,13 @@ MODULE_LICENSE("GPL"); static int brightness_switch_enabled = 1; module_param(brightness_switch_enabled, bool, 0644); +/* + * By default, we don't allow duplicate ACPI video bus devices + * under the same VGA controller + */ +static int allow_duplicates; +module_param(allow_duplicates, bool, 0644); + static int register_count = 0; static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); @@ -2233,11 +2240,47 @@ static int acpi_video_resume(struct acpi_device *device) return AE_OK; } +static acpi_status +acpi_video_bus_match(acpi_handle handle, u32 level, void *context, + void **return_value) +{ + struct acpi_device *device = context; + struct acpi_device *sibling; + int result; + + if (handle == device->handle) + return AE_CTRL_TERMINATE; + + result = acpi_bus_get_device(handle, &sibling); + if (result) + return AE_OK; + + if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME)) + return AE_ALREADY_EXISTS; + + return AE_OK; +} + static int acpi_video_bus_add(struct acpi_device *device) { struct acpi_video_bus *video; struct input_dev *input; int error; + acpi_status status; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, + device->parent->handle, 1, + acpi_video_bus_match, NULL, + device, NULL); + if (status == AE_ALREADY_EXISTS) { + printk(KERN_WARNING FW_BUG + "Duplicate ACPI video bus devices for the" + " same VGA controller, please try module " + "parameter \"video.allow_duplicates=1\"" + "if the current driver doesn't work.\n"); + if (!allow_duplicates) + return -ENODEV; + } video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); if (!video) -- cgit v1.2.3 From f5347867c5aea94c625246eaff8f7820b0a4cd8a Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 30 Dec 2009 15:53:03 +0300 Subject: ACPI: SBS: Move SBS HC callback to faster Notify queue SBS transactions should happen in Notify work queue, to not create a dead lock with GPE execution accessing SBS devices. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 ++- drivers/acpi/sbshc.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 9cc38857c33b..047330929821 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -535,7 +535,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec) return -ENOMEM; memcpy(copy, handler, sizeof(*copy)); pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); - return acpi_os_execute(OSL_GPE_HANDLER, + return acpi_os_execute((copy->func) ? + OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, acpi_ec_run, copy); } } diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index d9339806df45..fd09229282ea 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -242,7 +242,7 @@ static int smbus_alarm(void *context) case ACPI_SBS_CHARGER: case ACPI_SBS_MANAGER: case ACPI_SBS_BATTERY: - acpi_os_execute(OSL_GPE_HANDLER, + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_smbus_callback, hc); default:; } -- cgit v1.2.3 From 54070101f86ca9a6e9ba243c999d144721ec3db7 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 30 Dec 2009 15:53:10 +0300 Subject: ACPI: EC: Add wait for irq storm Merge of poll and irq modes accelerated EC transaction, so that keyboard starts to suffer again. Add msleep(1) into transaction path for the storm to allow keyboard controller to do its job. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14747 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 047330929821..d6471bb6852f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -259,7 +259,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); spin_unlock_irqrestore(&ec->curr_lock, tmp); ret = ec_poll(ec); - pr_debug(PREFIX "transaction end\n"); spin_lock_irqsave(&ec->curr_lock, tmp); ec->curr = NULL; spin_unlock_irqrestore(&ec->curr_lock, tmp); @@ -316,6 +315,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) /* check if we received SCI during transaction */ ec_check_sci_sync(ec, acpi_ec_read_status(ec)); if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + msleep(1); /* it is safe to enable GPE outside of transaction */ acpi_enable_gpe(NULL, ec->gpe); } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { @@ -323,6 +323,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } + pr_debug(PREFIX "transaction end\n"); end: if (ec->global_lock) acpi_release_global_lock(glk); -- cgit v1.2.3 From 6a4e2b7503d1f630bface040cf0f5a7aac1fabdb Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 21:29:58 +0800 Subject: ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes If the BIOS pokes the system-wide OSC bits to see if Linux supports evaluating _OST after a _PPC change notification, answer yes. Also, fix an oversight where we neglected to set the OSC bit advertising processor aggregator device support when acpi-pad is compiled as a module. Signed-off-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index cf761b904e4a..a52126e46307 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -490,9 +490,14 @@ static void acpi_bus_osc_support(void) capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ -#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR +#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ + defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; #endif + +#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) + capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; +#endif if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) -- cgit v1.2.3 From 070a24f4d238612bede515023893b18f494774c4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 8 Jan 2010 11:12:41 -0700 Subject: ACPI: Remove unnecessary cast. The struct seq_file 'private' member is a void *, the cast is not needed. Also, remove an extra whitespace line. Signed-off-by: H Hartley Sweeten Signed-off-by: Len Brown --- drivers/acpi/processor_thermal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 140c5c5b423c..6deafb4aa0da 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -443,8 +443,7 @@ struct thermal_cooling_device_ops processor_cooling_ops = { #ifdef CONFIG_ACPI_PROCFS static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = (struct acpi_processor *)seq->private; - + struct acpi_processor *pr = seq->private; if (!pr) goto end; -- cgit v1.2.3 From 7a0b73a49ab56fb1e836675c00d6d0d2ba39a714 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Mon, 28 Dec 2009 10:39:23 -0800 Subject: ACPI: Fix section mismatch error for acpi_early_processor_set_pdc() Alex Chiang introduced acpi_early_processor_set_pdc() in commit: ACPI: processor: call _PDC early 78f1699659963fff97975df44db6d5dbe7218e55 But this results in a section mismatch: WARNING: drivers/acpi/acpi.o(.text+0xa9c1): Section mismatch in reference from the function acpi_early_processor_set_pdc() to the variable .cpuinit.data:processor_idle_dmi_table The function acpi_early_processor_set_pdc() references the variable __cpuinitdata processor_idle_dmi_table. This is often because acpi_early_processor_set_pdc lacks a __cpuinitdata annotation or the annotation of processor_idle_dmi_table is wrong. The only caller of acpi_early_processor_set_pdc() is acpi_bus_init() which is an "__init" function. So the correct fix here is to mark acpi_early_processor_set_pdc() "__init" too. Signed-off-by: Tony Luck Acked-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 30e4dc0cdf30..7d4ee394d0b3 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -151,7 +151,7 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -void acpi_early_processor_set_pdc(void) +void __init acpi_early_processor_set_pdc(void) { /* * Check whether the system is DMI table. If yes, OSPM -- cgit v1.2.3 From c97adf9e7bebf17a86b95e2131bf9ba76c4857c7 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sun, 10 Jan 2010 17:15:36 +0100 Subject: acpi: make ACPI device id constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ids field of the struct acpi_driver is constant in so it is worth to make the initialization data also constant. The semantic match that finds this kind of pattern is as follows: (http://coccinelle.lip6.fr/) // @r@ disable decl_init,const_decl_init; identifier I1, I2, x; @@ struct I1 { ... const struct I2 *x; ... }; @s@ identifier r.I1, y; identifier r.x, E; @@ struct I1 y = { .x = E, }; @c@ identifier r.I2; identifier s.E; @@ const struct I2 E[] = ... ; @depends on !c@ identifier r.I2; identifier s.E; @@ + const struct I2 E[] = ...; // Signed-off-by: Márton Németh Cc: Julia Lawall Cc: cocci@diku.dk Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 2 +- drivers/acpi/pci_root.c | 2 +- drivers/acpi/power.c | 2 +- drivers/acpi/power_meter.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 394ae89409c2..04b0f007c9b7 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -56,7 +56,7 @@ ACPI_MODULE_NAME("pci_link"); static int acpi_pci_link_add(struct acpi_device *device); static int acpi_pci_link_remove(struct acpi_device *device, int type); -static struct acpi_device_id link_device_ids[] = { +static const struct acpi_device_id link_device_ids[] = { {"PNP0C0F", 0}, {"", 0}, }; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 101cce3681d1..64f55b6db73c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -46,7 +46,7 @@ static int acpi_pci_root_add(struct acpi_device *device); static int acpi_pci_root_remove(struct acpi_device *device, int type); static int acpi_pci_root_start(struct acpi_device *device); -static struct acpi_device_id root_device_ids[] = { +static const struct acpi_device_id root_device_ids[] = { {"PNP0A03", 0}, {"", 0}, }; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 22b297916519..0f30c3c1eea4 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -65,7 +65,7 @@ static int acpi_power_remove(struct acpi_device *device, int type); static int acpi_power_resume(struct acpi_device *device); static int acpi_power_open_fs(struct inode *inode, struct file *file); -static struct acpi_device_id power_device_ids[] = { +static const struct acpi_device_id power_device_ids[] = { {ACPI_POWER_HID, 0}, {"", 0}, }; diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index 2ef7030a0c28..ca75c36f754c 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c @@ -64,7 +64,7 @@ static int can_cap_in_hardware(void) return force_cap_on || cap_in_hardware; } -static struct acpi_device_id power_meter_ids[] = { +static const struct acpi_device_id power_meter_ids[] = { {"ACPI000D", 0}, {"", 0}, }; -- cgit v1.2.3 From c19bdb6126a5e1f43b4a4fc3c4b09c926667e5ef Mon Sep 17 00:00:00 2001 From: Rakib Mullick Date: Sun, 3 Jan 2010 19:27:56 +0600 Subject: ACPI: Fix unused variable warning in sbs.c When CONFIG_ACPI_SYSFS_POWER=n and CONFIG_ACPI_PROCFS_POWER=n, then we're warned by the following warning: drivers/acpi/sbs.c: In function `acpi_battery_remove': drivers/acpi/sbs.c:825: warning: unused variable `battery' Signed-off-by: Rakib Mullick Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/sbs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 52b9db8afc20..b16ddbf23a9c 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -822,7 +822,10 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { +#if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER) struct acpi_battery *battery = &sbs->battery[id]; +#endif + #ifdef CONFIG_ACPI_SYSFS_POWER if (battery->bat.dev) { if (battery->have_sysfs_alarm) -- cgit v1.2.3 From 2205cbe8ecaf5f3ab911cef839c94d05ea5b0c76 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Tue, 19 Jan 2010 16:55:41 -0700 Subject: ACPI: processor: restrict early _PDC to opt-in platforms Commit 78f1699 (ACPI: processor: call _PDC early) blindly walks the namespace and calls _PDC on every processor object it finds. This change may cause issues on platforms that declare dummy values for SSDTs on non-present processors (disabled in MADT). When we call _PDC and dynamically attempt to execute the AML Load() op on these dummy SSDTs, there's no telling what might happen. Rather than finding every platform that has bogus SSDTs, restrict early _PDC calls to platforms that are known to need early evaluation of _PDC. This is a minimal, temporary fix (given the context of the current release cycle). A real solution of checking the MADT for non-present processors will be written for the next merge window. References: http://bugzilla.kernel.org/show_bug.cgi?id=14710 http://bugzilla.kernel.org/show_bug.cgi?id=14954 Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 30e4dc0cdf30..f3364371207e 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -144,6 +144,29 @@ void acpi_processor_set_pdc(acpi_handle handle) } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); +static int early_pdc_optin; +static int set_early_pdc_optin(const struct dmi_system_id *id) +{ + early_pdc_optin = 1; + return 0; +} + +static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = { + { + set_early_pdc_optin, "HP Envy", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL}, + { + set_early_pdc_optin, "HP Pavilion dv6", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL}, + { + set_early_pdc_optin, "HP Pavilion dv7", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL}, + {}, +}; + static acpi_status early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) { @@ -159,6 +182,13 @@ void acpi_early_processor_set_pdc(void) */ dmi_check_system(processor_idle_dmi_table); + /* + * Allow systems to opt-in to early _PDC evaluation. + */ + dmi_check_system(early_pdc_optin_table); + if (!early_pdc_optin) + return; + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, early_init_pdc, NULL, NULL, NULL); -- cgit v1.2.3 From 7f07a605a3929d2d94dcbad8ccb7d280958d21f9 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Tue, 12 Jan 2010 23:37:07 +1100 Subject: ACPI: power_meter: remove double kfree() resource->domain_devices can be double kfree()'d in a couple of places. Fix this by setting num_domain_devices = 0 after the kfree(). Coverity CID: 13356, 13355, 13354 Signed-off-by: Darren Jenkins Acked-by: Darrick J. Wong Signed-off-by: Len Brown --- drivers/acpi/power_meter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index ca75c36f754c..dc4ffadf8122 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c @@ -534,6 +534,7 @@ static void remove_domain_devices(struct acpi_power_meter_resource *resource) kfree(resource->domain_devices); kobject_put(resource->holders_dir); + resource->num_domain_devices = 0; } static int read_domain_devices(struct acpi_power_meter_resource *resource) @@ -740,7 +741,6 @@ skip_unsafe_cap: return res; error: - remove_domain_devices(resource); remove_attrs(resource); return res; } -- cgit v1.2.3 From 5d76b6f6c17572e662f5c99c2023adae92100855 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 19 Jan 2010 22:41:14 -0500 Subject: ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C Linux has always ignored ACPI BIOS C2 with exit latency > 100 usec, and the ACPI spec is clear that is correct FADT-supplied C2. However, the ACPI spec explicitly states that _CST-supplied C-states have no latency limits. So move the 100usec C2 test out of the code shared by FADT and _CST code-paths, and into the FADT-specific path. This bug has not been visible until Nehalem, which advertises a CPU-C2 worst case exit latency on servers of 205usec. That (incorrect) figure is being used by BIOS writers on mobile Nehalem systems for the AC configuration. Thus, Linux ignores C2 leaving just C1, which is saves less power, and also impacts performance by preventing the use of turbo mode. http://bugzilla.kernel.org/show_bug.cgi?id=15064 Tested-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d1676b1754d9..8f6da9acc8e4 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -305,6 +305,17 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; + /* + * FADT specified C2 latency must be less than or equal to + * 100 microseconds. + */ + if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency)); + /* invalidate C2 */ + pr->power.states[ACPI_STATE_C2].address = 0; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "lvl2[0x%08x] lvl3[0x%08x]\n", pr->power.states[ACPI_STATE_C2].address, @@ -500,16 +511,6 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) if (!cx->address) return; - /* - * C2 latency must be less than or equal to 100 - * microseconds. - */ - else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "latency too large [%d]\n", cx->latency)); - return; - } - /* * Otherwise we've met all of our C2 requirements. * Normalize the C2 latency to expidite policy -- cgit v1.2.3 From a6d72c189f6c4292ba1a323e8af24083790529f8 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 19 Jan 2010 23:10:04 -0500 Subject: ACPI: allow C3 > 1000usec Do for C3 what the previous patch did for C2. The C2 patch was in response to a highly visible and multiply reported C-state/turbo failure, while this change has no bug report in-hand. This will enable C3 in Linux on systems where BIOS overstates C3 latency in _CST. It will also enable future systems which may actually have C3 > 1000usec. Linux has always ignored ACPI BIOS C3 with exit latency > 1000 usec, and the ACPI spec is clear that is correct FADT-supplied C3. However, the ACPI spec explicitly states that _CST-supplied C-states have no latency limits. So move the 1000usec C3 test out of the code shared by FADT and _CST code-paths, and into the FADT-specific path. Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 8f6da9acc8e4..2c543b42eb1c 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -316,6 +316,17 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) pr->power.states[ACPI_STATE_C2].address = 0; } + /* + * FADT supplied C3 latency must be less than or equal to + * 1000 microseconds. + */ + if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency)); + /* invalidate C3 */ + pr->power.states[ACPI_STATE_C3].address = 0; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "lvl2[0x%08x] lvl3[0x%08x]\n", pr->power.states[ACPI_STATE_C2].address, @@ -532,16 +543,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, if (!cx->address) return; - /* - * C3 latency must be less than or equal to 1000 - * microseconds. - */ - else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "latency too large [%d]\n", cx->latency)); - return; - } - /* * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) * DMA transfers are used by any ISA device to avoid livelock. -- cgit v1.2.3 From d22edd293ff3f1e2d252f164fe2cf744620cb660 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 19 Jan 2010 23:29:09 -0500 Subject: ACPI: delete acpi_processor_power_verify_c2() no functional change -- cleanup only. acpi_processor_power_verify_c2() was nearly empty due to a previous patch, so expand its remains into its one caller and delete it. Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2c543b42eb1c..7c0441f63b39 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -516,23 +516,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) return status; } -static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) -{ - - if (!cx->address) - return; - - /* - * Otherwise we've met all of our C2 requirements. - * Normalize the C2 latency to expidite policy - */ - cx->valid = 1; - - cx->latency_ticks = cx->latency; - - return; -} - static void acpi_processor_power_verify_c3(struct acpi_processor *pr, struct acpi_processor_cx *cx) { @@ -631,7 +614,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) break; case ACPI_STATE_C2: - acpi_processor_power_verify_c2(cx); + if (!cx->address) + break; + cx->valid = 1; + cx->latency_ticks = cx->latency; /* Normalize latency */ break; case ACPI_STATE_C3: -- cgit v1.2.3