From: Christian König <christian.koenig@xxxxxxx> This allows us to have multiple GEM objects for one BO. Signed-off-by: Christian König <christian.koenig at amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling at amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 12 +++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 41 +++++++++++++++++++++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 7 +---- drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 20 ++++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 17 +++++++++++-- 5 files changed, 77 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2129fbb..f3d99cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -414,6 +414,12 @@ struct amdgpu_bo_va { #define AMDGPU_GEM_DOMAIN_MAX 0x3 +struct amdgpu_gem_object { + struct drm_gem_object base; + struct list_head list; + struct amdgpu_bo *bo; +}; + struct amdgpu_bo { /* Protected by tbo.reserved */ u32 prefered_domains; @@ -430,12 +436,14 @@ struct amdgpu_bo { void *metadata; u32 metadata_size; unsigned prime_shared_count; + /* GEM objects refereing to this BO */ + struct list_head gem_objects; + /* list of all virtual address to which this bo * is associated to */ struct list_head va; /* Constant after initialization */ - struct drm_gem_object gem_base; struct amdgpu_bo *parent; struct amdgpu_bo *shadow; @@ -444,7 +452,7 @@ struct amdgpu_bo { struct list_head mn_list; struct list_head shadow_list; }; -#define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, gem_base) +#define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_gem_object, base)->bo void amdgpu_gem_object_free(struct drm_gem_object *obj); int amdgpu_gem_object_open(struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 96c4493..f7e9bdf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -33,14 +33,20 @@ void amdgpu_gem_object_free(struct drm_gem_object *gobj) { - struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj); + struct amdgpu_gem_object *aobj; - if (robj) { - if (robj->gem_base.import_attach) - drm_prime_gem_destroy(&robj->gem_base, robj->tbo.sg); - amdgpu_mn_unregister(robj); - amdgpu_bo_unref(&robj); - } + aobj = container_of((gobj), struct amdgpu_gem_object, base); + if (aobj->base.import_attach) + drm_prime_gem_destroy(&aobj->base, aobj->bo->tbo.sg); + + ww_mutex_lock(&aobj->bo->tbo.resv->lock, NULL); + list_del(&aobj->list); + ww_mutex_unlock(&aobj->bo->tbo.resv->lock); + + amdgpu_mn_unregister(aobj->bo); + amdgpu_bo_unref(&aobj->bo); + drm_gem_object_release(&aobj->base); + kfree(aobj); } int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, @@ -49,6 +55,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, struct drm_gem_object **obj) { struct amdgpu_bo *robj; + struct amdgpu_gem_object *gobj; unsigned long max_size; int r; @@ -83,7 +90,23 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, } return r; } - *obj = &robj->gem_base; + + gobj = kzalloc(sizeof(struct amdgpu_gem_object), GFP_KERNEL); + if (unlikely(!gobj)) { + amdgpu_bo_unref(&robj); + return -ENOMEM; + } + + r = drm_gem_object_init(adev->ddev, &gobj->base, amdgpu_bo_size(robj)); + if (unlikely(r)) { + kfree(gobj); + amdgpu_bo_unref(&robj); + return r; + } + + list_add(&gobj->list, &robj->gem_objects); + gobj->bo = robj; + *obj = &gobj->base; return 0; } @@ -703,7 +726,7 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, struct drm_amdgpu_gem_create_in info; void __user *out = (void __user *)(uintptr_t)args->value; - info.bo_size = robj->gem_base.size; + info.bo_size = amdgpu_bo_size(robj); info.alignment = robj->tbo.mem.page_alignment << PAGE_SHIFT; info.domains = robj->prefered_domains; info.domain_flags = robj->flags; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index c34cf2c..44b7e71 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -95,7 +95,6 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo) amdgpu_update_memory_usage(adev, &bo->tbo.mem, NULL); - drm_gem_object_release(&bo->gem_base); amdgpu_bo_unref(&bo->parent); if (!list_empty(&bo->shadow_list)) { mutex_lock(&adev->shadow_list_lock); @@ -344,13 +343,9 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, bo = kzalloc(sizeof(struct amdgpu_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; - r = drm_gem_object_init(adev->ddev, &bo->gem_base, size); - if (unlikely(r)) { - kfree(bo); - return r; - } INIT_LIST_HEAD(&bo->shadow_list); INIT_LIST_HEAD(&bo->va); + INIT_LIST_HEAD(&bo->gem_objects); bo->prefered_domains = domain & (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT | AMDGPU_GEM_DOMAIN_CPU | diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c index 6bdc866..b9425ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c @@ -65,6 +65,7 @@ struct drm_gem_object * struct reservation_object *resv = attach->dmabuf->resv; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_bo *bo; + struct amdgpu_gem_object *gobj; int ret; ww_mutex_lock(&resv->lock, NULL); @@ -75,7 +76,24 @@ struct drm_gem_object * return ERR_PTR(ret); bo->prime_shared_count = 1; - return &bo->gem_base; + + gobj = kzalloc(sizeof(struct amdgpu_gem_object), GFP_KERNEL); + if (unlikely(!gobj)) { + amdgpu_bo_unref(&bo); + return ERR_PTR(-ENOMEM); + } + + ret = drm_gem_object_init(adev->ddev, &gobj->base, amdgpu_bo_size(bo)); + if (unlikely(ret)) { + kfree(gobj); + amdgpu_bo_unref(&bo); + return ERR_PTR(ret); + } + + list_add(&gobj->list, &bo->gem_objects); + gobj->bo = amdgpu_bo_ref(bo); + + return &gobj->base; } int amdgpu_gem_prime_pin(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 3f927c2..d0198f3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -235,11 +235,24 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) { struct amdgpu_bo *abo = container_of(bo, struct amdgpu_bo, tbo); + struct drm_file *file_priv = filp->private_data; + struct amdgpu_gem_object *gobj; if (amdgpu_ttm_tt_get_usermm(bo->ttm)) return -EPERM; - return drm_vma_node_verify_access(&abo->gem_base.vma_node, - filp->private_data); + + ww_mutex_lock(&abo->tbo.resv->lock, NULL); + list_for_each_entry(gobj, &abo->gem_objects, list) { + if (gobj->base.dev != file_priv->minor->dev) + continue; + + ww_mutex_unlock(&abo->tbo.resv->lock); + return drm_vma_node_verify_access(&gobj->base.vma_node, + file_priv); + } + ww_mutex_unlock(&abo->tbo.resv->lock); + + return -EPERM; } static void amdgpu_move_null(struct ttm_buffer_object *bo, -- 1.9.1