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); |
