aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2014-03-09 17:00:57 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2014-03-24 10:07:49 -0400
commit156baca8d31e1aced2c8a14262637aef1ab416b9 (patch)
tree0753e871798fd4af853c7c41ac3fa95fd5cd0ec5 /drivers/iommu
parent9b226624bbf7102cee67b6459bcb9c66dd081ca7 (diff)
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: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/intel-iommu.c78
1 files changed, 46 insertions, 32 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 1030230d4851..cfc5eef81b82 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -664,37 +664,53 @@ static void domain_update_iommu_cap(struct dmar_domain *domain)
664 domain_update_iommu_superpage(domain); 664 domain_update_iommu_superpage(domain);
665} 665}
666 666
667static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) 667static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
668{ 668{
669 struct dmar_drhd_unit *drhd = NULL; 669 struct dmar_drhd_unit *drhd = NULL;
670 struct intel_iommu *iommu; 670 struct intel_iommu *iommu;
671 struct device *dev; 671 struct device *tmp;
672 struct pci_dev *pdev; 672 struct pci_dev *ptmp, *pdev = NULL;
673 u16 segment;
673 int i; 674 int i;
674 675
676 if (dev_is_pci(dev)) {
677 pdev = to_pci_dev(dev);
678 segment = pci_domain_nr(pdev->bus);
679 } else if (ACPI_COMPANION(dev))
680 dev = &ACPI_COMPANION(dev)->dev;
681
675 rcu_read_lock(); 682 rcu_read_lock();
676 for_each_active_iommu(iommu, drhd) { 683 for_each_active_iommu(iommu, drhd) {
677 if (segment != drhd->segment) 684 if (pdev && segment != drhd->segment)
678 continue; 685 continue;
679 686
680 for_each_active_dev_scope(drhd->devices, 687 for_each_active_dev_scope(drhd->devices,
681 drhd->devices_cnt, i, dev) { 688 drhd->devices_cnt, i, tmp) {
682 if (!dev_is_pci(dev)) 689 if (tmp == dev) {
683 continue; 690 *bus = drhd->devices[i].bus;
684 pdev = to_pci_dev(dev); 691 *devfn = drhd->devices[i].devfn;
685 if (pdev->bus->number == bus && pdev->devfn == devfn)
686 goto out;
687 if (pdev->subordinate &&
688 pdev->subordinate->number <= bus &&
689 pdev->subordinate->busn_res.end >= bus)
690 goto out; 692 goto out;
693 }
694
695 if (!pdev || !dev_is_pci(tmp))
696 continue;
697
698 ptmp = to_pci_dev(tmp);
699 if (ptmp->subordinate &&
700 ptmp->subordinate->number <= pdev->bus->number &&
701 ptmp->subordinate->busn_res.end >= pdev->bus->number)
702 goto got_pdev;
691 } 703 }
692 704
693 if (drhd->include_all) 705 if (pdev && drhd->include_all) {
706 got_pdev:
707 *bus = pdev->bus->number;
708 *devfn = pdev->devfn;
694 goto out; 709 goto out;
710 }
695 } 711 }
696 iommu = NULL; 712 iommu = NULL;
697out: 713 out:
698 rcu_read_unlock(); 714 rcu_read_unlock();
699 715
700 return iommu; 716 return iommu;
@@ -1830,14 +1846,13 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
1830 int ret; 1846 int ret;
1831 struct pci_dev *tmp, *parent; 1847 struct pci_dev *tmp, *parent;
1832 struct intel_iommu *iommu; 1848 struct intel_iommu *iommu;
1849 u8 bus, devfn;
1833 1850
1834 iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, 1851 iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
1835 pdev->devfn);
1836 if (!iommu) 1852 if (!iommu)
1837 return -ENODEV; 1853 return -ENODEV;
1838 1854
1839 ret = domain_context_mapping_one(domain, iommu, 1855 ret = domain_context_mapping_one(domain, iommu, bus, devfn,
1840 pdev->bus->number, pdev->devfn,
1841 translation); 1856 translation);
1842 if (ret) 1857 if (ret)
1843 return ret; 1858 return ret;
@@ -1872,13 +1887,13 @@ static int domain_context_mapped(struct pci_dev *pdev)
1872 int ret; 1887 int ret;
1873 struct pci_dev *tmp, *parent; 1888 struct pci_dev *tmp, *parent;
1874 struct intel_iommu *iommu; 1889 struct intel_iommu *iommu;
1890 u8 bus, devfn;
1875 1891
1876 iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, 1892 iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
1877 pdev->devfn);
1878 if (!iommu) 1893 if (!iommu)
1879 return -ENODEV; 1894 return -ENODEV;
1880 1895
1881 ret = device_context_mapped(iommu, pdev->bus->number, pdev->devfn); 1896 ret = device_context_mapped(iommu, bus, devfn);
1882 if (!ret) 1897 if (!ret)
1883 return ret; 1898 return ret;
1884 /* dependent device mapping */ 1899 /* dependent device mapping */
@@ -2459,15 +2474,14 @@ static int domain_add_dev_info(struct dmar_domain *domain,
2459{ 2474{
2460 struct dmar_domain *ndomain; 2475 struct dmar_domain *ndomain;
2461 struct intel_iommu *iommu; 2476 struct intel_iommu *iommu;
2477 u8 bus, devfn;
2462 int ret; 2478 int ret;
2463 2479
2464 iommu = device_to_iommu(pci_domain_nr(pdev->bus), 2480 iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
2465 pdev->bus->number, pdev->devfn);
2466 if (!iommu) 2481 if (!iommu)
2467 return -ENODEV; 2482 return -ENODEV;
2468 2483
2469 ndomain = dmar_insert_dev_info(iommu, pdev->bus->number, pdev->devfn, 2484 ndomain = dmar_insert_dev_info(iommu, bus, devfn, &pdev->dev, domain);
2470 &pdev->dev, domain);
2471 if (ndomain != domain) 2485 if (ndomain != domain)
2472 return -EBUSY; 2486 return -EBUSY;
2473 2487
@@ -4020,9 +4034,9 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
4020 struct intel_iommu *iommu; 4034 struct intel_iommu *iommu;
4021 unsigned long flags; 4035 unsigned long flags;
4022 int found = 0; 4036 int found = 0;
4037 u8 bus, devfn;
4023 4038
4024 iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, 4039 iommu = device_to_iommu(&pdev->dev, &bus, &devfn);
4025 pdev->devfn);
4026 if (!iommu) 4040 if (!iommu)
4027 return; 4041 return;
4028 4042
@@ -4142,6 +4156,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
4142 struct pci_dev *pdev = to_pci_dev(dev); 4156 struct pci_dev *pdev = to_pci_dev(dev);
4143 struct intel_iommu *iommu; 4157 struct intel_iommu *iommu;
4144 int addr_width; 4158 int addr_width;
4159 u8 bus, devfn;
4145 4160
4146 /* normally pdev is not mapped */ 4161 /* normally pdev is not mapped */
4147 if (unlikely(domain_context_mapped(pdev))) { 4162 if (unlikely(domain_context_mapped(pdev))) {
@@ -4157,8 +4172,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
4157 } 4172 }
4158 } 4173 }
4159 4174
4160 iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number, 4175 iommu = device_to_iommu(dev, &bus, &devfn);
4161 pdev->devfn);
4162 if (!iommu) 4176 if (!iommu)
4163 return -ENODEV; 4177 return -ENODEV;
4164 4178
@@ -4324,9 +4338,9 @@ static int intel_iommu_add_device(struct device *dev)
4324 struct pci_dev *bridge, *dma_pdev = NULL; 4338 struct pci_dev *bridge, *dma_pdev = NULL;
4325 struct iommu_group *group; 4339 struct iommu_group *group;
4326 int ret; 4340 int ret;
4341 u8 bus, devfn;
4327 4342
4328 if (!device_to_iommu(pci_domain_nr(pdev->bus), 4343 if (!device_to_iommu(dev, &bus, &devfn))
4329 pdev->bus->number, pdev->devfn))
4330 return -ENODEV; 4344 return -ENODEV;
4331 4345
4332 bridge = pci_find_upstream_pcie_bridge(pdev); 4346 bridge = pci_find_upstream_pcie_bridge(pdev);