diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2014-03-09 17:00:57 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2014-03-24 10:07:49 -0400 |
commit | 156baca8d31e1aced2c8a14262637aef1ab416b9 (patch) | |
tree | 0753e871798fd4af853c7c41ac3fa95fd5cd0ec5 /drivers/iommu | |
parent | 9b226624bbf7102cee67b6459bcb9c66dd081ca7 (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.c | 78 |
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 | ||
667 | static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) | 667 | static 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; |
697 | out: | 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); |