| @@ -77,7 +77,55 @@ static struct workqueue_struct *kacpi_notify_wq; · 76 unmodified lines |
| 77 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ | 77 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ |
| 78 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; | 78 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; |
| 79 | | 79 | |
| 80 | static int osi_linux; /* disable _OSI(Linux) by default */ | 80 | /* |
| | 81 | * "Ode to _OSI(Linux)" |
| | 82 | * |
| | 83 | * osi_linux -- Control response to BIOS _OSI(Linux) query. |
| | 84 | * |
| | 85 | * As Linux evolves, the features that it supports change. |
| | 86 | * So an OSI string such as "Linux" is not specific enough |
| | 87 | * to be useful across multiple versions of Linux. It |
| | 88 | * doesn't identify any particular feature, interface, |
| | 89 | * or even any particular version of Linux... |
| | 90 | * |
| | 91 | * Unfortunately, Linux-2.6.22 and earlier responded "yes" |
| | 92 | * to a BIOS _OSI(Linux) query. When |
| | 93 | * a reference mobile BIOS started using it, its use |
| | 94 | * started to spread to many vendor platforms. |
| | 95 | * As it is not supportable, we need to halt that spread. |
| | 96 | * |
| | 97 | * Today, most BIOS references to _OSI(Linux) are noise -- |
| | 98 | * they have no functional effect and are just dead code |
| | 99 | * carried over from the reference BIOS. |
| | 100 | * |
| | 101 | * The next most common case is that _OSI(Linux) harms Linux, |
| | 102 | * usually by causing the BIOS to follow paths that are |
| | 103 | * not tested during Windows validation. |
| | 104 | * |
| | 105 | * Finally, there is a short list of platforms |
| | 106 | * where OSI(Linux) benefits Linux. |
| | 107 | * |
| | 108 | * In Linux-2.6.23, OSI(Linux) is first disabled by default. |
| | 109 | * DMI is used to disable the dmesg warning about OSI(Linux) |
| | 110 | * on platforms where it is known to have no effect. |
| | 111 | * But a dmesg warning remains for systems where |
| | 112 | * we do not know if OSI(Linux) is good or bad for the system. |
| | 113 | * DMI is also used to enable OSI(Linux) for the machines |
| | 114 | * that are known to need it. |
| | 115 | * |
| | 116 | * BIOS writers should NOT query _OSI(Linux) on future systems. |
| | 117 | * It will be ignored by default, and to get Linux to |
| | 118 | * not ignore it will require a kernel source update to |
| | 119 | * add a DMI entry, or a boot-time "acpi_osi=Linux" invocation. |
| | 120 | */ |
| | 121 | #define OSI_LINUX_ENABLE 0 |
| | 122 | |
| | 123 | struct osi_linux { |
| | 124 | unsigned int enable:1; |
| | 125 | unsigned int dmi:1; |
| | 126 | unsigned int cmdline:1; |
| | 127 | unsigned int known:1; |
| | 128 | } osi_linux = { OSI_LINUX_ENABLE, 0, 0, 0}; |
| 81 | | 129 | |
| 82 | static void __init acpi_request_region (struct acpi_generic_address *addr, | 130 | static void __init acpi_request_region (struct acpi_generic_address *addr, |
| 83 | unsigned int length, char *desc) | 131 | unsigned int length, char *desc) |
| @@ -959,13 +1007,37 @@ static int __init acpi_os_name_setup(char *str) · 875 unmodified lines |
| 959 | | 1007 | |
| 960 | __setup("acpi_os_name=", acpi_os_name_setup); | 1008 | __setup("acpi_os_name=", acpi_os_name_setup); |
| 961 | | 1009 | |
| 962 | static void enable_osi_linux(int enable) { | 1010 | static void __init set_osi_linux(unsigned int enable) |
| | 1011 | { |
| | 1012 | if (osi_linux.enable != enable) { |
| | 1013 | osi_linux.enable = enable; |
| | 1014 | printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n", |
| | 1015 | enable ? "Add": "Delet"); |
| | 1016 | } |
| | 1017 | return; |
| | 1018 | } |
| | 1019 | |
| | 1020 | static void __init acpi_cmdline_osi_linux(unsigned int enable) |
| | 1021 | { |
| | 1022 | osi_linux.cmdline = 1; /* cmdline set the default */ |
| | 1023 | set_osi_linux(enable); |
| | 1024 | |
| | 1025 | return; |
| | 1026 | } |
| | 1027 | |
| | 1028 | void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) |
| | 1029 | { |
| | 1030 | osi_linux.dmi = 1; /* DMI knows that this box asks OSI(Linux) */ |
| | 1031 | |
| | 1032 | printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); |
| | 1033 | |
| | 1034 | if (enable == -1) |
| | 1035 | return; |
| | 1036 | |
| | 1037 | osi_linux.known = 1; /* DMI knows which OSI(Linux) default needed */ |
| 963 | | 1038 | |
| 964 | if (osi_linux != enable) | 1039 | set_osi_linux(enable); |
| 965 | printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n", | | |
| 966 | enable ? "En": "Dis"); | | |
| 967 | | 1040 | |
| 968 | osi_linux = enable; | | |
| 969 | return; | 1041 | return; |
| 970 | } | 1042 | } |
| 971 | | 1043 | |
| @@ -982,12 +1054,12 @@ static int __init acpi_osi_setup(char *str) · 10 unmodified lines |
| 982 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); | 1054 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); |
| 983 | acpi_gbl_create_osi_method = FALSE; | 1055 | acpi_gbl_create_osi_method = FALSE; |
| 984 | } else if (!strcmp("!Linux", str)) { | 1056 | } else if (!strcmp("!Linux", str)) { |
| 985 | enable_osi_linux(0); | 1057 | acpi_cmdline_osi_linux(0); /* !enable */ |
| 986 | } else if (*str == '!') { | 1058 | } else if (*str == '!') { |
| 987 | if (acpi_osi_invalidate(++str) == AE_OK) | 1059 | if (acpi_osi_invalidate(++str) == AE_OK) |
| 988 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); | 1060 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); |
| 989 | } else if (!strcmp("Linux", str)) { | 1061 | } else if (!strcmp("Linux", str)) { |
| 990 | enable_osi_linux(1); | 1062 | acpi_cmdline_osi_linux(1); /* enable */ |
| 991 | } else if (*osi_additional_string == '\0') { | 1063 | } else if (*osi_additional_string == '\0') { |
| 992 | strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); | 1064 | strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); |
| 993 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); | 1065 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); |
| @@ -1183,19 +1255,29 @@ acpi_os_validate_interface (char *interface) · 189 unmodified lines |
| 1183 | if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) | 1255 | if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) |
| 1184 | return AE_OK; | 1256 | return AE_OK; |
| 1185 | if (!strcmp("Linux", interface)) { | 1257 | if (!strcmp("Linux", interface)) { |
| 1186 | printk(KERN_WARNING PREFIX | 1258 | |
| 1187 | "System BIOS is requesting _OSI(Linux)\n"); | | |
| 1188 | if (acpi_dmi_dump()) | | |
| 1189 | printk(KERN_NOTICE PREFIX | | |
| 1190 | "[please extract dmidecode output]\n"); | | |
| 1191 | printk(KERN_NOTICE PREFIX | | |
| 1192 | "Please send DMI info above to " | | |
| 1193 | "linux-acpi@vger.kernel.org\n"); | | |
| 1194 | printk(KERN_NOTICE PREFIX | 1259 | printk(KERN_NOTICE PREFIX |
| 1195 | "If \"acpi_osi=%sLinux\" works better, " | 1260 | "BIOS _OSI(Linux) query %s%s\n", |
| 1196 | "please notify linux-acpi@vger.kernel.org\n", | 1261 | osi_linux.enable ? "honored" : "ignored", |
| 1197 | osi_linux ? "!" : ""); | 1262 | osi_linux.cmdline ? " via cmdline" : |
| 1198 | if(osi_linux) | 1263 | osi_linux.dmi ? " via DMI" : ""); |
| | 1264 | |
| | 1265 | if (!osi_linux.dmi) { |
| | 1266 | if (acpi_dmi_dump()) |
| | 1267 | printk(KERN_NOTICE PREFIX |
| | 1268 | "[please extract dmidecode output]\n"); |
| | 1269 | printk(KERN_NOTICE PREFIX |
| | 1270 | "Please send DMI info above to " |
| | 1271 | "linux-acpi@vger.kernel.org\n"); |
| | 1272 | } |
| | 1273 | if (!osi_linux.known && !osi_linux.cmdline) { |
| | 1274 | printk(KERN_NOTICE PREFIX |
| | 1275 | "If \"acpi_osi=%sLinux\" works better, " |
| | 1276 | "please notify linux-acpi@vger.kernel.org\n", |
| | 1277 | osi_linux.enable ? "!" : ""); |
| | 1278 | } |
| | 1279 | |
| | 1280 | if (osi_linux.enable) |
| 1199 | return AE_OK; | 1281 | return AE_OK; |
| 1200 | } | 1282 | } |
| 1201 | return AE_SUPPORT; | 1283 | return AE_SUPPORT; |