diff options
author | Dmitry Osipenko <digetx@gmail.com> | 2018-12-12 21:39:02 +0100 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2019-01-16 13:54:14 +0100 |
commit | 7d849b7b40b9b3f574f50bbf44503b38e319fca5 (patch) | |
tree | 9d2e09f357d7e817c2652a88f51c0ae7ccc91507 /drivers | |
parent | iommu/tegra: gart: Fix NULL pointer dereference (diff) | |
download | linux-7d849b7b40b9b3f574f50bbf44503b38e319fca5.tar.xz linux-7d849b7b40b9b3f574f50bbf44503b38e319fca5.zip |
iommu/tegra: gart: Allow only one active domain at a time
GART has a single address space that is shared by all devices, hence only
one domain could be active at a time.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/iommu/tegra-gart.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 7fdd8b12efd5..71ff22be9560 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -57,6 +57,7 @@ struct gart_device { spinlock_t pte_lock; /* for pagetable */ struct list_head client; spinlock_t client_lock; /* for client list */ + struct iommu_domain *active_domain; /* current active domain */ struct device *dev; struct iommu_device iommu; /* IOMMU Core handle */ @@ -186,6 +187,12 @@ static int gart_iommu_attach_dev(struct iommu_domain *domain, goto fail; } } + if (gart->active_domain && gart->active_domain != domain) { + dev_err(gart->dev, "Only one domain can be active at a time\n"); + err = -EINVAL; + goto fail; + } + gart->active_domain = domain; list_add(&client->list, &gart->client); spin_unlock(&gart->client_lock); dev_dbg(gart->dev, "Attached %s\n", dev_name(dev)); @@ -208,6 +215,8 @@ static void __gart_iommu_detach_dev(struct iommu_domain *domain, if (c->dev == dev) { list_del(&c->list); devm_kfree(gart->dev, c); + if (list_empty(&gart->client)) + gart->active_domain = NULL; dev_dbg(gart->dev, "Detached %s\n", dev_name(dev)); return; } |