| @@ -77,7 +77,55 @@ static struct workqueue_struct *kacpi_notify_wq; · 76 unmodified lines |
| 77 | 77 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ |
| 78 | 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 | 130 | static void __init acpi_request_region (struct acpi_generic_address *addr, |
| 83 | 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 | 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) |
| 965 | | − printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n", |
| 966 | | − enable ? "En": "Dis"); |
| 1039 | + set_osi_linux(enable); |
| 967 | 1040 | |
| 968 | | − osi_linux = enable; |
| 969 | 1041 | return; |
| 970 | 1042 | } |
| 971 | 1043 | |
| @@ -982,12 +1054,12 @@ static int __init acpi_osi_setup(char *str) · 10 unmodified lines |
| 982 | 1054 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); |
| 983 | 1055 | acpi_gbl_create_osi_method = FALSE; |
| 984 | 1056 | } else if (!strcmp("!Linux", str)) { |
| 985 | | − enable_osi_linux(0); |
| 1057 | + acpi_cmdline_osi_linux(0); /* !enable */ |
| 986 | 1058 | } else if (*str == '!') { |
| 987 | 1059 | if (acpi_osi_invalidate(++str) == AE_OK) |
| 988 | 1060 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); |
| 989 | 1061 | } else if (!strcmp("Linux", str)) { |
| 990 | | − enable_osi_linux(1); |
| 1062 | + acpi_cmdline_osi_linux(1); /* enable */ |
| 991 | 1063 | } else if (*osi_additional_string == '\0') { |
| 992 | 1064 | strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); |
| 993 | 1065 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); |
| @@ -1183,19 +1255,29 @@ acpi_os_validate_interface (char *interface) · 189 unmodified lines |
| 1183 | 1255 | if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) |
| 1184 | 1256 | return AE_OK; |
| 1185 | 1257 | if (!strcmp("Linux", interface)) { |
| 1186 | | − printk(KERN_WARNING PREFIX |
| 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"); |
| 1258 | + |
| 1194 | 1259 | printk(KERN_NOTICE PREFIX |
| 1195 | | − "If \"acpi_osi=%sLinux\" works better, " |
| 1196 | | − "please notify linux-acpi@vger.kernel.org\n", |
| 1197 | | − osi_linux ? "!" : ""); |
| 1198 | | − if(osi_linux) |
| 1260 | + "BIOS _OSI(Linux) query %s%s\n", |
| 1261 | + osi_linux.enable ? "honored" : "ignored", |
| 1262 | + osi_linux.cmdline ? " via cmdline" : |
| 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 | 1281 | return AE_OK; |
| 1200 | 1282 | } |
| 1201 | 1283 | return AE_SUPPORT; |