summaryrefslogtreecommitdiff
path: root/drivers/iommu
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2015-05-19 15:20:33 +0200
committerJoerg Roedel <jroedel@suse.de>2015-05-29 10:49:47 +0200
commit1b09205436847897da1826a88e5cefd9cde5eed7 (patch)
tree02755b9a79b18bc90cca0131352efcd98777ef77 /drivers/iommu
parent06801db0d3bba2b4e585130981fadf71bbce4159 (diff)
iommu/exynos: Add support for binding more than one sysmmu to master device
This patch adds support for assigning more than one SYSMMU controller to the master device. This has been achieved simply by chaning the struct device pointer in struct exynos_iommu_owner into the list of struct sysmmu_drvdata of all controllers assigned to the given master device. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Tested-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/exynos-iommu.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 99ed39c89e0b..b7f679c4659c 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -187,7 +187,7 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
* pointer.
*/
struct exynos_iommu_owner {
- struct device *sysmmu; /* sysmmu controller for given master */
+ struct list_head controllers; /* list of sysmmu_drvdata.owner_node */
};
/*
@@ -221,6 +221,7 @@ struct sysmmu_drvdata {
spinlock_t lock; /* lock for modyfying state */
struct exynos_iommu_domain *domain; /* domain we belong to */
struct list_head domain_node; /* node for domain clients list */
+ struct list_head owner_node; /* node for owner controllers list */
phys_addr_t pgtable; /* assigned page table structure */
unsigned int version; /* our version */
};
@@ -713,8 +714,7 @@ static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
if (!has_sysmmu(dev))
return -ENODEV;
- data = dev_get_drvdata(owner->sysmmu);
- if (data) {
+ list_for_each_entry(data, &owner->controllers, owner_node) {
ret = __sysmmu_enable(data, pagetable, domain);
if (ret >= 0) {
data->master = dev;
@@ -742,7 +742,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
{
struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain);
phys_addr_t pagetable = virt_to_phys(domain->pgtable);
- struct sysmmu_drvdata *data;
+ struct sysmmu_drvdata *data, *next;
unsigned long flags;
bool found = false;
@@ -750,14 +750,13 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
return;
spin_lock_irqsave(&domain->lock, flags);
- list_for_each_entry(data, &domain->clients, domain_node) {
+ list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
if (data->master == dev) {
if (__sysmmu_disable(data)) {
data->master = NULL;
list_del_init(&data->domain_node);
}
found = true;
- break;
}
}
spin_unlock_irqrestore(&domain->lock, flags);