Blame view

drivers/acpi/blacklist.c 8.89 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /*
   *  blacklist.c
   *
   *  Check to see if the given machine has a known bad ACPI BIOS
   *  or if the BIOS is too old.
d4b7dc499   Len Brown   ACPI: make _OSI(L...
6
   *  Check given machine against acpi_osi_dmi_table[].
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
   *
   *  Copyright (C) 2004 Len Brown <len.brown@intel.com>
   *  Copyright (C) 2002 Andy Grover <andrew.grover@intel.com>
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or (at
   *  your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful, but
   *  WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   *  General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License along
   *  with this program; if not, write to the Free Software Foundation, Inc.,
   *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
  #include <linux/init.h>
  #include <linux/acpi.h>
  #include <acpi/acpi_bus.h>
  #include <linux/dmi.h>
a192a9580   Len Brown   ACPI: Move defini...
34
  #include "internal.h"
4be44fcd3   Len Brown   [ACPI] Lindent al...
35
36
37
38
39
  enum acpi_blacklist_predicates {
  	all_versions,
  	less_than_or_equal,
  	equal,
  	greater_than_or_equal,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  };
4be44fcd3   Len Brown   [ACPI] Lindent al...
41
42
43
44
  struct acpi_blacklist_item {
  	char oem_id[7];
  	char oem_table_id[9];
  	u32 oem_revision;
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
45
  	char *table;
4be44fcd3   Len Brown   [ACPI] Lindent al...
46
47
48
  	enum acpi_blacklist_predicates oem_revision_predicate;
  	char *reason;
  	u32 is_critical_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  };
d4b7dc499   Len Brown   ACPI: make _OSI(L...
50
  static struct dmi_system_id acpi_osi_dmi_table[] __initdata;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
  /*
   * POLICY: If *anything* doesn't work, put it on the blacklist.
   *	   If they are critical errors, mark it critical, and abort driver load.
   */
