summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2018-05-14 11:14:00 +0200
committerThierry Reding <treding@nvidia.com>2018-05-17 17:44:48 +0200
commitf40e1590c5270e5559fb95a5a0a7c1f5266a522d (patch)
tree15ca7fa9e087653bb225d3667cecf37b2dac9071 /drivers/gpu/host1x
parentdrm/tegra: Acquire a reference to the IOVA cache (diff)
downloadlinux-f40e1590c5270e5559fb95a5a0a7c1f5266a522d.tar.xz
linux-f40e1590c5270e5559fb95a5a0a7c1f5266a522d.zip
gpu: host1x: Acquire a reference to the IOVA cache
The IOVA API uses a memory cache to allocate IOVA nodes from. To make sure that this cache is available, obtain a reference to it and release the reference when the cache is no longer needed. On 64-bit ARM this is hidden by the fact that the DMA mapping API gets that reference and never releases it. On 32-bit ARM, this is papered over by the Tegra DRM driver (the sole user of the host1x API requiring the cache) acquiring a reference to the IOVA cache for its own purposes. However, there may be additional users of this API in the future, so fix this upfront to avoid surprises. Fixes: 404bfb78daf3 ("gpu: host1x: Add IOMMU support") Reviewed-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/host1x')
-rw-r--r--drivers/gpu/host1x/dev.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 03db71173f5d..f1d5f76e9c33 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -223,10 +223,14 @@ static int host1x_probe(struct platform_device *pdev)
struct iommu_domain_geometry *geometry;
unsigned long order;
+ err = iova_cache_get();
+ if (err < 0)
+ goto put_group;
+
host->domain = iommu_domain_alloc(&platform_bus_type);
if (!host->domain) {
err = -ENOMEM;
- goto put_group;
+ goto put_cache;
}
err = iommu_attach_group(host->domain, host->group);
@@ -234,6 +238,7 @@ static int host1x_probe(struct platform_device *pdev)
if (err == -ENODEV) {
iommu_domain_free(host->domain);
host->domain = NULL;
+ iova_cache_put();
iommu_group_put(host->group);
host->group = NULL;
goto skip_iommu;
@@ -308,6 +313,9 @@ fail_detach_device:
fail_free_domain:
if (host->domain)
iommu_domain_free(host->domain);
+put_cache:
+ if (host->group)
+ iova_cache_put();
put_group:
iommu_group_put(host->group);
@@ -328,6 +336,7 @@ static int host1x_remove(struct platform_device *pdev)
put_iova_domain(&host->iova);
iommu_detach_group(host->domain, host->group);
iommu_domain_free(host->domain);
+ iova_cache_put();
iommu_group_put(host->group);
}