intel-iommu: Support IOMMU groups
authorAlex Williamson <alex.williamson@redhat.com>
Wed, 30 May 2012 20:19:19 +0000 (14:19 -0600)
committerJoerg Roedel <joerg.roedel@amd.com>
Mon, 25 Jun 2012 11:48:28 +0000 (13:48 +0200)
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>
drivers/iommu/intel-iommu.c

index c62f2df..4a43452 100644 (file)
@@ -4090,6 +4090,47 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
        return 0;
 }
 
+static int intel_iommu_add_device(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct pci_dev *bridge, *dma_pdev;
+       struct iommu_group *group;
+       int ret;
+
+       if (!device_to_iommu(pci_domain_nr(pdev->bus),
+                            pdev->bus->number, pdev->devfn))
+               return -ENODEV;
+
+       bridge = pci_find_upstream_pcie_bridge(pdev);
+       if (bridge) {
+               if (pci_is_pcie(bridge))
+                       dma_pdev = pci_get_domain_bus_and_slot(
+                                               pci_domain_nr(pdev->bus),
+                                               bridge->subordinate->number, 0);
+               else
+                       dma_pdev = pci_dev_get(bridge);
+       } else
+               dma_pdev = pci_dev_get(pdev);
+
+       group = iommu_group_get(&dma_pdev->dev);
+       pci_dev_put(dma_pdev);
+       if (!group) {
+               group = iommu_group_alloc();
+               if (IS_ERR(group))
+                       return PTR_ERR(group);
+       }
+
+       ret = iommu_group_add_device(group, dev);
+
+       iommu_group_put(group);
+       return ret;
+}
+
+static void intel_iommu_remove_device(struct device *dev)
+{
+       iommu_group_remove_device(dev);
+}
+
 static struct iommu_ops intel_iommu_ops = {
        .domain_init    = intel_iommu_domain_init,
        .domain_destroy = intel_iommu_domain_destroy,
@@ -4099,6 +4140,8 @@ static struct iommu_ops intel_iommu_ops = {
        .unmap          = intel_iommu_unmap,
        .iova_to_phys   = intel_iommu_iova_to_phys,
        .domain_has_cap = intel_iommu_domain_has_cap,
+       .add_device     = intel_iommu_add_device,
+       .remove_device  = intel_iommu_remove_device,
        .pgsize_bitmap  = INTEL_IOMMU_PGSIZES,
 };