diff options
author | Jordan Crouse | 2018-11-07 15:35:48 -0700 |
---|---|---|
committer | Rob Clark | 2018-12-11 13:05:31 -0500 |
commit | c0ee9794693c1ff5bf540fc642fac954e39234a0 (patch) | |
tree | 1ca89be98fadad513d8abcf896abff892dd0879f /drivers/gpu/drm/msm/msm_gem.c | |
parent | 70dc51b447f570ba3881e289b8134d364977a6f0 (diff) |
drm/msm: Split msm_gem_get_iova into two steps
Split the operation of msm_gem_get_iova into two operations:
1) allocate an iova and 2) map (pin) the backing memory int the
iommu. This is the first step toward allowing memory pinning
to occur independently of the iova management.
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gem.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem.c | 80 |
1 files changed, 52 insertions, 28 deletions
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 0b9b8a21dfbb..013b023528b8 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -357,52 +357,76 @@ put_iova(struct drm_gem_object *obj) } } -/* get iova, taking a reference. Should have a matching put */ -int msm_gem_get_iova(struct drm_gem_object *obj, +static int msm_gem_get_iova_locked(struct drm_gem_object *obj, struct msm_gem_address_space *aspace, uint64_t *iova) { struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_gem_vma *vma; int ret = 0; - mutex_lock(&msm_obj->lock); - - if (WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) { - mutex_unlock(&msm_obj->lock); - return -EBUSY; - } + WARN_ON(!mutex_is_locked(&msm_obj->lock)); vma = lookup_vma(obj, aspace); if (!vma) { - struct page **pages; - vma = add_vma(obj, aspace); - if (IS_ERR(vma)) { - ret = PTR_ERR(vma); - goto unlock; - } + if (IS_ERR(vma)) + return PTR_ERR(vma); - pages = get_pages(obj); - if (IS_ERR(pages)) { - ret = PTR_ERR(pages); - goto fail; + ret = msm_gem_init_vma(aspace, vma, obj->size >> PAGE_SHIFT); + if (ret) { + del_vma(vma); + return ret; } - - ret = msm_gem_map_vma(aspace, vma, msm_obj->sgt, - obj->size >> PAGE_SHIFT); - if (ret) - goto fail; } *iova = vma->iova; - - mutex_unlock(&msm_obj->lock); return 0; +} + +static int msm_gem_pin_iova(struct drm_gem_object *obj, + struct msm_gem_address_space *aspace) +{ + struct msm_gem_object *msm_obj = to_msm_bo(obj); + struct msm_gem_vma *vma; + struct page **pages; + + WARN_ON(!mutex_is_locked(&msm_obj->lock)); + + if (WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) + return -EBUSY; + + vma = lookup_vma(obj, aspace); + if (WARN_ON(!vma)) + return -EINVAL; + + pages = get_pages(obj); + if (IS_ERR(pages)) + return PTR_ERR(pages); + + return msm_gem_map_vma(aspace, vma, msm_obj->sgt, + obj->size >> PAGE_SHIFT); +} + + +/* get iova, taking a reference. Should have a matching put */ +int msm_gem_get_iova(struct drm_gem_object *obj, + struct msm_gem_address_space *aspace, uint64_t *iova) +{ + struct msm_gem_object *msm_obj = to_msm_bo(obj); + u64 local; + int ret; + + mutex_lock(&msm_obj->lock); + + ret = msm_gem_get_iova_locked(obj, aspace, &local); + + if (!ret) + ret = msm_gem_pin_iova(obj, aspace); + + if (!ret) + *iova = local; -fail: - del_vma(vma); -unlock: mutex_unlock(&msm_obj->lock); return ret; } |