aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap/iommu.c')
-rw-r--r--arch/arm/plat-omap/iommu.c43
1 files changed, 26 insertions, 17 deletions
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index 0e137663349c..1e83facb6b77 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -172,15 +172,12 @@ static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
172 l->base = MMU_LOCK_BASE(val); 172 l->base = MMU_LOCK_BASE(val);
173 l->vict = MMU_LOCK_VICT(val); 173 l->vict = MMU_LOCK_VICT(val);
174 174
175 BUG_ON(l->base != 0); /* Currently no preservation is used */
176} 175}
177 176
178static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l) 177static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l)
179{ 178{
180 u32 val; 179 u32 val;
181 180
182 BUG_ON(l->base != 0); /* Currently no preservation is used */
183
184 val = (l->base << MMU_LOCK_BASE_SHIFT); 181 val = (l->base << MMU_LOCK_BASE_SHIFT);
185 val |= (l->vict << MMU_LOCK_VICT_SHIFT); 182 val |= (l->vict << MMU_LOCK_VICT_SHIFT);
186 183
@@ -231,22 +228,32 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
231 228
232 clk_enable(obj->clk); 229 clk_enable(obj->clk);
233 230
234 for (i = 0; i < obj->nr_tlb_entries; i++) { 231 iotlb_lock_get(obj, &l);
235 struct cr_regs tmp; 232 if (l.base == obj->nr_tlb_entries) {
236 233 dev_warn(obj->dev, "%s: preserve entries full\n", __func__);
237 iotlb_lock_get(obj, &l);
238 l.vict = i;
239 iotlb_lock_set(obj, &l);
240 iotlb_read_cr(obj, &tmp);
241 if (!iotlb_cr_valid(&tmp))
242 break;
243 }
244
245 if (i == obj->nr_tlb_entries) {
246 dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
247 err = -EBUSY; 234 err = -EBUSY;
248 goto out; 235 goto out;
249 } 236 }
237 if (!e->prsvd) {
238 for (i = l.base; i < obj->nr_tlb_entries; i++) {
239 struct cr_regs tmp;
240
241 iotlb_lock_get(obj, &l);
242 l.vict = i;
243 iotlb_lock_set(obj, &l);
244 iotlb_read_cr(obj, &tmp);
245 if (!iotlb_cr_valid(&tmp))
246 break;
247 }
248 if (i == obj->nr_tlb_entries) {
249 dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
250 err = -EBUSY;
251 goto out;
252 }
253 } else {
254 l.vict = l.base;
255 iotlb_lock_set(obj, &l);
256 }
250 257
251 cr = iotlb_alloc_cr(obj, e); 258 cr = iotlb_alloc_cr(obj, e);
252 if (IS_ERR(cr)) { 259 if (IS_ERR(cr)) {
@@ -257,9 +264,11 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
257 iotlb_load_cr(obj, cr); 264 iotlb_load_cr(obj, cr);
258 kfree(cr); 265 kfree(cr);
259 266
267 if (e->prsvd)
268 l.base++;
260 /* increment victim for next tlb load */ 269 /* increment victim for next tlb load */
261 if (++l.vict == obj->nr_tlb_entries) 270 if (++l.vict == obj->nr_tlb_entries)
262 l.vict = 0; 271 l.vict = l.base;
263 iotlb_lock_set(obj, &l); 272 iotlb_lock_set(obj, &l);
264out: 273out:
265 clk_disable(obj->clk); 274 clk_disable(obj->clk);