diff options
-rw-r--r-- | drivers/iommu/omap-iommu.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 6899dcd02dfa..e70ee2b59df9 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
@@ -41,11 +41,13 @@ | |||
41 | * @pgtable: the page table | 41 | * @pgtable: the page table |
42 | * @iommu_dev: an omap iommu device attached to this domain. only a single | 42 | * @iommu_dev: an omap iommu device attached to this domain. only a single |
43 | * iommu device can be attached for now. | 43 | * iommu device can be attached for now. |
44 | * @dev: Device using this domain. | ||
44 | * @lock: domain lock, should be taken when attaching/detaching | 45 | * @lock: domain lock, should be taken when attaching/detaching |
45 | */ | 46 | */ |
46 | struct omap_iommu_domain { | 47 | struct omap_iommu_domain { |
47 | u32 *pgtable; | 48 | u32 *pgtable; |
48 | struct omap_iommu *iommu_dev; | 49 | struct omap_iommu *iommu_dev; |
50 | struct device *dev; | ||
49 | spinlock_t lock; | 51 | spinlock_t lock; |
50 | }; | 52 | }; |
51 | 53 | ||
@@ -1081,6 +1083,7 @@ omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
1081 | } | 1083 | } |
1082 | 1084 | ||
1083 | omap_domain->iommu_dev = arch_data->iommu_dev = oiommu; | 1085 | omap_domain->iommu_dev = arch_data->iommu_dev = oiommu; |
1086 | omap_domain->dev = dev; | ||
1084 | oiommu->domain = domain; | 1087 | oiommu->domain = domain; |
1085 | 1088 | ||
1086 | out: | 1089 | out: |
@@ -1088,19 +1091,16 @@ out: | |||
1088 | return ret; | 1091 | return ret; |
1089 | } | 1092 | } |
1090 | 1093 | ||
1091 | static void omap_iommu_detach_dev(struct iommu_domain *domain, | 1094 | static void _omap_iommu_detach_dev(struct omap_iommu_domain *omap_domain, |
1092 | struct device *dev) | 1095 | struct device *dev) |
1093 | { | 1096 | { |
1094 | struct omap_iommu_domain *omap_domain = domain->priv; | ||
1095 | struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; | ||
1096 | struct omap_iommu *oiommu = dev_to_omap_iommu(dev); | 1097 | struct omap_iommu *oiommu = dev_to_omap_iommu(dev); |
1097 | 1098 | struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; | |
1098 | spin_lock(&omap_domain->lock); | ||
1099 | 1099 | ||
1100 | /* only a single device is supported per domain for now */ | 1100 | /* only a single device is supported per domain for now */ |
1101 | if (omap_domain->iommu_dev != oiommu) { | 1101 | if (omap_domain->iommu_dev != oiommu) { |
1102 | dev_err(dev, "invalid iommu device\n"); | 1102 | dev_err(dev, "invalid iommu device\n"); |
1103 | goto out; | 1103 | return; |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | iopgtable_clear_entry_all(oiommu); | 1106 | iopgtable_clear_entry_all(oiommu); |
@@ -1108,8 +1108,16 @@ static void omap_iommu_detach_dev(struct iommu_domain *domain, | |||
1108 | omap_iommu_detach(oiommu); | 1108 | omap_iommu_detach(oiommu); |
1109 | 1109 | ||
1110 | omap_domain->iommu_dev = arch_data->iommu_dev = NULL; | 1110 | omap_domain->iommu_dev = arch_data->iommu_dev = NULL; |
1111 | omap_domain->dev = NULL; | ||
1112 | } | ||
1111 | 1113 | ||
1112 | out: | 1114 | static void omap_iommu_detach_dev(struct iommu_domain *domain, |
1115 | struct device *dev) | ||
1116 | { | ||
1117 | struct omap_iommu_domain *omap_domain = domain->priv; | ||
1118 | |||
1119 | spin_lock(&omap_domain->lock); | ||
1120 | _omap_iommu_detach_dev(omap_domain, dev); | ||
1113 | spin_unlock(&omap_domain->lock); | 1121 | spin_unlock(&omap_domain->lock); |
1114 | } | 1122 | } |
1115 | 1123 | ||
@@ -1148,13 +1156,19 @@ out: | |||
1148 | return -ENOMEM; | 1156 | return -ENOMEM; |
1149 | } | 1157 | } |
1150 | 1158 | ||
1151 | /* assume device was already detached */ | ||
1152 | static void omap_iommu_domain_destroy(struct iommu_domain *domain) | 1159 | static void omap_iommu_domain_destroy(struct iommu_domain *domain) |
1153 | { | 1160 | { |
1154 | struct omap_iommu_domain *omap_domain = domain->priv; | 1161 | struct omap_iommu_domain *omap_domain = domain->priv; |
1155 | 1162 | ||
1156 | domain->priv = NULL; | 1163 | domain->priv = NULL; |
1157 | 1164 | ||
1165 | /* | ||
1166 | * An iommu device is still attached | ||
1167 | * (currently, only one device can be attached) ? | ||
1168 | */ | ||
1169 | if (omap_domain->iommu_dev) | ||
1170 | _omap_iommu_detach_dev(omap_domain, omap_domain->dev); | ||
1171 | |||
1158 | kfree(omap_domain->pgtable); | 1172 | kfree(omap_domain->pgtable); |
1159 | kfree(omap_domain); | 1173 | kfree(omap_domain); |
1160 | } | 1174 | } |