diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 71e27087951b5f275e95b9181510dece1e1c4c77..8ee854a4b3f5bdfe60db7907027fd0c67b96dfd9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -137,6 +137,7 @@ enum nouveau_flags {
 #define NVOBJ_FLAG_ZERO_FREE		(1 << 2)
 struct nouveau_gpuobj {
 	struct drm_device *dev;
+	struct kref refcount;
 	struct list_head list;
 
 	struct drm_mm_node *im_pramin;
@@ -145,7 +146,6 @@ struct nouveau_gpuobj {
 	int im_bound;
 
 	uint32_t flags;
-	int refcount;
 
 	u32 size;
 	u32 pinst;
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index 198c2514f8935f66fee1b45191daecc3f00c0d42..02a0151b073855a91c883928b642707e99890d9d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -90,7 +90,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
 	NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
 	gpuobj->dev = dev;
 	gpuobj->flags = flags;
-	gpuobj->refcount = 1;
+	kref_init(&gpuobj->refcount);
 	gpuobj->size = size;
 
 	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
@@ -198,25 +198,15 @@ void
 nouveau_gpuobj_late_takedown(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *gpuobj = NULL;
-	struct list_head *entry, *tmp;
-
-	NV_DEBUG(dev, "\n");
-
-	list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) {
-		gpuobj = list_entry(entry, struct nouveau_gpuobj, list);
 
-		NV_ERROR(dev, "gpuobj %p still exists at takedown, refs=%d\n",
-			 gpuobj, gpuobj->refcount);
-
-		gpuobj->refcount = 1;
-		nouveau_gpuobj_ref(NULL, &gpuobj);
-	}
+	BUG_ON(!list_empty(&dev_priv->gpuobj_list));
 }
 
-static int
-nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj)
+static void
+nouveau_gpuobj_del(struct kref *ref)
 {
+	struct nouveau_gpuobj *gpuobj =
+		container_of(ref, struct nouveau_gpuobj, refcount);
 	struct drm_device *dev = gpuobj->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_engine *engine = &dev_priv->engine;
@@ -242,17 +232,16 @@ nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj)
 	list_del(&gpuobj->list);
 
 	kfree(gpuobj);
-	return 0;
 }
 
 void
 nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr)
 {
 	if (ref)
-		ref->refcount++;
+		kref_get(&ref->refcount);
 
-	if (*ptr && --(*ptr)->refcount == 0)
-		nouveau_gpuobj_del(*ptr);
+	if (*ptr)
+		kref_put(&(*ptr)->refcount, nouveau_gpuobj_del);
 
 	*ptr = ref;
 }
@@ -275,7 +264,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
 	NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
 	gpuobj->dev = dev;
 	gpuobj->flags = flags;
-	gpuobj->refcount = 1;
+	kref_init(&gpuobj->refcount);
 	gpuobj->size  = size;
 	gpuobj->pinst = pinst;
 	gpuobj->cinst = 0xdeadbeef;
@@ -561,7 +550,7 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
 	gpuobj->dev = chan->dev;
 	gpuobj->engine = NVOBJ_ENGINE_SW;
 	gpuobj->class = class;
-	gpuobj->refcount = 1;
+	kref_init(&gpuobj->refcount);
 	gpuobj->cinst = 0x40;
 
 	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);