diff options
36 files changed, 377 insertions, 211 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 2311dad7a57a..bc3478581f67 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -229,6 +229,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 229 | use by PCI | 229 | use by PCI |
| 230 | Format: <irq>,<irq>... | 230 | Format: <irq>,<irq>... |
| 231 | 231 | ||
| 232 | acpi_no_auto_serialize [HW,ACPI] | ||
| 233 | Disable auto-serialization of AML methods | ||
| 234 | AML control methods that contain the opcodes to create | ||
| 235 | named objects will be marked as "Serialized" by the | ||
| 236 | auto-serialization feature. | ||
| 237 | This feature is enabled by default. | ||
| 238 | This option allows to turn off the feature. | ||
| 239 | |||
| 232 | acpi_no_auto_ssdt [HW,ACPI] Disable automatic loading of SSDT | 240 | acpi_no_auto_ssdt [HW,ACPI] Disable automatic loading of SSDT |
| 233 | 241 | ||
| 234 | acpica_no_return_repair [HW, ACPI] | 242 | acpica_no_return_repair [HW, ACPI] |
| @@ -306,8 +314,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 306 | acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode | 314 | acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode |
| 307 | Format: { level | edge | high | low } | 315 | Format: { level | edge | high | low } |
| 308 | 316 | ||
| 309 | acpi_serialize [HW,ACPI] force serialization of AML methods | ||
| 310 | |||
| 311 | acpi_skip_timer_override [HW,ACPI] | 317 | acpi_skip_timer_override [HW,ACPI] |
| 312 | Recognize and ignore IRQ0/pin2 Interrupt Override. | 318 | Recognize and ignore IRQ0/pin2 Interrupt Override. |
| 313 | For broken nForce2 BIOS resulting in XT-PIC timer. | 319 | For broken nForce2 BIOS resulting in XT-PIC timer. |
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index b6ce00b2be9a..5f96daf8566a 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt | |||
| @@ -232,7 +232,7 @@ defined in include/linux/pm.h: | |||
| 232 | equal to zero); the initial value of it is 1 (i.e. runtime PM is | 232 | equal to zero); the initial value of it is 1 (i.e. runtime PM is |
| 233 | initially disabled for all devices) | 233 | initially disabled for all devices) |
| 234 | 234 | ||
| 235 | unsigned int runtime_error; | 235 | int runtime_error; |
| 236 | - if set, there was a fatal error (one of the callbacks returned error code | 236 | - if set, there was a fatal error (one of the callbacks returned error code |
| 237 | as described in Section 2), so the helper funtions will not work until | 237 | as described in Section 2), so the helper funtions will not work until |
| 238 | this flag is cleared; this is the error code returned by the failing | 238 | this flag is cleared; this is the error code returned by the failing |
| @@ -401,11 +401,11 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: | |||
| 401 | int pm_runtime_disable(struct device *dev); | 401 | int pm_runtime_disable(struct device *dev); |
| 402 | - increment the device's 'power.disable_depth' field (if the value of that | 402 | - increment the device's 'power.disable_depth' field (if the value of that |
| 403 | field was previously zero, this prevents subsystem-level runtime PM | 403 | field was previously zero, this prevents subsystem-level runtime PM |
| 404 | callbacks from being run for the device), make sure that all of the pending | 404 | callbacks from being run for the device), make sure that all of the |
| 405 | runtime PM operations on the device are either completed or canceled; | 405 | pending runtime PM operations on the device are either completed or |
| 406 | returns 1 if there was a resume request pending and it was necessary to | 406 | canceled; returns 1 if there was a resume request pending and it was |
| 407 | execute the subsystem-level resume callback for the device to satisfy that | 407 | necessary to execute the subsystem-level resume callback for the device |
| 408 | request, otherwise 0 is returned | 408 | to satisfy that request, otherwise 0 is returned |
| 409 | 409 | ||
| 410 | int pm_runtime_barrier(struct device *dev); | 410 | int pm_runtime_barrier(struct device *dev); |
| 411 | - check if there's a resume request pending for the device and resume it | 411 | - check if there's a resume request pending for the device and resume it |
| @@ -667,11 +667,11 @@ driver/base/power/generic_ops.c: | |||
| 667 | 667 | ||
| 668 | int pm_generic_runtime_suspend(struct device *dev); | 668 | int pm_generic_runtime_suspend(struct device *dev); |
| 669 | - invoke the ->runtime_suspend() callback provided by the driver of this | 669 | - invoke the ->runtime_suspend() callback provided by the driver of this |
| 670 | device and return its result, or return -EINVAL if not defined | 670 | device and return its result, or return 0 if not defined |
| 671 | 671 | ||
| 672 | int pm_generic_runtime_resume(struct device *dev); | 672 | int pm_generic_runtime_resume(struct device *dev); |
| 673 | - invoke the ->runtime_resume() callback provided by the driver of this | 673 | - invoke the ->runtime_resume() callback provided by the driver of this |
| 674 | device and return its result, or return -EINVAL if not defined | 674 | device and return its result, or return 0 if not defined |
| 675 | 675 | ||
| 676 | int pm_generic_suspend(struct device *dev); | 676 | int pm_generic_suspend(struct device *dev); |
| 677 | - if the device has not been suspended at run time, invoke the ->suspend() | 677 | - if the device has not been suspended at run time, invoke the ->suspend() |
| @@ -727,15 +727,12 @@ driver/base/power/generic_ops.c: | |||
| 727 | int pm_generic_restore_noirq(struct device *dev); | 727 | int pm_generic_restore_noirq(struct device *dev); |
| 728 | - invoke the ->restore_noirq() callback provided by the device's driver | 728 | - invoke the ->restore_noirq() callback provided by the device's driver |
| 729 | 729 | ||
| 730 | These functions can be assigned to the ->runtime_idle(), ->runtime_suspend(), | 730 | These functions are the defaults used by the PM core, if a subsystem doesn't |
| 731 | provide its own callbacks for ->runtime_idle(), ->runtime_suspend(), | ||
| 731 | ->runtime_resume(), ->suspend(), ->suspend_noirq(), ->resume(), | 732 | ->runtime_resume(), ->suspend(), ->suspend_noirq(), ->resume(), |
| 732 | ->resume_noirq(), ->freeze(), ->freeze_noirq(), ->thaw(), ->thaw_noirq(), | 733 | ->resume_noirq(), ->freeze(), ->freeze_noirq(), ->thaw(), ->thaw_noirq(), |
| 733 | ->poweroff(), ->poweroff_noirq(), ->restore(), ->restore_noirq() callback | 734 | ->poweroff(), ->poweroff_noirq(), ->restore(), ->restore_noirq() in the |
| 734 | pointers in the subsystem-level dev_pm_ops structures. | 735 | subsystem-level dev_pm_ops structure. |
| 735 | |||
| 736 | If a subsystem wishes to use all of them at the same time, it can simply assign | ||
| 737 | the GENERIC_SUBSYS_PM_OPS macro, defined in include/linux/pm.h, to its | ||
| 738 | dev_pm_ops structure pointer. | ||
| 739 | 736 | ||
| 740 | Device drivers that wish to use the same function as a system suspend, freeze, | 737 | Device drivers that wish to use the same function as a system suspend, freeze, |
| 741 | poweroff and runtime suspend callback, and similarly for system resume, thaw, | 738 | poweroff and runtime suspend callback, and similarly for system resume, thaw, |
| @@ -873,7 +870,7 @@ Here is a schematic pseudo-code example: | |||
| 873 | foo->is_suspended = 0; | 870 | foo->is_suspended = 0; |
| 874 | pm_runtime_mark_last_busy(&foo->dev); | 871 | pm_runtime_mark_last_busy(&foo->dev); |
| 875 | if (foo->num_pending_requests > 0) | 872 | if (foo->num_pending_requests > 0) |
| 876 | foo_process_requests(foo); | 873 | foo_process_next_request(foo); |
| 877 | unlock(&foo->private_lock); | 874 | unlock(&foo->private_lock); |
| 878 | return 0; | 875 | return 0; |
| 879 | } | 876 | } |
diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h index 5b472c43c31d..d3e2cc395d7f 100644 --- a/drivers/acpi/acpica/acdispat.h +++ b/drivers/acpi/acpica/acdispat.h | |||
| @@ -139,20 +139,21 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
| 139 | struct acpi_walk_state *walk_state); | 139 | struct acpi_walk_state *walk_state); |
| 140 | 140 | ||
| 141 | /* | 141 | /* |
| 142 | * dsload - Parser/Interpreter interface, pass 1 namespace load callbacks | 142 | * dsload - Parser/Interpreter interface |
| 143 | */ | 143 | */ |
| 144 | acpi_status | 144 | acpi_status |
| 145 | acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number); | 145 | acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number); |
| 146 | 146 | ||
| 147 | /* dsload - pass 1 namespace load callbacks */ | ||
| 148 | |||
| 147 | acpi_status | 149 | acpi_status |
| 148 | acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state, | 150 | acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state, |
| 149 | union acpi_parse_object **out_op); | 151 | union acpi_parse_object **out_op); |
| 150 | 152 | ||
| 151 | acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state); | 153 | acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state); |
| 152 | 154 | ||
| 153 | /* | 155 | /* dsload - pass 2 namespace load callbacks */ |
| 154 | * dsload - Parser/Interpreter interface, pass 2 namespace load callbacks | 156 | |
| 155 | */ | ||
| 156 | acpi_status | 157 | acpi_status |
| 157 | acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, | 158 | acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, |
| 158 | union acpi_parse_object **out_op); | 159 | union acpi_parse_object **out_op); |
| @@ -200,7 +201,9 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state); | |||
| 200 | /* | 201 | /* |
| 201 | * dsmethod - Parser/Interpreter interface - control method parsing | 202 | * dsmethod - Parser/Interpreter interface - control method parsing |
| 202 | */ | 203 | */ |
| 203 | acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node); | 204 | acpi_status |
| 205 | acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, | ||
| 206 | union acpi_operand_object *obj_desc); | ||
| 204 | 207 | ||
| 205 | acpi_status | 208 | acpi_status |
| 206 | acpi_ds_call_control_method(struct acpi_thread_state *thread, | 209 | acpi_ds_call_control_method(struct acpi_thread_state *thread, |
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 8f40bb972ae3..49bbc71fad54 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h | |||
| @@ -93,12 +93,13 @@ | |||
| 93 | ACPI_INIT_GLOBAL(u8, acpi_gbl_enable_interpreter_slack, FALSE); | 93 | ACPI_INIT_GLOBAL(u8, acpi_gbl_enable_interpreter_slack, FALSE); |
| 94 | 94 | ||
| 95 | /* | 95 | /* |
| 96 | * Automatically serialize ALL control methods? Default is FALSE, meaning | 96 | * Automatically serialize all methods that create named objects? Default |
| 97 | * to use the Serialized/not_serialized method flags on a per method basis. | 97 | * is TRUE, meaning that all non_serialized methods are scanned once at |
| 98 | * Only change this if the ASL code is poorly written and cannot handle | 98 | * table load time to determine those that create named objects. Methods |
| 99 | * reentrancy even though methods are marked "NotSerialized". | 99 | * that create named objects are marked Serialized in order to prevent |
| 100 | * possible run-time problems if they are entered by more than one thread. | ||
| 100 | */ | 101 | */ |
| 101 | ACPI_INIT_GLOBAL(u8, acpi_gbl_all_methods_serialized, FALSE); | 102 | ACPI_INIT_GLOBAL(u8, acpi_gbl_auto_serialize_methods, TRUE); |
| 102 | 103 | ||
| 103 | /* | 104 | /* |
| 104 | * Create the predefined _OSI method in the namespace? Default is TRUE | 105 | * Create the predefined _OSI method in the namespace? Default is TRUE |
diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index c54267748be5..b01f71ce0523 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h | |||
| @@ -458,10 +458,6 @@ void acpi_ex_enter_interpreter(void); | |||
| 458 | 458 | ||
| 459 | void acpi_ex_exit_interpreter(void); | 459 | void acpi_ex_exit_interpreter(void); |
| 460 | 460 | ||
| 461 | void acpi_ex_reacquire_interpreter(void); | ||
| 462 | |||
| 463 | void acpi_ex_relinquish_interpreter(void); | ||
| 464 | |||
| 465 | u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); | 461 | u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); |
| 466 | 462 | ||
| 467 | void acpi_ex_acquire_global_lock(u32 rule); | 463 | void acpi_ex_acquire_global_lock(u32 rule); |
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 1a4d61805ebc..22fb6449d3d6 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h | |||
| @@ -193,7 +193,8 @@ struct acpi_object_method { | |||
| 193 | #define ACPI_METHOD_INTERNAL_ONLY 0x02 /* Method is implemented internally (_OSI) */ | 193 | #define ACPI_METHOD_INTERNAL_ONLY 0x02 /* Method is implemented internally (_OSI) */ |
| 194 | #define ACPI_METHOD_SERIALIZED 0x04 /* Method is serialized */ | 194 | #define ACPI_METHOD_SERIALIZED 0x04 /* Method is serialized */ |
| 195 | #define ACPI_METHOD_SERIALIZED_PENDING 0x08 /* Method is to be marked serialized */ | 195 | #define ACPI_METHOD_SERIALIZED_PENDING 0x08 /* Method is to be marked serialized */ |
| 196 | #define ACPI_METHOD_MODIFIED_NAMESPACE 0x10 /* Method modified the namespace */ | 196 | #define ACPI_METHOD_IGNORE_SYNC_LEVEL 0x10 /* Method was auto-serialized at table load time */ |
| 197 | #define ACPI_METHOD_MODIFIED_NAMESPACE 0x20 /* Method modified the namespace */ | ||
| 197 | 198 | ||
| 198 | /****************************************************************************** | 199 | /****************************************************************************** |
| 199 | * | 200 | * |
diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h index 5d2989a1b68c..cf7346110bd8 100644 --- a/drivers/acpi/acpica/acstruct.h +++ b/drivers/acpi/acpica/acstruct.h | |||
| @@ -133,6 +133,9 @@ struct acpi_init_walk_info { | |||
| 133 | u32 table_index; | 133 | u32 table_index; |
| 134 | u32 object_count; | 134 | u32 object_count; |
| 135 | u32 method_count; | 135 | u32 method_count; |
| 136 | u32 serial_method_count; | ||
| 137 | u32 non_serial_method_count; | ||
| 138 | u32 serialized_method_count; | ||
| 136 | u32 device_count; | 139 | u32 device_count; |
| 137 | u32 op_region_count; | 140 | u32 op_region_count; |
| 138 | u32 field_count; | 141 | u32 field_count; |
diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index 96644d5ac0e1..aee5e45f6d35 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c | |||
| @@ -83,8 +83,8 @@ acpi_ds_init_one_object(acpi_handle obj_handle, | |||
| 83 | (struct acpi_init_walk_info *)context; | 83 | (struct acpi_init_walk_info *)context; |
| 84 | struct acpi_namespace_node *node = | 84 | struct acpi_namespace_node *node = |
| 85 | (struct acpi_namespace_node *)obj_handle; | 85 | (struct acpi_namespace_node *)obj_handle; |
| 86 | acpi_object_type type; | ||
| 87 | acpi_status status; | 86 | acpi_status status; |
| 87 | union acpi_operand_object *obj_desc; | ||
| 88 | 88 | ||
| 89 | ACPI_FUNCTION_ENTRY(); | 89 | ACPI_FUNCTION_ENTRY(); |
| 90 | 90 | ||
| @@ -100,9 +100,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle, | |||
| 100 | 100 | ||
| 101 | /* And even then, we are only interested in a few object types */ | 101 | /* And even then, we are only interested in a few object types */ |
| 102 | 102 | ||
| 103 | type = acpi_ns_get_type(obj_handle); | 103 | switch (acpi_ns_get_type(obj_handle)) { |
| 104 | |||
| 105 | switch (type) { | ||
| 106 | case ACPI_TYPE_REGION: | 104 | case ACPI_TYPE_REGION: |
| 107 | 105 | ||
| 108 | status = acpi_ds_initialize_region(obj_handle); | 106 | status = acpi_ds_initialize_region(obj_handle); |
| @@ -117,8 +115,44 @@ acpi_ds_init_one_object(acpi_handle obj_handle, | |||
| 117 | break; | 115 | break; |
| 118 | 116 | ||
| 119 | case ACPI_TYPE_METHOD: | 117 | case ACPI_TYPE_METHOD: |
| 120 | 118 | /* | |
| 119 | * Auto-serialization support. We will examine each method that is | ||
| 120 | * not_serialized to determine if it creates any Named objects. If | ||
| 121 | * it does, it will be marked serialized to prevent problems if | ||
| 122 | * the method is entered by two or more threads and an attempt is | ||
| 123 | * made to create the same named object twice -- which results in | ||
| 124 | * an AE_ALREADY_EXISTS exception and method abort. | ||
| 125 | */ | ||
| 121 | info->method_count++; | 126 | info->method_count++; |
| 127 | obj_desc = acpi_ns_get_attached_object(node); | ||
| 128 | if (!obj_desc) { | ||
| 129 | break; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* Ignore if already serialized */ | ||
| 133 | |||
| 134 | if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) { | ||
| 135 | info->serial_method_count++; | ||
| 136 | break; | ||
| 137 | } | ||
| 138 | |||
| 139 | if (acpi_gbl_auto_serialize_methods) { | ||
| 140 | |||
| 141 | /* Parse/scan method and serialize it if necessary */ | ||
| 142 | |||
| 143 | acpi_ds_auto_serialize_method(node, obj_desc); | ||
| 144 | if (obj_desc->method. | ||
| 145 | info_flags & ACPI_METHOD_SERIALIZED) { | ||
| 146 | |||
| 147 | /* Method was just converted to Serialized */ | ||
| 148 | |||
| 149 | info->serial_method_count++; | ||
| 150 | info->serialized_method_count++; | ||
| 151 | break; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | info->non_serial_method_count++; | ||
| 122 | break; | 156 | break; |
| 123 | 157 | ||
| 124 | case ACPI_TYPE_DEVICE: | 158 | case ACPI_TYPE_DEVICE: |
| @@ -170,7 +204,6 @@ acpi_ds_initialize_objects(u32 table_index, | |||
| 170 | 204 | ||
| 171 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 205 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
| 172 | "**** Starting initialization of namespace objects ****\n")); | 206 | "**** Starting initialization of namespace objects ****\n")); |
| 173 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:")); | ||
| 174 | 207 | ||
| 175 | /* Set all init info to zero */ | 208 | /* Set all init info to zero */ |
| 176 | 209 | ||
| @@ -205,14 +238,16 @@ acpi_ds_initialize_objects(u32 table_index, | |||
| 205 | } | 238 | } |
| 206 | 239 | ||
| 207 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, | 240 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, |
| 208 | "\nTable [%4.4s](id %4.4X) - %u Objects with %u Devices %u Methods %u Regions\n", | 241 | "Table [%4.4s] (id %4.4X) - %4u Objects with %3u Devices, " |
| 242 | "%3u Regions, %3u Methods (%u/%u/%u Serial/Non/Cvt)\n", | ||
| 209 | table->signature, owner_id, info.object_count, | 243 | table->signature, owner_id, info.object_count, |
| 210 | info.device_count, info.method_count, | 244 | info.device_count, info.op_region_count, |
| 211 | info.op_region_count)); | 245 | info.method_count, info.serial_method_count, |
| 246 | info.non_serial_method_count, | ||
| 247 | info.serialized_method_count)); | ||
| 212 | 248 | ||
| 213 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 249 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "%u Methods, %u Regions\n", |
| 214 | "%u Methods, %u Regions\n", info.method_count, | 250 | info.method_count, info.op_region_count)); |
| 215 | info.op_region_count)); | ||
| 216 | 251 | ||
| 217 | return_ACPI_STATUS(AE_OK); | 252 | return_ACPI_STATUS(AE_OK); |
| 218 | } | 253 | } |
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index 2c6d42c2bc01..3c7f7378b94d 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c | |||
| @@ -49,16 +49,155 @@ | |||
| 49 | #ifdef ACPI_DISASSEMBLER | 49 | #ifdef ACPI_DISASSEMBLER |
| 50 | #include "acdisasm.h" | 50 | #include "acdisasm.h" |
| 51 | #endif | 51 | #endif |
| 52 | #include "acparser.h" | ||
| 53 | #include "amlcode.h" | ||
| 52 | 54 | ||
| 53 | #define _COMPONENT ACPI_DISPATCHER | 55 | #define _COMPONENT ACPI_DISPATCHER |
| 54 | ACPI_MODULE_NAME("dsmethod") | 56 | ACPI_MODULE_NAME("dsmethod") |
| 55 | 57 | ||
| 56 | /* Local prototypes */ | 58 | /* Local prototypes */ |
| 57 | static acpi_status | 59 | static acpi_status |
| 60 | acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state, | ||
| 61 | union acpi_parse_object **out_op); | ||
| 62 | |||
| 63 | static acpi_status | ||
| 58 | acpi_ds_create_method_mutex(union acpi_operand_object *method_desc); | 64 | acpi_ds_create_method_mutex(union acpi_operand_object *method_desc); |
| 59 | 65 | ||
| 60 | /******************************************************************************* | 66 | /******************************************************************************* |
| 61 | * | 67 | * |
| 68 | * FUNCTION: acpi_ds_auto_serialize_method | ||
| 69 | * | ||
| 70 | * PARAMETERS: node - Namespace Node of the method | ||
| 71 | * obj_desc - Method object attached to node | ||
| 72 | * | ||
| 73 | * RETURN: Status | ||
| 74 | * | ||
| 75 | * DESCRIPTION: Parse a control method AML to scan for control methods that | ||
| 76 | * need serialization due to the creation of named objects. | ||
| 77 | * | ||
| 78 | * NOTE: It is a bit of overkill to mark all such methods serialized, since | ||
| 79 | * there is only a problem if the method actually blocks during execution. | ||
| 80 | * A blocking operation is, for example, a Sleep() operation, or any access | ||
| 81 | * to an operation region. However, it is probably not possible to easily | ||
| 82 | * detect whether a method will block or not, so we simply mark all suspicious | ||
| 83 | * methods as serialized. | ||
| 84 | * | ||
| 85 | * NOTE2: This code is essentially a generic routine for parsing a single | ||
| 86 | * control method. | ||
| 87 | * | ||
| 88 | ******************************************************************************/ | ||
| 89 | |||
| 90 | acpi_status | ||
| 91 | acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, | ||
| 92 | union acpi_operand_object *obj_desc) | ||
| 93 | { | ||
| 94 | acpi_status status; | ||
| 95 | union acpi_parse_object *op = NULL; | ||
| 96 | struct acpi_walk_state *walk_state; | ||
| 97 | |||
| 98 | ACPI_FUNCTION_TRACE_PTR(ds_auto_serialize_method, node); | ||
| 99 | |||
| 100 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | ||
| 101 | "Method auto-serialization parse [%4.4s] %p\n", | ||
| 102 | acpi_ut_get_node_name(node), node)); | ||
| 103 | |||
| 104 | /* Create/Init a root op for the method parse tree */ | ||
| 105 | |||
| 106 | op = acpi_ps_alloc_op(AML_METHOD_OP); | ||
| 107 | if (!op) { | ||
| 108 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
| 109 | } | ||
| 110 | |||
| 111 | acpi_ps_set_name(op, node->name.integer); | ||
| 112 | op->common.node = node; | ||
| 113 | |||
| 114 | /* Create and initialize a new walk state */ | ||
| 115 | |||
| 116 | walk_state = | ||
| 117 | acpi_ds_create_walk_state(node->owner_id, NULL, NULL, NULL); | ||
| 118 | if (!walk_state) { | ||
| 119 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
| 120 | } | ||
| 121 | |||
| 122 | status = | ||
| 123 | acpi_ds_init_aml_walk(walk_state, op, node, | ||
| 124 | obj_desc->method.aml_start, | ||
| 125 | obj_desc->method.aml_length, NULL, 0); | ||
| 126 | if (ACPI_FAILURE(status)) { | ||
| 127 | acpi_ds_delete_walk_state(walk_state); | ||
| 128 | return_ACPI_STATUS(status); | ||
| 129 | } | ||
| 130 | |||
| 131 | walk_state->descending_callback = acpi_ds_detect_named_opcodes; | ||
| 132 | |||
| 133 | /* Parse the method, scan for creation of named objects */ | ||
| 134 | |||
| 135 | status = acpi_ps_parse_aml(walk_state); | ||
| 136 | if (ACPI_FAILURE(status)) { | ||
| 137 | return_ACPI_STATUS(status); | ||
| 138 | } | ||
| 139 | |||
| 140 | acpi_ps_delete_parse_tree(op); | ||
| 141 | return_ACPI_STATUS(status); | ||
| 142 | } | ||
| 143 | |||
| 144 | /******************************************************************************* | ||
| 145 | * | ||
| 146 | * FUNCTION: acpi_ds_detect_named_opcodes | ||
| 147 | * | ||
| 148 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
| 149 | * out_op - Unused, required for parser interface | ||
| 150 | * | ||
| 151 | * RETURN: Status | ||
| 152 | * | ||
| 153 | * DESCRIPTION: Descending callback used during the loading of ACPI tables. | ||
| 154 | * Currently used to detect methods that must be marked serialized | ||
| 155 | * in order to avoid problems with the creation of named objects. | ||
| 156 | * | ||
| 157 | ******************************************************************************/ | ||
| 158 | |||
| 159 | static acpi_status | ||
| 160 | acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state, | ||
| 161 | union acpi_parse_object **out_op) | ||
| 162 | { | ||
| 163 | |||
| 164 | ACPI_FUNCTION_NAME(acpi_ds_detect_named_opcodes); | ||
| 165 | |||
| 166 | /* We are only interested in opcodes that create a new name */ | ||
| 167 | |||
| 168 | if (! | ||
| 169 | (walk_state->op_info-> | ||
| 170 | flags & (AML_NAMED | AML_CREATE | AML_FIELD))) { | ||
| 171 | return (AE_OK); | ||
| 172 | } | ||
| 173 | |||
| 174 | /* | ||
| 175 | * At this point, we know we have a Named object opcode. | ||
| 176 | * Mark the method as serialized. Later code will create a mutex for | ||
| 177 | * this method to enforce serialization. | ||
| 178 | * | ||
| 179 | * Note, ACPI_METHOD_IGNORE_SYNC_LEVEL flag means that we will ignore the | ||
| 180 | * Sync Level mechanism for this method, even though it is now serialized. | ||
| 181 | * Otherwise, there can be conflicts with existing ASL code that actually | ||
| 182 | * uses sync levels. | ||
| 183 | */ | ||
| 184 | walk_state->method_desc->method.sync_level = 0; | ||
| 185 | walk_state->method_desc->method.info_flags |= | ||
| 186 | (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL); | ||
| 187 | |||
| 188 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 189 | "Method serialized [%4.4s] %p - [%s] (%4.4X)\n", | ||
| 190 | walk_state->method_node->name.ascii, | ||
| 191 | walk_state->method_node, walk_state->op_info->name, | ||
| 192 | walk_state->opcode)); | ||
| 193 | |||
| 194 | /* Abort the parse, no need to examine this method any further */ | ||
| 195 | |||
| 196 | return (AE_CTRL_TERMINATE); | ||
| 197 | } | ||
| 198 | |||
| 199 | /******************************************************************************* | ||
| 200 | * | ||
| 62 | * FUNCTION: acpi_ds_method_error | 201 | * FUNCTION: acpi_ds_method_error |
| 63 | * | 202 | * |
| 64 | * PARAMETERS: status - Execution status | 203 | * PARAMETERS: status - Execution status |
| @@ -74,7 +213,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc); | |||
| 74 | ******************************************************************************/ | 213 | ******************************************************************************/ |
| 75 | 214 | ||
| 76 | acpi_status | 215 | acpi_status |
| 77 | acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) | 216 | acpi_ds_method_error(acpi_status status, struct acpi_walk_state * walk_state) |
| 78 | { | 217 | { |
| 79 | ACPI_FUNCTION_ENTRY(); | 218 | ACPI_FUNCTION_ENTRY(); |
| 80 | 219 | ||
| @@ -217,13 +356,19 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, | |||
| 217 | /* | 356 | /* |
| 218 | * The current_sync_level (per-thread) must be less than or equal to | 357 | * The current_sync_level (per-thread) must be less than or equal to |
| 219 | * the sync level of the method. This mechanism provides some | 358 | * the sync level of the method. This mechanism provides some |
| 220 | * deadlock prevention | 359 | * deadlock prevention. |
| 360 | * | ||
| 361 | * If the method was auto-serialized, we just ignore the sync level | ||
| 362 | * mechanism, because auto-serialization of methods can interfere | ||
| 363 | * with ASL code that actually uses sync levels. | ||
| 221 | * | 364 | * |
| 222 | * Top-level method invocation has no walk state at this point | 365 | * Top-level method invocation has no walk state at this point |
| 223 | */ | 366 | */ |
| 224 | if (walk_state && | 367 | if (walk_state && |
| 225 | (walk_state->thread->current_sync_level > | 368 | (!(obj_desc->method. |
| 226 | obj_desc->method.mutex->mutex.sync_level)) { | 369 | info_flags & ACPI_METHOD_IGNORE_SYNC_LEVEL)) |
| 370 | && (walk_state->thread->current_sync_level > | ||
| 371 | obj_desc->method.mutex->mutex.sync_level)) { | ||
| 227 | ACPI_ERROR((AE_INFO, | 372 | ACPI_ERROR((AE_INFO, |
| 228 | "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)", | 373 | "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)", |
| 229 | acpi_ut_get_node_name(method_node), | 374 | acpi_ut_get_node_name(method_node), |
| @@ -668,7 +813,8 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
| 668 | method_desc->method.info_flags &= | 813 | method_desc->method.info_flags &= |
| 669 | ~ACPI_METHOD_SERIALIZED_PENDING; | 814 | ~ACPI_METHOD_SERIALIZED_PENDING; |
| 670 | method_desc->method.info_flags |= | 815 | method_desc->method.info_flags |= |
| 671 | ACPI_METHOD_SERIALIZED; | 816 | (ACPI_METHOD_SERIALIZED | |
| 817 | ACPI_METHOD_IGNORE_SYNC_LEVEL); | ||
| 672 | method_desc->method.sync_level = 0; | 818 | method_desc->method.sync_level = 0; |
| 673 | } | 819 | } |
| 674 | 820 | ||
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index bd7811c64169..15623da26200 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c | |||
| @@ -73,8 +73,20 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) | |||
| 73 | { | 73 | { |
| 74 | 74 | ||
| 75 | switch (pass_number) { | 75 | switch (pass_number) { |
| 76 | case 0: | ||
| 77 | |||
| 78 | /* Parse only - caller will setup callbacks */ | ||
| 79 | |||
| 80 | walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | | ||
| 81 | ACPI_PARSE_DELETE_TREE | ACPI_PARSE_DISASSEMBLE; | ||
| 82 | walk_state->descending_callback = NULL; | ||
| 83 | walk_state->ascending_callback = NULL; | ||
| 84 | break; | ||
| 85 | |||
| 76 | case 1: | 86 | case 1: |
| 77 | 87 | ||
| 88 | /* Load pass 1 */ | ||
| 89 | |||
| 78 | walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | | 90 | walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | |
| 79 | ACPI_PARSE_DELETE_TREE; | 91 | ACPI_PARSE_DELETE_TREE; |
| 80 | walk_state->descending_callback = acpi_ds_load1_begin_op; | 92 | walk_state->descending_callback = acpi_ds_load1_begin_op; |
| @@ -83,6 +95,8 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) | |||
| 83 | 95 | ||
| 84 | case 2: | 96 | case 2: |
| 85 | 97 | ||
| 98 | /* Load pass 2 */ | ||
| 99 | |||
| 86 | walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | | 100 | walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | |
| 87 | ACPI_PARSE_DELETE_TREE; | 101 | ACPI_PARSE_DELETE_TREE; |
| 88 | walk_state->descending_callback = acpi_ds_load2_begin_op; | 102 | walk_state->descending_callback = acpi_ds_load2_begin_op; |
| @@ -91,6 +105,8 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) | |||
| 91 | 105 | ||
| 92 | case 3: | 106 | case 3: |
| 93 | 107 | ||
| 108 | /* Execution pass */ | ||
| 109 | |||
| 94 | #ifndef ACPI_NO_METHOD_EXECUTION | 110 | #ifndef ACPI_NO_METHOD_EXECUTION |
| 95 | walk_state->parse_flags |= ACPI_PARSE_EXECUTE | | 111 | walk_state->parse_flags |= ACPI_PARSE_EXECUTE | |
| 96 | ACPI_PARSE_DELETE_TREE; | 112 | ACPI_PARSE_DELETE_TREE; |
diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c index 841caed11c08..f7da64123ed5 100644 --- a/drivers/acpi/acpica/exsystem.c +++ b/drivers/acpi/acpica/exsystem.c | |||
| @@ -77,7 +77,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) | |||
| 77 | 77 | ||
| 78 | /* We must wait, so unlock the interpreter */ | 78 | /* We must wait, so unlock the interpreter */ |
| 79 | 79 | ||
| 80 | acpi_ex_relinquish_interpreter(); | 80 | acpi_ex_exit_interpreter(); |
| 81 | 81 | ||
| 82 | status = acpi_os_wait_semaphore(semaphore, 1, timeout); | 82 | status = acpi_os_wait_semaphore(semaphore, 1, timeout); |
| 83 | 83 | ||
| @@ -87,7 +87,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) | |||
| 87 | 87 | ||
| 88 | /* Reacquire the interpreter */ | 88 | /* Reacquire the interpreter */ |
| 89 | 89 | ||
| 90 | acpi_ex_reacquire_interpreter(); | 90 | acpi_ex_enter_interpreter(); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | return_ACPI_STATUS(status); | 93 | return_ACPI_STATUS(status); |
| @@ -123,7 +123,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) | |||
| 123 | 123 | ||
| 124 | /* We must wait, so unlock the interpreter */ | 124 | /* We must wait, so unlock the interpreter */ |
| 125 | 125 | ||
| 126 | acpi_ex_relinquish_interpreter(); | 126 | acpi_ex_exit_interpreter(); |
| 127 | 127 | ||
| 128 | status = acpi_os_acquire_mutex(mutex, timeout); | 128 | status = acpi_os_acquire_mutex(mutex, timeout); |
| 129 | 129 | ||
| @@ -133,7 +133,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) | |||
| 133 | 133 | ||
| 134 | /* Reacquire the interpreter */ | 134 | /* Reacquire the interpreter */ |
| 135 | 135 | ||
| 136 | acpi_ex_reacquire_interpreter(); | 136 | acpi_ex_enter_interpreter(); |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | return_ACPI_STATUS(status); | 139 | return_ACPI_STATUS(status); |
| @@ -198,7 +198,7 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long) | |||
| 198 | 198 | ||
| 199 | /* Since this thread will sleep, we must release the interpreter */ | 199 | /* Since this thread will sleep, we must release the interpreter */ |
| 200 | 200 | ||
| 201 | acpi_ex_relinquish_interpreter(); | 201 | acpi_ex_exit_interpreter(); |
| 202 | 202 | ||
| 203 | /* | 203 | /* |
| 204 | * For compatibility with other ACPI implementations and to prevent | 204 | * For compatibility with other ACPI implementations and to prevent |
| @@ -212,7 +212,7 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long) | |||
| 212 | 212 | ||
| 213 | /* And now we must get the interpreter again */ | 213 | /* And now we must get the interpreter again */ |
| 214 | 214 | ||
| 215 | acpi_ex_reacquire_interpreter(); | 215 | acpi_ex_enter_interpreter(); |
| 216 | return (AE_OK); | 216 | return (AE_OK); |
| 217 | } | 217 | } |
| 218 | 218 | ||
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 5b16c5484bee..d9d72dff2a76 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c | |||
| @@ -100,37 +100,6 @@ void acpi_ex_enter_interpreter(void) | |||
| 100 | 100 | ||
| 101 | /******************************************************************************* | 101 | /******************************************************************************* |
| 102 | * | 102 | * |
| 103 | * FUNCTION: acpi_ex_reacquire_interpreter | ||
| 104 | * | ||
| 105 | * PARAMETERS: None | ||
| 106 | * | ||
| 107 | * RETURN: None | ||
| 108 | * | ||
| 109 | * DESCRIPTION: Reacquire the interpreter execution region from within the | ||
| 110 | * interpreter code. Failure to enter the interpreter region is a | ||
| 111 | * fatal system error. Used in conjunction with | ||
| 112 | * relinquish_interpreter | ||
| 113 | * | ||
| 114 | ******************************************************************************/ | ||
| 115 | |||
| 116 | void acpi_ex_reacquire_interpreter(void) | ||
| 117 | { | ||
| 118 | ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); | ||
| 119 | |||
| 120 | /* | ||
| 121 | * If the global serialized flag is set, do not release the interpreter, | ||
| 122 | * since it was not actually released by acpi_ex_relinquish_interpreter. | ||
| 123 | * This forces the interpreter to be single threaded. | ||
| 124 | */ | ||
| 125 | if (!acpi_gbl_all_methods_serialized) { | ||
| 126 | acpi_ex_enter_interpreter(); | ||
| 127 | } | ||
| 128 | |||
| 129 | return_VOID; | ||
| 130 | } | ||
| 131 | |||
| 132 | /******************************************************************************* | ||
| 133 | * | ||
| 134 | * FUNCTION: acpi_ex_exit_interpreter | 103 | * FUNCTION: acpi_ex_exit_interpreter |
| 135 | * | 104 | * |
| 136 | * PARAMETERS: None | 105 | * PARAMETERS: None |
| @@ -139,7 +108,16 @@ void acpi_ex_reacquire_interpreter(void) | |||
| 139 | * | 108 | * |
| 140 | * DESCRIPTION: Exit the interpreter execution region. This is the top level | 109 | * DESCRIPTION: Exit the interpreter execution region. This is the top level |
| 141 | * routine used to exit the interpreter when all processing has | 110 | * routine used to exit the interpreter when all processing has |
| 142 | * been completed. | 111 | * been completed, or when the method blocks. |
| 112 | * | ||
| 113 | * Cases where the interpreter is unlocked internally: | ||
| 114 | * 1) Method will be blocked on a Sleep() AML opcode | ||
| 115 | * 2) Method will be blocked on an Acquire() AML opcode | ||
| 116 | * 3) Method will be blocked on a Wait() AML opcode | ||
| 117 | * 4) Method will be blocked to acquire the global lock | ||
| 118 | * 5) Method will be blocked waiting to execute a serialized control | ||
| 119 | * method that is currently executing | ||
| 120 | * 6) About to invoke a user-installed opregion handler | ||
| 143 | * | 121 | * |
| 144 | ******************************************************************************/ | 122 | ******************************************************************************/ |
| 145 | 123 | ||
| @@ -160,44 +138,6 @@ void acpi_ex_exit_interpreter(void) | |||
| 160 | 138 | ||
| 161 | /******************************************************************************* | 139 | /******************************************************************************* |
| 162 | * | 140 | * |
| 163 | * FUNCTION: acpi_ex_relinquish_interpreter | ||
| 164 | * | ||
| 165 | * PARAMETERS: None | ||
| 166 | * | ||
| 167 | * RETURN: None | ||
| 168 | * | ||
| 169 | * DESCRIPTION: Exit the interpreter execution region, from within the | ||
| 170 | * interpreter - before attempting an operation that will possibly | ||
| 171 | * block the running thread. | ||
| 172 | * | ||
| 173 | * Cases where the interpreter is unlocked internally | ||
| 174 | * 1) Method to be blocked on a Sleep() AML opcode | ||
| 175 | * 2) Method to be blocked on an Acquire() AML opcode | ||
| 176 | * 3) Method to be blocked on a Wait() AML opcode | ||
| 177 | * 4) Method to be blocked to acquire the global lock | ||
| 178 | * 5) Method to be blocked waiting to execute a serialized control method | ||
| 179 | * that is currently executing | ||
| 180 | * 6) About to invoke a user-installed opregion handler | ||
| 181 | * | ||
| 182 | ******************************************************************************/ | ||
| 183 | |||
| 184 | void acpi_ex_relinquish_interpreter(void) | ||
| 185 | { | ||
| 186 | ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); | ||
| 187 | |||
| 188 | /* | ||
| 189 | * If the global serialized flag is set, do not release the interpreter. | ||
| 190 | * This forces the interpreter to be single threaded. | ||
| 191 | */ | ||
| 192 | if (!acpi_gbl_all_methods_serialized) { | ||
| 193 | acpi_ex_exit_interpreter(); | ||
| 194 | } | ||
| 195 | |||
| 196 | return_VOID; | ||
| 197 | } | ||
| 198 | |||
| 199 | /******************************************************************************* | ||
| 200 | * | ||
| 201 | * FUNCTION: acpi_ex_truncate_for32bit_table | 141 | * FUNCTION: acpi_ex_truncate_for32bit_table |
| 202 | * | 142 | * |
| 203 | * PARAMETERS: obj_desc - Object to be truncated | 143 | * PARAMETERS: obj_desc - Object to be truncated |
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 5b74677bf74d..a3fb7e4c0809 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c | |||
| @@ -111,9 +111,8 @@ acpi_status acpi_ns_initialize_objects(void) | |||
| 111 | info.object_count)); | 111 | info.object_count)); |
| 112 | 112 | ||
| 113 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 113 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
| 114 | "%u Control Methods found\n", info.method_count)); | 114 | "%u Control Methods found\n%u Op Regions found\n", |
| 115 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 115 | info.method_count, info.op_region_count)); |
| 116 | "%u Op Regions found\n", info.op_region_count)); | ||
| 117 | 116 | ||
| 118 | return_ACPI_STATUS(AE_OK); | 117 | return_ACPI_STATUS(AE_OK); |
| 119 | } | 118 | } |
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index 7ae521ce8d3f..7c9d0181f341 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c | |||
| @@ -128,12 +128,12 @@ unlock: | |||
| 128 | * parse trees. | 128 | * parse trees. |
| 129 | */ | 129 | */ |
| 130 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 130 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 131 | "**** Begin Table Method Parsing and Object Initialization\n")); | 131 | "**** Begin Table Object Initialization\n")); |
| 132 | 132 | ||
| 133 | status = acpi_ds_initialize_objects(table_index, node); | 133 | status = acpi_ds_initialize_objects(table_index, node); |
| 134 | 134 | ||
| 135 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 135 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 136 | "**** Completed Table Method Parsing and Object Initialization\n")); | 136 | "**** Completed Table Object Initialization\n")); |
| 137 | 137 | ||
| 138 | return_ACPI_STATUS(status); | 138 | return_ACPI_STATUS(status); |
| 139 | } | 139 | } |
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index 646d1a3f6e27..b058e2390fdd 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c | |||
| @@ -480,6 +480,10 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) | |||
| 480 | status = AE_OK; | 480 | status = AE_OK; |
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | if (status == AE_CTRL_TERMINATE) { | ||
| 484 | return_ACPI_STATUS(status); | ||
| 485 | } | ||
| 486 | |||
| 483 | status = | 487 | status = |
| 484 | acpi_ps_complete_op(walk_state, &op, | 488 | acpi_ps_complete_op(walk_state, &op, |
| 485 | status); | 489 | status); |
diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c index af1f46cd37a5..a6885077d59e 100644 --- a/drivers/acpi/acpica/psobject.c +++ b/drivers/acpi/acpica/psobject.c | |||
| @@ -219,7 +219,10 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state, | |||
| 219 | 219 | ||
| 220 | status = walk_state->descending_callback(walk_state, op); | 220 | status = walk_state->descending_callback(walk_state, op); |
| 221 | if (ACPI_FAILURE(status)) { | 221 | if (ACPI_FAILURE(status)) { |
| 222 | ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); | 222 | if (status != AE_CTRL_TERMINATE) { |
| 223 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 224 | "During name lookup/catalog")); | ||
| 225 | } | ||
| 223 | return_ACPI_STATUS(status); | 226 | return_ACPI_STATUS(status); |
| 224 | } | 227 | } |
| 225 | 228 | ||
| @@ -230,7 +233,7 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state, | |||
| 230 | status = acpi_ps_next_parse_state(walk_state, *op, status); | 233 | status = acpi_ps_next_parse_state(walk_state, *op, status); |
| 231 | if (ACPI_FAILURE(status)) { | 234 | if (ACPI_FAILURE(status)) { |
| 232 | if (status == AE_CTRL_PENDING) { | 235 | if (status == AE_CTRL_PENDING) { |
| 233 | return_ACPI_STATUS(AE_CTRL_PARSE_PENDING); | 236 | status = AE_CTRL_PARSE_PENDING; |
| 234 | } | 237 | } |
| 235 | return_ACPI_STATUS(status); | 238 | return_ACPI_STATUS(status); |
| 236 | } | 239 | } |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 27f84af4e337..f7fd72ac69cf 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -1537,17 +1537,21 @@ static int __init osi_setup(char *str) | |||
| 1537 | 1537 | ||
| 1538 | __setup("acpi_osi=", osi_setup); | 1538 | __setup("acpi_osi=", osi_setup); |
| 1539 | 1539 | ||
| 1540 | /* enable serialization to combat AE_ALREADY_EXISTS errors */ | 1540 | /* |
| 1541 | static int __init acpi_serialize_setup(char *str) | 1541 | * Disable the auto-serialization of named objects creation methods. |
| 1542 | * | ||
| 1543 | * This feature is enabled by default. It marks the AML control methods | ||
| 1544 | * that contain the opcodes to create named objects as "Serialized". | ||
| 1545 | */ | ||
| 1546 | static int __init acpi_no_auto_serialize_setup(char *str) | ||
| 1542 | { | 1547 | { |
| 1543 | printk(KERN_INFO PREFIX "serialize enabled\n"); | 1548 | acpi_gbl_auto_serialize_methods = FALSE; |
| 1544 | 1549 | pr_info("ACPI: auto-serialization disabled\n"); | |
| 1545 | acpi_gbl_all_methods_serialized = TRUE; | ||
| 1546 | 1550 | ||
| 1547 | return 1; | 1551 | return 1; |
| 1548 | } | 1552 | } |
| 1549 | 1553 | ||
| 1550 | __setup("acpi_serialize", acpi_serialize_setup); | 1554 | __setup("acpi_no_auto_serialize", acpi_no_auto_serialize_setup); |
| 1551 | 1555 | ||
| 1552 | /* Check of resource interference between native drivers and ACPI | 1556 | /* Check of resource interference between native drivers and ACPI |
| 1553 | * OperationRegions (SystemIO and System Memory only). | 1557 | * OperationRegions (SystemIO and System Memory only). |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 86d73d5d503f..71e2065639a6 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -70,28 +70,6 @@ static int map_lsapic_id(struct acpi_subtable_header *entry, | |||
| 70 | return 0; | 70 | return 0; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static int map_gic_id(struct acpi_subtable_header *entry, | ||
| 74 | int device_declaration, u32 acpi_id, int *apic_id) | ||
| 75 | { | ||
| 76 | struct acpi_madt_generic_interrupt *gic = | ||
| 77 | (struct acpi_madt_generic_interrupt *)entry; | ||
| 78 | |||
| 79 | if (!(gic->flags & ACPI_MADT_ENABLED)) | ||
| 80 | return -ENODEV; | ||
| 81 | |||
| 82 | /* | ||
| 83 | * In the GIC interrupt model, logical processors are | ||
| 84 | * required to have a Processor Device object in the DSDT, | ||
| 85 | * so we should check device_declaration here | ||
| 86 | */ | ||
| 87 | if (device_declaration && (gic->uid == acpi_id)) { | ||
| 88 | *apic_id = gic->gic_id; | ||
| 89 | return 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | return -EINVAL; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int map_madt_entry(int type, u32 acpi_id) | 73 | static int map_madt_entry(int type, u32 acpi_id) |
| 96 | { | 74 | { |
| 97 | unsigned long madt_end, entry; | 75 | unsigned long madt_end, entry; |
| @@ -127,9 +105,6 @@ static int map_madt_entry(int type, u32 acpi_id) | |||
| 127 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { | 105 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { |
| 128 | if (!map_lsapic_id(header, type, acpi_id, &apic_id)) | 106 | if (!map_lsapic_id(header, type, acpi_id, &apic_id)) |
| 129 | break; | 107 | break; |
| 130 | } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { | ||
| 131 | if (!map_gic_id(header, type, acpi_id, &apic_id)) | ||
| 132 | break; | ||
| 133 | } | 108 | } |
| 134 | entry += header->length; | 109 | entry += header->length; |
| 135 | } | 110 | } |
| @@ -160,8 +135,6 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) | |||
| 160 | map_lapic_id(header, acpi_id, &apic_id); | 135 | map_lapic_id(header, acpi_id, &apic_id); |
| 161 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { | 136 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { |
| 162 | map_lsapic_id(header, type, acpi_id, &apic_id); | 137 | map_lsapic_id(header, type, acpi_id, &apic_id); |
| 163 | } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { | ||
| 164 | map_gic_id(header, type, acpi_id, &apic_id); | ||
| 165 | } | 138 | } |
| 166 | 139 | ||
| 167 | exit: | 140 | exit: |
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c index a2e55bfdf572..96a92db83cad 100644 --- a/drivers/base/power/generic_ops.c +++ b/drivers/base/power/generic_ops.c | |||
| @@ -285,7 +285,7 @@ int pm_generic_restore(struct device *dev) | |||
| 285 | EXPORT_SYMBOL_GPL(pm_generic_restore); | 285 | EXPORT_SYMBOL_GPL(pm_generic_restore); |
| 286 | 286 | ||
| 287 | /** | 287 | /** |
| 288 | * pm_generic_complete - Generic routine competing a device power transition. | 288 | * pm_generic_complete - Generic routine completing a device power transition. |
| 289 | * @dev: Device to handle. | 289 | * @dev: Device to handle. |
| 290 | * | 290 | * |
| 291 | * Complete a device power transition during a system-wide power transition. | 291 | * Complete a device power transition during a system-wide power transition. |
diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c index a05b876f375e..bc447b9003c3 100644 --- a/drivers/cpufreq/cpufreq-nforce2.c +++ b/drivers/cpufreq/cpufreq-nforce2.c | |||
| @@ -270,7 +270,7 @@ static int nforce2_target(struct cpufreq_policy *policy, | |||
| 270 | pr_debug("Old CPU frequency %d kHz, new %d kHz\n", | 270 | pr_debug("Old CPU frequency %d kHz, new %d kHz\n", |
| 271 | freqs.old, freqs.new); | 271 | freqs.old, freqs.new); |
| 272 | 272 | ||
| 273 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 273 | cpufreq_freq_transition_begin(policy, &freqs); |
| 274 | 274 | ||
| 275 | /* Disable IRQs */ | 275 | /* Disable IRQs */ |
| 276 | /* local_irq_save(flags); */ | 276 | /* local_irq_save(flags); */ |
| @@ -285,7 +285,7 @@ static int nforce2_target(struct cpufreq_policy *policy, | |||
| 285 | /* Enable IRQs */ | 285 | /* Enable IRQs */ |
| 286 | /* local_irq_restore(flags); */ | 286 | /* local_irq_restore(flags); */ |
| 287 | 287 | ||
| 288 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | 288 | cpufreq_freq_transition_end(policy, &freqs, 0); |
| 289 | 289 | ||
| 290 | return 0; | 290 | return 0; |
| 291 | } | 291 | } |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 3aa7a7a226b3..abda6609d3e7 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -331,16 +331,15 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, | |||
| 331 | * function. It is called twice on all CPU frequency changes that have | 331 | * function. It is called twice on all CPU frequency changes that have |
| 332 | * external effects. | 332 | * external effects. |
| 333 | */ | 333 | */ |
| 334 | void cpufreq_notify_transition(struct cpufreq_policy *policy, | 334 | static void cpufreq_notify_transition(struct cpufreq_policy *policy, |
| 335 | struct cpufreq_freqs *freqs, unsigned int state) | 335 | struct cpufreq_freqs *freqs, unsigned int state) |
| 336 | { | 336 | { |
| 337 | for_each_cpu(freqs->cpu, policy->cpus) | 337 | for_each_cpu(freqs->cpu, policy->cpus) |
| 338 | __cpufreq_notify_transition(policy, freqs, state); | 338 | __cpufreq_notify_transition(policy, freqs, state); |
| 339 | } | 339 | } |
| 340 | EXPORT_SYMBOL_GPL(cpufreq_notify_transition); | ||
| 341 | 340 | ||
| 342 | /* Do post notifications when there are chances that transition has failed */ | 341 | /* Do post notifications when there are chances that transition has failed */ |
| 343 | void cpufreq_notify_post_transition(struct cpufreq_policy *policy, | 342 | static void cpufreq_notify_post_transition(struct cpufreq_policy *policy, |
| 344 | struct cpufreq_freqs *freqs, int transition_failed) | 343 | struct cpufreq_freqs *freqs, int transition_failed) |
| 345 | { | 344 | { |
| 346 | cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE); | 345 | cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE); |
| @@ -351,7 +350,41 @@ void cpufreq_notify_post_transition(struct cpufreq_policy *policy, | |||
| 351 | cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE); | 350 | cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE); |
| 352 | cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE); | 351 | cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE); |
| 353 | } | 352 | } |
| 354 | EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition); | 353 | |
| 354 | void cpufreq_freq_transition_begin(struct cpufreq_policy *policy, | ||
| 355 | struct cpufreq_freqs *freqs) | ||
| 356 | { | ||
| 357 | wait: | ||
| 358 | wait_event(policy->transition_wait, !policy->transition_ongoing); | ||
| 359 | |||
| 360 | spin_lock(&policy->transition_lock); | ||
| 361 | |||
| 362 | if (unlikely(policy->transition_ongoing)) { | ||
| 363 | spin_unlock(&policy->transition_lock); | ||
| 364 | goto wait; | ||
| 365 | } | ||
| 366 | |||
| 367 | policy->transition_ongoing = true; | ||
| 368 | |||
| 369 | spin_unlock(&policy->transition_lock); | ||
| 370 | |||
| 371 | cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE); | ||
| 372 | } | ||
| 373 | EXPORT_SYMBOL_GPL(cpufreq_freq_transition_begin); | ||
| 374 | |||
| 375 | void cpufreq_freq_transition_end(struct cpufreq_policy *policy, | ||
| 376 | struct cpufreq_freqs *freqs, int transition_failed) | ||
| 377 | { | ||
| 378 | if (unlikely(WARN_ON(!policy->transition_ongoing))) | ||
| 379 | return; | ||
| 380 | |||
| 381 | cpufreq_notify_post_transition(policy, freqs, transition_failed); | ||
| 382 | |||
| 383 | policy->transition_ongoing = false; | ||
| 384 | |||
| 385 | wake_up(&policy->transition_wait); | ||
| 386 | } | ||
| 387 | EXPORT_SYMBOL_GPL(cpufreq_freq_transition_end); | ||
| 355 | 388 | ||
| 356 | 389 | ||
| 357 | /********************************************************************* | 390 | /********************************************************************* |
| @@ -985,6 +1018,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(void) | |||
| 985 | 1018 | ||
| 986 | INIT_LIST_HEAD(&policy->policy_list); | 1019 | INIT_LIST_HEAD(&policy->policy_list); |
| 987 | init_rwsem(&policy->rwsem); | 1020 | init_rwsem(&policy->rwsem); |
| 1021 | spin_lock_init(&policy->transition_lock); | ||
| 1022 | init_waitqueue_head(&policy->transition_wait); | ||
| 988 | 1023 | ||
| 989 | return policy; | 1024 | return policy; |
| 990 | 1025 | ||
| @@ -1470,8 +1505,8 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, | |||
| 1470 | policy = per_cpu(cpufreq_cpu_data, cpu); | 1505 | policy = per_cpu(cpufreq_cpu_data, cpu); |
| 1471 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1506 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| 1472 | 1507 | ||
| 1473 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 1508 | cpufreq_freq_transition_begin(policy, &freqs); |
| 1474 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | 1509 | cpufreq_freq_transition_end(policy, &freqs, 0); |
| 1475 | } | 1510 | } |
| 1476 | 1511 | ||
| 1477 | /** | 1512 | /** |
| @@ -1652,14 +1687,13 @@ void cpufreq_resume(void) | |||
| 1652 | cpufreq_suspended = false; | 1687 | cpufreq_suspended = false; |
| 1653 | 1688 | ||
| 1654 | list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { | 1689 | list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { |
| 1655 | if (__cpufreq_governor(policy, CPUFREQ_GOV_START) | 1690 | if (cpufreq_driver->resume && cpufreq_driver->resume(policy)) |
| 1691 | pr_err("%s: Failed to resume driver: %p\n", __func__, | ||
| 1692 | policy); | ||
| 1693 | else if (__cpufreq_governor(policy, CPUFREQ_GOV_START) | ||
| 1656 | || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS)) | 1694 | || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS)) |
| 1657 | pr_err("%s: Failed to start governor for policy: %p\n", | 1695 | pr_err("%s: Failed to start governor for policy: %p\n", |
| 1658 | __func__, policy); | 1696 | __func__, policy); |
| 1659 | else if (cpufreq_driver->resume | ||
| 1660 | && cpufreq_driver->resume(policy)) | ||
| 1661 | pr_err("%s: Failed to resume driver: %p\n", __func__, | ||
| 1662 | policy); | ||
| 1663 | 1697 | ||
| 1664 | /* | 1698 | /* |
| 1665 | * schedule call cpufreq_update_policy() for boot CPU, i.e. last | 1699 | * schedule call cpufreq_update_policy() for boot CPU, i.e. last |
| @@ -1832,8 +1866,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, | |||
| 1832 | pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n", | 1866 | pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n", |
| 1833 | __func__, policy->cpu, freqs.old, freqs.new); | 1867 | __func__, policy->cpu, freqs.old, freqs.new); |
| 1834 | 1868 | ||
| 1835 | cpufreq_notify_transition(policy, &freqs, | 1869 | cpufreq_freq_transition_begin(policy, &freqs); |
| 1836 | CPUFREQ_PRECHANGE); | ||
| 1837 | } | 1870 | } |
| 1838 | 1871 | ||
| 1839 | retval = cpufreq_driver->target_index(policy, index); | 1872 | retval = cpufreq_driver->target_index(policy, index); |
| @@ -1842,7 +1875,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, | |||
| 1842 | __func__, retval); | 1875 | __func__, retval); |
| 1843 | 1876 | ||
| 1844 | if (notify) | 1877 | if (notify) |
| 1845 | cpufreq_notify_post_transition(policy, &freqs, retval); | 1878 | cpufreq_freq_transition_end(policy, &freqs, retval); |
| 1846 | } | 1879 | } |
| 1847 | 1880 | ||
| 1848 | out: | 1881 | out: |
diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index 7f776aa91e2f..a6b8214d7b77 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c | |||
| @@ -219,7 +219,7 @@ static int exynos_target(struct cpufreq_policy *policy, unsigned int index) | |||
| 219 | freqs.old = policy->cur; | 219 | freqs.old = policy->cur; |
| 220 | freqs.new = freq_table[index].frequency; | 220 | freqs.new = freq_table[index].frequency; |
| 221 | 221 | ||
| 222 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 222 | cpufreq_freq_transition_begin(policy, &freqs); |
| 223 | 223 | ||
| 224 | /* Set the target frequency in all C0_3_PSTATE register */ | 224 | /* Set the target frequency in all C0_3_PSTATE register */ |
| 225 | for_each_cpu(i, policy->cpus) { | 225 | for_each_cpu(i, policy->cpus) { |
| @@ -258,7 +258,7 @@ static void exynos_cpufreq_work(struct work_struct *work) | |||
| 258 | dev_crit(dvfs_info->dev, "New frequency out of range\n"); | 258 | dev_crit(dvfs_info->dev, "New frequency out of range\n"); |
| 259 | freqs.new = freqs.old; | 259 | freqs.new = freqs.old; |
| 260 | } | 260 | } |
| 261 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | 261 | cpufreq_freq_transition_end(policy, &freqs, 0); |
| 262 | 262 | ||
| 263 | cpufreq_cpu_put(policy); | 263 | cpufreq_cpu_put(policy); |
| 264 | mutex_unlock(&cpufreq_lock); | 264 | mutex_unlock(&cpufreq_lock); |
diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c index d83e8266a58e..1d723dc8880c 100644 --- a/drivers/cpufreq/gx-suspmod.c +++ b/drivers/cpufreq/gx-suspmod.c | |||
| @@ -265,7 +265,7 @@ static void gx_set_cpuspeed(struct cpufreq_policy *policy, unsigned int khz) | |||
| 265 | 265 | ||
| 266 | freqs.new = new_khz; | 266 | freqs.new = new_khz; |
| 267 | 267 | ||
| 268 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 268 | cpufreq_freq_transition_begin(policy, &freqs); |
| 269 | local_irq_save(flags); | 269 | local_irq_save(flags); |
| 270 | 270 | ||
| 271 | if (new_khz != stock_freq) { | 271 | if (new_khz != stock_freq) { |
| @@ -314,7 +314,7 @@ static void gx_set_cpuspeed(struct cpufreq_policy *policy, unsigned int khz) | |||
| 314 | 314 | ||
| 315 | gx_params->pci_suscfg = suscfg; | 315 | gx_params->pci_suscfg = suscfg; |
| 316 | 316 | ||
| 317 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | 317 | cpufreq_freq_transition_end(policy, &freqs, 0); |
| 318 | 318 | ||
| 319 | pr_debug("suspend modulation w/ duration of ON:%d us, OFF:%d us\n", | 319 | pr_debug("suspend modulation w/ duration of ON:%d us, OFF:%d us\n", |
| 320 | gx_params->on_duration * 32, gx_params->off_duration * 32); | 320 | gx_params->on_duration * 32, gx_params->off_duration * 32); |
diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c index 0e27844e8c2d..e5122f1bfe78 100644 --- a/drivers/cpufreq/integrator-cpufreq.c +++ b/drivers/cpufreq/integrator-cpufreq.c | |||
| @@ -122,7 +122,7 @@ static int integrator_set_target(struct cpufreq_policy *policy, | |||
| 122 | return 0; | 122 | return 0; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 125 | cpufreq_freq_transition_begin(policy, &freqs); |
| 126 | 126 | ||
| 127 | cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET); | 127 | cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET); |
| 128 | 128 | ||
| @@ -143,7 +143,7 @@ static int integrator_set_target(struct cpufreq_policy *policy, | |||
| 143 | */ | 143 | */ |
| 144 | set_cpus_allowed(current, cpus_allowed); | 144 | set_cpus_allowed(current, cpus_allowed); |
| 145 | 145 | ||
| 146 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | 146 | cpufreq_freq_transition_end(policy, &freqs, 0); |
| 147 | 147 | ||
| 148 | return 0; | 148 | return 0; |
| 149 | } | 149 | } |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index bcb9a6d0ae11..099967302bf2 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
| @@ -778,7 +778,7 @@ static void intel_pstate_stop_cpu(struct cpufreq_policy *policy) | |||
| 778 | 778 | ||
| 779 | pr_info("intel_pstate CPU %d exiting\n", cpu_num); | 779 | pr_info("intel_pstate CPU %d exiting\n", cpu_num); |
| 780 | 780 | ||
| 781 | del_timer(&all_cpu_data[cpu_num]->timer); | 781 | del_timer_sync(&all_cpu_data[cpu_num]->timer); |
| 782 | intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate); | 782 | intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate); |
| 783 | kfree(all_cpu_data[cpu_num]); | 783 | kfree(all_cpu_data[cpu_num]); |
| 784 | all_cpu_data[cpu_num] = NULL; | 784 | all_cpu_data[cpu_num] = NULL; |
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 7b94da3d2d10..5c440f87ba8a 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c | |||
| @@ -269,7 +269,7 @@ static void longhaul_setstate(struct cpufreq_policy *policy, | |||
| 269 | freqs.old = calc_speed(longhaul_get_cpu_mult()); | 269 | freqs.old = calc_speed(longhaul_get_cpu_mult()); |
| 270 | freqs.new = speed; | 270 | freqs.new = speed; |
| 271 | 271 | ||
| 272 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 272 | cpufreq_freq_transition_begin(policy, &freqs); |
| 273 | 273 | ||
| 274 | pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", | 274 | pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", |
| 275 | fsb, mult/10, mult%10, print_speed(speed/1000)); | 275 | fsb, mult/10, mult%10, print_speed(speed/1000)); |
| @@ -386,7 +386,7 @@ retry_loop: | |||
| 386 | } | 386 | } |
| 387 | } | 387 | } |
| 388 | /* Report true CPU frequency */ | 388 | /* Report true CPU frequency */ |
| 389 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | 389 | cpufreq_freq_transition_end(policy, &freqs, 0); |
| 390 | 390 | ||
| 391 | if (!bm_timeout) | 391 | if (!bm_timeout) |
| 392 | printk(KERN_INFO PFX "Warning: Timeout while waiting for " | 392 | printk(KERN_INFO PFX "Warning: Timeout while waiting for " |
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 1c0f1067af73..728a2d879499 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c | |||
| @@ -215,7 +215,7 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy, | |||
| 215 | 215 | ||
| 216 | freqs.old = policy->cur; | 216 | freqs.old = policy->cur; |
| 217 | freqs.new = target_freq; | 217 | freqs.new = target_freq; |
| 218 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 218 | cpufreq_freq_transition_begin(policy, &freqs); |
| 219 | 219 | ||
| 220 | input_buffer = 0x1 | (((target_freq * 100) | 220 | input_buffer = 0x1 | (((target_freq * 100) |
| 221 | / (ioread32(&pcch_hdr->nominal) * 1000)) << 8); | 221 | / (ioread32(&pcch_hdr->nominal) * 1000)) << 8); |
| @@ -231,7 +231,7 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy, | |||
| 231 | status = ioread16(&pcch_hdr->status); | 231 | status = ioread16(&pcch_hdr->status); |
| 232 | iowrite16(0, &pcch_hdr->status); | 232 | iowrite16(0, &pcch_hdr->status); |
| 233 | 233 | ||
| 234 | cpufreq_notify_post_transition(policy, &freqs, status != CMD_COMPLETE); | 234 | cpufreq_freq_transition_end(policy, &freqs, status != CMD_COMPLETE); |
| 235 | spin_unlock(&pcc_lock); | 235 | spin_unlock(&pcc_lock); |
| 236 | 236 | ||
| 237 | if (status != CMD_COMPLETE) { | 237 | if (status != CMD_COMPLETE) { |
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index ce27e6c26c94..62c6f2e5afce 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c | |||
| @@ -148,11 +148,11 @@ static int powernow_k6_target(struct cpufreq_policy *policy, | |||
| 148 | freqs.old = busfreq * powernow_k6_get_cpu_multiplier(); | 148 | freqs.old = busfreq * powernow_k6_get_cpu_multiplier(); |
| 149 | freqs.new = busfreq * clock_ratio[best_i].driver_data; | 149 | freqs.new = busfreq * clock_ratio[best_i].driver_data; |
| 150 | 150 | ||
| 151 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 151 | cpufreq_freq_transition_begin(policy, &freqs); |
| 152 | 152 | ||
| 153 | powernow_k6_set_cpu_multiplier(best_i); | 153 | powernow_k6_set_cpu_multiplier(best_i); |
| 154 | 154 | ||
| 155 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | 155 | cpufreq_freq_transition_end(policy, &freqs, 0); |
| 156 | 156 | ||
| 157 | return 0; | 157 | return 0; |
| 158 | } | 158 | } |
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index 0e68e0275621..f911645c3f6d 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c | |||
| @@ -269,7 +269,7 @@ static int powernow_target(struct cpufreq_policy *policy, unsigned int index) | |||
| 269 | 269 | ||
| 270 | freqs.new = powernow_table[index].frequency; | 270 | freqs.new = powernow_table[index].frequency; |
| 271 | 271 | ||
| 272 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 272 | cpufreq_freq_transition_begin(policy, &freqs); |
| 273 | 273 | ||
| 274 | /* Now do the magic poking into the MSRs. */ | 274 | /* Now do the magic poking into the MSRs. */ |
| 275 | 275 | ||
| @@ -290,7 +290,7 @@ static int powernow_target(struct cpufreq_policy *policy, unsigned int index) | |||
| 290 | if (have_a0 == 1) | 290 | if (have_a0 == 1) |
| 291 | local_irq_enable(); | 291 | local_irq_enable(); |
| 292 | 292 | ||
| 293 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | 293 | cpufreq_freq_transition_end(policy, &freqs, 0); |
| 294 | 294 | ||
| 295 | return 0; | 295 | return 0; |
| 296 | } | 296 | } |
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 27eb2be44de5..770a9e1b3468 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c | |||
| @@ -963,9 +963,9 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, | |||
| 963 | policy = cpufreq_cpu_get(smp_processor_id()); | 963 | policy = cpufreq_cpu_get(smp_processor_id()); |
| 964 | cpufreq_cpu_put(policy); | 964 | cpufreq_cpu_put(policy); |
| 965 | 965 | ||
| 966 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 966 | cpufreq_freq_transition_begin(policy, &freqs); |
| 967 | res = transition_fid_vid(data, fid, vid); | 967 | res = transition_fid_vid(data, fid, vid); |
| 968 | cpufreq_notify_post_transition(policy, &freqs, res); | 968 | cpufreq_freq_transition_end(policy, &freqs, res); |
| 969 | 969 | ||
| 970 | return res; | 970 | return res; |
| 971 | } | 971 | } |
diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index 25069741b507..a3dc192d21f9 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c | |||
| @@ -217,7 +217,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy, | |||
| 217 | s3c_cpufreq_updateclk(clk_pclk, cpu_new.freq.pclk); | 217 | s3c_cpufreq_updateclk(clk_pclk, cpu_new.freq.pclk); |
| 218 | 218 | ||
| 219 | /* start the frequency change */ | 219 | /* start the frequency change */ |
| 220 | cpufreq_notify_transition(policy, &freqs.freqs, CPUFREQ_PRECHANGE); | 220 | cpufreq_freq_transition_begin(policy, &freqs.freqs); |
| 221 | 221 | ||
| 222 | /* If hclk is staying the same, then we do not need to | 222 | /* If hclk is staying the same, then we do not need to |
| 223 | * re-write the IO or the refresh timings whilst we are changing | 223 | * re-write the IO or the refresh timings whilst we are changing |
| @@ -261,7 +261,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy, | |||
| 261 | local_irq_restore(flags); | 261 | local_irq_restore(flags); |
| 262 | 262 | ||
| 263 | /* notify everyone we've done this */ | 263 | /* notify everyone we've done this */ |
| 264 | cpufreq_notify_transition(policy, &freqs.freqs, CPUFREQ_POSTCHANGE); | 264 | cpufreq_freq_transition_end(policy, &freqs.freqs, 0); |
| 265 | 265 | ||
| 266 | s3c_freq_dbg("%s: finished\n", __func__); | 266 | s3c_freq_dbg("%s: finished\n", __func__); |
| 267 | return 0; | 267 | return 0; |
diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c index 696170ebd3a3..86628e22b2a3 100644 --- a/drivers/cpufreq/sh-cpufreq.c +++ b/drivers/cpufreq/sh-cpufreq.c | |||
| @@ -68,10 +68,10 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy, | |||
| 68 | freqs.new = (freq + 500) / 1000; | 68 | freqs.new = (freq + 500) / 1000; |
| 69 | freqs.flags = 0; | 69 | freqs.flags = 0; |
| 70 | 70 | ||
| 71 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 71 | cpufreq_freq_transition_begin(policy, &freqs); |
| 72 | set_cpus_allowed_ptr(current, &cpus_allowed); | 72 | set_cpus_allowed_ptr(current, &cpus_allowed); |
| 73 | clk_set_rate(cpuclk, freq); | 73 | clk_set_rate(cpuclk, freq); |
| 74 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | 74 | cpufreq_freq_transition_end(policy, &freqs, 0); |
| 75 | 75 | ||
| 76 | dev_dbg(dev, "set frequency %lu Hz\n", freq); | 76 | dev_dbg(dev, "set frequency %lu Hz\n", freq); |
| 77 | 77 | ||
diff --git a/drivers/cpufreq/unicore2-cpufreq.c b/drivers/cpufreq/unicore2-cpufreq.c index 36cc330b8747..13be802b6170 100644 --- a/drivers/cpufreq/unicore2-cpufreq.c +++ b/drivers/cpufreq/unicore2-cpufreq.c | |||
| @@ -44,9 +44,9 @@ static int ucv2_target(struct cpufreq_policy *policy, | |||
| 44 | freqs.old = policy->cur; | 44 | freqs.old = policy->cur; |
| 45 | freqs.new = target_freq; | 45 | freqs.new = target_freq; |
| 46 | 46 | ||
| 47 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | 47 | cpufreq_freq_transition_begin(policy, &freqs); |
| 48 | ret = clk_set_rate(policy->mclk, target_freq * 1000); | 48 | ret = clk_set_rate(policy->mclk, target_freq * 1000); |
| 49 | cpufreq_notify_post_transition(policy, &freqs, ret); | 49 | cpufreq_freq_transition_end(policy, &freqs, ret); |
| 50 | 50 | ||
| 51 | return ret; | 51 | return ret; |
| 52 | } | 52 | } |
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index bacddd102ae9..01712cbfd92e 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c | |||
| @@ -385,7 +385,7 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res) | |||
| 385 | * device is active because it itself may be in use */ | 385 | * device is active because it itself may be in use */ |
| 386 | if (!dev->active) { | 386 | if (!dev->active) { |
| 387 | if (request_irq(*irq, pnp_test_handler, | 387 | if (request_irq(*irq, pnp_test_handler, |
| 388 | IRQF_DISABLED | IRQF_PROBE_SHARED, "pnp", NULL)) | 388 | IRQF_PROBE_SHARED, "pnp", NULL)) |
| 389 | return 0; | 389 | return 0; |
| 390 | free_irq(*irq, NULL); | 390 | free_irq(*irq, NULL); |
| 391 | } | 391 | } |
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index b0b01b13ea99..44f5e9749601 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h | |||
| @@ -71,7 +71,7 @@ extern u32 acpi_dbg_layer; | |||
| 71 | 71 | ||
| 72 | /* ACPICA runtime options */ | 72 | /* ACPICA runtime options */ |
| 73 | 73 | ||
| 74 | extern u8 acpi_gbl_all_methods_serialized; | 74 | extern u8 acpi_gbl_auto_serialize_methods; |
| 75 | extern u8 acpi_gbl_copy_dsdt_locally; | 75 | extern u8 acpi_gbl_copy_dsdt_locally; |
| 76 | extern u8 acpi_gbl_create_osi_method; | 76 | extern u8 acpi_gbl_create_osi_method; |
| 77 | extern u8 acpi_gbl_disable_auto_repair; | 77 | extern u8 acpi_gbl_disable_auto_repair; |
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 2d2e62c8666a..c48e595f623e 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/completion.h> | 16 | #include <linux/completion.h> |
| 17 | #include <linux/kobject.h> | 17 | #include <linux/kobject.h> |
| 18 | #include <linux/notifier.h> | 18 | #include <linux/notifier.h> |
| 19 | #include <linux/spinlock.h> | ||
| 19 | #include <linux/sysfs.h> | 20 | #include <linux/sysfs.h> |
| 20 | 21 | ||
| 21 | /********************************************************************* | 22 | /********************************************************************* |
| @@ -104,6 +105,11 @@ struct cpufreq_policy { | |||
| 104 | * __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); | 105 | * __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); |
| 105 | */ | 106 | */ |
| 106 | struct rw_semaphore rwsem; | 107 | struct rw_semaphore rwsem; |
| 108 | |||
| 109 | /* Synchronization for frequency transitions */ | ||
| 110 | bool transition_ongoing; /* Tracks transition status */ | ||
| 111 | spinlock_t transition_lock; | ||
| 112 | wait_queue_head_t transition_wait; | ||
| 107 | }; | 113 | }; |
| 108 | 114 | ||
| 109 | /* Only for ACPI */ | 115 | /* Only for ACPI */ |
| @@ -333,9 +339,9 @@ static inline void cpufreq_resume(void) {} | |||
| 333 | int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); | 339 | int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); |
| 334 | int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); | 340 | int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); |
| 335 | 341 | ||
| 336 | void cpufreq_notify_transition(struct cpufreq_policy *policy, | 342 | void cpufreq_freq_transition_begin(struct cpufreq_policy *policy, |
| 337 | struct cpufreq_freqs *freqs, unsigned int state); | 343 | struct cpufreq_freqs *freqs); |
| 338 | void cpufreq_notify_post_transition(struct cpufreq_policy *policy, | 344 | void cpufreq_freq_transition_end(struct cpufreq_policy *policy, |
| 339 | struct cpufreq_freqs *freqs, int transition_failed); | 345 | struct cpufreq_freqs *freqs, int transition_failed); |
| 340 | 346 | ||
| 341 | #else /* CONFIG_CPU_FREQ */ | 347 | #else /* CONFIG_CPU_FREQ */ |
