summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2015-05-28 18:41:29 +0200
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:15:05 -0700
commitced8e797c4da332d86c9bd8feac0306f69722e9c (patch)
tree92a66d9dba6be04b526e5acc96e0710848289d11
parenteb95bbc100d14f1fd4526655fa4403ccc3bc5ab2 (diff)
iommu: Allocate a default domain for iommu groups
The default domain will be used (if supported by the iommu driver) when the devices in the iommu group are not attached to any other domain. Change-Id: I9bb6a8619c66694e5fef37a46a53cce8c99d44ec Signed-off-by: Joerg Roedel <jroedel@suse.de> [pdaly@codeaurora.org Resolve minor conflicts]
-rw-r--r--drivers/iommu/iommu.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 82ccfa22ef3e..1b6ea33d5d19 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -54,6 +54,7 @@ struct iommu_group {
void (*iommu_data_release)(void *iommu_data);
char *name;
int id;
+ struct iommu_domain *default_domain;
};
struct iommu_device {
@@ -78,6 +79,9 @@ struct iommu_group_attribute iommu_group_attr_##_name = \
#define to_iommu_group(_kobj) \
container_of(_kobj, struct iommu_group, kobj)
+static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
+ unsigned type);
+
static ssize_t iommu_group_attr_show(struct kobject *kobj,
struct attribute *__attr, char *buf)
{
@@ -140,6 +144,9 @@ static void iommu_group_release(struct kobject *kobj)
ida_remove(&iommu_group_ida, group->id);
mutex_unlock(&iommu_group_mutex);
+ if (group->default_domain)
+ iommu_domain_free(group->default_domain);
+
kfree(group->name);
kfree(group);
}
@@ -704,7 +711,17 @@ static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev)
return group;
/* No shared group found, allocate new */
- return iommu_group_alloc();
+ group = iommu_group_alloc();
+ if (group) {
+ /*
+ * Try to allocate a default domain - needs support from the
+ * IOMMU driver.
+ */
+ group->default_domain = __iommu_domain_alloc(pdev->dev.bus,
+ IOMMU_DOMAIN_DMA);
+ }
+
+ return group;
}
/**
@@ -964,22 +981,28 @@ void iommu_reg_write(struct iommu_domain *domain, unsigned long offset,
domain->ops->reg_write(domain, offset, val);
}
-struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
+static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
+ unsigned type)
{
struct iommu_domain *domain;
if (bus == NULL || bus->iommu_ops == NULL)
return NULL;
- domain = bus->iommu_ops->domain_alloc(IOMMU_DOMAIN_UNMANAGED);
+ domain = bus->iommu_ops->domain_alloc(type);
if (!domain)
return NULL;
domain->ops = bus->iommu_ops;
- domain->type = IOMMU_DOMAIN_UNMANAGED;
+ domain->type = type;
return domain;
}
+
+struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
+{
+ return __iommu_domain_alloc(bus, IOMMU_DOMAIN_UNMANAGED);
+}
EXPORT_SYMBOL_GPL(iommu_domain_alloc);
void iommu_domain_free(struct iommu_domain *domain)