x86/smpboot: Init apic mapping before usage
[cascardo/linux.git] / drivers / acpi / blacklist.c
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_rev_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  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24  */
25
26 #include <linux/kernel.h>
27 #include <linux/init.h>
28 #include <linux/acpi.h>
29 #include <linux/dmi.h>
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_rev_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         (void)early_acpi_osi_init();
132         dmi_check_system(acpi_rev_dmi_table);
133
134         return blacklisted;
135 }
136 #ifdef CONFIG_DMI
137 #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE
138 static int __init dmi_enable_rev_override(const struct dmi_system_id *d)
139 {
140         printk(KERN_NOTICE PREFIX "DMI detected: %s (force ACPI _REV to 5)\n",
141                d->ident);
142         acpi_rev_override_setup(NULL);
143         return 0;
144 }
145 #endif
146
147 static struct dmi_system_id acpi_rev_dmi_table[] __initdata = {
148 #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE
149         /*
150          * DELL XPS 13 (2015) switches sound between HDA and I2S
151          * depending on the ACPI _REV callback. If userspace supports
152          * I2S sufficiently (or if you do not care about sound), you
153          * can safely disable this quirk.
154          */
155         {
156          .callback = dmi_enable_rev_override,
157          .ident = "DELL XPS 13 (2015)",
158          .matches = {
159                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
160                       DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343"),
161                 },
162         },
163 #endif
164         {}
165 };
166
167 #endif /* CONFIG_DMI */