4be44fcd3   Len Brown   [ACPI] Lindent al...
55
  static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  	/* Compaq Presario 1700 */
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
57
  	{"PTLTD ", "  DSDT  ", 0x06040000, ACPI_SIG_DSDT, less_than_or_equal,
4be44fcd3   Len Brown   [ACPI] Lindent al...
58
  	 "Multiple problems", 1},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  	/* Sony FX120, FX140, FX150? */
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
60
  	{"SONY  ", "U0      ", 0x20010313, ACPI_SIG_DSDT, less_than_or_equal,
4be44fcd3   Len Brown   [ACPI] Lindent al...
61
  	 "ACPI driver problem", 1},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  	/* Compaq Presario 800, Insyde BIOS */
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
63
  	{"INT440", "SYSFexxx", 0x00001001, ACPI_SIG_DSDT, less_than_or_equal,
4be44fcd3   Len Brown   [ACPI] Lindent al...
64
  	 "Does not use _REG to protect EC OpRegions", 1},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  	/* IBM 600E - _ADR should return 7, but it returns 1 */
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
66
  	{"IBM   ", "TP600E  ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal,
4be44fcd3   Len Brown   [ACPI] Lindent al...
67
  	 "Incorrect _ADR", 1},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
  
  	{""}
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  #if	CONFIG_ACPI_BLACKLIST_YEAR
4be44fcd3   Len Brown   [ACPI] Lindent al...
72
  static int __init blacklist_by_year(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  {
3e5cd1f25   Tejun Heo   dmi: extend dmi_g...
74
  	int year;
f083a329e   Andi Kleen   [PATCH] x86_64: C...
75
  	/* Doesn't exist? Likely an old system */
3e5cd1f25   Tejun Heo   dmi: extend dmi_g...
76
  	if (!dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL)) {
5b27b176d   Anthony Godshall, Ampro Computers, Inc   ACPI: make blackl...
77
78
79
  		printk(KERN_ERR PREFIX "no DMI BIOS year, "
  			"acpi=force is required to enable ACPI
  " );
f083a329e   Andi Kleen   [PATCH] x86_64: C...
80
  		return 1;
5b27b176d   Anthony Godshall, Ampro Computers, Inc   ACPI: make blackl...
81
  	}
f083a329e   Andi Kleen   [PATCH] x86_64: C...
82
  	/* 0? Likely a buggy new BIOS */
5b27b176d   Anthony Godshall, Ampro Computers, Inc   ACPI: make blackl...
83
84
85
86
  	if (year == 0) {
  		printk(KERN_ERR PREFIX "DMI BIOS year==0, "
  			"assuming ACPI-capable machine
  " );
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  		return 0;
5b27b176d   Anthony Godshall, Ampro Computers, Inc   ACPI: make blackl...
88
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  	if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
90
91
92
93
  		printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
  		       "acpi=force is required to enable ACPI
  ",
  		       year, CONFIG_ACPI_BLACKLIST_YEAR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
  		return 1;
  	}
  	return 0;
  }
  #else
4be44fcd3   Len Brown   [ACPI] Lindent al...
99
100
101
102
  static inline int blacklist_by_year(void)
  {
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  #endif
4be44fcd3   Len Brown   [ACPI] Lindent al...
104
  int __init acpi_blacklisted(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
  {
  	int i = 0;
  	int blacklisted = 0;
428f21129   Alexey Starikovskiy   ACPICA: Miscellan...
108
  	struct acpi_table_header table_header;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109

4be44fcd3   Len Brown   [ACPI] Lindent al...
110
  	while (acpi_blacklist[i].oem_id[0] != '\0') {
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
111
  		if (acpi_get_table_header(acpi_blacklist[i].table, 0, &table_header)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
  			i++;
  			continue;
  		}
428f21129   Alexey Starikovskiy   ACPICA: Miscellan...
115
  		if (strncmp(acpi_blacklist[i].oem_id, table_header.oem_id, 6)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
  			i++;
  			continue;
  		}
4be44fcd3   Len Brown   [ACPI] Lindent al...
119
  		if (strncmp
428f21129   Alexey Starikovskiy   ACPICA: Miscellan...
120
  		    (acpi_blacklist[i].oem_table_id, table_header.oem_table_id,
4be44fcd3   Len Brown   [ACPI] Lindent al...
121
  		     8)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
  			i++;
  			continue;
  		}
  
  		if ((acpi_blacklist[i].oem_revision_predicate == all_versions)
4be44fcd3   Len Brown   [ACPI] Lindent al...
127
128
  		    || (acpi_blacklist[i].oem_revision_predicate ==
  			less_than_or_equal
428f21129   Alexey Starikovskiy   ACPICA: Miscellan...
129
  			&& table_header.oem_revision <=
4be44fcd3   Len Brown   [ACPI] Lindent al...
130
131
132
  			acpi_blacklist[i].oem_revision)
  		    || (acpi_blacklist[i].oem_revision_predicate ==
  			greater_than_or_equal
428f21129   Alexey Starikovskiy   ACPICA: Miscellan...
133
  			&& table_header.oem_revision >=
4be44fcd3   Len Brown   [ACPI] Lindent al...
134
  			acpi_blacklist[i].oem_revision)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  		    || (acpi_blacklist[i].oem_revision_predicate == equal
428f21129   Alexey Starikovskiy   ACPICA: Miscellan...
136
  			&& table_header.oem_revision ==
4be44fcd3   Len Brown   [ACPI] Lindent al...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  			acpi_blacklist[i].oem_revision)) {
  
  			printk(KERN_ERR PREFIX
  			       "Vendor \"%6.6s\" System \"%8.8s\" "
  			       "Revision 0x%x has a known ACPI BIOS problem.
  ",
  			       acpi_blacklist[i].oem_id,
  			       acpi_blacklist[i].oem_table_id,
  			       acpi_blacklist[i].oem_revision);
  
  			printk(KERN_ERR PREFIX
  			       "Reason: %s. This is a %s error
  ",
  			       acpi_blacklist[i].reason,
  			       (acpi_blacklist[i].
  				is_critical_error ? "non-recoverable" :
  				"recoverable"));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
  
  			blacklisted = acpi_blacklist[i].is_critical_error;
  			break;
4be44fcd3   Len Brown   [ACPI] Lindent al...
157
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
162
  			i++;
  		}
  	}
  
  	blacklisted += blacklist_by_year();
d4b7dc499   Len Brown   ACPI: make _OSI(L...
163
  	dmi_check_system(acpi_osi_dmi_table);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
  	return blacklisted;
  }
d4b7dc499   Len Brown   ACPI: make _OSI(L...
166
  #ifdef CONFIG_DMI
98f1db22d   Len Brown   ACPI: Add ThinkPa...
167
168
169
170
171
  static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
  {
  	acpi_dmi_osi_linux(1, d);	/* enable */
  	return 0;
  }
46c1fbdb7   Len Brown   ACPI: DMI: quirk ...
172
173
174
175
176
  static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
  {
  	printk(KERN_NOTICE PREFIX "DMI detected: %s
  ", d->ident);
  	acpi_osi_setup("!Windows 2006");
bbb7030fb   Len Brown   ACPI: expand Vist...
177
178
  	acpi_osi_setup("!Windows 2006 SP1");
  	acpi_osi_setup("!Windows 2006 SP2");
46c1fbdb7   Len Brown   ACPI: DMI: quirk ...
179
180
  	return 0;
  }
81074e90f   Zhang Rui   ACPI: disable _OS...
181
182
183
184
185
186
187
  static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
  {
  	printk(KERN_NOTICE PREFIX "DMI detected: %s
  ", d->ident);
  	acpi_osi_setup("!Windows 2009");
  	return 0;
  }
a1bd4e35e   Len Brown   ACPI: DMI blackli...
188

d4b7dc499   Len Brown   ACPI: make _OSI(L...
189
  static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
46c1fbdb7   Len Brown   ACPI: DMI: quirk ...
190
191
192
193
194
  	{
  	.callback = dmi_disable_osi_vista,
  	.ident = "Fujitsu Siemens",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
a6e0887f2   Len Brown   ACPI: delete OSI(...
195
  		     DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
46c1fbdb7   Len Brown   ACPI: DMI: quirk ...
196
197
  		},
  	},
35a7c64fb   Zhang Rui   ACPI: DMI to disa...
198
  	{
3deb11ef1   Lee, Chun-Yi   ACPI: add DMI to ...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  	/*
  	 * There have a NVIF method in MSI GX723 DSDT need call by Nvidia
  	 * driver (e.g. nouveau) when user press brightness hotkey.
  	 * Currently, nouveau driver didn't do the job and it causes there
  	 * have a infinite while loop in DSDT when user press hotkey.
  	 * We add MSI GX723's dmi information to this table for workaround
  	 * this issue.
  	 * Will remove MSI GX723 from the table after nouveau grows support.
  	 */
  	.callback = dmi_disable_osi_vista,
  	.ident = "MSI GX723",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
  		     DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
  		},
  	},
  	{
35a7c64fb   Zhang Rui   ACPI: DMI to disa...
216
217
218
219
220
221
222
223
224
225
226
227
  	.callback = dmi_disable_osi_vista,
  	.ident = "Sony VGN-NS10J_S",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
  		},
  	},
  	{
  	.callback = dmi_disable_osi_vista,
  	.ident = "Sony VGN-SR290J",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
096486eec   Nik A. Melchior   ACPI video: fix s...
228
  		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
35a7c64fb   Zhang Rui   ACPI: DMI to disa...
229
230
  		},
  	},
81074e90f   Zhang Rui   ACPI: disable _OS...
231
  	{
4b1b29bc8   Zhang Rui   ACPI: Disable Vis...
232
233
234
235
236
237
238
239
  	.callback = dmi_disable_osi_vista,
  	.ident = "VGN-NS50B_L",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
  		},
  	},
  	{
7a1d602f5   Len Brown   ACPI: EC: add Vis...
240
241
242
243
244
245
246
247
  	.callback = dmi_disable_osi_vista,
  	.ident = "Toshiba Satellite L355",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  		     DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
  		},
  	},
  	{
81074e90f   Zhang Rui   ACPI: disable _OS...
248
249
250
251
252
253
254
  	.callback = dmi_disable_osi_win7,
  	.ident = "ASUS K50IJ",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
  		     DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
  		},
  	},
337279ce3   Zhang Rui   ACPI: Disable Win...
255
256
257
258
259
260
261
262
  	{
  	.callback = dmi_disable_osi_vista,
  	.ident = "Toshiba P305D",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  		     DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
  		},
  	},
a6e0887f2   Len Brown   ACPI: delete OSI(...
263

a1bd4e35e   Len Brown   ACPI: DMI blackli...
264
  	/*
a6e0887f2   Len Brown   ACPI: delete OSI(...
265
266
  	 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
  	 * Linux ignores it, except for the machines enumerated below.
a1bd4e35e   Len Brown   ACPI: DMI blackli...
267
  	 */
a6e0887f2   Len Brown   ACPI: delete OSI(...
268

a1bd4e35e   Len Brown   ACPI: DMI blackli...
269
270
271
272
  	/*
  	 * Lenovo has a mix of systems OSI(Linux) situations
  	 * and thus we can not wildcard the vendor.
  	 *
98f1db22d   Len Brown   ACPI: Add ThinkPa...
273
274
275
  	 * _OSI(Linux) helps sound
  	 * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"),
  	 * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"),
8b1edc57a   Jerone Young   ACPI: Add Thinkpa...
276
  	 * T400, T500
bb54675b9   Len Brown   ACPI: DMI blackli...
277
278
  	 * _OSI(Linux) has Linux specific hooks
  	 * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"),
a1bd4e35e   Len Brown   ACPI: DMI blackli...
279
280
  	 * _OSI(Linux) is a NOP:
  	 * DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
bb54675b9   Len Brown   ACPI: DMI blackli...
281
  	 * DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"),
98f1db22d   Len Brown   ACPI: Add ThinkPa...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  	 */
  	{
  	.callback = dmi_enable_osi_linux,
  	.ident = "Lenovo ThinkPad R61",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"),
  		},
  	},
  	{
  	.callback = dmi_enable_osi_linux,
  	.ident = "Lenovo ThinkPad T61",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"),
  		},
  	},
a1bd4e35e   Len Brown   ACPI: DMI blackli...
299
  	{
bb54675b9   Len Brown   ACPI: DMI blackli...
300
  	.callback = dmi_enable_osi_linux,
446b1dfc4   Len Brown   ACPI: DMI: add Pa...
301
302
303
304
305
306
  	.ident = "Lenovo ThinkPad X61",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"),
  		},
  	},
8b1edc57a   Jerone Young   ACPI: Add Thinkpa...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  	{
  	.callback = dmi_enable_osi_linux,
  	.ident = "Lenovo ThinkPad T400",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T400"),
  		},
  	},
  	{
  	.callback = dmi_enable_osi_linux,
  	.ident = "Lenovo ThinkPad T500",
  	.matches = {
  		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T500"),
  		},
  	},
d4b7dc499   Len Brown   ACPI: make _OSI(L...
323
324
325
326
  	{}
  };
  
  #endif /* CONFIG_DMI */