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 { 164 .callback = dmi_enable_rev_override, 165 .ident = "DELL Precision 5520", 166 .matches = { 167 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 168 DMI_MATCH(DMI_PRODUCT_NAME, "Precision 5520"), 169 }, 170 }, 171 { 172 .callback = dmi_enable_rev_override, 173 .ident = "DELL Precision 3520", 174 .matches = { 175 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 176 DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3520"), 177 }, 178 }, 179 /* 180 * Resolves a quirk with the Dell Latitude 3350 that 181 * causes the ethernet adapter to not function. 182 */ 183 { 184 .callback = dmi_enable_rev_override, 185 .ident = "DELL Latitude 3350", 186 .matches = { 187 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 188 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 3350"), 189 }, 190 }, 191 { 192 .callback = dmi_enable_rev_override, 193 .ident = "DELL Inspiron 7537", 194 .matches = { 195 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 196 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"), 197 }, 198 }, 199 #endif 200 {} 201 }; 202 203 #endif /* CONFIG_DMI */ 204