diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-10-02 04:15:17 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-10-09 00:37:55 -0400 |
commit | 55fb74adc628b99424360b0123f47ea4484c56fd (patch) | |
tree | 3c8b51cc6047af2a59a40989e18c4844afa0a23e /drivers/gpu/drm/nouveau/nouveau_gem.c | |
parent | 51bbd276015661a28b69450e104632bc2b633311 (diff) |
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: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Reviewed-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_gem.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 36 |
1 files changed, 17 insertions, 19 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index f32b71238c03..6618318abf50 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -43,20 +43,17 @@ nouveau_gem_object_new(struct drm_gem_object *gem) | |||
43 | void | 43 | void |
44 | nouveau_gem_object_del(struct drm_gem_object *gem) | 44 | nouveau_gem_object_del(struct drm_gem_object *gem) |
45 | { | 45 | { |
46 | struct nouveau_bo *nvbo = gem->driver_private; | 46 | struct nouveau_bo *nvbo = nouveau_gem_object(gem); |
47 | struct ttm_buffer_object *bo = &nvbo->bo; | 47 | struct ttm_buffer_object *bo = &nvbo->bo; |
48 | 48 | ||
49 | if (!nvbo) | ||
50 | return; | ||
51 | nvbo->gem = NULL; | ||
52 | |||
53 | if (gem->import_attach) | 49 | if (gem->import_attach) |
54 | drm_prime_gem_destroy(gem, nvbo->bo.sg); | 50 | drm_prime_gem_destroy(gem, nvbo->bo.sg); |
55 | 51 | ||
56 | ttm_bo_unref(&bo); | ||
57 | |||
58 | drm_gem_object_release(gem); | 52 | drm_gem_object_release(gem); |
59 | kfree(gem); | 53 | |
54 | /* reset filp so nouveau_bo_del_ttm() can test for it */ | ||
55 | gem->filp = NULL; | ||
56 | ttm_bo_unref(&bo); | ||
60 | } | 57 | } |
61 | 58 | ||
62 | int | 59 | int |
@@ -186,14 +183,15 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain, | |||
186 | if (nv_device(drm->device)->card_type >= NV_50) | 183 | if (nv_device(drm->device)->card_type >= NV_50) |
187 | nvbo->valid_domains &= domain; | 184 | nvbo->valid_domains &= domain; |
188 | 185 | ||
189 | nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); | 186 | /* Initialize the embedded gem-object. We return a single gem-reference |
190 | if (!nvbo->gem) { | 187 | * to the caller, instead of a normal nouveau_bo ttm reference. */ |
188 | ret = drm_gem_object_init(dev, &nvbo->gem, nvbo->bo.mem.size); | ||
189 | if (ret) { | ||
191 | nouveau_bo_ref(NULL, pnvbo); | 190 | nouveau_bo_ref(NULL, pnvbo); |
192 | return -ENOMEM; | 191 | return -ENOMEM; |
193 | } | 192 | } |
194 | 193 | ||
195 | nvbo->bo.persistent_swap_storage = nvbo->gem->filp; | 194 | nvbo->bo.persistent_swap_storage = nvbo->gem.filp; |
196 | nvbo->gem->driver_private = nvbo; | ||
197 | return 0; | 195 | return 0; |
198 | } | 196 | } |
199 | 197 | ||
@@ -250,15 +248,15 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, | |||
250 | if (ret) | 248 | if (ret) |
251 | return ret; | 249 | return ret; |
252 | 250 | ||
253 | ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle); | 251 | ret = drm_gem_handle_create(file_priv, &nvbo->gem, &req->info.handle); |
254 | if (ret == 0) { | 252 | if (ret == 0) { |
255 | ret = nouveau_gem_info(file_priv, nvbo->gem, &req->info); | 253 | ret = nouveau_gem_info(file_priv, &nvbo->gem, &req->info); |
256 | if (ret) | 254 | if (ret) |
257 | drm_gem_handle_delete(file_priv, req->info.handle); | 255 | drm_gem_handle_delete(file_priv, req->info.handle); |
258 | } | 256 | } |
259 | 257 | ||
260 | /* drop reference from allocate - handle holds it now */ | 258 | /* drop reference from allocate - handle holds it now */ |
261 | drm_gem_object_unreference_unlocked(nvbo->gem); | 259 | drm_gem_object_unreference_unlocked(&nvbo->gem); |
262 | return ret; | 260 | return ret; |
263 | } | 261 | } |
264 | 262 | ||
@@ -266,7 +264,7 @@ static int | |||
266 | nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, | 264 | nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, |
267 | uint32_t write_domains, uint32_t valid_domains) | 265 | uint32_t write_domains, uint32_t valid_domains) |
268 | { | 266 | { |
269 | struct nouveau_bo *nvbo = gem->driver_private; | 267 | struct nouveau_bo *nvbo = nouveau_gem_object(gem); |
270 | struct ttm_buffer_object *bo = &nvbo->bo; | 268 | struct ttm_buffer_object *bo = &nvbo->bo; |
271 | uint32_t domains = valid_domains & nvbo->valid_domains & | 269 | uint32_t domains = valid_domains & nvbo->valid_domains & |
272 | (write_domains ? write_domains : read_domains); | 270 | (write_domains ? write_domains : read_domains); |
@@ -327,7 +325,7 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence, | |||
327 | list_del(&nvbo->entry); | 325 | list_del(&nvbo->entry); |
328 | nvbo->reserved_by = NULL; | 326 | nvbo->reserved_by = NULL; |
329 | ttm_bo_unreserve_ticket(&nvbo->bo, ticket); | 327 | ttm_bo_unreserve_ticket(&nvbo->bo, ticket); |
330 | drm_gem_object_unreference_unlocked(nvbo->gem); | 328 | drm_gem_object_unreference_unlocked(&nvbo->gem); |
331 | } | 329 | } |
332 | } | 330 | } |
333 | 331 | ||
@@ -376,7 +374,7 @@ retry: | |||
376 | validate_fini(op, NULL); | 374 | validate_fini(op, NULL); |
377 | return -ENOENT; | 375 | return -ENOENT; |
378 | } | 376 | } |
379 | nvbo = gem->driver_private; | 377 | nvbo = nouveau_gem_object(gem); |
380 | if (nvbo == res_bo) { | 378 | if (nvbo == res_bo) { |
381 | res_bo = NULL; | 379 | res_bo = NULL; |
382 | drm_gem_object_unreference_unlocked(gem); | 380 | drm_gem_object_unreference_unlocked(gem); |
@@ -478,7 +476,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, | |||
478 | return ret; | 476 | return ret; |
479 | } | 477 | } |
480 | 478 | ||
481 | ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains, | 479 | ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains, |
482 | b->write_domains, | 480 | b->write_domains, |
483 | b->valid_domains); | 481 | b->valid_domains); |
484 | if (unlikely(ret)) { | 482 | if (unlikely(ret)) { |