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 | |
| 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>
| -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); |
