aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/osl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/osl.c')
-rw-r--r--drivers/acpi/osl.c181
1 files changed, 136 insertions, 45 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 21d34595dbae..07c18dbde698 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -77,11 +77,55 @@ static struct workqueue_struct *kacpi_notify_wq;
77#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ 77#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
78static char osi_additional_string[OSI_STRING_LENGTH_MAX]; 78static char osi_additional_string[OSI_STRING_LENGTH_MAX];
79 79
80static 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
81 122
82#ifdef CONFIG_DMI 123static struct osi_linux {
83static struct __initdata dmi_system_id acpi_osl_dmi_table[]; 124 unsigned int enable:1;
84#endif 125 unsigned int dmi:1;
126 unsigned int cmdline:1;
127 unsigned int known:1;
128} osi_linux = { OSI_LINUX_ENABLE, 0, 0, 0};
85 129
86static void __init acpi_request_region (struct acpi_generic_address *addr, 130static void __init acpi_request_region (struct acpi_generic_address *addr,
87 unsigned int length, char *desc) 131 unsigned int length, char *desc)
@@ -133,7 +177,6 @@ device_initcall(acpi_reserve_resources);
133 177
134acpi_status __init acpi_os_initialize(void) 178acpi_status __init acpi_os_initialize(void)
135{ 179{
136 dmi_check_system(acpi_osl_dmi_table);
137 return AE_OK; 180 return AE_OK;
138} 181}
139 182
@@ -207,8 +250,12 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
207 "System description tables not found\n"); 250 "System description tables not found\n");
208 return 0; 251 return 0;
209 } 252 }
210 } else 253 } else {
211 return acpi_find_rsdp(); 254 acpi_physical_address pa = 0;
255
256 acpi_find_root_pointer(&pa);
257 return pa;
258 }
212} 259}
213 260
214void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) 261void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
@@ -938,13 +985,37 @@ static int __init acpi_os_name_setup(char *str)
938 985
939__setup("acpi_os_name=", acpi_os_name_setup); 986__setup("acpi_os_name=", acpi_os_name_setup);
940 987
941static void enable_osi_linux(int enable) { 988static void __init set_osi_linux(unsigned int enable)
989{
990 if (osi_linux.enable != enable) {
991 osi_linux.enable = enable;
992 printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
993 enable ? "Add": "Delet");
994 }
995 return;
996}
997
998static void __init acpi_cmdline_osi_linux(unsigned int enable)
999{
1000 osi_linux.cmdline = 1; /* cmdline set the default */
1001 set_osi_linux(enable);
1002
1003 return;
1004}
1005
1006void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
1007{
1008 osi_linux.dmi = 1; /* DMI knows that this box asks OSI(Linux) */
1009
1010 printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
1011
1012 if (enable == -1)
1013 return;
1014
1015 osi_linux.known = 1; /* DMI knows which OSI(Linux) default needed */
942 1016
943 if (osi_linux != enable) 1017 set_osi_linux(enable);
944 printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n",
945 enable ? "En": "Dis");
946 1018
947 osi_linux = enable;
948 return; 1019 return;
949} 1020}
950 1021
@@ -961,12 +1032,12 @@ static int __init acpi_osi_setup(char *str)
961 printk(KERN_INFO PREFIX "_OSI method disabled\n"); 1032 printk(KERN_INFO PREFIX "_OSI method disabled\n");
962 acpi_gbl_create_osi_method = FALSE; 1033 acpi_gbl_create_osi_method = FALSE;
963 } else if (!strcmp("!Linux", str)) { 1034 } else if (!strcmp("!Linux", str)) {
964 enable_osi_linux(0); 1035 acpi_cmdline_osi_linux(0); /* !enable */
965 } else if (*str == '!') { 1036 } else if (*str == '!') {
966 if (acpi_osi_invalidate(++str) == AE_OK) 1037 if (acpi_osi_invalidate(++str) == AE_OK)
967 printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); 1038 printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
968 } else if (!strcmp("Linux", str)) { 1039 } else if (!strcmp("Linux", str)) {
969 enable_osi_linux(1); 1040 acpi_cmdline_osi_linux(1); /* enable */
970 } else if (*osi_additional_string == '\0') { 1041 } else if (*osi_additional_string == '\0') {
971 strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); 1042 strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX);
972 printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); 1043 printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
@@ -1115,6 +1186,34 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
1115 return (AE_OK); 1186 return (AE_OK);
1116} 1187}
1117 1188
1189/**
1190 * acpi_dmi_dump - dump DMI slots needed for blacklist entry
1191 *
1192 * Returns 0 on success
1193 */
1194static int acpi_dmi_dump(void)
1195{
1196
1197 if (!dmi_available)
1198 return -1;
1199
1200 printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
1201 dmi_get_system_info(DMI_SYS_VENDOR));
1202 printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
1203 dmi_get_system_info(DMI_PRODUCT_NAME));
1204 printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
1205 dmi_get_system_info(DMI_PRODUCT_VERSION));
1206 printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
1207 dmi_get_system_info(DMI_BOARD_NAME));
1208 printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
1209 dmi_get_system_info(DMI_BIOS_VENDOR));
1210 printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
1211 dmi_get_system_info(DMI_BIOS_DATE));
1212
1213 return 0;
1214}
1215
1216
1118/****************************************************************************** 1217/******************************************************************************
1119 * 1218 *
1120 * FUNCTION: acpi_os_validate_interface 1219 * FUNCTION: acpi_os_validate_interface
@@ -1134,13 +1233,29 @@ acpi_os_validate_interface (char *interface)
1134 if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) 1233 if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX))
1135 return AE_OK; 1234 return AE_OK;
1136 if (!strcmp("Linux", interface)) { 1235 if (!strcmp("Linux", interface)) {
1137 printk(KERN_WARNING PREFIX 1236
1138 "System BIOS is requesting _OSI(Linux)\n"); 1237 printk(KERN_NOTICE PREFIX
1139 printk(KERN_WARNING PREFIX 1238 "BIOS _OSI(Linux) query %s%s\n",
1140 "If \"acpi_osi=Linux\" works better,\n" 1239 osi_linux.enable ? "honored" : "ignored",
1141 "Please send dmidecode " 1240 osi_linux.cmdline ? " via cmdline" :
1142 "to linux-acpi@vger.kernel.org\n"); 1241 osi_linux.dmi ? " via DMI" : "");
1143 if(osi_linux) 1242
1243 if (!osi_linux.dmi) {
1244 if (acpi_dmi_dump())
1245 printk(KERN_NOTICE PREFIX
1246 "[please extract dmidecode output]\n");
1247 printk(KERN_NOTICE PREFIX
1248 "Please send DMI info above to "
1249 "linux-acpi@vger.kernel.org\n");
1250 }
1251 if (!osi_linux.known && !osi_linux.cmdline) {
1252 printk(KERN_NOTICE PREFIX
1253 "If \"acpi_osi=%sLinux\" works better, "
1254 "please notify linux-acpi@vger.kernel.org\n",
1255 osi_linux.enable ? "!" : "");
1256 }
1257
1258 if (osi_linux.enable)
1144 return AE_OK; 1259 return AE_OK;
1145 } 1260 }
1146 return AE_SUPPORT; 1261 return AE_SUPPORT;
@@ -1172,28 +1287,4 @@ acpi_os_validate_address (
1172 return AE_OK; 1287 return AE_OK;
1173} 1288}
1174 1289
1175#ifdef CONFIG_DMI
1176static int dmi_osi_linux(const struct dmi_system_id *d)
1177{
1178 printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident);
1179 enable_osi_linux(1);
1180 return 0;
1181}
1182
1183static struct dmi_system_id acpi_osl_dmi_table[] __initdata = {
1184 /*
1185 * Boxes that need _OSI(Linux)
1186 */
1187 {
1188 .callback = dmi_osi_linux,
1189 .ident = "Intel Napa CRB",
1190 .matches = {
1191 DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
1192 DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"),
1193 },
1194 },
1195 {}
1196};
1197#endif /* CONFIG_DMI */
1198
1199#endif 1290#endif