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 */ |