Skip to content

Commit

Permalink
VT-d: parse ATSR in DMA Remapping Reporting Structure
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yu Zhao authored and David Woodhouse committed May 18, 2009
1 parent e277d2f commit aa5d2b5
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 6 deletions.
112 changes: 106 additions & 6 deletions drivers/pci/dmar.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,29 +267,113 @@ rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
}
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

static void __init
dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
{
struct acpi_dmar_hardware_unit *drhd;
struct acpi_dmar_reserved_memory *rmrr;
struct acpi_dmar_atsr *atsr;

switch (header->type) {
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
"DRHD (flags: 0x%08x)base: 0x%016Lx\n",
drhd->flags, (unsigned long long)drhd->address);
"DRHD base: %#016Lx flags: %#x\n",
(unsigned long long)drhd->address, drhd->flags);
break;
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
"RMRR base: 0x%016Lx end: 0x%016Lx\n",
"RMRR base: %#016Lx end: %#016Lx\n",
(unsigned long long)rmrr->base_address,
(unsigned long long)rmrr->end_address);
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;
}
}

Expand Down Expand Up @@ -361,6 +445,11 @@ parse_dmar_table(void)
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
#ifdef CONFIG_DMAR
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
break;
default:
Expand Down Expand Up @@ -431,11 +520,19 @@ int __init dmar_dev_scope_init(void)
#ifdef CONFIG_DMAR
{
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) {
ret = rmrr_parse_dev(rmrr);
if (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

Expand Down Expand Up @@ -468,6 +565,9 @@ int __init dmar_table_init(void)
#ifdef CONFIG_DMAR
if (list_empty(&dmar_rmrr_units))
printk(KERN_INFO PREFIX "No RMRR found\n");

if (list_empty(&dmar_atsr_units))
printk(KERN_INFO PREFIX "No ATSR found\n");
#endif

#ifdef CONFIG_INTR_REMAP
Expand Down
9 changes: 9 additions & 0 deletions include/linux/dmar.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,15 @@ struct dmar_rmrr_unit {

#define for_each_rmrr_units(rmrr) \
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 */
extern int intel_iommu_init(void);
#else
Expand Down
1 change: 1 addition & 0 deletions include/linux/intel-iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 int dmar_find_matched_atsr_unit(struct pci_dev *dev);

extern int alloc_iommu(struct dmar_drhd_unit *drhd);
extern void free_iommu(struct intel_iommu *iommu);
Expand Down

0 comments on commit aa5d2b5

Please sign in to comment.