aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/omap-iommu.c32
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 */
46struct omap_iommu_domain { 47struct 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
1086out: 1089out:
@@ -1088,19 +1091,16 @@ out:
1088 return ret; 1091 return ret;
1089} 1092}
1090 1093
1091static void omap_iommu_detach_dev(struct iommu_domain *domain, 1094static 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
1112out: 1114static 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 */
1152static void omap_iommu_domain_destroy(struct iommu_domain *domain) 1159static 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}