aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/intel-iommu.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2012-01-09 07:06:28 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2012-01-09 07:06:28 -0500
commitf93ea733878733f3e98475bc3e2ccf789bebcfb8 (patch)
treece4981e49a75d5bac7f0d2fa4ddcdcc130cf56f0 /drivers/iommu/intel-iommu.c
parent00fb5430f547e411ab03385cfa548776aaac1c92 (diff)
parent95bdaf71ccf2cb4bba0c9a3d2baea0e7916f466b (diff)
Merge branches 'iommu/page-sizes' and 'iommu/group-id' into next
Conflicts: drivers/iommu/amd_iommu.c drivers/iommu/intel-iommu.c include/linux/iommu.h
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r--drivers/iommu/intel-iommu.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index aea72e11e166..77e3b917c8da 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4080,6 +4080,54 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
4080 return 0; 4080 return 0;
4081} 4081}
4082 4082
4083/*
4084 * Group numbers are arbitrary. Device with the same group number
4085 * indicate the iommu cannot differentiate between them. To avoid
4086 * tracking used groups we just use the seg|bus|devfn of the lowest
4087 * level we're able to differentiate devices
4088 */
4089static int intel_iommu_device_group(struct device *dev, unsigned int *groupid)
4090{
4091 struct pci_dev *pdev = to_pci_dev(dev);
4092 struct pci_dev *bridge;
4093 union {
4094 struct {
4095 u8 devfn;
4096 u8 bus;
4097 u16 segment;
4098 } pci;
4099 u32 group;
4100 } id;
4101
4102 if (iommu_no_mapping(dev))
4103 return -ENODEV;
4104
4105 id.pci.segment = pci_domain_nr(pdev->bus);
4106 id.pci.bus = pdev->bus->number;
4107 id.pci.devfn = pdev->devfn;
4108
4109 if (!device_to_iommu(id.pci.segment, id.pci.bus, id.pci.devfn))
4110 return -ENODEV;
4111
4112 bridge = pci_find_upstream_pcie_bridge(pdev);
4113 if (bridge) {
4114 if (pci_is_pcie(bridge)) {
4115 id.pci.bus = bridge->subordinate->number;
4116 id.pci.devfn = 0;
4117 } else {
4118 id.pci.bus = bridge->bus->number;
4119 id.pci.devfn = bridge->devfn;
4120 }
4121 }
4122
4123 if (!pdev->is_virtfn && iommu_group_mf)
4124 id.pci.devfn = PCI_DEVFN(PCI_SLOT(id.pci.devfn), 0);
4125
4126 *groupid = id.group;
4127
4128 return 0;
4129}
4130
4083static struct iommu_ops intel_iommu_ops = { 4131static struct iommu_ops intel_iommu_ops = {
4084 .domain_init = intel_iommu_domain_init, 4132 .domain_init = intel_iommu_domain_init,
4085 .domain_destroy = intel_iommu_domain_destroy, 4133 .domain_destroy = intel_iommu_domain_destroy,
@@ -4089,6 +4137,7 @@ static struct iommu_ops intel_iommu_ops = {
4089 .unmap = intel_iommu_unmap, 4137 .unmap = intel_iommu_unmap,
4090 .iova_to_phys = intel_iommu_iova_to_phys, 4138 .iova_to_phys = intel_iommu_iova_to_phys,
4091 .domain_has_cap = intel_iommu_domain_has_cap, 4139 .domain_has_cap = intel_iommu_domain_has_cap,
4140 .device_group = intel_iommu_device_group,
4092 .pgsize_bitmap = INTEL_IOMMU_PGSIZES, 4141 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
4093}; 4142};
4094 4143