/** * load_iotlb_entry - Set an iommu tlb entry * @obj: target iommu * @e: an iommu tlb entry info **/ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) { int i; int err = 0; struct iotlb_lock l; struct cr_regs *cr; if (!obj || !obj->nr_tlb_entries || !e) return -EINVAL; clk_enable(obj->clk); for (i = 0; i < obj->nr_tlb_entries; i++) { struct cr_regs tmp; iotlb_lock_get(obj, &l); l.vict = i; iotlb_lock_set(obj, &l); iotlb_read_cr(obj, &tmp); if (!iotlb_cr_valid(&tmp)) break; } if (i == obj->nr_tlb_entries) { dev_dbg(obj->dev, "%s: full: no entry\n", __func__); err = -EBUSY; goto out; } cr = iotlb_alloc_cr(obj, e); if (IS_ERR(cr)) { clk_disable(obj->clk); return PTR_ERR(cr); } iotlb_load_cr(obj, cr); kfree(cr); /* increment victim for next tlb load */ if (++l.vict == obj->nr_tlb_entries) l.vict = 0; iotlb_lock_set(obj, &l); out: clk_disable(obj->clk); return err; }
/** * load_iotlb_entry - Set an iommu tlb entry * @obj: target iommu * @e: an iommu tlb entry info **/ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) { int i; int err = 0; struct iotlb_lock l; struct cr_regs *cr; if (!obj || !obj->nr_tlb_entries || !e) return -EINVAL; if (!cpu_is_omap44xx()) clk_enable(obj->clk); iotlb_lock_get(obj, &l); if (l.base == obj->nr_tlb_entries) { dev_warn(obj->dev, "%s: preserve entries full\n", __func__); err = -EBUSY; goto out; } if (!e->prsvd) { for (i = l.base; i < obj->nr_tlb_entries; i++) { struct cr_regs tmp; iotlb_lock_get(obj, &l); l.vict = i; iotlb_lock_set(obj, &l); iotlb_read_cr(obj, &tmp); if (!iotlb_cr_valid(&tmp)) break; } if (i == obj->nr_tlb_entries) { dev_dbg(obj->dev, "%s: full: no entry\n", __func__); err = -EBUSY; goto out; } } else { l.vict = l.base; iotlb_lock_set(obj, &l); } cr = iotlb_alloc_cr(obj, e); if (IS_ERR(cr)) { if (!cpu_is_omap44xx()) clk_disable(obj->clk); return PTR_ERR(cr); } iotlb_load_cr(obj, cr); kfree(cr); /* Increment base number if preservation is set */ if (e->prsvd) l.base++; /* increment victim for next tlb load */ if (++l.vict == obj->nr_tlb_entries) { l.vict = l.base; goto out; } iotlb_lock_set(obj, &l); out: if (!cpu_is_omap44xx()) clk_disable(obj->clk); return err; }