Commit 156baca8 authored by David Woodhouse's avatar David Woodhouse

iommu/vt-d: Make device_to_iommu() cope with non-PCI devices

Pass the struct device to it, and also make it return the bus/devfn to use,
since that is also stored in the DMAR table.
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 9b226624
...@@ -664,37 +664,53 @@ static void domain_update_iommu_cap(struct dmar_domain *domain) ...@@ -664,37 +664,53 @@ static void domain_update_iommu_cap(struct dmar_domain *domain)
domain_update_iommu_superpage(domain); domain_update_iommu_superpage(domain);
} }
static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
{ {
struct dmar_drhd_unit *drhd = NULL; struct dmar_drhd_unit *drhd = NULL;
struct intel_iommu *iommu; struct intel_iommu *iommu;
struct device *dev; struct device *tmp;
struct pci_dev *pdev; struct pci_dev *ptmp, *pdev = NULL;
u16 segment;
int i; int i;
if (dev_is_pci(dev)) {
pdev = to_pci_dev(dev);
segment = pci_domain_nr(pdev->bus);
} else if (ACPI_COMPANION(dev))
dev = &ACPI_COMPANION(dev)->dev;
rcu_read_lock(); rcu_read_lock();
for_each_active_iommu(iommu, drhd) { for_each_active_iommu(iommu, drhd) {
if (segment != drhd->segment) if (pdev && segment != drhd->segment)
continue; continue;
for_each_active_dev_scope(drhd->devices, for_each_active_dev_scope(drhd->devices,
drhd->devices_cnt, i, dev) { drhd->devices_cnt, i, tmp) {
if (!dev_is_pci(dev)) if (tmp == dev) {
continue; *bus = drhd->devices[i].bus;
pdev = to_pci_dev(dev); *devfn = drhd->devices[i].devfn;
if (pdev->bus->number == bus && pdev->devfn == devfn)
goto out;
if (pdev->subordinate &&
pdev->subordinate->number <= bus &&
pdev->subordinate->busn_res.end >= bus)
goto out; goto out;
}
if (!pdev || !dev_is_pci(tmp))
continue;
ptmp = to_pci_dev(tmp);
if (ptmp->subordinate &&
ptmp->subordinate->number <= pdev->bus->number &&
ptmp->subordinate->busn_res.end >= pdev->bus->number)
goto got_pdev;
} }
if (drhd->include_all) if (pdev && drhd->include_all) {
got_pdev:
*bus = pdev->bus->number;
*devfn = pdev->devfn;
goto out; goto out;
}
} }
iommu = NULL; iommu = NULL;
out: out:
rcu_read_unlock(); rcu_read_unlock();
return iommu; return iommu;
...@@ -1830,14 +1846,13 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev, ...@@ -1830,14 +1846,13 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
int ret; int ret;
struct pci_dev *tmp, *parent; struct pci_dev *tmp, *parent;
struct intel_iommu *iommu; struct intel_iommu *iommu;
u8 bus, devfn;
iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
pdev->devfn);
if (!iommu) if (!iommu)
return -ENODEV; return -ENODEV;
ret = domain_context_mapping_one(domain, iommu, ret = domain_context_mapping_one(domain, iommu, bus, devfn,
pdev->bus->number, pdev->devfn,
translation); translation);
if (ret) if (ret)
return ret; return ret;
...@@ -1872,13 +1887,13 @@ static int domain_context_mapped(struct pci_dev *pdev) ...@@ -1872,13 +1887,13 @@ static int domain_context_mapped(struct pci_dev *pdev)
int ret; int ret;
struct pci_dev *tmp, *parent; struct pci_dev *tmp, *parent;
struct intel_iommu *iommu; struct intel_iommu *iommu;
u8 bus, devfn;
iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
pdev->devfn);
if (!iommu) if (!iommu)
return -ENODEV; return -ENODEV;
ret = device_context_mapped(iommu, pdev->bus->number, pdev->devfn); ret = device_context_mapped(iommu, bus, devfn);
if (!ret) if (!ret)
return ret; return ret;
/* dependent device mapping */ /* dependent device mapping */
...@@ -2459,15 +2474,14 @@ static int domain_add_dev_info(struct dmar_domain *domain, ...@@ -2459,15 +2474,14 @@ static int domain_add_dev_info(struct dmar_domain *domain,
{ {
struct dmar_domain *ndomain; struct dmar_domain *ndomain;
struct intel_iommu *iommu; struct intel_iommu *iommu;
u8 bus, devfn;
int ret; int ret;
iommu = device_to_iommu(pci_domain_nr(pdev->bus), iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
pdev->bus->number, pdev->devfn);
if (!iommu) if (!iommu)
return -ENODEV; return -ENODEV;
ndomain = dmar_insert_dev_info(iommu, pdev->bus->number, pdev->devfn, ndomain = dmar_insert_dev_info(iommu, bus, devfn, &pdev->dev, domain);
&pdev->dev, domain);
if (ndomain != domain) if (ndomain != domain)
return -EBUSY; return -EBUSY;
...@@ -4020,9 +4034,9 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain, ...@@ -4020,9 +4034,9 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
struct intel_iommu *iommu; struct intel_iommu *iommu;
unsigned long flags; unsigned long flags;
int found = 0; int found = 0;
u8 bus, devfn;
iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
pdev->devfn);
if (!iommu) if (!iommu)
return; return;
...@@ -4142,6 +4156,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, ...@@ -4142,6 +4156,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct intel_iommu *iommu; struct intel_iommu *iommu;
int addr_width; int addr_width;
u8 bus, devfn;
/* normally pdev is not mapped */ /* normally pdev is not mapped */
if (unlikely(domain_context_mapped(pdev))) { if (unlikely(domain_context_mapped(pdev))) {
...@@ -4157,8 +4172,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, ...@@ -4157,8 +4172,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
} }
} }
iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, iommu = device_to_iommu(dev, &bus, &devfn);
pdev->devfn);
if (!iommu) if (!iommu)
return -ENODEV; return -ENODEV;
...@@ -4324,9 +4338,9 @@ static int intel_iommu_add_device(struct device *dev) ...@@ -4324,9 +4338,9 @@ static int intel_iommu_add_device(struct device *dev)
struct pci_dev *bridge, *dma_pdev = NULL; struct pci_dev *bridge, *dma_pdev = NULL;
struct iommu_group *group; struct iommu_group *group;
int ret; int ret;
u8 bus, devfn;
if (!device_to_iommu(pci_domain_nr(pdev->bus), if (!device_to_iommu(dev, &bus, &devfn))
pdev->bus->number, pdev->devfn))
return -ENODEV; return -ENODEV;
bridge = pci_find_upstream_pcie_bridge(pdev); bridge = pci_find_upstream_pcie_bridge(pdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment