diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2012-05-30 16:19:19 -0400 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2012-06-25 07:48:28 -0400 |
commit | abdfdde2534c48d7a761fc437ad3d840a5947dbc (patch) | |
tree | 6096f56dea5007d20d3be0590e849d9ed4464467 /drivers/iommu/intel-iommu.c | |
parent | 9dcd61303af862c279df86aa97fde7ce371be774 (diff) |
intel-iommu: Support IOMMU groups
Add IOMMU group support to Intel VT-d code. This driver sets up
devices ondemand, so make use of the add_device/remove_device
callbacks in IOMMU API to manage setting up the groups.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r-- | drivers/iommu/intel-iommu.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c62f2df25221..4a434528cd1c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -4090,6 +4090,47 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain, | |||
4090 | return 0; | 4090 | return 0; |
4091 | } | 4091 | } |
4092 | 4092 | ||
4093 | static int intel_iommu_add_device(struct device *dev) | ||
4094 | { | ||
4095 | struct pci_dev *pdev = to_pci_dev(dev); | ||
4096 | struct pci_dev *bridge, *dma_pdev; | ||
4097 | struct iommu_group *group; | ||
4098 | int ret; | ||
4099 | |||
4100 | if (!device_to_iommu(pci_domain_nr(pdev->bus), | ||
4101 | pdev->bus->number, pdev->devfn)) | ||
4102 | return -ENODEV; | ||
4103 | |||
4104 | bridge = pci_find_upstream_pcie_bridge(pdev); | ||
4105 | if (bridge) { | ||
4106 | if (pci_is_pcie(bridge)) | ||
4107 | dma_pdev = pci_get_domain_bus_and_slot( | ||
4108 | pci_domain_nr(pdev->bus), | ||
4109 | bridge->subordinate->number, 0); | ||
4110 | else | ||
4111 | dma_pdev = pci_dev_get(bridge); | ||
4112 | } else | ||
4113 | dma_pdev = pci_dev_get(pdev); | ||
4114 | |||
4115 | group = iommu_group_get(&dma_pdev->dev); | ||
4116 | pci_dev_put(dma_pdev); | ||
4117 | if (!group) { | ||
4118 | group = iommu_group_alloc(); | ||
4119 | if (IS_ERR(group)) | ||
4120 | return PTR_ERR(group); | ||
4121 | } | ||
4122 | |||
4123 | ret = iommu_group_add_device(group, dev); | ||
4124 | |||
4125 | iommu_group_put(group); | ||
4126 | return ret; | ||
4127 | } | ||
4128 | |||
4129 | static void intel_iommu_remove_device(struct device *dev) | ||
4130 | { | ||
4131 | iommu_group_remove_device(dev); | ||
4132 | } | ||
4133 | |||
4093 | static struct iommu_ops intel_iommu_ops = { | 4134 | static struct iommu_ops intel_iommu_ops = { |
4094 | .domain_init = intel_iommu_domain_init, | 4135 | .domain_init = intel_iommu_domain_init, |
4095 | .domain_destroy = intel_iommu_domain_destroy, | 4136 | .domain_destroy = intel_iommu_domain_destroy, |
@@ -4099,6 +4140,8 @@ static struct iommu_ops intel_iommu_ops = { | |||
4099 | .unmap = intel_iommu_unmap, | 4140 | .unmap = intel_iommu_unmap, |
4100 | .iova_to_phys = intel_iommu_iova_to_phys, | 4141 | .iova_to_phys = intel_iommu_iova_to_phys, |
4101 | .domain_has_cap = intel_iommu_domain_has_cap, | 4142 | .domain_has_cap = intel_iommu_domain_has_cap, |
4143 | .add_device = intel_iommu_add_device, | ||
4144 | .remove_device = intel_iommu_remove_device, | ||
4102 | .pgsize_bitmap = INTEL_IOMMU_PGSIZES, | 4145 | .pgsize_bitmap = INTEL_IOMMU_PGSIZES, |
4103 | }; | 4146 | }; |
4104 | 4147 | ||