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>
This commit is contained in:
Dmitry Osipenko 2018-12-12 23:39:02 +03:00 committed by Joerg Roedel
parent 8e924910dd
commit 7d849b7b40
1 changed files with 9 additions and 0 deletions

View File

@ -57,6 +57,7 @@ struct gart_device {
spinlock_t pte_lock; /* for pagetable */ spinlock_t pte_lock; /* for pagetable */
struct list_head client; struct list_head client;
spinlock_t client_lock; /* for client list */ spinlock_t client_lock; /* for client list */
struct iommu_domain *active_domain; /* current active domain */
struct device *dev; struct device *dev;
struct iommu_device iommu; /* IOMMU Core handle */ struct iommu_device iommu; /* IOMMU Core handle */
@ -186,6 +187,12 @@ static int gart_iommu_attach_dev(struct iommu_domain *domain,
goto fail; 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); list_add(&client->list, &gart->client);
spin_unlock(&gart->client_lock); spin_unlock(&gart->client_lock);
dev_dbg(gart->dev, "Attached %s\n", dev_name(dev)); 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) { if (c->dev == dev) {
list_del(&c->list); list_del(&c->list);
devm_kfree(gart->dev, c); devm_kfree(gart->dev, c);
if (list_empty(&gart->client))
gart->active_domain = NULL;
dev_dbg(gart->dev, "Detached %s\n", dev_name(dev)); dev_dbg(gart->dev, "Detached %s\n", dev_name(dev));
return; return;
} }