mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 14:14:24 +08:00
More ACPI and power management updates for 3.15-rc1
- Remaining changes from upstream ACPICA release 20140214 that introduce code to automatically serialize the execution of methods creating any named objects which really cannot be executed in parallel with each other anyway (previously ACPICA attempted to address that by aborting methods upon conflict detection, but that wasn't reliable enough and led to other issues). From Bob Moore and Lv Zheng. - intel_pstate fix to use del_timer_sync() instead of del_timer() in the exit path before freeing the timer structure from Dirk Brandewie (original patch from Thomas Gleixner). - cpufreq fix related to system resume from Viresh Kumar. - Serialization of frequency transitions in cpufreq that involve PRECHANGE and POSTCHANGE notifications to avoid ordering issues resulting from race conditions. From Srivatsa S Bhat and Viresh Kumar. - Revert of an ACPI processor driver change that was based on a specific interpretation of the ACPI spec which may not be correct (the relevant part of the spec appears to be incomplete). From Hanjun Guo. - Runtime PM core cleanups and documentation updates from Geert Uytterhoeven. - PNP core cleanup from Michael Opdenacker. / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCAAGBQJTO1+vAAoJEILEb/54YlRxHYgP/RB18RLcwSIPMTWoZPo5t+pd IGtHkG5xzCBZXiqL9OJLm+dH1V5w+wZVXh2865ZDiqq4CZYZWD6RUQnx5q0rSVR5 54PYzx2I0i8ApPxRYTTmnb2NHUPedp3l0YSRC0gt73Q/6o9TcmOMtcn5pfTyCvbB m3am3mpKKxRD+vYCADjjUtuj4NQ62z9DjM5iJIql7Pj4kAJVgSxP8nsfHY6EwNaT m9mnNCA6Zemh89luM1W2vw69ZoZwLAbXIXJYCNy3khT13SYO2SCNhX/tlY7ncCvv P+9gawJb6Wio7pVHqRR0Lesc8J29uzivEeS8WqZ3R0P0HoTP6z5a5R+b06ecGQjF OWvj7wURjZE4t7qEtIOHmwIyCRE4Nxly90r5upj9kKVBaczz/LbDeCVfKU/Y2Vu6 PPxmjRwjO4S8FqLihwiXCSYVf3pxBrDKgjjofM7f2CiO8D41C4KhgowbUqyUSCgw VKXU6UQbzVigfrGXsdqIJiTnEMmbOvrPy6PaVh27NlwXX3sg1SwYcoegsW+ee7m1 jJdl1TRI27pl7NPgTkLpf5K7n6mkDsou8Y+PcQhFa6FNTn/k8gp/RfOHpLHaNTjL 15Aswkm70Ojeae+Ahx8ZgrWXF7iu+uBX7KakeUVQJg/PFjXIspx+c/SrGzh7ZLa1 aOqoKfFY7zDke4AV3eH/ =EfZ8 -----END PGP SIGNATURE----- Merge tag 'pm+acpi-3.15-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull more ACPI and power management updates from Rafael Wysocki: "These are commits that were not quite ready when I sent the original pull request for 3.15-rc1 several days ago, but they have spent some time in linux-next since then and appear to be good to go. All of them are fixes and cleanups. Specifics: - Remaining changes from upstream ACPICA release 20140214 that introduce code to automatically serialize the execution of methods creating any named objects which really cannot be executed in parallel with each other anyway (previously ACPICA attempted to address that by aborting methods upon conflict detection, but that wasn't reliable enough and led to other issues). From Bob Moore and Lv Zheng. - intel_pstate fix to use del_timer_sync() instead of del_timer() in the exit path before freeing the timer structure from Dirk Brandewie (original patch from Thomas Gleixner). - cpufreq fix related to system resume from Viresh Kumar. - Serialization of frequency transitions in cpufreq that involve PRECHANGE and POSTCHANGE notifications to avoid ordering issues resulting from race conditions. From Srivatsa S Bhat and Viresh Kumar. - Revert of an ACPI processor driver change that was based on a specific interpretation of the ACPI spec which may not be correct (the relevant part of the spec appears to be incomplete). From Hanjun Guo. - Runtime PM core cleanups and documentation updates from Geert Uytterhoeven. - PNP core cleanup from Michael Opdenacker" * tag 'pm+acpi-3.15-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: cpufreq: Make cpufreq_notify_transition & cpufreq_notify_post_transition static cpufreq: Convert existing drivers to use cpufreq_freq_transition_{begin|end} cpufreq: Make sure frequency transitions are serialized intel_pstate: Use del_timer_sync in intel_pstate_cpu_stop cpufreq: resume drivers before enabling governors PM / Runtime: Spelling s/competing/completing/ PM / Runtime: s/foo_process_requests/foo_process_next_request/ PM / Runtime: GENERIC_SUBSYS_PM_OPS is gone PM / Runtime: Correct documented return values for generic PM callbacks PM / Runtime: Split line longer than 80 characters PM / Runtime: dev_pm_info.runtime_error is signed Revert "ACPI / processor: Make it possible to get APIC ID via GIC" ACPICA: Enable auto-serialization as a default kernel behavior. ACPICA: Ignore sync_level for methods that have been auto-serialized. ACPICA: Add additional named objects for the auto-serialize method scan. ACPICA: Add auto-serialization support for ill-behaved control methods. ACPICA: Remove global option to serialize all control methods. PNP: remove deprecated IRQF_DISABLED
This commit is contained in:
commit
70f6c08757
@ -229,6 +229,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
use by PCI
|
||||
Format: <irq>,<irq>...
|
||||
|
||||
acpi_no_auto_serialize [HW,ACPI]
|
||||
Disable auto-serialization of AML methods
|
||||
AML control methods that contain the opcodes to create
|
||||
named objects will be marked as "Serialized" by the
|
||||
auto-serialization feature.
|
||||
This feature is enabled by default.
|
||||
This option allows to turn off the feature.
|
||||
|
||||
acpi_no_auto_ssdt [HW,ACPI] Disable automatic loading of SSDT
|
||||
|
||||
acpica_no_return_repair [HW, ACPI]
|
||||
@ -306,8 +314,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode
|
||||
Format: { level | edge | high | low }
|
||||
|
||||
acpi_serialize [HW,ACPI] force serialization of AML methods
|
||||
|
||||
acpi_skip_timer_override [HW,ACPI]
|
||||
Recognize and ignore IRQ0/pin2 Interrupt Override.
|
||||
For broken nForce2 BIOS resulting in XT-PIC timer.
|
||||
|
@ -232,7 +232,7 @@ defined in include/linux/pm.h:
|
||||
equal to zero); the initial value of it is 1 (i.e. runtime PM is
|
||||
initially disabled for all devices)
|
||||
|
||||
unsigned int runtime_error;
|
||||
int runtime_error;
|
||||
- if set, there was a fatal error (one of the callbacks returned error code
|
||||
as described in Section 2), so the helper funtions will not work until
|
||||
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:
|
||||
int pm_runtime_disable(struct device *dev);
|
||||
- increment the device's 'power.disable_depth' field (if the value of that
|
||||
field was previously zero, this prevents subsystem-level runtime PM
|
||||
callbacks from being run for the device), make sure that all of the pending
|
||||
runtime PM operations on the device are either completed or canceled;
|
||||
returns 1 if there was a resume request pending and it was necessary to
|
||||
execute the subsystem-level resume callback for the device to satisfy that
|
||||
request, otherwise 0 is returned
|
||||
callbacks from being run for the device), make sure that all of the
|
||||
pending runtime PM operations on the device are either completed or
|
||||
canceled; returns 1 if there was a resume request pending and it was
|
||||
necessary to execute the subsystem-level resume callback for the device
|
||||
to satisfy that request, otherwise 0 is returned
|
||||
|
||||
int pm_runtime_barrier(struct device *dev);
|
||||
- check if there's a resume request pending for the device and resume it
|
||||
@ -667,11 +667,11 @@ driver/base/power/generic_ops.c:
|
||||
|
||||
int pm_generic_runtime_suspend(struct device *dev);
|
||||
- invoke the ->runtime_suspend() callback provided by the driver of this
|
||||
device and return its result, or return -EINVAL if not defined
|
||||
device and return its result, or return 0 if not defined
|
||||
|
||||
int pm_generic_runtime_resume(struct device *dev);
|
||||
- invoke the ->runtime_resume() callback provided by the driver of this
|
||||
device and return its result, or return -EINVAL if not defined
|
||||
device and return its result, or return 0 if not defined
|
||||
|
||||
int pm_generic_suspend(struct device *dev);
|
||||
- if the device has not been suspended at run time, invoke the ->suspend()
|
||||
@ -727,15 +727,12 @@ driver/base/power/generic_ops.c:
|
||||
int pm_generic_restore_noirq(struct device *dev);
|
||||
- invoke the ->restore_noirq() callback provided by the device's driver
|
||||
|
||||
These functions can be assigned to the ->runtime_idle(), ->runtime_suspend(),
|
||||
These functions are the defaults used by the PM core, if a subsystem doesn't
|
||||
provide its own callbacks for ->runtime_idle(), ->runtime_suspend(),
|
||||
->runtime_resume(), ->suspend(), ->suspend_noirq(), ->resume(),
|
||||
->resume_noirq(), ->freeze(), ->freeze_noirq(), ->thaw(), ->thaw_noirq(),
|
||||
->poweroff(), ->poweroff_noirq(), ->restore(), ->restore_noirq() callback
|
||||
pointers in the subsystem-level dev_pm_ops structures.
|
||||
|
||||
If a subsystem wishes to use all of them at the same time, it can simply assign
|
||||
the GENERIC_SUBSYS_PM_OPS macro, defined in include/linux/pm.h, to its
|
||||
dev_pm_ops structure pointer.
|
||||
->poweroff(), ->poweroff_noirq(), ->restore(), ->restore_noirq() in the
|
||||
subsystem-level dev_pm_ops structure.
|
||||
|
||||
Device drivers that wish to use the same function as a system suspend, freeze,
|
||||
poweroff and runtime suspend callback, and similarly for system resume, thaw,
|
||||
@ -873,7 +870,7 @@ Here is a schematic pseudo-code example:
|
||||
foo->is_suspended = 0;
|
||||
pm_runtime_mark_last_busy(&foo->dev);
|
||||
if (foo->num_pending_requests > 0)
|
||||
foo_process_requests(foo);
|
||||
foo_process_next_request(foo);
|
||||
unlock(&foo->private_lock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -139,20 +139,21 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
|
||||
struct acpi_walk_state *walk_state);
|
||||
|
||||
/*
|
||||
* dsload - Parser/Interpreter interface, pass 1 namespace load callbacks
|
||||
* dsload - Parser/Interpreter interface
|
||||
*/
|
||||
acpi_status
|
||||
acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number);
|
||||
|
||||
/* dsload - pass 1 namespace load callbacks */
|
||||
|
||||
acpi_status
|
||||
acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object **out_op);
|
||||
|
||||
acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state);
|
||||
|
||||
/*
|
||||
* dsload - Parser/Interpreter interface, pass 2 namespace load callbacks
|
||||
*/
|
||||
/* dsload - pass 2 namespace load callbacks */
|
||||
|
||||
acpi_status
|
||||
acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object **out_op);
|
||||
@ -200,7 +201,9 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state);
|
||||
/*
|
||||
* dsmethod - Parser/Interpreter interface - control method parsing
|
||||
*/
|
||||
acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node);
|
||||
acpi_status
|
||||
acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
|
||||
union acpi_operand_object *obj_desc);
|
||||
|
||||
acpi_status
|
||||
acpi_ds_call_control_method(struct acpi_thread_state *thread,
|
||||
|
@ -93,12 +93,13 @@
|
||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_enable_interpreter_slack, FALSE);
|
||||
|
||||
/*
|
||||
* Automatically serialize ALL control methods? Default is FALSE, meaning
|
||||
* to use the Serialized/not_serialized method flags on a per method basis.
|
||||
* Only change this if the ASL code is poorly written and cannot handle
|
||||
* reentrancy even though methods are marked "NotSerialized".
|
||||
* Automatically serialize all methods that create named objects? Default
|
||||
* is TRUE, meaning that all non_serialized methods are scanned once at
|
||||
* table load time to determine those that create named objects. Methods
|
||||
* that create named objects are marked Serialized in order to prevent
|
||||
* possible run-time problems if they are entered by more than one thread.
|
||||
*/
|
||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_all_methods_serialized, FALSE);
|
||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_auto_serialize_methods, TRUE);
|
||||
|
||||
/*
|
||||
* Create the predefined _OSI method in the namespace? Default is TRUE
|
||||
|
@ -458,10 +458,6 @@ void acpi_ex_enter_interpreter(void);
|
||||
|
||||
void acpi_ex_exit_interpreter(void);
|
||||
|
||||
void acpi_ex_reacquire_interpreter(void);
|
||||
|
||||
void acpi_ex_relinquish_interpreter(void);
|
||||
|
||||
u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc);
|
||||
|
||||
void acpi_ex_acquire_global_lock(u32 rule);
|
||||
|
@ -193,7 +193,8 @@ struct acpi_object_method {
|
||||
#define ACPI_METHOD_INTERNAL_ONLY 0x02 /* Method is implemented internally (_OSI) */
|
||||
#define ACPI_METHOD_SERIALIZED 0x04 /* Method is serialized */
|
||||
#define ACPI_METHOD_SERIALIZED_PENDING 0x08 /* Method is to be marked serialized */
|
||||
#define ACPI_METHOD_MODIFIED_NAMESPACE 0x10 /* Method modified the namespace */
|
||||
#define ACPI_METHOD_IGNORE_SYNC_LEVEL 0x10 /* Method was auto-serialized at table load time */
|
||||
#define ACPI_METHOD_MODIFIED_NAMESPACE 0x20 /* Method modified the namespace */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
|
@ -133,6 +133,9 @@ struct acpi_init_walk_info {
|
||||
u32 table_index;
|
||||
u32 object_count;
|
||||
u32 method_count;
|
||||
u32 serial_method_count;
|
||||
u32 non_serial_method_count;
|
||||
u32 serialized_method_count;
|
||||
u32 device_count;
|
||||
u32 op_region_count;
|
||||
u32 field_count;
|
||||
|
@ -83,8 +83,8 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
|
||||
(struct acpi_init_walk_info *)context;
|
||||
struct acpi_namespace_node *node =
|
||||
(struct acpi_namespace_node *)obj_handle;
|
||||
acpi_object_type type;
|
||||
acpi_status status;
|
||||
union acpi_operand_object *obj_desc;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
@ -100,9 +100,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
|
||||
|
||||
/* And even then, we are only interested in a few object types */
|
||||
|
||||
type = acpi_ns_get_type(obj_handle);
|
||||
|
||||
switch (type) {
|
||||
switch (acpi_ns_get_type(obj_handle)) {
|
||||
case ACPI_TYPE_REGION:
|
||||
|
||||
status = acpi_ds_initialize_region(obj_handle);
|
||||
@ -117,8 +115,44 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_METHOD:
|
||||
|
||||
/*
|
||||
* Auto-serialization support. We will examine each method that is
|
||||
* not_serialized to determine if it creates any Named objects. If
|
||||
* it does, it will be marked serialized to prevent problems if
|
||||
* the method is entered by two or more threads and an attempt is
|
||||
* made to create the same named object twice -- which results in
|
||||
* an AE_ALREADY_EXISTS exception and method abort.
|
||||
*/
|
||||
info->method_count++;
|
||||
obj_desc = acpi_ns_get_attached_object(node);
|
||||
if (!obj_desc) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ignore if already serialized */
|
||||
|
||||
if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) {
|
||||
info->serial_method_count++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (acpi_gbl_auto_serialize_methods) {
|
||||
|
||||
/* Parse/scan method and serialize it if necessary */
|
||||
|
||||
acpi_ds_auto_serialize_method(node, obj_desc);
|
||||
if (obj_desc->method.
|
||||
info_flags & ACPI_METHOD_SERIALIZED) {
|
||||
|
||||
/* Method was just converted to Serialized */
|
||||
|
||||
info->serial_method_count++;
|
||||
info->serialized_method_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
info->non_serial_method_count++;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_DEVICE:
|
||||
@ -170,7 +204,6 @@ acpi_ds_initialize_objects(u32 table_index,
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"**** Starting initialization of namespace objects ****\n"));
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:"));
|
||||
|
||||
/* Set all init info to zero */
|
||||
|
||||
@ -205,14 +238,16 @@ acpi_ds_initialize_objects(u32 table_index,
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
|
||||
"\nTable [%4.4s](id %4.4X) - %u Objects with %u Devices %u Methods %u Regions\n",
|
||||
"Table [%4.4s] (id %4.4X) - %4u Objects with %3u Devices, "
|
||||
"%3u Regions, %3u Methods (%u/%u/%u Serial/Non/Cvt)\n",
|
||||
table->signature, owner_id, info.object_count,
|
||||
info.device_count, info.method_count,
|
||||
info.op_region_count));
|
||||
info.device_count, info.op_region_count,
|
||||
info.method_count, info.serial_method_count,
|
||||
info.non_serial_method_count,
|
||||
info.serialized_method_count));
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"%u Methods, %u Regions\n", info.method_count,
|
||||
info.op_region_count));
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "%u Methods, %u Regions\n",
|
||||
info.method_count, info.op_region_count));
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
@ -49,14 +49,153 @@
|
||||
#ifdef ACPI_DISASSEMBLER
|
||||
#include "acdisasm.h"
|
||||
#endif
|
||||
#include "acparser.h"
|
||||
#include "amlcode.h"
|
||||
|
||||
#define _COMPONENT ACPI_DISPATCHER
|
||||
ACPI_MODULE_NAME("dsmethod")
|
||||
|
||||
/* Local prototypes */
|
||||
static acpi_status
|
||||
acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object **out_op);
|
||||
|
||||
static acpi_status
|
||||
acpi_ds_create_method_mutex(union acpi_operand_object *method_desc);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_auto_serialize_method
|
||||
*
|
||||
* PARAMETERS: node - Namespace Node of the method
|
||||
* obj_desc - Method object attached to node
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Parse a control method AML to scan for control methods that
|
||||
* need serialization due to the creation of named objects.
|
||||
*
|
||||
* NOTE: It is a bit of overkill to mark all such methods serialized, since
|
||||
* there is only a problem if the method actually blocks during execution.
|
||||
* A blocking operation is, for example, a Sleep() operation, or any access
|
||||
* to an operation region. However, it is probably not possible to easily
|
||||
* detect whether a method will block or not, so we simply mark all suspicious
|
||||
* methods as serialized.
|
||||
*
|
||||
* NOTE2: This code is essentially a generic routine for parsing a single
|
||||
* control method.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
|
||||
union acpi_operand_object *obj_desc)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_parse_object *op = NULL;
|
||||
struct acpi_walk_state *walk_state;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ds_auto_serialize_method, node);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
|
||||
"Method auto-serialization parse [%4.4s] %p\n",
|
||||
acpi_ut_get_node_name(node), node));
|
||||
|
||||
/* Create/Init a root op for the method parse tree */
|
||||
|
||||
op = acpi_ps_alloc_op(AML_METHOD_OP);
|
||||
if (!op) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
acpi_ps_set_name(op, node->name.integer);
|
||||
op->common.node = node;
|
||||
|
||||
/* Create and initialize a new walk state */
|
||||
|
||||
walk_state =
|
||||
acpi_ds_create_walk_state(node->owner_id, NULL, NULL, NULL);
|
||||
if (!walk_state) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
status =
|
||||
acpi_ds_init_aml_walk(walk_state, op, node,
|
||||
obj_desc->method.aml_start,
|
||||
obj_desc->method.aml_length, NULL, 0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_ds_delete_walk_state(walk_state);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
walk_state->descending_callback = acpi_ds_detect_named_opcodes;
|
||||
|
||||
/* Parse the method, scan for creation of named objects */
|
||||
|
||||
status = acpi_ps_parse_aml(walk_state);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
acpi_ps_delete_parse_tree(op);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_detect_named_opcodes
|
||||
*
|
||||
* PARAMETERS: walk_state - Current state of the parse tree walk
|
||||
* out_op - Unused, required for parser interface
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Descending callback used during the loading of ACPI tables.
|
||||
* Currently used to detect methods that must be marked serialized
|
||||
* in order to avoid problems with the creation of named objects.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object **out_op)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_NAME(acpi_ds_detect_named_opcodes);
|
||||
|
||||
/* We are only interested in opcodes that create a new name */
|
||||
|
||||
if (!
|
||||
(walk_state->op_info->
|
||||
flags & (AML_NAMED | AML_CREATE | AML_FIELD))) {
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, we know we have a Named object opcode.
|
||||
* Mark the method as serialized. Later code will create a mutex for
|
||||
* this method to enforce serialization.
|
||||
*
|
||||
* Note, ACPI_METHOD_IGNORE_SYNC_LEVEL flag means that we will ignore the
|
||||
* Sync Level mechanism for this method, even though it is now serialized.
|
||||
* Otherwise, there can be conflicts with existing ASL code that actually
|
||||
* uses sync levels.
|
||||
*/
|
||||
walk_state->method_desc->method.sync_level = 0;
|
||||
walk_state->method_desc->method.info_flags |=
|
||||
(ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Method serialized [%4.4s] %p - [%s] (%4.4X)\n",
|
||||
walk_state->method_node->name.ascii,
|
||||
walk_state->method_node, walk_state->op_info->name,
|
||||
walk_state->opcode));
|
||||
|
||||
/* Abort the parse, no need to examine this method any further */
|
||||
|
||||
return (AE_CTRL_TERMINATE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_method_error
|
||||
@ -74,7 +213,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc);
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
|
||||
acpi_ds_method_error(acpi_status status, struct acpi_walk_state * walk_state)
|
||||
{
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
|
||||
@ -217,13 +356,19 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
|
||||
/*
|
||||
* The current_sync_level (per-thread) must be less than or equal to
|
||||
* the sync level of the method. This mechanism provides some
|
||||
* deadlock prevention
|
||||
* deadlock prevention.
|
||||
*
|
||||
* If the method was auto-serialized, we just ignore the sync level
|
||||
* mechanism, because auto-serialization of methods can interfere
|
||||
* with ASL code that actually uses sync levels.
|
||||
*
|
||||
* Top-level method invocation has no walk state at this point
|
||||
*/
|
||||
if (walk_state &&
|
||||
(walk_state->thread->current_sync_level >
|
||||
obj_desc->method.mutex->mutex.sync_level)) {
|
||||
(!(obj_desc->method.
|
||||
info_flags & ACPI_METHOD_IGNORE_SYNC_LEVEL))
|
||||
&& (walk_state->thread->current_sync_level >
|
||||
obj_desc->method.mutex->mutex.sync_level)) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)",
|
||||
acpi_ut_get_node_name(method_node),
|
||||
@ -668,7 +813,8 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
|
||||
method_desc->method.info_flags &=
|
||||
~ACPI_METHOD_SERIALIZED_PENDING;
|
||||
method_desc->method.info_flags |=
|
||||
ACPI_METHOD_SERIALIZED;
|
||||
(ACPI_METHOD_SERIALIZED |
|
||||
ACPI_METHOD_IGNORE_SYNC_LEVEL);
|
||||
method_desc->method.sync_level = 0;
|
||||
}
|
||||
|
||||
|
@ -73,8 +73,20 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)
|
||||
{
|
||||
|
||||
switch (pass_number) {
|
||||
case 0:
|
||||
|
||||
/* Parse only - caller will setup callbacks */
|
||||
|
||||
walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
|
||||
ACPI_PARSE_DELETE_TREE | ACPI_PARSE_DISASSEMBLE;
|
||||
walk_state->descending_callback = NULL;
|
||||
walk_state->ascending_callback = NULL;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
/* Load pass 1 */
|
||||
|
||||
walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
|
||||
ACPI_PARSE_DELETE_TREE;
|
||||
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)
|
||||
|
||||
case 2:
|
||||
|
||||
/* Load pass 2 */
|
||||
|
||||
walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
|
||||
ACPI_PARSE_DELETE_TREE;
|
||||
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)
|
||||
|
||||
case 3:
|
||||
|
||||
/* Execution pass */
|
||||
|
||||
#ifndef ACPI_NO_METHOD_EXECUTION
|
||||
walk_state->parse_flags |= ACPI_PARSE_EXECUTE |
|
||||
ACPI_PARSE_DELETE_TREE;
|
||||
|
@ -77,7 +77,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
|
||||
|
||||
/* We must wait, so unlock the interpreter */
|
||||
|
||||
acpi_ex_relinquish_interpreter();
|
||||
acpi_ex_exit_interpreter();
|
||||
|
||||
status = acpi_os_wait_semaphore(semaphore, 1, timeout);
|
||||
|
||||
@ -87,7 +87,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
|
||||
|
||||
/* Reacquire the interpreter */
|
||||
|
||||
acpi_ex_reacquire_interpreter();
|
||||
acpi_ex_enter_interpreter();
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
@ -123,7 +123,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
|
||||
|
||||
/* We must wait, so unlock the interpreter */
|
||||
|
||||
acpi_ex_relinquish_interpreter();
|
||||
acpi_ex_exit_interpreter();
|
||||
|
||||
status = acpi_os_acquire_mutex(mutex, timeout);
|
||||
|
||||
@ -133,7 +133,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
|
||||
|
||||
/* Reacquire the interpreter */
|
||||
|
||||
acpi_ex_reacquire_interpreter();
|
||||
acpi_ex_enter_interpreter();
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
@ -198,7 +198,7 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long)
|
||||
|
||||
/* Since this thread will sleep, we must release the interpreter */
|
||||
|
||||
acpi_ex_relinquish_interpreter();
|
||||
acpi_ex_exit_interpreter();
|
||||
|
||||
/*
|
||||
* For compatibility with other ACPI implementations and to prevent
|
||||
@ -212,7 +212,7 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long)
|
||||
|
||||
/* And now we must get the interpreter again */
|
||||
|
||||
acpi_ex_reacquire_interpreter();
|
||||
acpi_ex_enter_interpreter();
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
|
@ -98,37 +98,6 @@ void acpi_ex_enter_interpreter(void)
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_reacquire_interpreter
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Reacquire the interpreter execution region from within the
|
||||
* interpreter code. Failure to enter the interpreter region is a
|
||||
* fatal system error. Used in conjunction with
|
||||
* relinquish_interpreter
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_ex_reacquire_interpreter(void)
|
||||
{
|
||||
ACPI_FUNCTION_TRACE(ex_reacquire_interpreter);
|
||||
|
||||
/*
|
||||
* If the global serialized flag is set, do not release the interpreter,
|
||||
* since it was not actually released by acpi_ex_relinquish_interpreter.
|
||||
* This forces the interpreter to be single threaded.
|
||||
*/
|
||||
if (!acpi_gbl_all_methods_serialized) {
|
||||
acpi_ex_enter_interpreter();
|
||||
}
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_exit_interpreter
|
||||
@ -139,7 +108,16 @@ void acpi_ex_reacquire_interpreter(void)
|
||||
*
|
||||
* DESCRIPTION: Exit the interpreter execution region. This is the top level
|
||||
* routine used to exit the interpreter when all processing has
|
||||
* been completed.
|
||||
* been completed, or when the method blocks.
|
||||
*
|
||||
* Cases where the interpreter is unlocked internally:
|
||||
* 1) Method will be blocked on a Sleep() AML opcode
|
||||
* 2) Method will be blocked on an Acquire() AML opcode
|
||||
* 3) Method will be blocked on a Wait() AML opcode
|
||||
* 4) Method will be blocked to acquire the global lock
|
||||
* 5) Method will be blocked waiting to execute a serialized control
|
||||
* method that is currently executing
|
||||
* 6) About to invoke a user-installed opregion handler
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
@ -158,44 +136,6 @@ void acpi_ex_exit_interpreter(void)
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_relinquish_interpreter
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Exit the interpreter execution region, from within the
|
||||
* interpreter - before attempting an operation that will possibly
|
||||
* block the running thread.
|
||||
*
|
||||
* Cases where the interpreter is unlocked internally
|
||||
* 1) Method to be blocked on a Sleep() AML opcode
|
||||
* 2) Method to be blocked on an Acquire() AML opcode
|
||||
* 3) Method to be blocked on a Wait() AML opcode
|
||||
* 4) Method to be blocked to acquire the global lock
|
||||
* 5) Method to be blocked waiting to execute a serialized control method
|
||||
* that is currently executing
|
||||
* 6) About to invoke a user-installed opregion handler
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_ex_relinquish_interpreter(void)
|
||||
{
|
||||
ACPI_FUNCTION_TRACE(ex_relinquish_interpreter);
|
||||
|
||||
/*
|
||||
* If the global serialized flag is set, do not release the interpreter.
|
||||
* This forces the interpreter to be single threaded.
|
||||
*/
|
||||
if (!acpi_gbl_all_methods_serialized) {
|
||||
acpi_ex_exit_interpreter();
|
||||
}
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_truncate_for32bit_table
|
||||
|
@ -111,9 +111,8 @@ acpi_status acpi_ns_initialize_objects(void)
|
||||
info.object_count));
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"%u Control Methods found\n", info.method_count));
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"%u Op Regions found\n", info.op_region_count));
|
||||
"%u Control Methods found\n%u Op Regions found\n",
|
||||
info.method_count, info.op_region_count));
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
@ -128,12 +128,12 @@ unlock:
|
||||
* parse trees.
|
||||
*/
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"**** Begin Table Method Parsing and Object Initialization\n"));
|
||||
"**** Begin Table Object Initialization\n"));
|
||||
|
||||
status = acpi_ds_initialize_objects(table_index, node);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"**** Completed Table Method Parsing and Object Initialization\n"));
|
||||
"**** Completed Table Object Initialization\n"));
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
@ -480,6 +480,10 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
|
||||
status = AE_OK;
|
||||
}
|
||||
|
||||
if (status == AE_CTRL_TERMINATE) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
status =
|
||||
acpi_ps_complete_op(walk_state, &op,
|
||||
status);
|
||||
|
@ -219,7 +219,10 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
|
||||
|
||||
status = walk_state->descending_callback(walk_state, op);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog"));
|
||||
if (status != AE_CTRL_TERMINATE) {
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"During name lookup/catalog"));
|
||||
}
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
@ -230,7 +233,7 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
|
||||
status = acpi_ps_next_parse_state(walk_state, *op, status);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
if (status == AE_CTRL_PENDING) {
|
||||
return_ACPI_STATUS(AE_CTRL_PARSE_PENDING);
|
||||
status = AE_CTRL_PARSE_PENDING;
|
||||
}
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
@ -1537,17 +1537,21 @@ static int __init osi_setup(char *str)
|
||||
|
||||
__setup("acpi_osi=", osi_setup);
|
||||
|
||||
/* enable serialization to combat AE_ALREADY_EXISTS errors */
|
||||
static int __init acpi_serialize_setup(char *str)
|
||||
/*
|
||||
* Disable the auto-serialization of named objects creation methods.
|
||||
*
|
||||
* This feature is enabled by default. It marks the AML control methods
|
||||
* that contain the opcodes to create named objects as "Serialized".
|
||||
*/
|
||||
static int __init acpi_no_auto_serialize_setup(char *str)
|
||||
{
|
||||
printk(KERN_INFO PREFIX "serialize enabled\n");
|
||||
|
||||
acpi_gbl_all_methods_serialized = TRUE;
|
||||
acpi_gbl_auto_serialize_methods = FALSE;
|
||||
pr_info("ACPI: auto-serialization disabled\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("acpi_serialize", acpi_serialize_setup);
|
||||
__setup("acpi_no_auto_serialize", acpi_no_auto_serialize_setup);
|
||||
|
||||
/* Check of resource interference between native drivers and ACPI
|
||||
* OperationRegions (SystemIO and System Memory only).
|
||||
|
@ -70,28 +70,6 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int map_gic_id(struct acpi_subtable_header *entry,
|
||||
int device_declaration, u32 acpi_id, int *apic_id)
|
||||
{
|
||||
struct acpi_madt_generic_interrupt *gic =
|
||||
(struct acpi_madt_generic_interrupt *)entry;
|
||||
|
||||
if (!(gic->flags & ACPI_MADT_ENABLED))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* In the GIC interrupt model, logical processors are
|
||||
* required to have a Processor Device object in the DSDT,
|
||||
* so we should check device_declaration here
|
||||
*/
|
||||
if (device_declaration && (gic->uid == acpi_id)) {
|
||||
*apic_id = gic->gic_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int map_madt_entry(int type, u32 acpi_id)
|
||||
{
|
||||
unsigned long madt_end, entry;
|
||||
@ -127,9 +105,6 @@ static int map_madt_entry(int type, u32 acpi_id)
|
||||
} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
|
||||
if (!map_lsapic_id(header, type, acpi_id, &apic_id))
|
||||
break;
|
||||
} else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
|
||||
if (!map_gic_id(header, type, acpi_id, &apic_id))
|
||||
break;
|
||||
}
|
||||
entry += header->length;
|
||||
}
|
||||
@ -160,8 +135,6 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
|
||||
map_lapic_id(header, acpi_id, &apic_id);
|
||||
} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
|
||||
map_lsapic_id(header, type, acpi_id, &apic_id);
|
||||
} else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
|
||||
map_gic_id(header, type, acpi_id, &apic_id);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
@ -285,7 +285,7 @@ int pm_generic_restore(struct device *dev)
|
||||
EXPORT_SYMBOL_GPL(pm_generic_restore);
|
||||
|
||||
/**
|
||||
* pm_generic_complete - Generic routine competing a device power transition.
|
||||
* pm_generic_complete - Generic routine completing a device power transition.
|
||||
* @dev: Device to handle.
|
||||
*
|
||||
* Complete a device power transition during a system-wide power transition.
|
||||
|
@ -270,7 +270,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
|
||||
pr_debug("Old CPU frequency %d kHz, new %d kHz\n",
|
||||
freqs.old, freqs.new);
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
|
||||
/* Disable IRQs */
|
||||
/* local_irq_save(flags); */
|
||||
@ -285,7 +285,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
|
||||
/* Enable IRQs */
|
||||
/* local_irq_restore(flags); */
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
|
||||
cpufreq_freq_transition_end(policy, &freqs, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -331,16 +331,15 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
|
||||
* function. It is called twice on all CPU frequency changes that have
|
||||
* external effects.
|
||||
*/
|
||||
void cpufreq_notify_transition(struct cpufreq_policy *policy,
|
||||
static void cpufreq_notify_transition(struct cpufreq_policy *policy,
|
||||
struct cpufreq_freqs *freqs, unsigned int state)
|
||||
{
|
||||
for_each_cpu(freqs->cpu, policy->cpus)
|
||||
__cpufreq_notify_transition(policy, freqs, state);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
|
||||
|
||||
/* Do post notifications when there are chances that transition has failed */
|
||||
void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
|
||||
static void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
|
||||
struct cpufreq_freqs *freqs, int transition_failed)
|
||||
{
|
||||
cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE);
|
||||
@ -351,7 +350,41 @@ void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
|
||||
cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition);
|
||||
|
||||
void cpufreq_freq_transition_begin(struct cpufreq_policy *policy,
|
||||
struct cpufreq_freqs *freqs)
|
||||
{
|
||||
wait:
|
||||
wait_event(policy->transition_wait, !policy->transition_ongoing);
|
||||
|
||||
spin_lock(&policy->transition_lock);
|
||||
|
||||
if (unlikely(policy->transition_ongoing)) {
|
||||
spin_unlock(&policy->transition_lock);
|
||||
goto wait;
|
||||
}
|
||||
|
||||
policy->transition_ongoing = true;
|
||||
|
||||
spin_unlock(&policy->transition_lock);
|
||||
|
||||
cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_freq_transition_begin);
|
||||
|
||||
void cpufreq_freq_transition_end(struct cpufreq_policy *policy,
|
||||
struct cpufreq_freqs *freqs, int transition_failed)
|
||||
{
|
||||
if (unlikely(WARN_ON(!policy->transition_ongoing)))
|
||||
return;
|
||||
|
||||
cpufreq_notify_post_transition(policy, freqs, transition_failed);
|
||||
|
||||
policy->transition_ongoing = false;
|
||||
|
||||
wake_up(&policy->transition_wait);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_freq_transition_end);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
@ -985,6 +1018,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(void)
|
||||
|
||||
INIT_LIST_HEAD(&policy->policy_list);
|
||||
init_rwsem(&policy->rwsem);
|
||||
spin_lock_init(&policy->transition_lock);
|
||||
init_waitqueue_head(&policy->transition_wait);
|
||||
|
||||
return policy;
|
||||
|
||||
@ -1470,8 +1505,8 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
|
||||
policy = per_cpu(cpufreq_cpu_data, cpu);
|
||||
read_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
cpufreq_freq_transition_end(policy, &freqs, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1652,14 +1687,13 @@ void cpufreq_resume(void)
|
||||
cpufreq_suspended = false;
|
||||
|
||||
list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
|
||||
if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
|
||||
if (cpufreq_driver->resume && cpufreq_driver->resume(policy))
|
||||
pr_err("%s: Failed to resume driver: %p\n", __func__,
|
||||
policy);
|
||||
else if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
|
||||
|| __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
|
||||
pr_err("%s: Failed to start governor for policy: %p\n",
|
||||
__func__, policy);
|
||||
else if (cpufreq_driver->resume
|
||||
&& cpufreq_driver->resume(policy))
|
||||
pr_err("%s: Failed to resume driver: %p\n", __func__,
|
||||
policy);
|
||||
|
||||
/*
|
||||
* schedule call cpufreq_update_policy() for boot CPU, i.e. last
|
||||
@ -1832,8 +1866,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
|
||||
pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
|
||||
__func__, policy->cpu, freqs.old, freqs.new);
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs,
|
||||
CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
}
|
||||
|
||||
retval = cpufreq_driver->target_index(policy, index);
|
||||
@ -1842,7 +1875,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
|
||||
__func__, retval);
|
||||
|
||||
if (notify)
|
||||
cpufreq_notify_post_transition(policy, &freqs, retval);
|
||||
cpufreq_freq_transition_end(policy, &freqs, retval);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -219,7 +219,7 @@ static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
|
||||
freqs.old = policy->cur;
|
||||
freqs.new = freq_table[index].frequency;
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
|
||||
/* Set the target frequency in all C0_3_PSTATE register */
|
||||
for_each_cpu(i, policy->cpus) {
|
||||
@ -258,7 +258,7 @@ static void exynos_cpufreq_work(struct work_struct *work)
|
||||
dev_crit(dvfs_info->dev, "New frequency out of range\n");
|
||||
freqs.new = freqs.old;
|
||||
}
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
|
||||
cpufreq_freq_transition_end(policy, &freqs, 0);
|
||||
|
||||
cpufreq_cpu_put(policy);
|
||||
mutex_unlock(&cpufreq_lock);
|
||||
|
@ -265,7 +265,7 @@ static void gx_set_cpuspeed(struct cpufreq_policy *policy, unsigned int khz)
|
||||
|
||||
freqs.new = new_khz;
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
local_irq_save(flags);
|
||||
|
||||
if (new_khz != stock_freq) {
|
||||
@ -314,7 +314,7 @@ static void gx_set_cpuspeed(struct cpufreq_policy *policy, unsigned int khz)
|
||||
|
||||
gx_params->pci_suscfg = suscfg;
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
|
||||
cpufreq_freq_transition_end(policy, &freqs, 0);
|
||||
|
||||
pr_debug("suspend modulation w/ duration of ON:%d us, OFF:%d us\n",
|
||||
gx_params->on_duration * 32, gx_params->off_duration * 32);
|
||||
|
@ -122,7 +122,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
|
||||
return 0;
|
||||
}
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
|
||||
cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
|
||||
|
||||
@ -143,7 +143,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
|
||||
*/
|
||||
set_cpus_allowed(current, cpus_allowed);
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
|
||||
cpufreq_freq_transition_end(policy, &freqs, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -778,7 +778,7 @@ static void intel_pstate_stop_cpu(struct cpufreq_policy *policy)
|
||||
|
||||
pr_info("intel_pstate CPU %d exiting\n", cpu_num);
|
||||
|
||||
del_timer(&all_cpu_data[cpu_num]->timer);
|
||||
del_timer_sync(&all_cpu_data[cpu_num]->timer);
|
||||
intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
|
||||
kfree(all_cpu_data[cpu_num]);
|
||||
all_cpu_data[cpu_num] = NULL;
|
||||
|
@ -269,7 +269,7 @@ static void longhaul_setstate(struct cpufreq_policy *policy,
|
||||
freqs.old = calc_speed(longhaul_get_cpu_mult());
|
||||
freqs.new = speed;
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
|
||||
pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
|
||||
fsb, mult/10, mult%10, print_speed(speed/1000));
|
||||
@ -386,7 +386,7 @@ retry_loop:
|
||||
}
|
||||
}
|
||||
/* Report true CPU frequency */
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
|
||||
cpufreq_freq_transition_end(policy, &freqs, 0);
|
||||
|
||||
if (!bm_timeout)
|
||||
printk(KERN_INFO PFX "Warning: Timeout while waiting for "
|
||||
|
@ -215,7 +215,7 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy,
|
||||
|
||||
freqs.old = policy->cur;
|
||||
freqs.new = target_freq;
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
|
||||
input_buffer = 0x1 | (((target_freq * 100)
|
||||
/ (ioread32(&pcch_hdr->nominal) * 1000)) << 8);
|
||||
@ -231,7 +231,7 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy,
|
||||
status = ioread16(&pcch_hdr->status);
|
||||
iowrite16(0, &pcch_hdr->status);
|
||||
|
||||
cpufreq_notify_post_transition(policy, &freqs, status != CMD_COMPLETE);
|
||||
cpufreq_freq_transition_end(policy, &freqs, status != CMD_COMPLETE);
|
||||
spin_unlock(&pcc_lock);
|
||||
|
||||
if (status != CMD_COMPLETE) {
|
||||
|
@ -148,11 +148,11 @@ static int powernow_k6_target(struct cpufreq_policy *policy,
|
||||
freqs.old = busfreq * powernow_k6_get_cpu_multiplier();
|
||||
freqs.new = busfreq * clock_ratio[best_i].driver_data;
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
|
||||
powernow_k6_set_cpu_multiplier(best_i);
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
|
||||
cpufreq_freq_transition_end(policy, &freqs, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -269,7 +269,7 @@ static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
|
||||
|
||||
freqs.new = powernow_table[index].frequency;
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
|
||||
/* Now do the magic poking into the MSRs. */
|
||||
|
||||
@ -290,7 +290,7 @@ static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
|
||||
if (have_a0 == 1)
|
||||
local_irq_enable();
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
|
||||
cpufreq_freq_transition_end(policy, &freqs, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -963,9 +963,9 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
|
||||
policy = cpufreq_cpu_get(smp_processor_id());
|
||||
cpufreq_cpu_put(policy);
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
res = transition_fid_vid(data, fid, vid);
|
||||
cpufreq_notify_post_transition(policy, &freqs, res);
|
||||
cpufreq_freq_transition_end(policy, &freqs, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy,
|
||||
s3c_cpufreq_updateclk(clk_pclk, cpu_new.freq.pclk);
|
||||
|
||||
/* start the frequency change */
|
||||
cpufreq_notify_transition(policy, &freqs.freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs.freqs);
|
||||
|
||||
/* If hclk is staying the same, then we do not need to
|
||||
* 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,
|
||||
local_irq_restore(flags);
|
||||
|
||||
/* notify everyone we've done this */
|
||||
cpufreq_notify_transition(policy, &freqs.freqs, CPUFREQ_POSTCHANGE);
|
||||
cpufreq_freq_transition_end(policy, &freqs.freqs, 0);
|
||||
|
||||
s3c_freq_dbg("%s: finished\n", __func__);
|
||||
return 0;
|
||||
|
@ -68,10 +68,10 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy,
|
||||
freqs.new = (freq + 500) / 1000;
|
||||
freqs.flags = 0;
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
set_cpus_allowed_ptr(current, &cpus_allowed);
|
||||
clk_set_rate(cpuclk, freq);
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
|
||||
cpufreq_freq_transition_end(policy, &freqs, 0);
|
||||
|
||||
dev_dbg(dev, "set frequency %lu Hz\n", freq);
|
||||
|
||||
|
@ -44,9 +44,9 @@ static int ucv2_target(struct cpufreq_policy *policy,
|
||||
freqs.old = policy->cur;
|
||||
freqs.new = target_freq;
|
||||
|
||||
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
ret = clk_set_rate(policy->mclk, target_freq * 1000);
|
||||
cpufreq_notify_post_transition(policy, &freqs, ret);
|
||||
cpufreq_freq_transition_end(policy, &freqs, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
|
||||
* device is active because it itself may be in use */
|
||||
if (!dev->active) {
|
||||
if (request_irq(*irq, pnp_test_handler,
|
||||
IRQF_DISABLED | IRQF_PROBE_SHARED, "pnp", NULL))
|
||||
IRQF_PROBE_SHARED, "pnp", NULL))
|
||||
return 0;
|
||||
free_irq(*irq, NULL);
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ extern u32 acpi_dbg_layer;
|
||||
|
||||
/* ACPICA runtime options */
|
||||
|
||||
extern u8 acpi_gbl_all_methods_serialized;
|
||||
extern u8 acpi_gbl_auto_serialize_methods;
|
||||
extern u8 acpi_gbl_copy_dsdt_locally;
|
||||
extern u8 acpi_gbl_create_osi_method;
|
||||
extern u8 acpi_gbl_disable_auto_repair;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/completion.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
/*********************************************************************
|
||||
@ -104,6 +105,11 @@ struct cpufreq_policy {
|
||||
* __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
|
||||
*/
|
||||
struct rw_semaphore rwsem;
|
||||
|
||||
/* Synchronization for frequency transitions */
|
||||
bool transition_ongoing; /* Tracks transition status */
|
||||
spinlock_t transition_lock;
|
||||
wait_queue_head_t transition_wait;
|
||||
};
|
||||
|
||||
/* Only for ACPI */
|
||||
@ -333,9 +339,9 @@ static inline void cpufreq_resume(void) {}
|
||||
int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list);
|
||||
int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
|
||||
|
||||
void cpufreq_notify_transition(struct cpufreq_policy *policy,
|
||||
struct cpufreq_freqs *freqs, unsigned int state);
|
||||
void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
|
||||
void cpufreq_freq_transition_begin(struct cpufreq_policy *policy,
|
||||
struct cpufreq_freqs *freqs);
|
||||
void cpufreq_freq_transition_end(struct cpufreq_policy *policy,
|
||||
struct cpufreq_freqs *freqs, int transition_failed);
|
||||
|
||||
#else /* CONFIG_CPU_FREQ */
|
||||
|
Loading…
Reference in New Issue
Block a user