VT-d: parse ATSR in DMA Remapping Reporting Structure
Parse the Root Port ATS Capability Reporting Structure in the DMA Remapping Reporting Structure ACPI table. Signed-off-by: Yu Zhao <yu.zhao@intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
e277d2fc79
commit
aa5d2b515b
|
@ -267,6 +267,84 @@ rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LIST_HEAD(dmar_atsr_units);
|
||||||
|
|
||||||
|
static int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
|
||||||
|
{
|
||||||
|
struct acpi_dmar_atsr *atsr;
|
||||||
|
struct dmar_atsr_unit *atsru;
|
||||||
|
|
||||||
|
atsr = container_of(hdr, struct acpi_dmar_atsr, header);
|
||||||
|
atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
|
||||||
|
if (!atsru)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
atsru->hdr = hdr;
|
||||||
|
atsru->include_all = atsr->flags & 0x1;
|
||||||
|
|
||||||
|
list_add(&atsru->list, &dmar_atsr_units);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct acpi_dmar_atsr *atsr;
|
||||||
|
|
||||||
|
if (atsru->include_all)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
|
||||||
|
rc = dmar_parse_dev_scope((void *)(atsr + 1),
|
||||||
|
(void *)atsr + atsr->header.length,
|
||||||
|
&atsru->devices_cnt, &atsru->devices,
|
||||||
|
atsr->segment);
|
||||||
|
if (rc || !atsru->devices_cnt) {
|
||||||
|
list_del(&atsru->list);
|
||||||
|
kfree(atsru);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dmar_find_matched_atsr_unit(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct pci_bus *bus;
|
||||||
|
struct acpi_dmar_atsr *atsr;
|
||||||
|
struct dmar_atsr_unit *atsru;
|
||||||
|
|
||||||
|
list_for_each_entry(atsru, &dmar_atsr_units, list) {
|
||||||
|
atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
|
||||||
|
if (atsr->segment == pci_domain_nr(dev->bus))
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
found:
|
||||||
|
for (bus = dev->bus; bus; bus = bus->parent) {
|
||||||
|
struct pci_dev *bridge = bus->self;
|
||||||
|
|
||||||
|
if (!bridge || !bridge->is_pcie ||
|
||||||
|
bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
|
||||||
|
for (i = 0; i < atsru->devices_cnt; i++)
|
||||||
|
if (atsru->devices[i] == bridge)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atsru->include_all)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void __init
|
static void __init
|
||||||
|
@ -274,22 +352,28 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
|
||||||
{
|
{
|
||||||
struct acpi_dmar_hardware_unit *drhd;
|
struct acpi_dmar_hardware_unit *drhd;
|
||||||
struct acpi_dmar_reserved_memory *rmrr;
|
struct acpi_dmar_reserved_memory *rmrr;
|
||||||
|
struct acpi_dmar_atsr *atsr;
|
||||||
|
|
||||||
switch (header->type) {
|
switch (header->type) {
|
||||||
case ACPI_DMAR_TYPE_HARDWARE_UNIT:
|
case ACPI_DMAR_TYPE_HARDWARE_UNIT:
|
||||||
drhd = (struct acpi_dmar_hardware_unit *)header;
|
drhd = container_of(header, struct acpi_dmar_hardware_unit,
|
||||||
|
header);
|
||||||
printk (KERN_INFO PREFIX
|
printk (KERN_INFO PREFIX
|
||||||
"DRHD (flags: 0x%08x)base: 0x%016Lx\n",
|
"DRHD base: %#016Lx flags: %#x\n",
|
||||||
drhd->flags, (unsigned long long)drhd->address);
|
(unsigned long long)drhd->address, drhd->flags);
|
||||||
break;
|
break;
|
||||||
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
|
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
|
||||||
rmrr = (struct acpi_dmar_reserved_memory *)header;
|
rmrr = container_of(header, struct acpi_dmar_reserved_memory,
|
||||||
|
header);
|
||||||
printk (KERN_INFO PREFIX
|
printk (KERN_INFO PREFIX
|
||||||
"RMRR base: 0x%016Lx end: 0x%016Lx\n",
|
"RMRR base: %#016Lx end: %#016Lx\n",
|
||||||
(unsigned long long)rmrr->base_address,
|
(unsigned long long)rmrr->base_address,
|
||||||
(unsigned long long)rmrr->end_address);
|
(unsigned long long)rmrr->end_address);
|
||||||
break;
|
break;
|
||||||
|
case ACPI_DMAR_TYPE_ATSR:
|
||||||
|
atsr = container_of(header, struct acpi_dmar_atsr, header);
|
||||||
|
printk(KERN_INFO PREFIX "ATSR flags: %#x\n", atsr->flags);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,6 +445,11 @@ parse_dmar_table(void)
|
||||||
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
|
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
|
||||||
#ifdef CONFIG_DMAR
|
#ifdef CONFIG_DMAR
|
||||||
ret = dmar_parse_one_rmrr(entry_header);
|
ret = dmar_parse_one_rmrr(entry_header);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case ACPI_DMAR_TYPE_ATSR:
|
||||||
|
#ifdef CONFIG_DMAR
|
||||||
|
ret = dmar_parse_one_atsr(entry_header);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -431,11 +520,19 @@ int __init dmar_dev_scope_init(void)
|
||||||
#ifdef CONFIG_DMAR
|
#ifdef CONFIG_DMAR
|
||||||
{
|
{
|
||||||
struct dmar_rmrr_unit *rmrr, *rmrr_n;
|
struct dmar_rmrr_unit *rmrr, *rmrr_n;
|
||||||
|
struct dmar_atsr_unit *atsr, *atsr_n;
|
||||||
|
|
||||||
list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
|
list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
|
||||||
ret = rmrr_parse_dev(rmrr);
|
ret = rmrr_parse_dev(rmrr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
|
||||||
|
ret = atsr_parse_dev(atsr);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -468,6 +565,9 @@ int __init dmar_table_init(void)
|
||||||
#ifdef CONFIG_DMAR
|
#ifdef CONFIG_DMAR
|
||||||
if (list_empty(&dmar_rmrr_units))
|
if (list_empty(&dmar_rmrr_units))
|
||||||
printk(KERN_INFO PREFIX "No RMRR found\n");
|
printk(KERN_INFO PREFIX "No RMRR found\n");
|
||||||
|
|
||||||
|
if (list_empty(&dmar_atsr_units))
|
||||||
|
printk(KERN_INFO PREFIX "No ATSR found\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_INTR_REMAP
|
#ifdef CONFIG_INTR_REMAP
|
||||||
|
|
|
@ -185,6 +185,15 @@ struct dmar_rmrr_unit {
|
||||||
|
|
||||||
#define for_each_rmrr_units(rmrr) \
|
#define for_each_rmrr_units(rmrr) \
|
||||||
list_for_each_entry(rmrr, &dmar_rmrr_units, list)
|
list_for_each_entry(rmrr, &dmar_rmrr_units, list)
|
||||||
|
|
||||||
|
struct dmar_atsr_unit {
|
||||||
|
struct list_head list; /* list of ATSR units */
|
||||||
|
struct acpi_dmar_header *hdr; /* ACPI header */
|
||||||
|
struct pci_dev **devices; /* target devices */
|
||||||
|
int devices_cnt; /* target device count */
|
||||||
|
u8 include_all:1; /* include all ports */
|
||||||
|
};
|
||||||
|
|
||||||
/* Intel DMAR initialization functions */
|
/* Intel DMAR initialization functions */
|
||||||
extern int intel_iommu_init(void);
|
extern int intel_iommu_init(void);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -331,6 +331,7 @@ static inline void __iommu_flush_cache(
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
|
extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
|
||||||
|
extern int dmar_find_matched_atsr_unit(struct pci_dev *dev);
|
||||||
|
|
||||||
extern int alloc_iommu(struct dmar_drhd_unit *drhd);
|
extern int alloc_iommu(struct dmar_drhd_unit *drhd);
|
||||||
extern void free_iommu(struct intel_iommu *iommu);
|
extern void free_iommu(struct intel_iommu *iommu);
|
||||||
|
|
Loading…
Reference in New Issue