Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6595 | serge | 1 | /* |
2 | * blacklist.c |
||
3 | * |
||
4 | * Check to see if the given machine has a known bad ACPI BIOS |
||
5 | * or if the BIOS is too old. |
||
6 | * Check given machine against acpi_osi_dmi_table[]. |
||
7 | * |
||
8 | * Copyright (C) 2004 Len Brown |
||
9 | * Copyright (C) 2002 Andy Grover |
||
10 | * |
||
11 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
12 | * |
||
13 | * This program is free software; you can redistribute it and/or modify |
||
14 | * it under the terms of the GNU General Public License as published by |
||
15 | * the Free Software Foundation; either version 2 of the License, or (at |
||
16 | * your option) any later version. |
||
17 | * |
||
18 | * This program is distributed in the hope that it will be useful, but |
||
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
21 | * General Public License for more details. |
||
22 | * |
||
23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
24 | */ |
||
25 | |||
26 | #include |
||
27 | #include |
||
28 | #include |
||
29 | #include |
||
30 | |||
31 | #include "internal.h" |
||
32 | |||
33 | enum acpi_blacklist_predicates { |
||
34 | all_versions, |
||
35 | less_than_or_equal, |
||
36 | equal, |
||
37 | greater_than_or_equal, |
||
38 | }; |
||
39 | |||
40 | struct acpi_blacklist_item { |
||
41 | char oem_id[7]; |
||
42 | char oem_table_id[9]; |
||
43 | u32 oem_revision; |
||
44 | char *table; |
||
45 | enum acpi_blacklist_predicates oem_revision_predicate; |
||
46 | char *reason; |
||
47 | u32 is_critical_error; |
||
48 | }; |
||
49 | |||
50 | static struct dmi_system_id acpi_osi_dmi_table[] __initdata; |
||
51 | |||
52 | /* |
||
53 | * POLICY: If *anything* doesn't work, put it on the blacklist. |
||
54 | * If they are critical errors, mark it critical, and abort driver load. |
||
55 | */ |
||
56 | static struct acpi_blacklist_item acpi_blacklist[] __initdata = { |
||
57 | /* Compaq Presario 1700 */ |
||
58 | {"PTLTD ", " DSDT ", 0x06040000, ACPI_SIG_DSDT, less_than_or_equal, |
||
59 | "Multiple problems", 1}, |
||
60 | /* Sony FX120, FX140, FX150? */ |
||
61 | {"SONY ", "U0 ", 0x20010313, ACPI_SIG_DSDT, less_than_or_equal, |
||
62 | "ACPI driver problem", 1}, |
||
63 | /* Compaq Presario 800, Insyde BIOS */ |
||
64 | {"INT440", "SYSFexxx", 0x00001001, ACPI_SIG_DSDT, less_than_or_equal, |
||
65 | "Does not use _REG to protect EC OpRegions", 1}, |
||
66 | /* IBM 600E - _ADR should return 7, but it returns 1 */ |
||
67 | {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal, |
||
68 | "Incorrect _ADR", 1}, |
||
69 | |||
70 | {""} |
||
71 | }; |
||
72 | |||
73 | int __init acpi_blacklisted(void) |
||
74 | { |
||
75 | int i = 0; |
||
76 | int blacklisted = 0; |
||
77 | struct acpi_table_header table_header; |
||
78 | |||
79 | while (acpi_blacklist[i].oem_id[0] != '\0') { |
||
80 | if (acpi_get_table_header(acpi_blacklist[i].table, 0, &table_header)) { |
||
81 | i++; |
||
82 | continue; |
||
83 | } |
||
84 | |||
85 | if (strncmp(acpi_blacklist[i].oem_id, table_header.oem_id, 6)) { |
||
86 | i++; |
||
87 | continue; |
||
88 | } |
||
89 | |||
90 | if (strncmp |
||
91 | (acpi_blacklist[i].oem_table_id, table_header.oem_table_id, |
||
92 | 8)) { |
||
93 | i++; |
||
94 | continue; |
||
95 | } |
||
96 | |||
97 | if ((acpi_blacklist[i].oem_revision_predicate == all_versions) |
||
98 | || (acpi_blacklist[i].oem_revision_predicate == |
||
99 | less_than_or_equal |
||
100 | && table_header.oem_revision <= |
||
101 | acpi_blacklist[i].oem_revision) |
||
102 | || (acpi_blacklist[i].oem_revision_predicate == |
||
103 | greater_than_or_equal |
||
104 | && table_header.oem_revision >= |
||
105 | acpi_blacklist[i].oem_revision) |
||
106 | || (acpi_blacklist[i].oem_revision_predicate == equal |
||
107 | && table_header.oem_revision == |
||
108 | acpi_blacklist[i].oem_revision)) { |
||
109 | |||
110 | printk(KERN_ERR PREFIX |
||
111 | "Vendor \"%6.6s\" System \"%8.8s\" " |
||
112 | "Revision 0x%x has a known ACPI BIOS problem.\n", |
||
113 | acpi_blacklist[i].oem_id, |
||
114 | acpi_blacklist[i].oem_table_id, |
||
115 | acpi_blacklist[i].oem_revision); |
||
116 | |||
117 | printk(KERN_ERR PREFIX |
||
118 | "Reason: %s. This is a %s error\n", |
||
119 | acpi_blacklist[i].reason, |
||
120 | (acpi_blacklist[i]. |
||
121 | is_critical_error ? "non-recoverable" : |
||
122 | "recoverable")); |
||
123 | |||
124 | blacklisted = acpi_blacklist[i].is_critical_error; |
||
125 | break; |
||
126 | } else { |
||
127 | i++; |
||
128 | } |
||
129 | } |
||
130 | |||
131 | dmi_check_system(acpi_osi_dmi_table); |
||
132 | |||
133 | return blacklisted; |
||
134 | } |
||
135 | #ifdef CONFIG_DMI |
||
136 | static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) |
||
137 | { |
||
138 | acpi_dmi_osi_linux(1, d); /* enable */ |
||
139 | return 0; |
||
140 | } |
||
141 | static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) |
||
142 | { |
||
143 | printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); |
||
144 | acpi_osi_setup("!Windows 2006"); |
||
145 | acpi_osi_setup("!Windows 2006 SP1"); |
||
146 | acpi_osi_setup("!Windows 2006 SP2"); |
||
147 | return 0; |
||
148 | } |
||
149 | static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) |
||
150 | { |
||
151 | printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); |
||
152 | acpi_osi_setup("!Windows 2009"); |
||
153 | return 0; |
||
154 | } |
||
155 | static int __init dmi_disable_osi_win8(const struct dmi_system_id *d) |
||
156 | { |
||
157 | printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); |
||
158 | acpi_osi_setup("!Windows 2012"); |
||
159 | return 0; |
||
160 | } |
||
161 | #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE |
||
162 | static int __init dmi_enable_rev_override(const struct dmi_system_id *d) |
||
163 | { |
||
164 | printk(KERN_NOTICE PREFIX "DMI detected: %s (force ACPI _REV to 5)\n", |
||
165 | d->ident); |
||
166 | acpi_rev_override_setup(NULL); |
||
167 | return 0; |
||
168 | } |
||
169 | #endif |
||
170 | |||
171 | static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { |
||
172 | { |
||
173 | .callback = dmi_disable_osi_vista, |
||
174 | .ident = "Fujitsu Siemens", |
||
175 | .matches = { |
||
176 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
||
177 | DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), |
||
178 | }, |
||
179 | }, |
||
180 | { |
||
181 | /* |
||
182 | * There have a NVIF method in MSI GX723 DSDT need call by Nvidia |
||
183 | * driver (e.g. nouveau) when user press brightness hotkey. |
||
184 | * Currently, nouveau driver didn't do the job and it causes there |
||
185 | * have a infinite while loop in DSDT when user press hotkey. |
||
186 | * We add MSI GX723's dmi information to this table for workaround |
||
187 | * this issue. |
||
188 | * Will remove MSI GX723 from the table after nouveau grows support. |
||
189 | */ |
||
190 | .callback = dmi_disable_osi_vista, |
||
191 | .ident = "MSI GX723", |
||
192 | .matches = { |
||
193 | DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), |
||
194 | DMI_MATCH(DMI_PRODUCT_NAME, "GX723"), |
||
195 | }, |
||
196 | }, |
||
197 | { |
||
198 | .callback = dmi_disable_osi_vista, |
||
199 | .ident = "Sony VGN-NS10J_S", |
||
200 | .matches = { |
||
201 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), |
||
202 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"), |
||
203 | }, |
||
204 | }, |
||
205 | { |
||
206 | .callback = dmi_disable_osi_vista, |
||
207 | .ident = "Sony VGN-SR290J", |
||
208 | .matches = { |
||
209 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), |
||
210 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"), |
||
211 | }, |
||
212 | }, |
||
213 | { |
||
214 | .callback = dmi_disable_osi_vista, |
||
215 | .ident = "VGN-NS50B_L", |
||
216 | .matches = { |
||
217 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), |
||
218 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"), |
||
219 | }, |
||
220 | }, |
||
221 | { |
||
222 | .callback = dmi_disable_osi_vista, |
||
223 | .ident = "VGN-SR19XN", |
||
224 | .matches = { |
||
225 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), |
||
226 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"), |
||
227 | }, |
||
228 | }, |
||
229 | { |
||
230 | .callback = dmi_disable_osi_vista, |
||
231 | .ident = "Toshiba Satellite L355", |
||
232 | .matches = { |
||
233 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
||
234 | DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"), |
||
235 | }, |
||
236 | }, |
||
237 | { |
||
238 | .callback = dmi_disable_osi_win7, |
||
239 | .ident = "ASUS K50IJ", |
||
240 | .matches = { |
||
241 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), |
||
242 | DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"), |
||
243 | }, |
||
244 | }, |
||
245 | { |
||
246 | .callback = dmi_disable_osi_vista, |
||
247 | .ident = "Toshiba P305D", |
||
248 | .matches = { |
||
249 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
||
250 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), |
||
251 | }, |
||
252 | }, |
||
253 | { |
||
254 | .callback = dmi_disable_osi_vista, |
||
255 | .ident = "Toshiba NB100", |
||
256 | .matches = { |
||
257 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
||
258 | DMI_MATCH(DMI_PRODUCT_NAME, "NB100"), |
||
259 | }, |
||
260 | }, |
||
261 | |||
262 | /* |
||
263 | * The wireless hotkey does not work on those machines when |
||
264 | * returning true for _OSI("Windows 2012") |
||
265 | */ |
||
266 | { |
||
267 | .callback = dmi_disable_osi_win8, |
||
268 | .ident = "Dell Inspiron 7737", |
||
269 | .matches = { |
||
270 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
||
271 | DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"), |
||
272 | }, |
||
273 | }, |
||
274 | { |
||
275 | .callback = dmi_disable_osi_win8, |
||
276 | .ident = "Dell Inspiron 7537", |
||
277 | .matches = { |
||
278 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
||
279 | DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"), |
||
280 | }, |
||
281 | }, |
||
282 | { |
||
283 | .callback = dmi_disable_osi_win8, |
||
284 | .ident = "Dell Inspiron 5437", |
||
285 | .matches = { |
||
286 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
||
287 | DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"), |
||
288 | }, |
||
289 | }, |
||
290 | { |
||
291 | .callback = dmi_disable_osi_win8, |
||
292 | .ident = "Dell Inspiron 3437", |
||
293 | .matches = { |
||
294 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
||
295 | DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"), |
||
296 | }, |
||
297 | }, |
||
298 | { |
||
299 | .callback = dmi_disable_osi_win8, |
||
300 | .ident = "Dell Vostro 3446", |
||
301 | .matches = { |
||
302 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
||
303 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"), |
||
304 | }, |
||
305 | }, |
||
306 | { |
||
307 | .callback = dmi_disable_osi_win8, |
||
308 | .ident = "Dell Vostro 3546", |
||
309 | .matches = { |
||
310 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
||
311 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"), |
||
312 | }, |
||
313 | }, |
||
314 | |||
315 | /* |
||
316 | * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. |
||
317 | * Linux ignores it, except for the machines enumerated below. |
||
318 | */ |
||
319 | |||
320 | /* |
||
321 | * Without this this EEEpc exports a non working WMI interface, with |
||
322 | * this it exports a working "good old" eeepc_laptop interface, fixing |
||
323 | * both brightness control, and rfkill not working. |
||
324 | */ |
||
325 | { |
||
326 | .callback = dmi_enable_osi_linux, |
||
327 | .ident = "Asus EEE PC 1015PX", |
||
328 | .matches = { |
||
329 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), |
||
330 | DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"), |
||
331 | }, |
||
332 | }, |
||
333 | |||
334 | #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE |
||
335 | /* |
||
336 | * DELL XPS 13 (2015) switches sound between HDA and I2S |
||
337 | * depending on the ACPI _REV callback. If userspace supports |
||
338 | * I2S sufficiently (or if you do not care about sound), you |
||
339 | * can safely disable this quirk. |
||
340 | */ |
||
341 | { |
||
342 | .callback = dmi_enable_rev_override, |
||
343 | .ident = "DELL XPS 13 (2015)", |
||
344 | .matches = { |
||
345 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
||
346 | DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343"), |
||
347 | }, |
||
348 | }, |
||
349 | #endif |
||
350 | {} |
||
351 | }; |
||
352 | |||
353 | #endif /* CONFIG_DMI */= |