Skip to content

Commit 93d0515

Browse files
khfengjoergroedel
authored andcommitted
iommu/amd: Override wrong IVRS IOAPIC on Raven Ridge systems
Raven Ridge systems may have malfunction touchpad or hang at boot if incorrect IVRS IOAPIC is provided by BIOS. Users already found correct "ivrs_ioapic=" values, let's put them inside kernel to workaround buggy BIOS. BugLink: https://bugs.launchpad.net/bugs/1795292 BugLink: https://bugs.launchpad.net/bugs/1837688 Reported-by: kbuild test robot <[email protected]> Signed-off-by: Kai-Heng Feng <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent b9c6ff9 commit 93d0515

File tree

4 files changed

+111
-2
lines changed

4 files changed

+111
-2
lines changed

drivers/iommu/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
1010
obj-$(CONFIG_IOMMU_IOVA) += iova.o
1111
obj-$(CONFIG_OF_IOMMU) += of_iommu.o
1212
obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
13-
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
13+
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_quirks.o
1414
obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
1515
obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
1616
obj-$(CONFIG_ARM_SMMU) += arm-smmu.o

drivers/iommu/amd_iommu.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
#ifndef AMD_IOMMU_H
4+
#define AMD_IOMMU_H
5+
6+
int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line);
7+
8+
#ifdef CONFIG_DMI
9+
void amd_iommu_apply_ivrs_quirks(void);
10+
#else
11+
static void amd_iommu_apply_ivrs_quirks(void) { }
12+
#endif
13+
14+
#endif

drivers/iommu/amd_iommu_init.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <asm/irq_remapping.h>
3333

3434
#include <linux/crash_dump.h>
35+
#include "amd_iommu.h"
3536
#include "amd_iommu_proto.h"
3637
#include "amd_iommu_types.h"
3738
#include "irq_remapping.h"
@@ -1002,7 +1003,7 @@ static void __init set_dev_entry_from_acpi(struct amd_iommu *iommu,
10021003
set_iommu_for_device(iommu, devid);
10031004
}
10041005

1005-
static int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
1006+
int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
10061007
{
10071008
struct devid_map *entry;
10081009
struct list_head *list;
@@ -1153,6 +1154,8 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
11531154
if (ret)
11541155
return ret;
11551156

1157+
amd_iommu_apply_ivrs_quirks();
1158+
11561159
/*
11571160
* First save the recommended feature enable bits from ACPI
11581161
*/

drivers/iommu/amd_iommu_quirks.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
/*
4+
* Quirks for AMD IOMMU
5+
*
6+
* Copyright (C) 2019 Kai-Heng Feng <[email protected]>
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+
.callback = ivrs_ioapic_quirk_cb,
78+
.ident = "Lenovo ideapad 330S-15ARR",
79+
.matches = {
80+
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
81+
DMI_MATCH(DMI_PRODUCT_NAME, "81FB"),
82+
},
83+
.driver_data = (void *)&ivrs_ioapic_quirks[LENOVO_IDEAPAD_330S_15ARR],
84+
},
85+
{}
86+
};
87+
88+
void __init amd_iommu_apply_ivrs_quirks(void)
89+
{
90+
dmi_check_system(ivrs_quirks);
91+
}
92+
#endif

0 commit comments

Comments
 (0)