Commit 1000dccd authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Joerg Roedel

iommu: Allow IOMMU_RESV_DIRECT to work on ARM

For now several ARM drivers do not allow mappings to be created until a
domain is attached. This means they do not technically support
IOMMU_RESV_DIRECT as it requires the 1:1 maps to work continuously.

Currently if the platform requests these maps on ARM systems they are
silently ignored.

Work around this by trying again to establish the direct mappings after
the domain is attached if the pre-attach attempt failed.

In the long run the drivers will be fixed to fully setup domains when they
are created without waiting for attachment.
Reviewed-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Tested-by: default avatarHeiko Stuebner <heiko@sntech.de>
Tested-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/15-v5-1b99ae392328+44574-iommu_err_unwind_jgg@nvidia.comSigned-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent d99be00f
...@@ -2842,6 +2842,7 @@ static int iommu_setup_default_domain(struct iommu_group *group, ...@@ -2842,6 +2842,7 @@ static int iommu_setup_default_domain(struct iommu_group *group,
struct iommu_domain *old_dom = group->default_domain; struct iommu_domain *old_dom = group->default_domain;
struct group_device *gdev; struct group_device *gdev;
struct iommu_domain *dom; struct iommu_domain *dom;
bool direct_failed;
int req_type; int req_type;
int ret; int ret;
...@@ -2875,8 +2876,15 @@ static int iommu_setup_default_domain(struct iommu_group *group, ...@@ -2875,8 +2876,15 @@ static int iommu_setup_default_domain(struct iommu_group *group,
* mapped before their device is attached, in order to guarantee * mapped before their device is attached, in order to guarantee
* continuity with any FW activity * continuity with any FW activity
*/ */
for_each_group_device(group, gdev) direct_failed = false;
iommu_create_device_direct_mappings(dom, gdev->dev); for_each_group_device(group, gdev) {
if (iommu_create_device_direct_mappings(dom, gdev->dev)) {
direct_failed = true;
dev_warn_once(
gdev->dev->iommu->iommu_dev->dev,
"IOMMU driver was not able to establish FW requested direct mapping.");
}
}
/* We must set default_domain early for __iommu_device_set_domain */ /* We must set default_domain early for __iommu_device_set_domain */
group->default_domain = dom; group->default_domain = dom;
...@@ -2900,6 +2908,27 @@ static int iommu_setup_default_domain(struct iommu_group *group, ...@@ -2900,6 +2908,27 @@ static int iommu_setup_default_domain(struct iommu_group *group,
} }
} }
/*
* Drivers are supposed to allow mappings to be installed in a domain
* before device attachment, but some don't. Hack around this defect by
* trying again after attaching. If this happens it means the device
* will not continuously have the IOMMU_RESV_DIRECT map.
*/
if (direct_failed) {
for_each_group_device(group, gdev) {
ret = iommu_create_device_direct_mappings(dom, gdev->dev);
if (ret)
goto err_restore;
}
}
err_restore:
if (old_dom) {
__iommu_group_set_domain_internal(
group, old_dom, IOMMU_SET_DOMAIN_MUST_SUCCEED);
iommu_domain_free(dom);
old_dom = NULL;
}
out_free: out_free:
if (old_dom) if (old_dom)
iommu_domain_free(old_dom); iommu_domain_free(old_dom);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment