if (chan->ntfy) {
                nouveau_bo_vma_del(chan->ntfy, &chan->ntfy_vma);
                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)
                        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);
        if (ret)
                goto done;
 
        struct drm_device *dev = drm->dev;
        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);
        WARN_ON(nvbo->pin_refcnt > 0);
        nv10_bo_put_tile_region(dev, nvbo->tile, NULL);
 {
        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
 
        u32 tile_flags;
        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 */
        int pin_refcnt;
 
        struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
 
        if (fb->nvbo)
-               drm_gem_object_unreference_unlocked(fb->nvbo->gem);
+               drm_gem_object_unreference_unlocked(&fb->nvbo->gem);
 
        drm_framebuffer_cleanup(drm_fb);
        kfree(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 = {
        if (ret)
                return ret;
 
-       ret = drm_gem_handle_create(file_priv, bo->gem, &args->handle);
-       drm_gem_object_unreference_unlocked(bo->gem);
+       ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle);
+       drm_gem_object_unreference_unlocked(&bo->gem);
        return ret;
 }
 
 
        gem = drm_gem_object_lookup(dev, file_priv, handle);
        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);
                drm_gem_object_unreference_unlocked(gem);
                return 0;
 
                nouveau_bo_unmap(nouveau_fb->nvbo);
                nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma);
                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;
        }
        drm_fb_helper_fini(&fbcon->helper);
 
 void
 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;
 
-       if (!nvbo)
-               return;
-       nvbo->gem = NULL;
-
        if (gem->import_attach)
                drm_prime_gem_destroy(gem, nvbo->bo.sg);
 
-       ttm_bo_unref(&bo);
-
        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
        if (nv_device(drm->device)->card_type >= NV_50)
                nvbo->valid_domains &= domain;
 
-       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, pnvbo);
                return -ENOMEM;
        }
 
-       nvbo->bo.persistent_swap_storage = nvbo->gem->filp;
-       nvbo->gem->driver_private = nvbo;
+       nvbo->bo.persistent_swap_storage = nvbo->gem.filp;
        return 0;
 }
 
        if (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) {
-               ret = nouveau_gem_info(file_priv, nvbo->gem, &req->info);
+               ret = nouveau_gem_info(file_priv, &nvbo->gem, &req->info);
                if (ret)
                        drm_gem_handle_delete(file_priv, req->info.handle);
        }
 
        /* drop reference from allocate - handle holds it now */
-       drm_gem_object_unreference_unlocked(nvbo->gem);
+       drm_gem_object_unreference_unlocked(&nvbo->gem);
        return ret;
 }
 
 nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_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;
        uint32_t domains = valid_domains & nvbo->valid_domains &
                (write_domains ? write_domains : read_domains);
                list_del(&nvbo->entry);
                nvbo->reserved_by = NULL;
                ttm_bo_unreserve_ticket(&nvbo->bo, ticket);
-               drm_gem_object_unreference_unlocked(nvbo->gem);
+               drm_gem_object_unreference_unlocked(&nvbo->gem);
        }
 }
 
                        validate_fini(op, NULL);
                        return -ENOENT;
                }
-               nvbo = gem->driver_private;
+               nvbo = nouveau_gem_object(gem);
                if (nvbo == res_bo) {
                        res_bo = NULL;
                        drm_gem_object_unreference_unlocked(gem);
                        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->valid_domains);
                if (unlikely(ret)) {
 
 static inline struct nouveau_bo *
 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 */
 
                return ERR_PTR(ret);
 
        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);
                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)