aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/intel-iommu.c
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2012-05-30 16:19:19 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2012-06-25 07:48:28 -0400
commitabdfdde2534c48d7a761fc437ad3d840a5947dbc (patch)
tree6096f56dea5007d20d3be0590e849d9ed4464467 /drivers/iommu/intel-iommu.c
parent9dcd61303af862c279df86aa97fde7ce371be774 (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.c43
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
4093static 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
4129static void intel_iommu_remove_device(struct device *dev)
4130{
4131 iommu_group_remove_device(dev);
4132}
4133
4093static struct iommu_ops intel_iommu_ops = { 4134static 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