quirks.c 2.3 KB

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