Commit 55fb74ad authored by David Herrmann's avatar David Herrmann Committed by Dave Airlie

drm/nouveau: embed gem object in nouveau_bo

There is no reason to keep the gem object separately allocated. nouveau is
the last user of gem_obj->driver_private, so if we embed it, we can get
rid of 8bytes per gem-object.

The implementation follows the radeon driver. bo->gem is only valid, iff
the bo was created via the gem helpers _and_ iff the user holds a valid
gem reference. That is, as the gem object holds a reference to the
nouveau_bo. If you use nouveau_ref() to gain a bo reference, you are not
guaranteed to also hold a gem reference. The gem object might get
destroyed after the last user drops the gem-ref via
drm_gem_object_unreference(). Use drm_gem_object_reference() to gain a
gem-reference.

For debugging, we can use bo->gem.filp != NULL to test whether a gem-bo is
valid. However, this shouldn't be used for real functionality to avoid
gem-internal dependencies.

Note that the implementation follows the previous style. However, we no
longer can check for bo->gem != NULL to test for a valid gem object. This
wasn't done before, so we should be safe now.
Signed-off-by: default avatarDavid Herrmann <dh.herrmann@gmail.com>
Acked-by: default avatarMaarten Lankhorst <maarten.lankhorst@canonical.com>
Reviewed-by: default avatarBen Skeggs <bskeggs@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 51bbd276
...@@ -130,7 +130,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, ...@@ -130,7 +130,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
if (chan->ntfy) { if (chan->ntfy) {
nouveau_bo_vma_del(chan->ntfy, &chan->ntfy_vma); nouveau_bo_vma_del(chan->ntfy, &chan->ntfy_vma);
nouveau_bo_unpin(chan->ntfy); nouveau_bo_unpin(chan->ntfy);
drm_gem_object_unreference_unlocked(chan->ntfy->gem); drm_gem_object_unreference_unlocked(&chan->ntfy->gem);
} }
if (chan->heap.block_size) if (chan->heap.block_size)
...@@ -320,7 +320,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) ...@@ -320,7 +320,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
goto done; goto done;
} }
ret = drm_gem_handle_create(file_priv, chan->ntfy->gem, ret = drm_gem_handle_create(file_priv, &chan->ntfy->gem,
&init->notifier_handle); &init->notifier_handle);
if (ret) if (ret)
goto done; goto done;
......
...@@ -146,7 +146,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) ...@@ -146,7 +146,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
struct drm_device *dev = drm->dev; struct drm_device *dev = drm->dev;
struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_bo *nvbo = nouveau_bo(bo);
if (unlikely(nvbo->gem)) if (unlikely(nvbo->gem.filp))
DRM_ERROR("bo %p still attached to GEM object\n", bo); DRM_ERROR("bo %p still attached to GEM object\n", bo);
WARN_ON(nvbo->pin_refcnt > 0); WARN_ON(nvbo->pin_refcnt > 0);
nv10_bo_put_tile_region(dev, nvbo->tile, NULL); nv10_bo_put_tile_region(dev, nvbo->tile, NULL);
...@@ -1267,7 +1267,7 @@ nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp) ...@@ -1267,7 +1267,7 @@ nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
{ {
struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_bo *nvbo = nouveau_bo(bo);
return drm_vma_node_verify_access(&nvbo->gem->vma_node, filp); return drm_vma_node_verify_access(&nvbo->gem.vma_node, filp);
} }
static int static int
......
...@@ -27,7 +27,10 @@ struct nouveau_bo { ...@@ -27,7 +27,10 @@ struct nouveau_bo {
u32 tile_flags; u32 tile_flags;
struct nouveau_drm_tile *tile; struct nouveau_drm_tile *tile;
struct drm_gem_object *gem; /* Only valid if allocated via nouveau_gem_new() and iff you hold a
* gem reference to it! For debugging, use gem.filp != NULL to test
* whether it is valid. */
struct drm_gem_object gem;
/* protect by the ttm reservation lock */ /* protect by the ttm reservation lock */
int pin_refcnt; int pin_refcnt;
......
...@@ -50,7 +50,7 @@ nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) ...@@ -50,7 +50,7 @@ nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
if (fb->nvbo) if (fb->nvbo)
drm_gem_object_unreference_unlocked(fb->nvbo->gem); drm_gem_object_unreference_unlocked(&fb->nvbo->gem);
drm_framebuffer_cleanup(drm_fb); drm_framebuffer_cleanup(drm_fb);
kfree(fb); kfree(fb);
...@@ -63,7 +63,7 @@ nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb, ...@@ -63,7 +63,7 @@ nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb,
{ {
struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
return drm_gem_handle_create(file_priv, fb->nvbo->gem, handle); return drm_gem_handle_create(file_priv, &fb->nvbo->gem, handle);
} }
static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
...@@ -674,8 +674,8 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, ...@@ -674,8 +674,8 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
if (ret) if (ret)
return ret; return ret;
ret = drm_gem_handle_create(file_priv, bo->gem, &args->handle); ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle);
drm_gem_object_unreference_unlocked(bo->gem); drm_gem_object_unreference_unlocked(&bo->gem);
return ret; return ret;
} }
...@@ -688,7 +688,7 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv, ...@@ -688,7 +688,7 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv,
gem = drm_gem_object_lookup(dev, file_priv, handle); gem = drm_gem_object_lookup(dev, file_priv, handle);
if (gem) { if (gem) {
struct nouveau_bo *bo = gem->driver_private; struct nouveau_bo *bo = nouveau_gem_object(gem);
*poffset = drm_vma_node_offset_addr(&bo->bo.vma_node); *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node);
drm_gem_object_unreference_unlocked(gem); drm_gem_object_unreference_unlocked(gem);
return 0; return 0;
......
...@@ -420,7 +420,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) ...@@ -420,7 +420,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
nouveau_bo_unmap(nouveau_fb->nvbo); nouveau_bo_unmap(nouveau_fb->nvbo);
nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma); nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma);
nouveau_bo_unpin(nouveau_fb->nvbo); nouveau_bo_unpin(nouveau_fb->nvbo);
drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem); drm_gem_object_unreference_unlocked(&nouveau_fb->nvbo->gem);
nouveau_fb->nvbo = NULL; nouveau_fb->nvbo = NULL;
} }
drm_fb_helper_fini(&fbcon->helper); drm_fb_helper_fini(&fbcon->helper);
......
...@@ -43,20 +43,17 @@ nouveau_gem_object_new(struct drm_gem_object *gem) ...@@ -43,20 +43,17 @@ nouveau_gem_object_new(struct drm_gem_object *gem)
void void
nouveau_gem_object_del(struct drm_gem_object *gem) nouveau_gem_object_del(struct drm_gem_object *gem)
{ {
struct nouveau_bo *nvbo = gem->driver_private; struct nouveau_bo *nvbo = nouveau_gem_object(gem);
struct ttm_buffer_object *bo = &nvbo->bo; struct ttm_buffer_object *bo = &nvbo->bo;
if (!nvbo)
return;
nvbo->gem = NULL;
if (gem->import_attach) if (gem->import_attach)
drm_prime_gem_destroy(gem, nvbo->bo.sg); drm_prime_gem_destroy(gem, nvbo->bo.sg);
ttm_bo_unref(&bo);
drm_gem_object_release(gem); drm_gem_object_release(gem);
kfree(gem);
/* reset filp so nouveau_bo_del_ttm() can test for it */
gem->filp = NULL;
ttm_bo_unref(&bo);
} }
int int
...@@ -186,14 +183,15 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain, ...@@ -186,14 +183,15 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain,
if (nv_device(drm->device)->card_type >= NV_50) if (nv_device(drm->device)->card_type >= NV_50)
nvbo->valid_domains &= domain; nvbo->valid_domains &= domain;
nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); /* Initialize the embedded gem-object. We return a single gem-reference
if (!nvbo->gem) { * to the caller, instead of a normal nouveau_bo ttm reference. */
ret = drm_gem_object_init(dev, &nvbo->gem, nvbo->bo.mem.size);
if (ret) {
nouveau_bo_ref(NULL, pnvbo); nouveau_bo_ref(NULL, pnvbo);
return -ENOMEM; return -ENOMEM;
} }
nvbo->bo.persistent_swap_storage = nvbo->gem->filp; nvbo->bo.persistent_swap_storage = nvbo->gem.filp;
nvbo->gem->driver_private = nvbo;
return 0; return 0;
} }
...@@ -250,15 +248,15 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, ...@@ -250,15 +248,15 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
if (ret) if (ret)
return ret; return ret;
ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle); ret = drm_gem_handle_create(file_priv, &nvbo->gem, &req->info.handle);
if (ret == 0) { if (ret == 0) {
ret = nouveau_gem_info(file_priv, nvbo->gem, &req->info); ret = nouveau_gem_info(file_priv, &nvbo->gem, &req->info);
if (ret) if (ret)
drm_gem_handle_delete(file_priv, req->info.handle); drm_gem_handle_delete(file_priv, req->info.handle);
} }
/* drop reference from allocate - handle holds it now */ /* drop reference from allocate - handle holds it now */
drm_gem_object_unreference_unlocked(nvbo->gem); drm_gem_object_unreference_unlocked(&nvbo->gem);
return ret; return ret;
} }
...@@ -266,7 +264,7 @@ static int ...@@ -266,7 +264,7 @@ static int
nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,
uint32_t write_domains, uint32_t valid_domains) uint32_t write_domains, uint32_t valid_domains)
{ {
struct nouveau_bo *nvbo = gem->driver_private; struct nouveau_bo *nvbo = nouveau_gem_object(gem);
struct ttm_buffer_object *bo = &nvbo->bo; struct ttm_buffer_object *bo = &nvbo->bo;
uint32_t domains = valid_domains & nvbo->valid_domains & uint32_t domains = valid_domains & nvbo->valid_domains &
(write_domains ? write_domains : read_domains); (write_domains ? write_domains : read_domains);
...@@ -327,7 +325,7 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence, ...@@ -327,7 +325,7 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence,
list_del(&nvbo->entry); list_del(&nvbo->entry);
nvbo->reserved_by = NULL; nvbo->reserved_by = NULL;
ttm_bo_unreserve_ticket(&nvbo->bo, ticket); ttm_bo_unreserve_ticket(&nvbo->bo, ticket);
drm_gem_object_unreference_unlocked(nvbo->gem); drm_gem_object_unreference_unlocked(&nvbo->gem);
} }
} }
...@@ -376,7 +374,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, ...@@ -376,7 +374,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
validate_fini(op, NULL); validate_fini(op, NULL);
return -ENOENT; return -ENOENT;
} }
nvbo = gem->driver_private; nvbo = nouveau_gem_object(gem);
if (nvbo == res_bo) { if (nvbo == res_bo) {
res_bo = NULL; res_bo = NULL;
drm_gem_object_unreference_unlocked(gem); drm_gem_object_unreference_unlocked(gem);
...@@ -478,7 +476,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, ...@@ -478,7 +476,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
return ret; return ret;
} }
ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains, ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains,
b->write_domains, b->write_domains,
b->valid_domains); b->valid_domains);
if (unlikely(ret)) { if (unlikely(ret)) {
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
static inline struct nouveau_bo * static inline struct nouveau_bo *
nouveau_gem_object(struct drm_gem_object *gem) nouveau_gem_object(struct drm_gem_object *gem)
{ {
return gem ? gem->driver_private : NULL; return gem ? container_of(gem, struct nouveau_bo, gem) : NULL;
} }
/* nouveau_gem.c */ /* nouveau_gem.c */
......
...@@ -71,14 +71,16 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, ...@@ -71,14 +71,16 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,
return ERR_PTR(ret); return ERR_PTR(ret);
nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_GART; nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_GART;
nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size);
if (!nvbo->gem) { /* Initialize the embedded gem-object. We return a single gem-reference
* to the caller, instead of a normal nouveau_bo ttm reference. */
ret = drm_gem_object_init(dev, &nvbo->gem, nvbo->bo.mem.size);
if (ret) {
nouveau_bo_ref(NULL, &nvbo); nouveau_bo_ref(NULL, &nvbo);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
nvbo->gem->driver_private = nvbo; return &nvbo->gem;
return nvbo->gem;
} }
int nouveau_gem_prime_pin(struct drm_gem_object *obj) int nouveau_gem_prime_pin(struct drm_gem_object *obj)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment