diff options
author | Joerg Roedel <jroedel@suse.de> | 2015-05-28 18:41:36 +0200 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2015-06-11 09:01:55 +0200 |
commit | d290f1e70d85a9a4d124594c6a3d769329960bdc (patch) | |
tree | 56830081621c5c3681e7121967b7a69da46af360 /drivers/iommu | |
parent | 6827ca83695d5e41ad31b0719788ee65f00ca4b3 (diff) | |
download | blackbird-op-linux-d290f1e70d85a9a4d124594c6a3d769329960bdc.tar.gz blackbird-op-linux-d290f1e70d85a9a4d124594c6a3d769329960bdc.zip |
iommu: Introduce iommu_request_dm_for_dev()
This function can be called by an IOMMU driver to request
that a device's default domain is direct mapped.
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/iommu.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 224c6dd2d249..3b1a2551a747 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1538,3 +1538,56 @@ void iommu_put_dm_regions(struct device *dev, struct list_head *list) if (ops && ops->put_dm_regions) ops->put_dm_regions(dev, list); } + +/* Request that a device is direct mapped by the IOMMU */ +int iommu_request_dm_for_dev(struct device *dev) +{ + struct iommu_domain *dm_domain; + struct iommu_group *group; + int ret; + + /* Device must already be in a group before calling this function */ + group = iommu_group_get_for_dev(dev); + if (!group) + return -EINVAL; + + mutex_lock(&group->mutex); + + /* Check if the default domain is already direct mapped */ + ret = 0; + if (group->default_domain && + group->default_domain->type == IOMMU_DOMAIN_IDENTITY) + goto out; + + /* Don't change mappings of existing devices */ + ret = -EBUSY; + if (iommu_group_device_count(group) != 1) + goto out; + + /* Allocate a direct mapped domain */ + ret = -ENOMEM; + dm_domain = __iommu_domain_alloc(dev->bus, IOMMU_DOMAIN_IDENTITY); + if (!dm_domain) + goto out; + + /* Attach the device to the domain */ + ret = __iommu_attach_group(dm_domain, group); + if (ret) { + iommu_domain_free(dm_domain); + goto out; + } + + /* Make the direct mapped domain the default for this group */ + if (group->default_domain) + iommu_domain_free(group->default_domain); + group->default_domain = dm_domain; + + pr_info("Using direct mapping for device %s\n", dev_name(dev)); + + ret = 0; +out: + mutex_unlock(&group->mutex); + iommu_group_put(group); + + return ret; +} |