From 5ae74f2cc2f150c1a5cee54cabbd71dd0661285a Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 11 Apr 2016 10:13:18 +0800 Subject: ACPI / tables: Move table override mechanisms to tables.c This patch moves acpi_os_table_override() and acpi_os_physical_table_override() to tables.c. Along with the mechanisms, acpi_initrd_initialize_tables() is also moved to tables.c to form a static function. The following functions are renamed according to this change: 1. acpi_initrd_override() -> renamed to early_acpi_table_init(), which invokes acpi_table_initrd_init() 2. acpi_os_physical_table_override() -> which invokes acpi_table_initrd_override() 3. acpi_initialize_initrd_tables() -> renamed to acpi_table_initrd_scan() Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/linux/acpi.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'include/linux/acpi.h') diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 06ed7e54033e..7718c04aa09f 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -190,14 +190,6 @@ static inline int acpi_debugger_notify_command_complete(void) } #endif -#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE -void acpi_initrd_override(void *data, size_t size); -#else -static inline void acpi_initrd_override(void *data, size_t size) -{ -} -#endif - #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ ((struct acpi_subtable_header *)entry)->length < sizeof(*entry)) @@ -216,6 +208,7 @@ void acpi_boot_table_init (void); int acpi_mps_check (void); int acpi_numa_init (void); +void early_acpi_table_init(void *data, size_t size); int acpi_table_init (void); int acpi_table_parse(char *id, acpi_tbl_table_handler handler); int __init acpi_parse_entries(char *id, unsigned long table_size, @@ -596,6 +589,7 @@ static inline const char *acpi_dev_name(struct acpi_device *adev) return NULL; } +static inline void early_acpi_table_init(void *data, size_t size) { } static inline void acpi_early_init(void) { } static inline void acpi_subsystem_init(void) { } -- cgit v1.2.3-59-g8ed1b From e10cfdc33a0f23dc8449be7267f0a642e96a2a24 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Tue, 3 May 2016 16:48:39 +0800 Subject: ACPI / osi: Fix default _OSI(Darwin) support The following commit always reports positive value when Apple hardware queries _OSI("Darwin"): Commit: 7bc5a2bad0b8d9d1ac9f7b8b33150e4ddf197334 Subject: ACPI: Support _OSI("Darwin") correctly However since this implementation places the judgement in runtime, it breaks acpi_osi=!Darwin and cannot return unsupported for _OSI("WinXXX") invoked before invoking _OSI("Darwin"). This patch fixes the issues by reverting the wrong support and implementing the default behavior of _OSI("Darwin")/_OSI("WinXXX") on Apple hardware via DMI matching. Fixes: 7bc5a2bad0b8 (ACPI: Support _OSI("Darwin") correctly) Link: https://bugzilla.kernel.org/show_bug.cgi?id=92111 Reported-and-tested-by: Lukas Wunner Signed-off-by: Chen Yu Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 23 +++++++++++++++++++ drivers/acpi/osl.c | 58 ++++++++++++++++++++++++++++++++++++++++++------ include/linux/acpi.h | 1 + 3 files changed, 75 insertions(+), 7 deletions(-) (limited to 'include/linux/acpi.h') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 96809cd99ace..45390a953fb2 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -133,6 +133,11 @@ int __init acpi_blacklisted(void) return blacklisted; } #ifdef CONFIG_DMI +static int __init dmi_enable_osi_darwin(const struct dmi_system_id *d) +{ + acpi_dmi_osi_darwin(1, d); /* enable */ + return 0; +} static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) { acpi_dmi_osi_linux(1, d); /* enable */ @@ -331,6 +336,24 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, + /* + * Enable _OSI("Darwin") for all apple platforms. + */ + { + .callback = dmi_enable_osi_darwin, + .ident = "Apple hardware", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + }, + }, + { + .callback = dmi_enable_osi_darwin, + .ident = "Apple hardware", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), + }, + }, + #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE /* * DELL XPS 13 (2015) switches sound between HDA and I2S diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index f801b59f2a94..1b84e4635ae0 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -135,6 +135,9 @@ static struct acpi_osi_config { unsigned int linux_enable:1; unsigned int linux_dmi:1; unsigned int linux_cmdline:1; + unsigned int darwin_enable:1; + unsigned int darwin_dmi:1; + unsigned int darwin_cmdline:1; u8 default_disabling; } osi_config = {0, 0, 0, 0}; @@ -150,13 +153,12 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported) } if (!strcmp("Darwin", interface)) { - /* - * Apple firmware will behave poorly if it receives positive - * answers to "Darwin" and any other OS. Respond positively - * to Darwin and then disable all other vendor strings. - */ - acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS); - supported = ACPI_UINT32_MAX; + + printk_once(KERN_NOTICE PREFIX + "BIOS _OSI(Darwin) query %s%s\n", + osi_config.darwin_enable ? "honored" : "ignored", + osi_config.darwin_cmdline ? " via cmdline" : + osi_config.darwin_dmi ? " via DMI" : ""); } return supported; @@ -1783,6 +1785,44 @@ void __init acpi_osi_setup(char *str) } } +static void __init set_osi_darwin(unsigned int enable) +{ + if (osi_config.darwin_enable != enable) + osi_config.darwin_enable = enable; + + if (enable) { + acpi_osi_setup("!"); + acpi_osi_setup("Darwin"); + } else { + acpi_osi_setup("!!"); + acpi_osi_setup("!Darwin"); + } +} + +static void __init acpi_cmdline_osi_darwin(unsigned int enable) +{ + /* cmdline set the default and override DMI */ + osi_config.darwin_cmdline = 1; + osi_config.darwin_dmi = 0; + set_osi_darwin(enable); + + return; +} + +void __init acpi_dmi_osi_darwin(int enable, const struct dmi_system_id *d) +{ + printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); + + if (enable == -1) + return; + + /* DMI knows that this box asks OSI(Darwin) */ + osi_config.darwin_dmi = 1; + set_osi_darwin(enable); + + return; +} + static void __init set_osi_linux(unsigned int enable) { if (osi_config.linux_enable != enable) @@ -1870,6 +1910,10 @@ static int __init osi_setup(char *str) acpi_cmdline_osi_linux(1); else if (str && !strcmp("!Linux", str)) acpi_cmdline_osi_linux(0); + else if (str && !strcmp("Darwin", str)) + acpi_cmdline_osi_darwin(1); + else if (str && !strcmp("!Darwin", str)) + acpi_cmdline_osi_darwin(0); else acpi_osi_setup(str); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 06ed7e54033e..6c7176efd543 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -360,6 +360,7 @@ extern char acpi_video_backlight_string[]; extern long acpi_is_video_device(acpi_handle handle); extern int acpi_blacklisted(void); extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d); +extern void acpi_dmi_osi_darwin(int enable, const struct dmi_system_id *d); extern void acpi_osi_setup(char *str); extern bool acpi_osi_is_win8(void); -- cgit v1.2.3-59-g8ed1b From dc45eb20a83d11ed649169fbe9159ed6bf586c88 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 3 May 2016 16:48:46 +0800 Subject: ACPI / osi: Cleanup OSI handling code to use bool This patch changes "int/unsigned int" to "bool" to simplify the code. Tested-by: Lukas Wunner Tested-by: Chen Yu Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 4 ++-- drivers/acpi/osl.c | 36 +++++++++++++----------------------- include/linux/acpi.h | 4 ++-- 3 files changed, 17 insertions(+), 27 deletions(-) (limited to 'include/linux/acpi.h') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 45390a953fb2..d7d498abc5d3 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -135,12 +135,12 @@ int __init acpi_blacklisted(void) #ifdef CONFIG_DMI static int __init dmi_enable_osi_darwin(const struct dmi_system_id *d) { - acpi_dmi_osi_darwin(1, d); /* enable */ + acpi_dmi_osi_darwin(true, d); /* enable */ return 0; } static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) { - acpi_dmi_osi_linux(1, d); /* enable */ + acpi_dmi_osi_linux(true, d); /* enable */ return 0; } static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 1b84e4635ae0..e30f3251fd14 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1785,11 +1785,9 @@ void __init acpi_osi_setup(char *str) } } -static void __init set_osi_darwin(unsigned int enable) +static void __init set_osi_darwin(bool enable) { - if (osi_config.darwin_enable != enable) - osi_config.darwin_enable = enable; - + osi_config.darwin_enable = !!enable; if (enable) { acpi_osi_setup("!"); acpi_osi_setup("Darwin"); @@ -1799,7 +1797,7 @@ static void __init set_osi_darwin(unsigned int enable) } } -static void __init acpi_cmdline_osi_darwin(unsigned int enable) +static void __init acpi_cmdline_osi_darwin(bool enable) { /* cmdline set the default and override DMI */ osi_config.darwin_cmdline = 1; @@ -1809,13 +1807,10 @@ static void __init acpi_cmdline_osi_darwin(unsigned int enable) return; } -void __init acpi_dmi_osi_darwin(int enable, const struct dmi_system_id *d) +void __init acpi_dmi_osi_darwin(bool enable, const struct dmi_system_id *d) { printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); - if (enable == -1) - return; - /* DMI knows that this box asks OSI(Darwin) */ osi_config.darwin_dmi = 1; set_osi_darwin(enable); @@ -1823,12 +1818,10 @@ void __init acpi_dmi_osi_darwin(int enable, const struct dmi_system_id *d) return; } -static void __init set_osi_linux(unsigned int enable) +static void __init set_osi_linux(bool enable) { - if (osi_config.linux_enable != enable) - osi_config.linux_enable = enable; - - if (osi_config.linux_enable) + osi_config.linux_enable = !!enable; + if (enable) acpi_osi_setup("Linux"); else acpi_osi_setup("!Linux"); @@ -1836,7 +1829,7 @@ static void __init set_osi_linux(unsigned int enable) return; } -static void __init acpi_cmdline_osi_linux(unsigned int enable) +static void __init acpi_cmdline_osi_linux(bool enable) { /* cmdline set the default and override DMI */ osi_config.linux_cmdline = 1; @@ -1846,13 +1839,10 @@ static void __init acpi_cmdline_osi_linux(unsigned int enable) return; } -void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) +void __init acpi_dmi_osi_linux(bool enable, const struct dmi_system_id *d) { printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); - if (enable == -1) - return; - /* DMI knows that this box asks OSI(Linux) */ osi_config.linux_dmi = 1; set_osi_linux(enable); @@ -1907,13 +1897,13 @@ static void __init acpi_osi_setup_late(void) static int __init osi_setup(char *str) { if (str && !strcmp("Linux", str)) - acpi_cmdline_osi_linux(1); + acpi_cmdline_osi_linux(true); else if (str && !strcmp("!Linux", str)) - acpi_cmdline_osi_linux(0); + acpi_cmdline_osi_linux(false); else if (str && !strcmp("Darwin", str)) - acpi_cmdline_osi_darwin(1); + acpi_cmdline_osi_darwin(true); else if (str && !strcmp("!Darwin", str)) - acpi_cmdline_osi_darwin(0); + acpi_cmdline_osi_darwin(false); else acpi_osi_setup(str); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 6c7176efd543..0ccfeba71fcf 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -359,8 +359,8 @@ extern bool wmi_has_guid(const char *guid); extern char acpi_video_backlight_string[]; extern long acpi_is_video_device(acpi_handle handle); extern int acpi_blacklisted(void); -extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d); -extern void acpi_dmi_osi_darwin(int enable, const struct dmi_system_id *d); +extern void acpi_dmi_osi_linux(bool enable, const struct dmi_system_id *d); +extern void acpi_dmi_osi_darwin(bool enable, const struct dmi_system_id *d); extern void acpi_osi_setup(char *str); extern bool acpi_osi_is_win8(void); -- cgit v1.2.3-59-g8ed1b From d5a91d74c6d7da2cebadbb9f2d03e56f84d7be62 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 3 May 2016 16:48:53 +0800 Subject: ACPI / osi: Cleanup coding style issues before creating a separate OSI source file This patch performs necessary cleanups before moving OSI support to another file. 1. Change printk into pr_xxx 2. Do not initialize values to 0 3. Do not append additional "return" at the end of the function 4. Remove useless comments which may easily break line breaking rule After fixing the coding style issues, rename functions to make them looking like acpi_osi_xxx. No functional changes. Tested-by: Lukas Wunner Tested-by: Chen Yu Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 10 +++---- drivers/acpi/osl.c | 76 ++++++++++++++++++++---------------------------- include/linux/acpi.h | 4 +-- 3 files changed, 38 insertions(+), 52 deletions(-) (limited to 'include/linux/acpi.h') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index d7d498abc5d3..ba1601d26c48 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -135,17 +135,17 @@ int __init acpi_blacklisted(void) #ifdef CONFIG_DMI static int __init dmi_enable_osi_darwin(const struct dmi_system_id *d) { - acpi_dmi_osi_darwin(true, d); /* enable */ + acpi_osi_dmi_darwin(true, d); return 0; } static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) { - acpi_dmi_osi_linux(true, d); /* enable */ + acpi_osi_dmi_linux(true, d); return 0; } static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) { - printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); + pr_notice(PREFIX "DMI detected: %s\n", d->ident); acpi_osi_setup("!Windows 2006"); acpi_osi_setup("!Windows 2006 SP1"); acpi_osi_setup("!Windows 2006 SP2"); @@ -153,13 +153,13 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) } static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) { - printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); + pr_notice(PREFIX "DMI detected: %s\n", d->ident); acpi_osi_setup("!Windows 2009"); return 0; } static int __init dmi_disable_osi_win8(const struct dmi_system_id *d) { - printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); + pr_notice(PREFIX "DMI detected: %s\n", d->ident); acpi_osi_setup("!Windows 2012"); return 0; } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e30f3251fd14..134051689d72 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -139,13 +139,13 @@ static struct acpi_osi_config { unsigned int darwin_dmi:1; unsigned int darwin_cmdline:1; u8 default_disabling; -} osi_config = {0, 0, 0, 0}; +} osi_config; static u32 acpi_osi_handler(acpi_string interface, u32 supported) { if (!strcmp("Linux", interface)) { - printk_once(KERN_NOTICE FW_BUG PREFIX + pr_notice_once(FW_BUG PREFIX "BIOS _OSI(Linux) query %s%s\n", osi_config.linux_enable ? "honored" : "ignored", osi_config.linux_cmdline ? " via cmdline" : @@ -154,7 +154,7 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported) if (!strcmp("Darwin", interface)) { - printk_once(KERN_NOTICE PREFIX + pr_notice_once(PREFIX "BIOS _OSI(Darwin) query %s%s\n", osi_config.darwin_enable ? "honored" : "ignored", osi_config.darwin_cmdline ? " via cmdline" : @@ -1719,15 +1719,15 @@ static int __init acpi_os_name_setup(char *str) __setup("acpi_os_name=", acpi_os_name_setup); -#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ -#define OSI_STRING_ENTRIES_MAX 16 /* arbitrary */ +#define OSI_STRING_LENGTH_MAX 64 +#define OSI_STRING_ENTRIES_MAX 16 -struct osi_setup_entry { +struct acpi_osi_entry { char string[OSI_STRING_LENGTH_MAX]; bool enable; }; -static struct osi_setup_entry +static struct acpi_osi_entry osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = { {"Module Device", true}, {"Processor Device", true}, @@ -1737,7 +1737,7 @@ static struct osi_setup_entry void __init acpi_osi_setup(char *str) { - struct osi_setup_entry *osi; + struct acpi_osi_entry *osi; bool enable = true; int i; @@ -1745,7 +1745,7 @@ void __init acpi_osi_setup(char *str) return; if (str == NULL || *str == '\0') { - printk(KERN_INFO PREFIX "_OSI method disabled\n"); + pr_info(PREFIX "_OSI method disabled\n"); acpi_gbl_create_osi_method = FALSE; return; } @@ -1785,7 +1785,7 @@ void __init acpi_osi_setup(char *str) } } -static void __init set_osi_darwin(bool enable) +static void __init __acpi_osi_setup_darwin(bool enable) { osi_config.darwin_enable = !!enable; if (enable) { @@ -1797,57 +1797,43 @@ static void __init set_osi_darwin(bool enable) } } -static void __init acpi_cmdline_osi_darwin(bool enable) +static void __init acpi_osi_setup_darwin(bool enable) { - /* cmdline set the default and override DMI */ osi_config.darwin_cmdline = 1; osi_config.darwin_dmi = 0; - set_osi_darwin(enable); - - return; + __acpi_osi_setup_darwin(enable); } -void __init acpi_dmi_osi_darwin(bool enable, const struct dmi_system_id *d) +void __init acpi_osi_dmi_darwin(bool enable, const struct dmi_system_id *d) { - printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); - - /* DMI knows that this box asks OSI(Darwin) */ + pr_notice(PREFIX "DMI detected to setup _OSI(\"Darwin\"): %s\n", + d->ident); osi_config.darwin_dmi = 1; - set_osi_darwin(enable); - - return; + __acpi_osi_setup_darwin(enable); } -static void __init set_osi_linux(bool enable) +static void __init __acpi_osi_setup_linux(bool enable) { osi_config.linux_enable = !!enable; if (enable) acpi_osi_setup("Linux"); else acpi_osi_setup("!Linux"); - - return; } -static void __init acpi_cmdline_osi_linux(bool enable) +static void __init acpi_osi_setup_linux(bool enable) { - /* cmdline set the default and override DMI */ osi_config.linux_cmdline = 1; osi_config.linux_dmi = 0; - set_osi_linux(enable); - - return; + __acpi_osi_setup_linux(enable); } -void __init acpi_dmi_osi_linux(bool enable, const struct dmi_system_id *d) +void __init acpi_osi_dmi_linux(bool enable, const struct dmi_system_id *d) { - printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); - - /* DMI knows that this box asks OSI(Linux) */ + pr_notice(PREFIX "DMI detected to setup _OSI(\"Linux\"): %s\n", + d->ident); osi_config.linux_dmi = 1; - set_osi_linux(enable); - - return; + __acpi_osi_setup_linux(enable); } /* @@ -1859,7 +1845,7 @@ void __init acpi_dmi_osi_linux(bool enable, const struct dmi_system_id *d) */ static void __init acpi_osi_setup_late(void) { - struct osi_setup_entry *osi; + struct acpi_osi_entry *osi; char *str; int i; acpi_status status; @@ -1868,7 +1854,7 @@ static void __init acpi_osi_setup_late(void) status = acpi_update_interfaces(osi_config.default_disabling); if (ACPI_SUCCESS(status)) - printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors%s\n", + pr_info(PREFIX "Disabled all _OSI OS vendors%s\n", osi_config.default_disabling == ACPI_DISABLE_ALL_STRINGS ? " and feature groups" : ""); @@ -1884,12 +1870,12 @@ static void __init acpi_osi_setup_late(void) status = acpi_install_interface(str); if (ACPI_SUCCESS(status)) - printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); + pr_info(PREFIX "Added _OSI(%s)\n", str); } else { status = acpi_remove_interface(str); if (ACPI_SUCCESS(status)) - printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); + pr_info(PREFIX "Deleted _OSI(%s)\n", str); } } } @@ -1897,13 +1883,13 @@ static void __init acpi_osi_setup_late(void) static int __init osi_setup(char *str) { if (str && !strcmp("Linux", str)) - acpi_cmdline_osi_linux(true); + acpi_osi_setup_linux(true); else if (str && !strcmp("!Linux", str)) - acpi_cmdline_osi_linux(false); + acpi_osi_setup_linux(false); else if (str && !strcmp("Darwin", str)) - acpi_cmdline_osi_darwin(true); + acpi_osi_setup_darwin(true); else if (str && !strcmp("!Darwin", str)) - acpi_cmdline_osi_darwin(false); + acpi_osi_setup_darwin(false); else acpi_osi_setup(str); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 0ccfeba71fcf..bf0adc611aad 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -359,8 +359,8 @@ extern bool wmi_has_guid(const char *guid); extern char acpi_video_backlight_string[]; extern long acpi_is_video_device(acpi_handle handle); extern int acpi_blacklisted(void); -extern void acpi_dmi_osi_linux(bool enable, const struct dmi_system_id *d); -extern void acpi_dmi_osi_darwin(bool enable, const struct dmi_system_id *d); +extern void acpi_osi_dmi_linux(bool enable, const struct dmi_system_id *d); +extern void acpi_osi_dmi_darwin(bool enable, const struct dmi_system_id *d); extern void acpi_osi_setup(char *str); extern bool acpi_osi_is_win8(void); -- cgit v1.2.3-59-g8ed1b From e5f660ebef68e3ed1a988ad06ba23562153cee5c Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 3 May 2016 16:49:01 +0800 Subject: ACPI / osi: Collect _OSI handling into one single file _OSI handling code grows giant and it's time to move them into one file. This patch collects all _OSI handling code into one single file. So that we only have the following functions to be used externally: early_acpi_osi_init(): Used by DMI detections; acpi_osi_init(): Used to initialize OSI command line settings and install Linux specific _OSI handler; acpi_osi_setup(): The API that should be used by the external quirks. acpi_osi_is_win8(): The API is used by the external drivers to determine if BIOS supports Win8. CONFIG_DMI is not useful as stub dmi_check_system() can make everything stub because of strip. No functional changes. Tested-by: Lukas Wunner Tested-by: Chen Yu Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Makefile | 2 +- drivers/acpi/blacklist.c | 219 +------------------- drivers/acpi/internal.h | 2 + drivers/acpi/osi.c | 522 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/osl.c | 256 +---------------------- include/linux/acpi.h | 2 - 6 files changed, 531 insertions(+), 472 deletions(-) create mode 100644 drivers/acpi/osi.c (limited to 'include/linux/acpi.h') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index edeb2d1d99be..345df7f960b6 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_ACPI) += acpi.o \ acpica/ # All the builtin files are in the "acpi." module_param namespace. -acpi-y += osl.o utils.o reboot.o +acpi-y += osi.o osl.o utils.o reboot.o acpi-y += nvs.o # Power management related files diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index ba1601d26c48..bdc67bad61a7 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -3,7 +3,7 @@ * * Check to see if the given machine has a known bad ACPI BIOS * or if the BIOS is too old. - * Check given machine against acpi_osi_dmi_table[]. + * Check given machine against acpi_rev_dmi_table[]. * * Copyright (C) 2004 Len Brown * Copyright (C) 2002 Andy Grover @@ -47,7 +47,7 @@ struct acpi_blacklist_item { u32 is_critical_error; }; -static struct dmi_system_id acpi_osi_dmi_table[] __initdata; +static struct dmi_system_id acpi_rev_dmi_table[] __initdata; /* * POLICY: If *anything* doesn't work, put it on the blacklist. @@ -128,41 +128,12 @@ int __init acpi_blacklisted(void) } } - dmi_check_system(acpi_osi_dmi_table); + (void)early_acpi_osi_init(); + dmi_check_system(acpi_rev_dmi_table); return blacklisted; } #ifdef CONFIG_DMI -static int __init dmi_enable_osi_darwin(const struct dmi_system_id *d) -{ - acpi_osi_dmi_darwin(true, d); - return 0; -} -static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) -{ - acpi_osi_dmi_linux(true, d); - return 0; -} -static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) -{ - pr_notice(PREFIX "DMI detected: %s\n", d->ident); - acpi_osi_setup("!Windows 2006"); - acpi_osi_setup("!Windows 2006 SP1"); - acpi_osi_setup("!Windows 2006 SP2"); - return 0; -} -static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) -{ - pr_notice(PREFIX "DMI detected: %s\n", d->ident); - acpi_osi_setup("!Windows 2009"); - return 0; -} -static int __init dmi_disable_osi_win8(const struct dmi_system_id *d) -{ - pr_notice(PREFIX "DMI detected: %s\n", d->ident); - acpi_osi_setup("!Windows 2012"); - return 0; -} #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE static int __init dmi_enable_rev_override(const struct dmi_system_id *d) { @@ -173,187 +144,7 @@ static int __init dmi_enable_rev_override(const struct dmi_system_id *d) } #endif -static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { - { - .callback = dmi_disable_osi_vista, - .ident = "Fujitsu Siemens", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), - }, - }, - { - /* - * There have a NVIF method in MSI GX723 DSDT need call by Nvidia - * driver (e.g. nouveau) when user press brightness hotkey. - * Currently, nouveau driver didn't do the job and it causes there - * have a infinite while loop in DSDT when user press hotkey. - * We add MSI GX723's dmi information to this table for workaround - * this issue. - * Will remove MSI GX723 from the table after nouveau grows support. - */ - .callback = dmi_disable_osi_vista, - .ident = "MSI GX723", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), - DMI_MATCH(DMI_PRODUCT_NAME, "GX723"), - }, - }, - { - .callback = dmi_disable_osi_vista, - .ident = "Sony VGN-NS10J_S", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"), - }, - }, - { - .callback = dmi_disable_osi_vista, - .ident = "Sony VGN-SR290J", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"), - }, - }, - { - .callback = dmi_disable_osi_vista, - .ident = "VGN-NS50B_L", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"), - }, - }, - { - .callback = dmi_disable_osi_vista, - .ident = "VGN-SR19XN", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"), - }, - }, - { - .callback = dmi_disable_osi_vista, - .ident = "Toshiba Satellite L355", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"), - }, - }, - { - .callback = dmi_disable_osi_win7, - .ident = "ASUS K50IJ", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"), - }, - }, - { - .callback = dmi_disable_osi_vista, - .ident = "Toshiba P305D", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), - }, - }, - { - .callback = dmi_disable_osi_vista, - .ident = "Toshiba NB100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "NB100"), - }, - }, - - /* - * The wireless hotkey does not work on those machines when - * returning true for _OSI("Windows 2012") - */ - { - .callback = dmi_disable_osi_win8, - .ident = "Dell Inspiron 7737", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "Dell Inspiron 7537", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "Dell Inspiron 5437", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "Dell Inspiron 3437", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "Dell Vostro 3446", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "Dell Vostro 3546", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"), - }, - }, - - /* - * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. - * Linux ignores it, except for the machines enumerated below. - */ - - /* - * Without this this EEEpc exports a non working WMI interface, with - * this it exports a working "good old" eeepc_laptop interface, fixing - * both brightness control, and rfkill not working. - */ - { - .callback = dmi_enable_osi_linux, - .ident = "Asus EEE PC 1015PX", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"), - }, - }, - - /* - * Enable _OSI("Darwin") for all apple platforms. - */ - { - .callback = dmi_enable_osi_darwin, - .ident = "Apple hardware", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), - }, - }, - { - .callback = dmi_enable_osi_darwin, - .ident = "Apple hardware", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), - }, - }, - +static struct dmi_system_id acpi_rev_dmi_table[] __initdata = { #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE /* * DELL XPS 13 (2015) switches sound between HDA and I2S diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 7c188472d9c2..a8780a2e1975 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -20,6 +20,8 @@ #define PREFIX "ACPI: " +int early_acpi_osi_init(void); +int acpi_osi_init(void); void acpi_initrd_initialize_tables(void); acpi_status acpi_os_initialize1(void); void init_acpi_device_notify(void); diff --git a/drivers/acpi/osi.c b/drivers/acpi/osi.c new file mode 100644 index 000000000000..849f9d2245ca --- /dev/null +++ b/drivers/acpi/osi.c @@ -0,0 +1,522 @@ +/* + * osi.c - _OSI implementation + * + * Copyright (C) 2016 Intel Corporation + * Author: Lv Zheng + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +/* Uncomment next line to get verbose printout */ +/* #define DEBUG */ +#define pr_fmt(fmt) "ACPI: " fmt + +#include +#include +#include +#include + +#include "internal.h" + + +#define OSI_STRING_LENGTH_MAX 64 +#define OSI_STRING_ENTRIES_MAX 16 + +struct acpi_osi_entry { + char string[OSI_STRING_LENGTH_MAX]; + bool enable; +}; + +static struct acpi_osi_config { + u8 default_disabling; + unsigned int linux_enable:1; + unsigned int linux_dmi:1; + unsigned int linux_cmdline:1; + unsigned int darwin_enable:1; + unsigned int darwin_dmi:1; + unsigned int darwin_cmdline:1; +} osi_config; + +static struct acpi_osi_config osi_config; +static struct acpi_osi_entry +osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = { + {"Module Device", true}, + {"Processor Device", true}, + {"3.0 _SCP Extensions", true}, + {"Processor Aggregator Device", true}, +}; + +static u32 acpi_osi_handler(acpi_string interface, u32 supported) +{ + if (!strcmp("Linux", interface)) { + pr_notice_once(FW_BUG + "BIOS _OSI(Linux) query %s%s\n", + osi_config.linux_enable ? "honored" : "ignored", + osi_config.linux_cmdline ? " via cmdline" : + osi_config.linux_dmi ? " via DMI" : ""); + } + if (!strcmp("Darwin", interface)) { + pr_notice_once( + "BIOS _OSI(Darwin) query %s%s\n", + osi_config.darwin_enable ? "honored" : "ignored", + osi_config.darwin_cmdline ? " via cmdline" : + osi_config.darwin_dmi ? " via DMI" : ""); + } + + return supported; +} + +void __init acpi_osi_setup(char *str) +{ + struct acpi_osi_entry *osi; + bool enable = true; + int i; + + if (!acpi_gbl_create_osi_method) + return; + + if (str == NULL || *str == '\0') { + pr_info("_OSI method disabled\n"); + acpi_gbl_create_osi_method = FALSE; + return; + } + + if (*str == '!') { + str++; + if (*str == '\0') { + /* Do not override acpi_osi=!* */ + if (!osi_config.default_disabling) + osi_config.default_disabling = + ACPI_DISABLE_ALL_VENDOR_STRINGS; + return; + } else if (*str == '*') { + osi_config.default_disabling = ACPI_DISABLE_ALL_STRINGS; + for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { + osi = &osi_setup_entries[i]; + osi->enable = false; + } + return; + } else if (*str == '!') { + osi_config.default_disabling = 0; + return; + } + enable = false; + } + + for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { + osi = &osi_setup_entries[i]; + if (!strcmp(osi->string, str)) { + osi->enable = enable; + break; + } else if (osi->string[0] == '\0') { + osi->enable = enable; + strncpy(osi->string, str, OSI_STRING_LENGTH_MAX); + break; + } + } +} + +static void __init __acpi_osi_setup_darwin(bool enable) +{ + osi_config.darwin_enable = !!enable; + if (enable) { + acpi_osi_setup("!"); + acpi_osi_setup("Darwin"); + } else { + acpi_osi_setup("!!"); + acpi_osi_setup("!Darwin"); + } +} + +static void __init acpi_osi_setup_darwin(bool enable) +{ + /* Override acpi_osi_dmi_blacklisted() */ + osi_config.darwin_dmi = 0; + osi_config.darwin_cmdline = 1; + __acpi_osi_setup_darwin(enable); +} + +/* + * The story of _OSI(Linux) + * + * From pre-history through Linux-2.6.22, Linux responded TRUE upon a BIOS + * OSI(Linux) query. + * + * Unfortunately, reference BIOS writers got wind of this and put + * OSI(Linux) in their example code, quickly exposing this string as + * ill-conceived and opening the door to an un-bounded number of BIOS + * incompatibilities. + * + * For example, OSI(Linux) was used on resume to re-POST a video card on + * one system, because Linux at that time could not do a speedy restore in + * its native driver. But then upon gaining quick native restore + * capability, Linux has no way to tell the BIOS to skip the time-consuming + * POST -- putting Linux at a permanent performance disadvantage. On + * another system, the BIOS writer used OSI(Linux) to infer native OS + * support for IPMI! On other systems, OSI(Linux) simply got in the way of + * Linux claiming to be compatible with other operating systems, exposing + * BIOS issues such as skipped device initialization. + * + * So "Linux" turned out to be a really poor chose of OSI string, and from + * Linux-2.6.23 onward we respond FALSE. + * + * BIOS writers should NOT query _OSI(Linux) on future systems. Linux will + * complain on the console when it sees it, and return FALSE. To get Linux + * to return TRUE for your system will require a kernel source update to + * add a DMI entry, or boot with "acpi_osi=Linux" + */ +static void __init __acpi_osi_setup_linux(bool enable) +{ + osi_config.linux_enable = !!enable; + if (enable) + acpi_osi_setup("Linux"); + else + acpi_osi_setup("!Linux"); +} + +static void __init acpi_osi_setup_linux(bool enable) +{ + /* Override acpi_osi_dmi_blacklisted() */ + osi_config.linux_dmi = 0; + osi_config.linux_cmdline = 1; + __acpi_osi_setup_linux(enable); +} + +/* + * Modify the list of "OS Interfaces" reported to BIOS via _OSI + * + * empty string disables _OSI + * string starting with '!' disables that string + * otherwise string is added to list, augmenting built-in strings + */ +static void __init acpi_osi_setup_late(void) +{ + struct acpi_osi_entry *osi; + char *str; + int i; + acpi_status status; + + if (osi_config.default_disabling) { + status = acpi_update_interfaces(osi_config.default_disabling); + if (ACPI_SUCCESS(status)) + pr_info("Disabled all _OSI OS vendors%s\n", + osi_config.default_disabling == + ACPI_DISABLE_ALL_STRINGS ? + " and feature groups" : ""); + } + + for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { + osi = &osi_setup_entries[i]; + str = osi->string; + if (*str == '\0') + break; + if (osi->enable) { + status = acpi_install_interface(str); + if (ACPI_SUCCESS(status)) + pr_info("Added _OSI(%s)\n", str); + } else { + status = acpi_remove_interface(str); + if (ACPI_SUCCESS(status)) + pr_info("Deleted _OSI(%s)\n", str); + } + } +} + +static int __init osi_setup(char *str) +{ + if (str && !strcmp("Linux", str)) + acpi_osi_setup_linux(true); + else if (str && !strcmp("!Linux", str)) + acpi_osi_setup_linux(false); + else if (str && !strcmp("Darwin", str)) + acpi_osi_setup_darwin(true); + else if (str && !strcmp("!Darwin", str)) + acpi_osi_setup_darwin(false); + else + acpi_osi_setup(str); + + return 1; +} +__setup("acpi_osi=", osi_setup); + +bool acpi_osi_is_win8(void) +{ + return acpi_gbl_osi_data >= ACPI_OSI_WIN_8; +} +EXPORT_SYMBOL(acpi_osi_is_win8); + +static void __init acpi_osi_dmi_darwin(bool enable, + const struct dmi_system_id *d) +{ + pr_notice("DMI detected to setup _OSI(\"Darwin\"): %s\n", d->ident); + osi_config.darwin_dmi = 1; + __acpi_osi_setup_darwin(enable); +} + +void __init acpi_osi_dmi_linux(bool enable, const struct dmi_system_id *d) +{ + pr_notice("DMI detected to setup _OSI(\"Linux\"): %s\n", d->ident); + osi_config.linux_dmi = 1; + __acpi_osi_setup_linux(enable); +} + +static int __init dmi_enable_osi_darwin(const struct dmi_system_id *d) +{ + acpi_osi_dmi_darwin(true, d); + + return 0; +} + +static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) +{ + acpi_osi_dmi_linux(true, d); + + return 0; +} + +static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) +{ + pr_notice("DMI detected: %s\n", d->ident); + acpi_osi_setup("!Windows 2006"); + acpi_osi_setup("!Windows 2006 SP1"); + acpi_osi_setup("!Windows 2006 SP2"); + + return 0; +} + +static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) +{ + pr_notice("DMI detected: %s\n", d->ident); + acpi_osi_setup("!Windows 2009"); + + return 0; +} + +static int __init dmi_disable_osi_win8(const struct dmi_system_id *d) +{ + pr_notice("DMI detected: %s\n", d->ident); + acpi_osi_setup("!Windows 2012"); + + return 0; +} + +/* + * Linux default _OSI response behavior is determined by this DMI table. + * + * Note that _OSI("Linux")/_OSI("Darwin") determined here can be overridden + * by acpi_osi=!Linux/acpi_osi=!Darwin command line options. + */ +static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { + { + .callback = dmi_disable_osi_vista, + .ident = "Fujitsu Siemens", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), + }, + }, + { + /* + * There have a NVIF method in MSI GX723 DSDT need call by Nvidia + * driver (e.g. nouveau) when user press brightness hotkey. + * Currently, nouveau driver didn't do the job and it causes there + * have a infinite while loop in DSDT when user press hotkey. + * We add MSI GX723's dmi information to this table for workaround + * this issue. + * Will remove MSI GX723 from the table after nouveau grows support. + */ + .callback = dmi_disable_osi_vista, + .ident = "MSI GX723", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), + DMI_MATCH(DMI_PRODUCT_NAME, "GX723"), + }, + }, + { + .callback = dmi_disable_osi_vista, + .ident = "Sony VGN-NS10J_S", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"), + }, + }, + { + .callback = dmi_disable_osi_vista, + .ident = "Sony VGN-SR290J", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"), + }, + }, + { + .callback = dmi_disable_osi_vista, + .ident = "VGN-NS50B_L", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"), + }, + }, + { + .callback = dmi_disable_osi_vista, + .ident = "VGN-SR19XN", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"), + }, + }, + { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba Satellite L355", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"), + }, + }, + { + .callback = dmi_disable_osi_win7, + .ident = "ASUS K50IJ", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"), + }, + }, + { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba P305D", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), + }, + }, + { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba NB100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "NB100"), + }, + }, + + /* + * The wireless hotkey does not work on those machines when + * returning true for _OSI("Windows 2012") + */ + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Inspiron 7737", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Inspiron 7537", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Inspiron 5437", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Inspiron 3437", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Vostro 3446", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Vostro 3546", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"), + }, + }, + + /* + * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. + * Linux ignores it, except for the machines enumerated below. + */ + + /* + * Without this this EEEpc exports a non working WMI interface, with + * this it exports a working "good old" eeepc_laptop interface, fixing + * both brightness control, and rfkill not working. + */ + { + .callback = dmi_enable_osi_linux, + .ident = "Asus EEE PC 1015PX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"), + }, + }, + + /* + * Enable _OSI("Darwin") for all apple platforms. + */ + { + .callback = dmi_enable_osi_darwin, + .ident = "Apple hardware", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + }, + }, + { + .callback = dmi_enable_osi_darwin, + .ident = "Apple hardware", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), + }, + }, + {} +}; + +static __init void acpi_osi_dmi_blacklisted(void) +{ + dmi_check_system(acpi_osi_dmi_table); +} + +int __init early_acpi_osi_init(void) +{ + acpi_osi_dmi_blacklisted(); + + return 0; +} + +int __init acpi_osi_init(void) +{ + acpi_install_interface_handler(acpi_osi_handler); + acpi_osi_setup_late(); + + return 0; +} diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 134051689d72..29af6b40c93f 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -96,74 +96,6 @@ struct acpi_ioremap { static LIST_HEAD(acpi_ioremaps); static DEFINE_MUTEX(acpi_ioremap_lock); -static void __init acpi_osi_setup_late(void); - -/* - * The story of _OSI(Linux) - * - * From pre-history through Linux-2.6.22, - * Linux responded TRUE upon a BIOS OSI(Linux) query. - * - * Unfortunately, reference BIOS writers got wind of this - * and put OSI(Linux) in their example code, quickly exposing - * this string as ill-conceived and opening the door to - * an un-bounded number of BIOS incompatibilities. - * - * For example, OSI(Linux) was used on resume to re-POST a - * video card on one system, because Linux at that time - * could not do a speedy restore in its native driver. - * But then upon gaining quick native restore capability, - * Linux has no way to tell the BIOS to skip the time-consuming - * POST -- putting Linux at a permanent performance disadvantage. - * On another system, the BIOS writer used OSI(Linux) - * to infer native OS support for IPMI! On other systems, - * OSI(Linux) simply got in the way of Linux claiming to - * be compatible with other operating systems, exposing - * BIOS issues such as skipped device initialization. - * - * So "Linux" turned out to be a really poor chose of - * OSI string, and from Linux-2.6.23 onward we respond FALSE. - * - * BIOS writers should NOT query _OSI(Linux) on future systems. - * Linux will complain on the console when it sees it, and return FALSE. - * To get Linux to return TRUE for your system will require - * a kernel source update to add a DMI entry, - * or boot with "acpi_osi=Linux" - */ - -static struct acpi_osi_config { - unsigned int linux_enable:1; - unsigned int linux_dmi:1; - unsigned int linux_cmdline:1; - unsigned int darwin_enable:1; - unsigned int darwin_dmi:1; - unsigned int darwin_cmdline:1; - u8 default_disabling; -} osi_config; - -static u32 acpi_osi_handler(acpi_string interface, u32 supported) -{ - if (!strcmp("Linux", interface)) { - - pr_notice_once(FW_BUG PREFIX - "BIOS _OSI(Linux) query %s%s\n", - osi_config.linux_enable ? "honored" : "ignored", - osi_config.linux_cmdline ? " via cmdline" : - osi_config.linux_dmi ? " via DMI" : ""); - } - - if (!strcmp("Darwin", interface)) { - - pr_notice_once(PREFIX - "BIOS _OSI(Darwin) query %s%s\n", - osi_config.darwin_enable ? "honored" : "ignored", - osi_config.darwin_cmdline ? " via cmdline" : - osi_config.darwin_dmi ? " via DMI" : ""); - } - - return supported; -} - static void __init acpi_request_region (struct acpi_generic_address *gas, unsigned int length, char *desc) { @@ -1719,185 +1651,6 @@ static int __init acpi_os_name_setup(char *str) __setup("acpi_os_name=", acpi_os_name_setup); -#define OSI_STRING_LENGTH_MAX 64 -#define OSI_STRING_ENTRIES_MAX 16 - -struct acpi_osi_entry { - char string[OSI_STRING_LENGTH_MAX]; - bool enable; -}; - -static struct acpi_osi_entry - osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = { - {"Module Device", true}, - {"Processor Device", true}, - {"3.0 _SCP Extensions", true}, - {"Processor Aggregator Device", true}, -}; - -void __init acpi_osi_setup(char *str) -{ - struct acpi_osi_entry *osi; - bool enable = true; - int i; - - if (!acpi_gbl_create_osi_method) - return; - - if (str == NULL || *str == '\0') { - pr_info(PREFIX "_OSI method disabled\n"); - acpi_gbl_create_osi_method = FALSE; - return; - } - - if (*str == '!') { - str++; - if (*str == '\0') { - /* Do not override acpi_osi=!* */ - if (!osi_config.default_disabling) - osi_config.default_disabling = - ACPI_DISABLE_ALL_VENDOR_STRINGS; - return; - } else if (*str == '*') { - osi_config.default_disabling = ACPI_DISABLE_ALL_STRINGS; - for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { - osi = &osi_setup_entries[i]; - osi->enable = false; - } - return; - } else if (*str == '!') { - osi_config.default_disabling = 0; - return; - } - enable = false; - } - - for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { - osi = &osi_setup_entries[i]; - if (!strcmp(osi->string, str)) { - osi->enable = enable; - break; - } else if (osi->string[0] == '\0') { - osi->enable = enable; - strncpy(osi->string, str, OSI_STRING_LENGTH_MAX); - break; - } - } -} - -static void __init __acpi_osi_setup_darwin(bool enable) -{ - osi_config.darwin_enable = !!enable; - if (enable) { - acpi_osi_setup("!"); - acpi_osi_setup("Darwin"); - } else { - acpi_osi_setup("!!"); - acpi_osi_setup("!Darwin"); - } -} - -static void __init acpi_osi_setup_darwin(bool enable) -{ - osi_config.darwin_cmdline = 1; - osi_config.darwin_dmi = 0; - __acpi_osi_setup_darwin(enable); -} - -void __init acpi_osi_dmi_darwin(bool enable, const struct dmi_system_id *d) -{ - pr_notice(PREFIX "DMI detected to setup _OSI(\"Darwin\"): %s\n", - d->ident); - osi_config.darwin_dmi = 1; - __acpi_osi_setup_darwin(enable); -} - -static void __init __acpi_osi_setup_linux(bool enable) -{ - osi_config.linux_enable = !!enable; - if (enable) - acpi_osi_setup("Linux"); - else - acpi_osi_setup("!Linux"); -} - -static void __init acpi_osi_setup_linux(bool enable) -{ - osi_config.linux_cmdline = 1; - osi_config.linux_dmi = 0; - __acpi_osi_setup_linux(enable); -} - -void __init acpi_osi_dmi_linux(bool enable, const struct dmi_system_id *d) -{ - pr_notice(PREFIX "DMI detected to setup _OSI(\"Linux\"): %s\n", - d->ident); - osi_config.linux_dmi = 1; - __acpi_osi_setup_linux(enable); -} - -/* - * Modify the list of "OS Interfaces" reported to BIOS via _OSI - * - * empty string disables _OSI - * string starting with '!' disables that string - * otherwise string is added to list, augmenting built-in strings - */ -static void __init acpi_osi_setup_late(void) -{ - struct acpi_osi_entry *osi; - char *str; - int i; - acpi_status status; - - if (osi_config.default_disabling) { - status = acpi_update_interfaces(osi_config.default_disabling); - - if (ACPI_SUCCESS(status)) - pr_info(PREFIX "Disabled all _OSI OS vendors%s\n", - osi_config.default_disabling == - ACPI_DISABLE_ALL_STRINGS ? - " and feature groups" : ""); - } - - for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { - osi = &osi_setup_entries[i]; - str = osi->string; - - if (*str == '\0') - break; - if (osi->enable) { - status = acpi_install_interface(str); - - if (ACPI_SUCCESS(status)) - pr_info(PREFIX "Added _OSI(%s)\n", str); - } else { - status = acpi_remove_interface(str); - - if (ACPI_SUCCESS(status)) - pr_info(PREFIX "Deleted _OSI(%s)\n", str); - } - } -} - -static int __init osi_setup(char *str) -{ - if (str && !strcmp("Linux", str)) - acpi_osi_setup_linux(true); - else if (str && !strcmp("!Linux", str)) - acpi_osi_setup_linux(false); - else if (str && !strcmp("Darwin", str)) - acpi_osi_setup_darwin(true); - else if (str && !strcmp("!Darwin", str)) - acpi_osi_setup_darwin(false); - else - acpi_osi_setup(str); - - return 1; -} - -__setup("acpi_osi=", osi_setup); - /* * Disable the auto-serialization of named objects creation methods. * @@ -2017,12 +1770,6 @@ int acpi_resources_are_enforced(void) } EXPORT_SYMBOL(acpi_resources_are_enforced); -bool acpi_osi_is_win8(void) -{ - return acpi_gbl_osi_data >= ACPI_OSI_WIN_8; -} -EXPORT_SYMBOL(acpi_osi_is_win8); - /* * Deallocate the memory for a spinlock. */ @@ -2188,8 +1935,7 @@ acpi_status __init acpi_os_initialize1(void) BUG_ON(!kacpid_wq); BUG_ON(!kacpi_notify_wq); BUG_ON(!kacpi_hotplug_wq); - acpi_install_interface_handler(acpi_osi_handler); - acpi_osi_setup_late(); + acpi_osi_init(); return AE_OK; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index bf0adc611aad..58f707a399c2 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -359,8 +359,6 @@ extern bool wmi_has_guid(const char *guid); extern char acpi_video_backlight_string[]; extern long acpi_is_video_device(acpi_handle handle); extern int acpi_blacklisted(void); -extern void acpi_osi_dmi_linux(bool enable, const struct dmi_system_id *d); -extern void acpi_osi_dmi_darwin(bool enable, const struct dmi_system_id *d); extern void acpi_osi_setup(char *str); extern bool acpi_osi_is_win8(void); -- cgit v1.2.3-59-g8ed1b