linux/drivers/iommu/amd/quirks.c
<<
>>
Prefs
   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
  16struct ivrs_quirk_entry {
  17        u8 id;
  18        u16 devid;
  19};
  20
  21enum {
  22        DELL_INSPIRON_7375 = 0,
  23        DELL_LATITUDE_5495,
  24        LENOVO_IDEAPAD_330S_15ARR,
  25};
  26
  27static 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
  47static 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
  57static 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
 101void __init amd_iommu_apply_ivrs_quirks(void)
 102{
 103        dmi_check_system(ivrs_quirks);
 104}
 105#endif
 106