aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2016-05-03 04:48:20 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-05-04 18:13:51 -0400
commit30c9bb0d7603e7b3f4d6a0ea231e1cddae020c32 (patch)
tree984fe15324e281af1aa1840a83d4bd86daaa5e8f /drivers/acpi
parent04974df8049fc4240d22759a91e035082ccd18b4 (diff)
ACPI / osi: Fix an issue that acpi_osi=!* cannot disable ACPICA internal strings
The order of the _OSI related functionalities is as follows: acpi_blacklisted() acpi_dmi_osi_linux() acpi_osi_setup() acpi_osi_setup() acpi_update_interfaces() if "!*" <<<<<<<<<<<<<<<<<<<<<<<< parse_args() __setup("acpi_osi=") acpi_osi_setup_linux() acpi_update_interfaces() if "!*" <<<<<<<<<<<<<<<<<<<<<<<< acpi_early_init() acpi_initialize_subsystem() acpi_ut_initialize_interfaces() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ acpi_bus_init() acpi_os_initialize1() acpi_install_interface_handler(acpi_osi_handler) acpi_osi_setup_late() acpi_update_interfaces() for "!" >>>>>>>>>>>>>>>>>>>>>>>> acpi_osi_handler() Since acpi_osi_setup_linux() can override acpi_dmi_osi_linux(), the command line setting can override the DMI detection. That's why acpi_blacklisted() is put before __setup("acpi_osi="). Then we can notice the following wrong invocation order. There are acpi_update_interfaces() (marked by <<<<) calls invoked before acpi_ut_initialize_interfaces() (marked by ^^^^). This makes it impossible to use acpi_osi=!* correctly from OSI DMI table or from the command line. The use of acpi_osi=!* is meant to disable both ACPICA (acpi_gbl_supported_interfaces) and Linux specific strings (osi_setup_entries) while the ACPICA part should have stopped working because of the order issue. This patch fixes this issue by moving acpi_update_interfaces() to where it is invoked for acpi_osi=! (marked by >>>>) as this is ensured to be invoked after acpi_ut_initialize_interfaces() (marked by ^^^^). Linux specific strings are still handled in the original place in order to make the following command line working: acpi_osi=!* acpi_osi="Module Device". Note that since acpi_osi=!* is meant to further disable linux specific string comparing to the acpi_osi=!, there is no such use case in our bug fixing work and hence there is no one using acpi_osi=!* either from the command line or from the DMI quirks, this issue is just a theoretical issue. Fixes: 741d81280ad2 (ACPI: Add facility to remove all _OSI strings) Cc: 3.12+ <stable@vger.kernel.org> # 3.12+ Tested-by: Lukas Wunner <lukas@wunner.de> Tested-by: Chen Yu <yu.c.chen@intel.com> Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/osl.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 814d5f83b75e..f03677588b9d 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -135,7 +135,7 @@ static struct osi_linux {
135 unsigned int enable:1; 135 unsigned int enable:1;
136 unsigned int dmi:1; 136 unsigned int dmi:1;
137 unsigned int cmdline:1; 137 unsigned int cmdline:1;
138 unsigned int default_disabling:1; 138 u8 default_disabling;
139} osi_linux = {0, 0, 0, 0}; 139} osi_linux = {0, 0, 0, 0};
140 140
141static u32 acpi_osi_handler(acpi_string interface, u32 supported) 141static u32 acpi_osi_handler(acpi_string interface, u32 supported)
@@ -1751,10 +1751,13 @@ void __init acpi_osi_setup(char *str)
1751 if (*str == '!') { 1751 if (*str == '!') {
1752 str++; 1752 str++;
1753 if (*str == '\0') { 1753 if (*str == '\0') {
1754 osi_linux.default_disabling = 1; 1754 /* Do not override acpi_osi=!* */
1755 if (!osi_linux.default_disabling)
1756 osi_linux.default_disabling =
1757 ACPI_DISABLE_ALL_VENDOR_STRINGS;
1755 return; 1758 return;
1756 } else if (*str == '*') { 1759 } else if (*str == '*') {
1757 acpi_update_interfaces(ACPI_DISABLE_ALL_STRINGS); 1760 osi_linux.default_disabling = ACPI_DISABLE_ALL_STRINGS;
1758 for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { 1761 for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
1759 osi = &osi_setup_entries[i]; 1762 osi = &osi_setup_entries[i];
1760 osi->enable = false; 1763 osi->enable = false;
@@ -1827,10 +1830,13 @@ static void __init acpi_osi_setup_late(void)
1827 acpi_status status; 1830 acpi_status status;
1828 1831
1829 if (osi_linux.default_disabling) { 1832 if (osi_linux.default_disabling) {
1830 status = acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS); 1833 status = acpi_update_interfaces(osi_linux.default_disabling);
1831 1834
1832 if (ACPI_SUCCESS(status)) 1835 if (ACPI_SUCCESS(status))
1833 printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors\n"); 1836 printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors%s\n",
1837 osi_linux.default_disabling ==
1838 ACPI_DISABLE_ALL_STRINGS ?
1839 " and feature groups" : "");
1834 } 1840 }
1835 1841
1836 for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { 1842 for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {