1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 /* 4 * Quirks for AMD IOMMU 5 * 6 * Copyright (C) 2019 Kai-Heng Feng <kai.heng.feng@canonical.com> 7 */ 8 9 #ifdef CONFIG_DMI 10 #include <linux/dmi.h> 11 12 #include "amd_iommu.h" 13 14 #define IVHD_SPECIAL_IOAPIC 1 15 16 struct ivrs_quirk_entry { 17 u8 id; 18 u16 devid; 19 }; 20 21 enum { 22 DELL_INSPIRON_7375 = 0, 23 DELL_LATITUDE_5495, 24 LENOVO_IDEAPAD_330S_15ARR, 25 }; 26 27 static const struct ivrs_quirk_entry ivrs_ioapic_quirks[][3] __initconst = { 28 /* ivrs_ioapic[4]=00:14.0 ivrs_ioapic[5]=00:00.2 */ 29 [DELL_INSPIRON_7375] = { 30 { .id = 4, .devid = 0xa0 }, 31 { .id = 5, .devid = 0x2 }, 32 {} 33 }, 34 /* ivrs_ioapic[4]=00:14.0 */ 35 [DELL_LATITUDE_5495] = { 36 { .id = 4, .devid = 0xa0 }, 37 {} 38 }, 39 /* ivrs_ioapic[32]=00:14.0 */ 40 [LENOVO_IDEAPAD_330S_15ARR] = { 41 { .id = 32, .devid = 0xa0 }, 42 {} 43 }, 44 {} 45 }; 46 47 static int __init ivrs_ioapic_quirk_cb(const struct dmi_system_id *d) 48 { 49 const struct ivrs_quirk_entry *i; 50 51 for (i = d->driver_data; i->id != 0 && i->devid != 0; i++) 52 add_special_device(IVHD_SPECIAL_IOAPIC, i->id, (u16 *)&i->devid, 0); 53 54 return 0; 55 } 56 57 static const struct dmi_system_id ivrs_quirks[] __initconst = { 58 { 59 .callback = ivrs_ioapic_quirk_cb, 60 .ident = "Dell Inspiron 7375", 61 .matches = { 62 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 63 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7375"), 64 }, 65 .driver_data = (void *)&ivrs_ioapic_quirks[DELL_INSPIRON_7375], 66 }, 67 { 68 .callback = ivrs_ioapic_quirk_cb, 69 .ident = "Dell Latitude 5495", 70 .matches = { 71 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 72 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 5495"), 73 }, 74 .driver_data = (void *)&ivrs_ioapic_quirks[DELL_LATITUDE_5495], 75 }, 76 { 77 /* 78 * Acer Aspire A315-41 requires the very same workaround as 79 * Dell Latitude 5495 80 */ 81 .callback = ivrs_ioapic_quirk_cb, 82 .ident = "Acer Aspire A315-41", 83 .matches = { 84 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 85 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-41"), 86 }, 87 .driver_data = (void *)&ivrs_ioapic_quirks[DELL_LATITUDE_5495], 88 }, 89 { 90 .callback = ivrs_ioapic_quirk_cb, 91 .ident = "Lenovo ideapad 330S-15ARR", 92 .matches = { 93 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 94 DMI_MATCH(DMI_PRODUCT_NAME, "81FB"), 95 }, 96 .driver_data = (void *)&ivrs_ioapic_quirks[LENOVO_IDEAPAD_330S_15ARR], 97 }, 98 {} 99 }; 100 101 void __init amd_iommu_apply_ivrs_quirks(void) 102 { 103 dmi_check_system(ivrs_quirks); 104 } 105 #endif 106