diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index 7014e88..b667e80 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h @@ -285,6 +285,8 @@ struct protection_domain { }; +#define INVALID_ALIAS_ID (~0U) + /* * This struct contains device specific data for the IOMMU */ @@ -294,6 +296,9 @@ struct iommu_dev_data { struct device *alias; /* The Alias Device */ struct protection_domain *domain; /* Domain the device is bound to */ atomic_t bind; /* Domain attach reverent count */ + + u32 alias_id; /* Use in case device aliases to + non-existend PCI BDF */ }; /* diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 0d20286..673d0a4 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -148,11 +148,17 @@ static int iommu_init_device(struct device *dev) dev_data->dev = dev; + dev_data->alias_id = INVALID_ALIAS_ID; + devid = get_device_id(dev); alias = amd_iommu_alias_table[devid]; pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff); if (pdev) dev_data->alias = &pdev->dev; + else { + dev_data->alias = dev; + dev_data->alias_id = alias; + } atomic_set(&dev_data->bind, 0); @@ -1448,6 +1454,9 @@ static void do_attach(struct device *dev, struct protection_domain *domain) list_add(&dev_data->list, &domain->dev_list); set_dte_entry(devid, domain); + if (dev_data->alias_id != INVALID_ALIAS_ID) + set_dte_enry(dev_data->alias_id, domain); + /* Do reference counting */ domain->dev_iommu[iommu->index] += 1; domain->dev_cnt += 1; @@ -1475,6 +1484,9 @@ static void do_detach(struct device *dev) list_del(&dev_data->list); clear_dte_entry(devid); + if (dev_data->alias_id != INVALID_ALIAS_ID) + clear_dte_enry(dev_data->alias_id); + /* Flush the DTE entry */ iommu_flush_device(dev); }