From 4dcd78d80d37a360f5faab422a4e48b2cfd4abe4 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 27 Nov 2014 14:26:00 +0800 Subject: ACPICA: iASL: Add support for to_PLD macro. This macro is intended to simplify the constuction of _PLD buffers. NOTE: Prototype only, subject to change before this macro is added to the ACPI specification. David E. Box. Signed-off-by: David E. Box Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utxface.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 502a8492dc83..49c873c68756 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -531,7 +531,9 @@ acpi_decode_pld_buffer(u8 *in_buffer, ACPI_MOVE_32_TO_32(&dword, &buffer[0]); pld_info->revision = ACPI_PLD_GET_REVISION(&dword); pld_info->ignore_color = ACPI_PLD_GET_IGNORE_COLOR(&dword); - pld_info->color = ACPI_PLD_GET_COLOR(&dword); + pld_info->red = ACPI_PLD_GET_RED(&dword); + pld_info->green = ACPI_PLD_GET_GREEN(&dword); + pld_info->blue = ACPI_PLD_GET_BLUE(&dword); /* Second 32-bit DWord */ -- cgit v1.2.3 From b487867c9356d70345d96fbef86ea58d19cc7be6 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 27 Nov 2014 14:26:07 +0800 Subject: ACPICA: acpiexec: Add option to specify an object initialization file. This option (-fi) allows the specification of a file that is used to specify initialization values for individual namespace objects. Each line in the file is in the format: This patch only affects acpiexec which is not in the Linux kernel. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utxfinit.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index 13380d818462..b1fd6886e439 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -53,6 +53,9 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utxfinit") +/* For acpi_exec only */ +void ae_do_object_overrides(void); + /******************************************************************************* * * FUNCTION: acpi_initialize_subsystem @@ -65,6 +68,7 @@ ACPI_MODULE_NAME("utxfinit") * called, so any early initialization belongs here. * ******************************************************************************/ + acpi_status __init acpi_initialize_subsystem(void) { acpi_status status; @@ -275,6 +279,13 @@ acpi_status __init acpi_initialize_objects(u32 flags) return_ACPI_STATUS(status); } } +#ifdef ACPI_EXEC_APP + /* + * This call implements the "initialization file" option for acpi_exec. + * This is the precise point that we want to perform the overrides. + */ + ae_do_object_overrides(); +#endif /* * Execute any module-level code that was detected during the table load -- cgit v1.2.3 From 5f040fc77632eed68a89080ee2d2d8fd7b5f6df5 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 27 Nov 2014 14:26:12 +0800 Subject: ACPICA: Disassembler: Add support for C-style operators and expressions. Now emit ASL+ code which includes C-style operators. Optionally, legacy text ASL operators can still be emitted. This patch only affects compiler/disassembler support which is not in the Linux kernel. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acglobal.h | 1 + drivers/acpi/acpica/aclocal.h | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index ebf02cc10a43..7f60582d0c8c 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -305,6 +305,7 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_db_output_flags, ACPI_DB_CONSOLE_OUTPUT); ACPI_INIT_GLOBAL(u8, acpi_gbl_no_resource_disassembly, FALSE); ACPI_INIT_GLOBAL(u8, acpi_gbl_ignore_noop_operator, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_cstyle_disassembly, TRUE); ACPI_GLOBAL(u8, acpi_gbl_db_opt_disasm); ACPI_GLOBAL(u8, acpi_gbl_db_opt_verbose); diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index c00e7e41ad75..1c218d9478cb 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -722,6 +722,7 @@ union acpi_parse_value { ACPI_DISASM_ONLY_MEMBERS (\ u8 disasm_flags; /* Used during AML disassembly */\ u8 disasm_opcode; /* Subtype used for disassembly */\ + char *operator_symbol;/* Used for C-style operator name strings */\ char aml_op_name[16]) /* Op name (debug only) */ /* Flags for disasm_flags field above */ @@ -827,6 +828,7 @@ struct acpi_parse_state { #define ACPI_PARSEOP_EMPTY_TERMLIST 0x04 #define ACPI_PARSEOP_PREDEF_CHECKED 0x08 #define ACPI_PARSEOP_SPECIAL 0x10 +#define ACPI_PARSEOP_COMPOUND 0x20 /***************************************************************************** * -- cgit v1.2.3 From f8c73f8a64f48940d554ea2c4186ce7d778c46dc Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 27 Nov 2014 14:26:21 +0800 Subject: ACPICA: Disassembler: Update for C-style expressions. Add extra set of parens for assignments within an expression. This patch only affects compiler support which is not in the Linux kernel. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/aclocal.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 1c218d9478cb..80c74e90f3cc 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -829,6 +829,7 @@ struct acpi_parse_state { #define ACPI_PARSEOP_PREDEF_CHECKED 0x08 #define ACPI_PARSEOP_SPECIAL 0x10 #define ACPI_PARSEOP_COMPOUND 0x20 +#define ACPI_PARSEOP_ASSIGNMENT 0x40 /***************************************************************************** * -- cgit v1.2.3 From 11811738998bbaf6a96d086e1634cdb753b4726b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 27 Nov 2014 14:26:28 +0800 Subject: ACPICA: Disassembler: Emit correct string for 0 stop bits. Was stop_bits_none, corrected to stop_bits_zero. David E. Box. Signed-off-by: David E. Box Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utresrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index 5cd017c7ac0e..bc1ff820c7dd 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -263,7 +263,7 @@ const char *acpi_gbl_bpb_decode[] = { /* UART serial bus stop bits */ const char *acpi_gbl_sb_decode[] = { - "StopBitsNone", + "StopBitsZero", "StopBitsOne", "StopBitsOnePlusHalf", "StopBitsTwo" -- cgit v1.2.3 From c50f13c672df758b59e026c15b9118f3ed46edc4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 1 Dec 2014 23:50:16 +0100 Subject: ACPICA: Save current masks of enabled GPEs after enable register writes There is a race condition between acpi_hw_disable_all_gpes() or acpi_enable_all_wakeup_gpes() and acpi_ev_asynch_enable_gpe() such that if the latter wins the race, it may mistakenly enable a GPE disabled by the former. This may lead to premature system wakeups during system suspend and potentially to more serious consequences. The source of the problem is how acpi_hw_low_set_gpe() works when passed ACPI_GPE_CONDITIONAL_ENABLE as the second argument. In that case, the GPE will be enabled if the corresponding bit is set in the enable_for_run mask of the GPE enable register containing that bit. However, acpi_hw_disable_all_gpes() and acpi_enable_all_wakeup_gpes() don't modify the enable_for_run masks of GPE registers when writing to them. In consequence, if acpi_ev_asynch_enable_gpe(), which eventually calls acpi_hw_low_set_gpe() with the second argument equal to ACPI_GPE_CONDITIONAL_ENABLE, is executed in parallel with one of these functions, it may reverse changes made by them. To fix the problem, introduce a new enable_mask field in struct acpi_gpe_register_info in which to store the current mask of enabled GPEs and modify acpi_hw_low_set_gpe() to take this mask into account instead of enable_for_run when its second argument is equal to ACPI_GPE_CONDITIONAL_ENABLE. Also modify the low-level routines called by acpi_hw_disable_all_gpes(), acpi_enable_all_wakeup_gpes() and acpi_enable_all_runtime_gpes() to update the enable_mask masks of GPE registers after all (successful) writes to those registers. Acked-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/aclocal.h | 1 + drivers/acpi/acpica/evgpe.c | 6 ++--- drivers/acpi/acpica/hwgpe.c | 53 +++++++++++++++++++++++++++++++++++-------- include/acpi/actypes.h | 4 ++++ 4 files changed, 51 insertions(+), 13 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 80c74e90f3cc..680d23bbae7c 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -454,6 +454,7 @@ struct acpi_gpe_register_info { u16 base_gpe_number; /* Base GPE number for this register */ u8 enable_for_wake; /* GPEs to keep enabled when sleeping */ u8 enable_for_run; /* GPEs to keep enabled when running */ + u8 enable_mask; /* Current mask of enabled GPEs */ }; /* diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 2095dfb72bcb..81db932b15ee 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -134,7 +134,7 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) /* Enable the requested GPE */ - status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); + status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE_SAVE); return_ACPI_STATUS(status); } @@ -213,7 +213,7 @@ acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) if (ACPI_SUCCESS(status)) { status = acpi_hw_low_set_gpe(gpe_event_info, - ACPI_GPE_DISABLE); + ACPI_GPE_DISABLE_SAVE); } if (ACPI_FAILURE(status)) { @@ -655,7 +655,7 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info * gpe_event_info) /* * Enable this GPE, conditionally. This means that the GPE will - * only be physically enabled if the enable_for_run bit is set + * only be physically enabled if the enable_mask bit is set * in the event_info. */ (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 48ac7b7b59cd..494027f5c067 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -115,12 +115,12 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) /* Set or clear just the bit that corresponds to this GPE */ register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); - switch (action) { + switch (action & ~ACPI_GPE_SAVE_MASK) { case ACPI_GPE_CONDITIONAL_ENABLE: - /* Only enable if the enable_for_run bit is set */ + /* Only enable if the corresponding enable_mask bit is set */ - if (!(register_bit & gpe_register_info->enable_for_run)) { + if (!(register_bit & gpe_register_info->enable_mask)) { return (AE_BAD_PARAMETER); } @@ -145,6 +145,9 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) /* Write the updated enable mask */ status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); + if (ACPI_SUCCESS(status) && (action & ACPI_GPE_SAVE_MASK)) { + gpe_register_info->enable_mask = enable_mask; + } return (status); } @@ -260,6 +263,32 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, return (AE_OK); } +/****************************************************************************** + * + * FUNCTION: acpi_hw_gpe_enable_write + * + * PARAMETERS: enable_mask - Bit mask to write to the GPE register + * gpe_register_info - Gpe Register info + * + * RETURN: Status + * + * DESCRIPTION: Write the enable mask byte to the given GPE register. + * + ******************************************************************************/ + +static acpi_status +acpi_hw_gpe_enable_write(u8 enable_mask, + struct acpi_gpe_register_info *gpe_register_info) +{ + acpi_status status; + + status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); + if (ACPI_SUCCESS(status)) { + gpe_register_info->enable_mask = enable_mask; + } + return (status); +} + /****************************************************************************** * * FUNCTION: acpi_hw_disable_gpe_block @@ -287,8 +316,8 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /* Disable all GPEs in this register */ status = - acpi_hw_write(0x00, - &gpe_block->register_info[i].enable_address); + acpi_hw_gpe_enable_write(0x00, + &gpe_block->register_info[i]); if (ACPI_FAILURE(status)) { return (status); } @@ -355,21 +384,23 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, { u32 i; acpi_status status; + struct acpi_gpe_register_info *gpe_register_info; /* NOTE: assumes that all GPEs are currently disabled */ /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { - if (!gpe_block->register_info[i].enable_for_run) { + gpe_register_info = &gpe_block->register_info[i]; + if (!gpe_register_info->enable_for_run) { continue; } /* Enable all "runtime" GPEs in this register */ status = - acpi_hw_write(gpe_block->register_info[i].enable_for_run, - &gpe_block->register_info[i].enable_address); + acpi_hw_gpe_enable_write(gpe_register_info->enable_for_run, + gpe_register_info); if (ACPI_FAILURE(status)) { return (status); } @@ -399,10 +430,12 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, { u32 i; acpi_status status; + struct acpi_gpe_register_info *gpe_register_info; /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { + gpe_register_info = &gpe_block->register_info[i]; /* * Enable all "wake" GPEs in this register and disable the @@ -410,8 +443,8 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, */ status = - acpi_hw_write(gpe_block->register_info[i].enable_for_wake, - &gpe_block->register_info[i].enable_address); + acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake, + gpe_register_info); if (ACPI_FAILURE(status)) { return (status); } diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 7000e66f768e..bbef17368e49 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -736,6 +736,10 @@ typedef u32 acpi_event_status; #define ACPI_GPE_ENABLE 0 #define ACPI_GPE_DISABLE 1 #define ACPI_GPE_CONDITIONAL_ENABLE 2 +#define ACPI_GPE_SAVE_MASK 4 + +#define ACPI_GPE_ENABLE_SAVE (ACPI_GPE_ENABLE | ACPI_GPE_SAVE_MASK) +#define ACPI_GPE_DISABLE_SAVE (ACPI_GPE_DISABLE | ACPI_GPE_SAVE_MASK) /* * GPE info flags - Per GPE -- cgit v1.2.3 From 7dd882195695871d6da046de036214d32f09e2ea Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 2 Dec 2014 08:56:55 +0800 Subject: ACPICA: Events: Always modify GPE registers under the GPE lock It is reported that there are pieces of code invoking acpi_ev_finish_gpe() without holding acpi_gbl_gpe_lock. Since this function will modify GPE register values, there could be races breaking the register modification process. This patch fixes this issue. Lv Zheng. Reported-by: Joe Liu Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evgpe.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 81db932b15ee..aa70154cf4fa 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -616,8 +616,11 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context) { struct acpi_gpe_event_info *gpe_event_info = context; + acpi_cpu_flags flags; + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); (void)acpi_ev_finish_gpe(gpe_event_info); + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); ACPI_FREE(gpe_event_info); return; -- cgit v1.2.3