summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/exynos-iommu.c
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2015-05-19 09:20:33 -0400
committerJoerg Roedel <jroedel@suse.de>2015-05-29 04:49:47 -0400
commit1b09205436847897da1826a88e5cefd9cde5eed7 (patch)
tree02755b9a79b18bc90cca0131352efcd98777ef77 /drivers/iommu/exynos-iommu.c
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/exynos-iommu.c')
-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] = {
187 * pointer. 187 * pointer.
188*/ 188*/
189struct exynos_iommu_owner { 189struct exynos_iommu_owner {
190 struct device *sysmmu; /* sysmmu controller for given master */ 190 struct list_head controllers; /* list of sysmmu_drvdata.owner_node */
191}; 191};
192 192
193/* 193/*
@@ -221,6 +221,7 @@ struct sysmmu_drvdata {
221 spinlock_t lock; /* lock for modyfying state */ 221 spinlock_t lock; /* lock for modyfying state */
222 struct exynos_iommu_domain *domain; /* domain we belong to */ 222 struct exynos_iommu_domain *domain; /* domain we belong to */
223 struct list_head domain_node; /* node for domain clients list */ 223 struct list_head domain_node; /* node for domain clients list */
224 struct list_head owner_node; /* node for owner controllers list */
224 phys_addr_t pgtable; /* assigned page table structure */ 225 phys_addr_t pgtable; /* assigned page table structure */
225 unsigned int version; /* our version */ 226 unsigned int version; /* our version */
226}; 227};
@@ -713,8 +714,7 @@ static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
713 if (!has_sysmmu(dev)) 714 if (!has_sysmmu(dev))
714 return -ENODEV; 715 return -ENODEV;
715 716
716 data = dev_get_drvdata(owner->sysmmu); 717 list_for_each_entry(data, &owner->controllers, owner_node) {
717 if (data) {
718 ret = __sysmmu_enable(data, pagetable, domain); 718 ret = __sysmmu_enable(data, pagetable, domain);
719 if (ret >= 0) { 719 if (ret >= 0) {
720 data->master = dev; 720 data->master = dev;
@@ -742,7 +742,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
742{ 742{
743 struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); 743 struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain);
744 phys_addr_t pagetable = virt_to_phys(domain->pgtable); 744 phys_addr_t pagetable = virt_to_phys(domain->pgtable);
745 struct sysmmu_drvdata *data; 745 struct sysmmu_drvdata *data, *next;
746 unsigned long flags; 746 unsigned long flags;
747 bool found = false; 747 bool found = false;
748 748
@@ -750,14 +750,13 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
750 return; 750 return;
751 751
752 spin_lock_irqsave(&domain->lock, flags); 752 spin_lock_irqsave(&domain->lock, flags);
753 list_for_each_entry(data, &domain->clients, domain_node) { 753 list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
754 if (data->master == dev) { 754 if (data->master == dev) {
755 if (__sysmmu_disable(data)) { 755 if (__sysmmu_disable(data)) {
756 data->master = NULL; 756 data->master = NULL;
757 list_del_init(&data->domain_node); 757 list_del_init(&data->domain_node);
758 } 758 }
759 found = true; 759 found = true;
760 break;
761 } 760 }
762 } 761 }
763 spin_unlock_irqrestore(&domain->lock, flags); 762 spin_unlock_irqrestore(&domain->lock, flags);