blacklist.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  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 <len.brown@intel.com>
  9. * Copyright (C) 2002 Andy Grover <andrew.grover@intel.com>
  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. * You should have received a copy of the GNU General Public License along
  24. * with this program; if not, write to the Free Software Foundation, Inc.,
  25. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  26. *
  27. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  28. */
  29. #include <linux/kernel.h>
  30. #include <linux/init.h>
  31. #include <linux/acpi.h>
  32. #include <acpi/acpi_bus.h>
  33. #include <linux/dmi.h>
  34. #include "internal.h"
  35. enum acpi_blacklist_predicates {
  36. all_versions,
  37. less_than_or_equal,
  38. equal,
  39. greater_than_or_equal,
  40. };
  41. struct acpi_blacklist_item {
  42. char oem_id[7];
  43. char oem_table_id[9];
  44. u32 oem_revision;
  45. char *table;
  46. enum acpi_blacklist_predicates oem_revision_predicate;
  47. char *reason;
  48. u32 is_critical_error;
  49. };
  50. static struct dmi_system_id acpi_osi_dmi_table[] __initdata;
  51. /*
  52. * POLICY: If *anything* doesn't work, put it on the blacklist.
  53. * If they are critical errors, mark it critical, and abort driver load.
  54. */
  55. static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
  56. /* Compaq Presario 1700 */
  57. {"PTLTD ", " DSDT ", 0x06040000, ACPI_SIG_DSDT, less_than_or_equal,
  58. "Multiple problems", 1},
  59. /* Sony FX120, FX140, FX150? */
  60. {"SONY ", "U0 ", 0x20010313, ACPI_SIG_DSDT, less_than_or_equal,
  61. "ACPI driver problem", 1},
  62. /* Compaq Presario 800, Insyde BIOS */
  63. {"INT440", "SYSFexxx", 0x00001001, ACPI_SIG_DSDT, less_than_or_equal,
  64. "Does not use _REG to protect EC OpRegions", 1},
  65. /* IBM 600E - _ADR should return 7, but it returns 1 */
  66. {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal,
  67. "Incorrect _ADR", 1},
  68. {""}
  69. };
  70. int __init acpi_blacklisted(void)
  71. {
  72. int i = 0;
  73. int blacklisted = 0;
  74. struct acpi_table_header table_header;
  75. while (acpi_blacklist[i].oem_id[0] != '\0') {
  76. if (acpi_get_table_header(acpi_blacklist[i].table, 0, &table_header)) {
  77. i++;
  78. continue;
  79. }
  80. if (strncmp(acpi_blacklist[i].oem_id, table_header.oem_id, 6)) {
  81. i++;
  82. continue;
  83. }
  84. if (strncmp
  85. (acpi_blacklist[i].oem_table_id, table_header.oem_table_id,
  86. 8)) {
  87. i++;
  88. continue;
  89. }
  90. if ((acpi_blacklist[i].oem_revision_predicate == all_versions)
  91. || (acpi_blacklist[i].oem_revision_predicate ==
  92. less_than_or_equal
  93. && table_header.oem_revision <=
  94. acpi_blacklist[i].oem_revision)
  95. || (acpi_blacklist[i].oem_revision_predicate ==
  96. greater_than_or_equal
  97. && table_header.oem_revision >=
  98. acpi_blacklist[i].oem_revision)
  99. || (acpi_blacklist[i].oem_revision_predicate == equal
  100. && table_header.oem_revision ==
  101. acpi_blacklist[i].oem_revision)) {
  102. printk(KERN_ERR PREFIX
  103. "Vendor \"%6.6s\" System \"%8.8s\" "
  104. "Revision 0x%x has a known ACPI BIOS problem.\n",
  105. acpi_blacklist[i].oem_id,
  106. acpi_blacklist[i].oem_table_id,
  107. acpi_blacklist[i].oem_revision);
  108. printk(KERN_ERR PREFIX
  109. "Reason: %s. This is a %s error\n",
  110. acpi_blacklist[i].reason,
  111. (acpi_blacklist[i].
  112. is_critical_error ? "non-recoverable" :
  113. "recoverable"));
  114. blacklisted = acpi_blacklist[i].is_critical_error;
  115. break;
  116. } else {
  117. i++;
  118. }
  119. }
  120. dmi_check_system(acpi_osi_dmi_table);
  121. return blacklisted;
  122. }
  123. #ifdef CONFIG_DMI
  124. static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
  125. {
  126. acpi_dmi_osi_linux(1, d); /* enable */
  127. return 0;
  128. }
  129. static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
  130. {
  131. printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
  132. acpi_osi_setup("!Windows 2006");
  133. acpi_osi_setup("!Windows 2006 SP1");
  134. acpi_osi_setup("!Windows 2006 SP2");
  135. return 0;
  136. }
  137. static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
  138. {
  139. printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
  140. acpi_osi_setup("!Windows 2009");
  141. return 0;
  142. }
  143. static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
  144. {
  145. printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
  146. acpi_osi_setup("!Windows 2012");
  147. return 0;
  148. }
  149. static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
  150. {
  151. .callback = dmi_disable_osi_vista,
  152. .ident = "Fujitsu Siemens",
  153. .matches = {
  154. DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
  155. DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
  156. },
  157. },
  158. {
  159. /*
  160. * There have a NVIF method in MSI GX723 DSDT need call by Nvidia
  161. * driver (e.g. nouveau) when user press brightness hotkey.
  162. * Currently, nouveau driver didn't do the job and it causes there
  163. * have a infinite while loop in DSDT when user press hotkey.
  164. * We add MSI GX723's dmi information to this table for workaround
  165. * this issue.
  166. * Will remove MSI GX723 from the table after nouveau grows support.
  167. */
  168. .callback = dmi_disable_osi_vista,
  169. .ident = "MSI GX723",
  170. .matches = {
  171. DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
  172. DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
  173. },
  174. },
  175. {
  176. .callback = dmi_disable_osi_vista,
  177. .ident = "Sony VGN-NS10J_S",
  178. .matches = {
  179. DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  180. DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
  181. },
  182. },
  183. {
  184. .callback = dmi_disable_osi_vista,
  185. .ident = "Sony VGN-SR290J",
  186. .matches = {
  187. DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  188. DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
  189. },
  190. },
  191. {
  192. .callback = dmi_disable_osi_vista,
  193. .ident = "VGN-NS50B_L",
  194. .matches = {
  195. DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  196. DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
  197. },
  198. },
  199. {
  200. .callback = dmi_disable_osi_vista,
  201. .ident = "Toshiba Satellite L355",
  202. .matches = {
  203. DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  204. DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
  205. },
  206. },
  207. {
  208. .callback = dmi_disable_osi_win7,
  209. .ident = "ASUS K50IJ",
  210. .matches = {
  211. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
  212. DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
  213. },
  214. },
  215. {
  216. .callback = dmi_disable_osi_vista,
  217. .ident = "Toshiba P305D",
  218. .matches = {
  219. DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  220. DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
  221. },
  222. },
  223. {
  224. .callback = dmi_disable_osi_vista,
  225. .ident = "Toshiba NB100",
  226. .matches = {
  227. DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  228. DMI_MATCH(DMI_PRODUCT_NAME, "NB100"),
  229. },
  230. },
  231. /*
  232. * The following machines have broken backlight support when reporting
  233. * the Windows 2012 OSI, so disable it until their support is fixed.
  234. */
  235. {
  236. .callback = dmi_disable_osi_win8,
  237. .ident = "ASUS Zenbook Prime UX31A",
  238. .matches = {
  239. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
  240. DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"),
  241. },
  242. },
  243. {
  244. .callback = dmi_disable_osi_win8,
  245. .ident = "Dell Inspiron 15R SE",
  246. .matches = {
  247. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  248. DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"),
  249. },
  250. },
  251. {
  252. .callback = dmi_disable_osi_win8,
  253. .ident = "ThinkPad Edge E530",
  254. .matches = {
  255. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  256. DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
  257. },
  258. },
  259. {
  260. .callback = dmi_disable_osi_win8,
  261. .ident = "ThinkPad Edge E530",
  262. .matches = {
  263. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  264. DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"),
  265. },
  266. },
  267. {
  268. .callback = dmi_disable_osi_win8,
  269. .ident = "ThinkPad Edge E530",
  270. .matches = {
  271. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  272. DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"),
  273. },
  274. },
  275. {
  276. .callback = dmi_disable_osi_win8,
  277. .ident = "Acer Aspire V5-573G",
  278. .matches = {
  279. DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
  280. DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"),
  281. },
  282. },
  283. {
  284. .callback = dmi_disable_osi_win8,
  285. .ident = "Acer Aspire V5-572G",
  286. .matches = {
  287. DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
  288. DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"),
  289. },
  290. },
  291. {
  292. .callback = dmi_disable_osi_win8,
  293. .ident = "ThinkPad T431s",
  294. .matches = {
  295. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  296. DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"),
  297. },
  298. },
  299. {
  300. .callback = dmi_disable_osi_win8,
  301. .ident = "ThinkPad T430",
  302. .matches = {
  303. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  304. DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
  305. },
  306. },
  307. /*
  308. * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
  309. * Linux ignores it, except for the machines enumerated below.
  310. */
  311. /*
  312. * Lenovo has a mix of systems OSI(Linux) situations
  313. * and thus we can not wildcard the vendor.
  314. *
  315. * _OSI(Linux) helps sound
  316. * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"),
  317. * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"),
  318. * T400, T500
  319. * _OSI(Linux) has Linux specific hooks
  320. * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"),
  321. * _OSI(Linux) is a NOP:
  322. * DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
  323. * DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"),
  324. */
  325. {
  326. .callback = dmi_enable_osi_linux,
  327. .ident = "Lenovo ThinkPad R61",
  328. .matches = {
  329. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  330. DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"),
  331. },
  332. },
  333. {
  334. .callback = dmi_enable_osi_linux,
  335. .ident = "Lenovo ThinkPad T61",
  336. .matches = {
  337. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  338. DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"),
  339. },
  340. },
  341. {
  342. .callback = dmi_enable_osi_linux,
  343. .ident = "Lenovo ThinkPad X61",
  344. .matches = {
  345. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  346. DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"),
  347. },
  348. },
  349. {
  350. .callback = dmi_enable_osi_linux,
  351. .ident = "Lenovo ThinkPad T400",
  352. .matches = {
  353. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  354. DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T400"),
  355. },
  356. },
  357. {
  358. .callback = dmi_enable_osi_linux,
  359. .ident = "Lenovo ThinkPad T500",
  360. .matches = {
  361. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  362. DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T500"),
  363. },
  364. },
  365. {}
  366. };
  367. #endif /* CONFIG_DMI */