From 5dc17986fdc3d2425838cb8d699152c3c30d1208 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 22 Jul 2013 16:08:25 +0800 Subject: ACPI: Add facility to disable all _OSI OS vendor strings This patch introduces "acpi_osi=!" command line to force Linux replying "UNSUPPORTED" to all of the _OSI strings. This patch is based on an ACPICA enhancement - the new API acpi_update_interfaces(). The _OSI object provides the platform with the ability to query OSPM to determine the set of ACPI related interfaces, behaviors, or features that the operating system supports. The argument passed to the _OSI is a string like the followings: 1. Feature Group String, examples include Module Device Processor Device 3.0 _SCP Extensions Processor Aggregator Device ... 2. OS Vendor String, examples include Linux FreeBSD Windows ... There are AML codes provided in the ACPI namespace written in the following style to determine OSPM interfaces / features: Method(OSCK) { if (CondRefOf(_OSI, Local0)) { if (\_OSI("Windows")) { Return (One) } if (\_OSI("Windows 2006")) { Return (Ones) } Return (Zero) } Return (Zero) } There is a debugging facility implemented in Linux. Users can pass "acpi_osi=" boot parameters to the kernel to tune the _OSI evaluation result so that certain AML codes can be executed. Current implementation includes: 1. 'acpi_osi=' - this makes CondRefOf(_OSI, Local0) TRUE 2. 'acpi_osi="Windows"' - this makes \_OSI("Windows") TRUE 3. 'acpi_osi="!Windows"' - this makes \_OSI("Windows") FALSE The function to implement this feature is also used as a quirk mechanism in the Linux ACPI subystem. When _OSI is evaluatated by the AML codes, ACPICA replies "SUPPORTED" to all Windows operating system vendor strings. This is because Windows operating systems return "SUPPORTED" if the argument to the _OSI method specifies an earlier version of Windows. Please refer to the following MSDN document: How to Identify the Windows Version in ACPI by Using _OSI http://msdn.microsoft.com/en-us/library/hardware/gg463275.aspx This adds difficulties when developers want to feed specific Windows operating system vendor string to the BIOS codes for debugging purpose, multiple acpi_osi="!xxx" have to be specified in the command line to force Linux replying "UNSUPPORTED" to the Windows OS vendor strings listed in the AML codes. Signed-off-by: Lv Zheng Reviewed-by: Zhang Rui Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/acpi/osl.c') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 6ab2c3505520..e8baa408faef 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -140,7 +140,8 @@ static struct osi_linux { unsigned int enable:1; unsigned int dmi:1; unsigned int cmdline:1; -} osi_linux = {0, 0, 0}; + unsigned int default_disabling:1; +} osi_linux = {0, 0, 0, 0}; static u32 acpi_osi_handler(acpi_string interface, u32 supported) { @@ -1376,6 +1377,10 @@ void __init acpi_osi_setup(char *str) if (*str == '!') { str++; + if (*str == '\0') { + osi_linux.default_disabling = 1; + return; + } enable = false; } @@ -1441,6 +1446,13 @@ static void __init acpi_osi_setup_late(void) int i; acpi_status status; + if (osi_linux.default_disabling) { + status = acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS); + + if (ACPI_SUCCESS(status)) + printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors\n"); + } + for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { osi = &osi_setup_entries[i]; str = osi->string; -- cgit v1.2.3 From 741d81280ad2b31fc3d76c49fa5c1fe09f3a6f68 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 22 Jul 2013 16:08:36 +0800 Subject: ACPI: Add facility to remove all _OSI strings This patch changes the "acpi_osi=" boot parameter implementation so that: 1. "acpi_osi=!" can be used to disable all _OSI OS vendor strings by default. It is meaningless to specify "acpi_osi=!" multiple times as it can only affect the default state of the target _OSI strings. 2. "acpi_osi=!*" can be used to remove all _OSI OS vendor strings and all _OSI feature group strings. It is useful to specify "acpi_osi=!*" multiple times through kernel command line to override the current state of the target _OSI strings. Signed-off-by: Lv Zheng Reviewed-by: Zhang Rui Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/acpi/osl.c') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e8baa408faef..cc1ed12d0b89 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1380,6 +1380,13 @@ void __init acpi_osi_setup(char *str) if (*str == '\0') { osi_linux.default_disabling = 1; return; + } else if (*str == '*') { + acpi_update_interfaces(ACPI_DISABLE_ALL_STRINGS); + for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { + osi = &osi_setup_entries[i]; + osi->enable = false; + } + return; } enable = false; } -- cgit v1.2.3 From 1129c92faa069581bf3acf34cae92477bd6161d8 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 23 Jul 2013 16:11:55 +0800 Subject: ACPI: Cleanup sparse warning on acpi_os_initialize1() This patch cleans up the following sparse warning: # make C=2 drivers/acpi/osl.o ... drivers/acpi/osl.c:1775:20: warning: symbol 'acpi_os_initialize1' was not declared. Should it be static? ... CC drivers/acpi/osl.o Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi/osl.c') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 6ab2c3505520..605718f66642 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -52,6 +52,7 @@ #include #include #include +#include "internal.h" #define _COMPONENT ACPI_OS_SERVICES ACPI_MODULE_NAME("osl"); -- cgit v1.2.3 From d6b47b122473885abc882e337ac2d321bbcfb378 Mon Sep 17 00:00:00 2001 From: Ben Guthro Date: Tue, 30 Jul 2013 08:24:52 -0400 Subject: ACPI / sleep: Introduce acpi_os_prepare_extended_sleep() for extended sleep path Like acpi_os_prepare_sleep(), register a callback for use in systems like tboot, and xen, which have system specific requirements outside of ACPICA. This mirrors the functionality in acpi_os_prepare_sleep(), called from acpi_hw_sleep() Signed-off-by: Ben Guthro Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/acpi/osl.c') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 6ab2c3505520..a934950ff7a0 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -79,6 +79,8 @@ extern char line_buf[80]; static int (*__acpi_os_prepare_sleep)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl); +static int (*__acpi_os_prepare_extended_sleep)(u8 sleep_state, u32 val_a, + u32 val_b); static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; @@ -1779,6 +1781,28 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, __acpi_os_prepare_sleep = func; } +acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, + u32 val_b) +{ + int rc = 0; + if (__acpi_os_prepare_extended_sleep) + rc = __acpi_os_prepare_extended_sleep(sleep_state, + val_a, val_b); + if (rc < 0) + return AE_ERROR; + else if (rc > 0) + return AE_CTRL_SKIP; + + return AE_OK; +} + +void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, + u32 val_a, u32 val_b)) +{ + __acpi_os_prepare_extended_sleep = func; +} + + void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context, void (*func)(struct work_struct *work)) { -- cgit v1.2.3 From e73d3136355f511d3e1c2ef21acf02b19bd2b650 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 13 Aug 2013 18:31:15 +0800 Subject: ACPI / osl: Fix osi_setup_entries[] __initdata attribute location __initdata should come after the variable name being declared and nowhere else, in this way the variable will be placed in the intended section. Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi/osl.c') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 605718f66642..eb95978854a3 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1352,8 +1352,8 @@ struct osi_setup_entry { bool enable; }; -static struct osi_setup_entry __initdata - osi_setup_entries[OSI_STRING_ENTRIES_MAX] = { +static struct osi_setup_entry + osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = { {"Module Device", true}, {"Processor Device", true}, {"3.0 _SCP Extensions", true}, -- cgit v1.2.3 From 7702ae0dd9b40930931914866999a2ac9734d3eb Mon Sep 17 00:00:00 2001 From: Tang Chen Date: Wed, 14 Aug 2013 17:37:08 +0800 Subject: ACPI / osl: Kill macro INVALID_TABLE(). The macro INVALID_TABLE() is defined like this: #define INVALID_TABLE(x, path, name) \ { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; } And it is used like this: for (...) { ... if (...) INVALID_TABLE() ... } The "continue" in the macro makes the code hard to understand. And also, this macro is only used several times in a single file. As suggested by Joe Perches , we can remote it and use pr_err directly. So after this patch, this macro is removed, and pr_err() is used like this: for (...) { ... if (...) { pr_err("ACPI OVERRIDE: ......"); continue; } ... } Signed-off-by: Tang Chen Suggested-by: Joe Perches Acked-by: Tejun Heo Acked-by: Toshi Kani Reviewed-by: Zhang Yanfei Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'drivers/acpi/osl.c') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index eb95978854a3..6bc08272f050 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -564,10 +564,6 @@ static const char * const table_sigs[] = { ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT, ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL }; -/* Non-fatal errors: Affected tables/files are ignored */ -#define INVALID_TABLE(x, path, name) \ - { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; } - #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) /* Must not increase 10 or needs code modification below */ @@ -594,9 +590,11 @@ void __init acpi_initrd_override(void *data, size_t size) data += offset; size -= offset; - if (file.size < sizeof(struct acpi_table_header)) - INVALID_TABLE("Table smaller than ACPI header", - cpio_path, file.name); + if (file.size < sizeof(struct acpi_table_header)) { + pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n", + cpio_path, file.name); + continue; + } table = file.data; @@ -604,15 +602,21 @@ void __init acpi_initrd_override(void *data, size_t size) if (!memcmp(table->signature, table_sigs[sig], 4)) break; - if (!table_sigs[sig]) - INVALID_TABLE("Unknown signature", - cpio_path, file.name); - if (file.size != table->length) - INVALID_TABLE("File length does not match table length", - cpio_path, file.name); - if (acpi_table_checksum(file.data, table->length)) - INVALID_TABLE("Bad table checksum", - cpio_path, file.name); + if (!table_sigs[sig]) { + pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n", + cpio_path, file.name); + continue; + } + if (file.size != table->length) { + pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n", + cpio_path, file.name); + continue; + } + if (acpi_table_checksum(file.data, table->length)) { + pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n", + cpio_path, file.name); + continue; + } pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n", table->signature, cpio_path, file.name, table->length); -- cgit v1.2.3