mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-07 23:08:02 +07:00
iommu/amd: Add new map for storing IVHD dev entry type HID
This patch introduces acpihid_map, which is used to store the new IVHD device entry extracted from BIOS IVRS table. It also provides a utility function add_acpi_hid_device(), to add this types of devices to the map. Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com> Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
8c7142f56f
commit
2a0cb4e2d4
@ -72,6 +72,7 @@ static DEFINE_SPINLOCK(dev_data_list_lock);
|
|||||||
|
|
||||||
LIST_HEAD(ioapic_map);
|
LIST_HEAD(ioapic_map);
|
||||||
LIST_HEAD(hpet_map);
|
LIST_HEAD(hpet_map);
|
||||||
|
LIST_HEAD(acpihid_map);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Domain for untranslated devices - only allocated
|
* Domain for untranslated devices - only allocated
|
||||||
|
@ -60,6 +60,10 @@
|
|||||||
#define IVHD_DEV_SPECIAL 0x48
|
#define IVHD_DEV_SPECIAL 0x48
|
||||||
#define IVHD_DEV_ACPI_HID 0xf0
|
#define IVHD_DEV_ACPI_HID 0xf0
|
||||||
|
|
||||||
|
#define UID_NOT_PRESENT 0
|
||||||
|
#define UID_IS_INTEGER 1
|
||||||
|
#define UID_IS_CHARACTER 2
|
||||||
|
|
||||||
#define IVHD_SPECIAL_IOAPIC 1
|
#define IVHD_SPECIAL_IOAPIC 1
|
||||||
#define IVHD_SPECIAL_HPET 2
|
#define IVHD_SPECIAL_HPET 2
|
||||||
|
|
||||||
@ -116,6 +120,11 @@ struct ivhd_entry {
|
|||||||
u16 devid;
|
u16 devid;
|
||||||
u8 flags;
|
u8 flags;
|
||||||
u32 ext;
|
u32 ext;
|
||||||
|
u32 hidh;
|
||||||
|
u64 cid;
|
||||||
|
u8 uidf;
|
||||||
|
u8 uidl;
|
||||||
|
u8 uid;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -224,8 +233,12 @@ enum iommu_init_state {
|
|||||||
#define EARLY_MAP_SIZE 4
|
#define EARLY_MAP_SIZE 4
|
||||||
static struct devid_map __initdata early_ioapic_map[EARLY_MAP_SIZE];
|
static struct devid_map __initdata early_ioapic_map[EARLY_MAP_SIZE];
|
||||||
static struct devid_map __initdata early_hpet_map[EARLY_MAP_SIZE];
|
static struct devid_map __initdata early_hpet_map[EARLY_MAP_SIZE];
|
||||||
|
static struct acpihid_map_entry __initdata early_acpihid_map[EARLY_MAP_SIZE];
|
||||||
|
|
||||||
static int __initdata early_ioapic_map_size;
|
static int __initdata early_ioapic_map_size;
|
||||||
static int __initdata early_hpet_map_size;
|
static int __initdata early_hpet_map_size;
|
||||||
|
static int __initdata early_acpihid_map_size;
|
||||||
|
|
||||||
static bool __initdata cmdline_maps;
|
static bool __initdata cmdline_maps;
|
||||||
|
|
||||||
static enum iommu_init_state init_state = IOMMU_START_STATE;
|
static enum iommu_init_state init_state = IOMMU_START_STATE;
|
||||||
@ -765,6 +778,42 @@ static int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __init add_acpi_hid_device(u8 *hid, u8 *uid, u16 *devid,
|
||||||
|
bool cmd_line)
|
||||||
|
{
|
||||||
|
struct acpihid_map_entry *entry;
|
||||||
|
struct list_head *list = &acpihid_map;
|
||||||
|
|
||||||
|
list_for_each_entry(entry, list, list) {
|
||||||
|
if (strcmp(entry->hid, hid) ||
|
||||||
|
(*uid && *entry->uid && strcmp(entry->uid, uid)) ||
|
||||||
|
!entry->cmd_line)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pr_info("AMD-Vi: Command-line override for hid:%s uid:%s\n",
|
||||||
|
hid, uid);
|
||||||
|
*devid = entry->devid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
||||||
|
if (!entry)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memcpy(entry->uid, uid, strlen(uid));
|
||||||
|
memcpy(entry->hid, hid, strlen(hid));
|
||||||
|
entry->devid = *devid;
|
||||||
|
entry->cmd_line = cmd_line;
|
||||||
|
entry->root_devid = (entry->devid & (~0x7));
|
||||||
|
|
||||||
|
pr_info("AMD-Vi:%s, add hid:%s, uid:%s, rdevid:%d\n",
|
||||||
|
entry->cmd_line ? "cmd" : "ivrs",
|
||||||
|
entry->hid, entry->uid, entry->root_devid);
|
||||||
|
|
||||||
|
list_add_tail(&entry->list, list);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init add_early_maps(void)
|
static int __init add_early_maps(void)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
@ -787,6 +836,15 @@ static int __init add_early_maps(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < early_acpihid_map_size; ++i) {
|
||||||
|
ret = add_acpi_hid_device(early_acpihid_map[i].hid,
|
||||||
|
early_acpihid_map[i].uid,
|
||||||
|
&early_acpihid_map[i].devid,
|
||||||
|
early_acpihid_map[i].cmd_line);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1007,6 +1065,70 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case IVHD_DEV_ACPI_HID: {
|
||||||
|
u16 devid;
|
||||||
|
u8 hid[ACPIHID_HID_LEN] = {0};
|
||||||
|
u8 uid[ACPIHID_UID_LEN] = {0};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (h->type != 0x40) {
|
||||||
|
pr_err(FW_BUG "Invalid IVHD device type %#x\n",
|
||||||
|
e->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(hid, (u8 *)(&e->ext), ACPIHID_HID_LEN - 1);
|
||||||
|
hid[ACPIHID_HID_LEN - 1] = '\0';
|
||||||
|
|
||||||
|
if (!(*hid)) {
|
||||||
|
pr_err(FW_BUG "Invalid HID.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (e->uidf) {
|
||||||
|
case UID_NOT_PRESENT:
|
||||||
|
|
||||||
|
if (e->uidl != 0)
|
||||||
|
pr_warn(FW_BUG "Invalid UID length.\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
case UID_IS_INTEGER:
|
||||||
|
|
||||||
|
sprintf(uid, "%d", e->uid);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case UID_IS_CHARACTER:
|
||||||
|
|
||||||
|
memcpy(uid, (u8 *)(&e->uid), ACPIHID_UID_LEN - 1);
|
||||||
|
uid[ACPIHID_UID_LEN - 1] = '\0';
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DUMP_printk(" DEV_ACPI_HID(%s[%s])\t\tdevid: %02x:%02x.%x\n",
|
||||||
|
hid, uid,
|
||||||
|
PCI_BUS_NUM(devid),
|
||||||
|
PCI_SLOT(devid),
|
||||||
|
PCI_FUNC(devid));
|
||||||
|
|
||||||
|
devid = e->devid;
|
||||||
|
flags = e->flags;
|
||||||
|
|
||||||
|
ret = add_acpi_hid_device(hid, uid, &devid, false);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add_special_device might update the devid in case a
|
||||||
|
* command-line override is present. So call
|
||||||
|
* set_dev_entry_from_acpi after add_special_device.
|
||||||
|
*/
|
||||||
|
set_dev_entry_from_acpi(iommu, devid, e->flags, 0);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -527,6 +527,19 @@ struct amd_iommu {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ACPIHID_UID_LEN 256
|
||||||
|
#define ACPIHID_HID_LEN 9
|
||||||
|
|
||||||
|
struct acpihid_map_entry {
|
||||||
|
struct list_head list;
|
||||||
|
u8 uid[ACPIHID_UID_LEN];
|
||||||
|
u8 hid[ACPIHID_HID_LEN];
|
||||||
|
u16 devid;
|
||||||
|
u16 root_devid;
|
||||||
|
bool cmd_line;
|
||||||
|
struct iommu_group *group;
|
||||||
|
};
|
||||||
|
|
||||||
struct devid_map {
|
struct devid_map {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
u8 id;
|
u8 id;
|
||||||
@ -537,6 +550,7 @@ struct devid_map {
|
|||||||
/* Map HPET and IOAPIC ids to the devid used by the IOMMU */
|
/* Map HPET and IOAPIC ids to the devid used by the IOMMU */
|
||||||
extern struct list_head ioapic_map;
|
extern struct list_head ioapic_map;
|
||||||
extern struct list_head hpet_map;
|
extern struct list_head hpet_map;
|
||||||
|
extern struct list_head acpihid_map;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List with all IOMMUs in the system. This list is not locked because it is
|
* List with all IOMMUs in the system. This list is not locked because it is
|
||||||
|
Loading…
Reference in New Issue
Block a user