/* should be called under struct_mutex.. although it can be called * from atomic context without struct_mutex to acquire an extra * iova ref if you know one is already held. * * That means when I do eventually need to add support for unpinning * the refcnt counter needs to be atomic_t. */ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id, uint32_t *iova) { struct msm_gem_object *msm_obj = to_msm_bo(obj); int ret = 0; if (!msm_obj->domain[id].iova) { struct msm_drm_private *priv = obj->dev->dev_private; struct page **pages = get_pages(obj); if (IS_ERR(pages)) return PTR_ERR(pages); if (iommu_present(&platform_bus_type)) { struct msm_mmu *mmu = priv->mmus[id]; uint32_t offset; if (WARN_ON(!mmu)) return -EINVAL; offset = (uint32_t)mmap_offset(obj); ret = mmu->funcs->map(mmu, offset, msm_obj->sgt, obj->size, IOMMU_READ | IOMMU_WRITE); msm_obj->domain[id].iova = offset; } else { msm_obj->domain[id].iova = physaddr(obj); } } if (!ret) *iova = msm_obj->domain[id].iova; return ret; }
static void evict_entry(struct drm_gem_object *obj, enum tiler_fmt fmt, struct usergart_entry *entry) { if (obj->dev->dev_mapping) { struct omap_gem_object *omap_obj = to_omap_bo(obj); int n = usergart[fmt].height; size_t size = PAGE_SIZE * n; loff_t off = mmap_offset(obj) + (entry->obj_pgoff << PAGE_SHIFT); const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE); if (m > 1) { int i; /* if stride > than PAGE_SIZE then sparse mapping: */ for (i = n; i > 0; i--) { unmap_mapping_range(obj->dev->dev_mapping, off, PAGE_SIZE, 1); off += PAGE_SIZE * m; } } else { unmap_mapping_range(obj->dev->dev_mapping, off, size, 1); } } entry->obj = NULL; }
uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj) { uint64_t offset; mutex_lock(&obj->dev->struct_mutex); offset = mmap_offset(obj); mutex_unlock(&obj->dev->struct_mutex); return offset; }
static void evict_entry(struct drm_gem_object *obj, enum tiler_fmt fmt, struct usergart_entry *entry) { if (obj->dev->dev_mapping) { size_t size = PAGE_SIZE * usergart[fmt].height; loff_t off = mmap_offset(obj) + (entry->obj_pgoff << PAGE_SHIFT); unmap_mapping_range(obj->dev->dev_mapping, off, size, 1); } entry->obj = NULL; }