diff options
author | Lin Ming <ming.m.lin@intel.com> | 2010-12-09 03:50:52 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-12-11 01:28:58 -0500 |
commit | d90aa92c0c1625d7f02050e4d2924805840cda3d (patch) | |
tree | 89696463c63038cb37609873951b0cdb4dc473f6 | |
parent | cf7d7e5a1980d1116ee152d25dac382b112b9c17 (diff) |
acpi: fix _OSI string setup regression
commit b0ed7a91(ACPICA/ACPI: Add new host interfaces for _OSI suppor)
introduced a regression that _OSI string setup fails.
There are 2 paths to setup _OSI string.
DMI:
acpi_dmi_osi_linux -> set_osi_linux -> acpi_osi_setup -> copy _OSI
string to osi_setup_string
Boot command line:
acpi_osi_setup -> copy _OSI string to osi_setup_string
Later, acpi_osi_setup_late will be called to handle osi_setup_string.
If _OSI string is "Linux" or "!Linux", then the call path is,
acpi_osi_setup_late -> acpi_cmdline_osi_linux -> set_osi_linux ->
acpi_osi_setup -> copy _OSI string to osi_setup_string
This actually never installs _OSI string(acpi_install_interface not
called), but just copy the _OSI string to osi_setup_string.
This patch fixes the regression.
Reported-and-tested-by: Lukas Hejtmanek <xhejtman@ics.muni.cz>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/osl.c | 59 | ||||
-rw-r--r-- | include/linux/acpi.h | 2 |
2 files changed, 34 insertions, 27 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 966feddf6b1b..6867443c4941 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -152,8 +152,7 @@ static struct osi_linux { | |||
152 | unsigned int enable:1; | 152 | unsigned int enable:1; |
153 | unsigned int dmi:1; | 153 | unsigned int dmi:1; |
154 | unsigned int cmdline:1; | 154 | unsigned int cmdline:1; |
155 | unsigned int known:1; | 155 | } osi_linux = {0, 0, 0}; |
156 | } osi_linux = { 0, 0, 0, 0}; | ||
157 | 156 | ||
158 | static u32 acpi_osi_handler(acpi_string interface, u32 supported) | 157 | static u32 acpi_osi_handler(acpi_string interface, u32 supported) |
159 | { | 158 | { |
@@ -1055,13 +1054,22 @@ static int __init acpi_os_name_setup(char *str) | |||
1055 | 1054 | ||
1056 | __setup("acpi_os_name=", acpi_os_name_setup); | 1055 | __setup("acpi_os_name=", acpi_os_name_setup); |
1057 | 1056 | ||
1057 | void __init acpi_osi_setup(char *str) | ||
1058 | { | ||
1059 | if (!acpi_gbl_create_osi_method) | ||
1060 | return; | ||
1061 | |||
1062 | if (str == NULL || *str == '\0') { | ||
1063 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); | ||
1064 | acpi_gbl_create_osi_method = FALSE; | ||
1065 | } else | ||
1066 | strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX); | ||
1067 | } | ||
1068 | |||
1058 | static void __init set_osi_linux(unsigned int enable) | 1069 | static void __init set_osi_linux(unsigned int enable) |
1059 | { | 1070 | { |
1060 | if (osi_linux.enable != enable) { | 1071 | if (osi_linux.enable != enable) |
1061 | osi_linux.enable = enable; | 1072 | osi_linux.enable = enable; |
1062 | printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n", | ||
1063 | enable ? "Add": "Delet"); | ||
1064 | } | ||
1065 | 1073 | ||
1066 | if (osi_linux.enable) | 1074 | if (osi_linux.enable) |
1067 | acpi_osi_setup("Linux"); | 1075 | acpi_osi_setup("Linux"); |
@@ -1073,7 +1081,8 @@ static void __init set_osi_linux(unsigned int enable) | |||
1073 | 1081 | ||
1074 | static void __init acpi_cmdline_osi_linux(unsigned int enable) | 1082 | static void __init acpi_cmdline_osi_linux(unsigned int enable) |
1075 | { | 1083 | { |
1076 | osi_linux.cmdline = 1; /* cmdline set the default */ | 1084 | osi_linux.cmdline = 1; /* cmdline set the default and override DMI */ |
1085 | osi_linux.dmi = 0; | ||
1077 | set_osi_linux(enable); | 1086 | set_osi_linux(enable); |
1078 | 1087 | ||
1079 | return; | 1088 | return; |
@@ -1081,15 +1090,12 @@ static void __init acpi_cmdline_osi_linux(unsigned int enable) | |||
1081 | 1090 | ||
1082 | void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) | 1091 | void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) |
1083 | { | 1092 | { |
1084 | osi_linux.dmi = 1; /* DMI knows that this box asks OSI(Linux) */ | ||
1085 | |||
1086 | printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); | 1093 | printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); |
1087 | 1094 | ||
1088 | if (enable == -1) | 1095 | if (enable == -1) |
1089 | return; | 1096 | return; |
1090 | 1097 | ||
1091 | osi_linux.known = 1; /* DMI knows which OSI(Linux) default needed */ | 1098 | osi_linux.dmi = 1; /* DMI knows that this box asks OSI(Linux) */ |
1092 | |||
1093 | set_osi_linux(enable); | 1099 | set_osi_linux(enable); |
1094 | 1100 | ||
1095 | return; | 1101 | return; |
@@ -1105,36 +1111,37 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) | |||
1105 | static void __init acpi_osi_setup_late(void) | 1111 | static void __init acpi_osi_setup_late(void) |
1106 | { | 1112 | { |
1107 | char *str = osi_setup_string; | 1113 | char *str = osi_setup_string; |
1114 | acpi_status status; | ||
1108 | 1115 | ||
1109 | if (*str == '\0') | 1116 | if (*str == '\0') |
1110 | return; | 1117 | return; |
1111 | 1118 | ||
1112 | if (!strcmp("!Linux", str)) { | 1119 | if (*str == '!') { |
1113 | acpi_cmdline_osi_linux(0); /* !enable */ | 1120 | status = acpi_remove_interface(++str); |
1114 | } else if (*str == '!') { | 1121 | |
1115 | if (acpi_remove_interface(++str) == AE_OK) | 1122 | if (ACPI_SUCCESS(status)) |
1116 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); | 1123 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); |
1117 | } else if (!strcmp("Linux", str)) { | ||
1118 | acpi_cmdline_osi_linux(1); /* enable */ | ||
1119 | } else { | 1124 | } else { |
1120 | if (acpi_install_interface(str) == AE_OK) | 1125 | status = acpi_install_interface(str); |
1126 | |||
1127 | if (ACPI_SUCCESS(status)) | ||
1121 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); | 1128 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); |
1122 | } | 1129 | } |
1123 | } | 1130 | } |
1124 | 1131 | ||
1125 | int __init acpi_osi_setup(char *str) | 1132 | static int __init osi_setup(char *str) |
1126 | { | 1133 | { |
1127 | if (str == NULL || *str == '\0') { | 1134 | if (str && !strcmp("Linux", str)) |
1128 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); | 1135 | acpi_cmdline_osi_linux(1); |
1129 | acpi_gbl_create_osi_method = FALSE; | 1136 | else if (str && !strcmp("!Linux", str)) |
1130 | } else { | 1137 | acpi_cmdline_osi_linux(0); |
1131 | strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX); | 1138 | else |
1132 | } | 1139 | acpi_osi_setup(str); |
1133 | 1140 | ||
1134 | return 1; | 1141 | return 1; |
1135 | } | 1142 | } |
1136 | 1143 | ||
1137 | __setup("acpi_osi=", acpi_osi_setup); | 1144 | __setup("acpi_osi=", osi_setup); |
1138 | 1145 | ||
1139 | /* enable serialization to combat AE_ALREADY_EXISTS errors */ | 1146 | /* enable serialization to combat AE_ALREADY_EXISTS errors */ |
1140 | static int __init acpi_serialize_setup(char *str) | 1147 | static int __init acpi_serialize_setup(char *str) |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 050a7bccb836..67c91b4418b0 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -219,7 +219,7 @@ static inline int acpi_video_display_switch_support(void) | |||
219 | 219 | ||
220 | extern int acpi_blacklisted(void); | 220 | extern int acpi_blacklisted(void); |
221 | extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d); | 221 | extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d); |
222 | extern int acpi_osi_setup(char *str); | 222 | extern void acpi_osi_setup(char *str); |
223 | 223 | ||
224 | #ifdef CONFIG_ACPI_NUMA | 224 | #ifdef CONFIG_ACPI_NUMA |
225 | int acpi_get_pxm(acpi_handle handle); | 225 | int acpi_get_pxm(acpi_handle handle); |