diff options
Diffstat (limited to 'arch/arm/plat-omap/iommu.c')
-rw-r--r-- | arch/arm/plat-omap/iommu.c | 43 |
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 | ||
178 | static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l) | 177 | static 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); |
264 | out: | 273 | out: |
265 | clk_disable(obj->clk); | 274 | clk_disable(obj->clk); |